use std::env::args; use std::fs::File; use std::io::BufRead; use std::io::BufReader; const TURNS: usize = 11; fn get_data() -> (usize, usize) { let path = args().nth(1).unwrap(); let file = File::open(path).unwrap(); let mut state = 0; let mut player1 = 0; let mut player2 = 0; for line in BufReader::new(file).lines() { match state { 0 => { player1 = line.unwrap()[28..].parse::().unwrap(); state = 1; }, 1 => { player2 = line.unwrap()[28..].parse::().unwrap(); state = 2; }, _ => unreachable!(), } } return (player1 - 1, player2 - 1); } fn index(turn: usize, score: usize, position: usize) -> usize { assert!(turn < TURNS); assert!(score < 21); assert!(position < 10); return turn + score * TURNS + position * TURNS * 21; } fn main() { let (player1, player2) = get_data(); let mut counts1 = [0u64; TURNS * 21 * 10]; let mut counts2 = [0u64; TURNS * 21 * 10]; let mut finishes1 = [0u64; TURNS]; let mut finishes2 = [0u64; TURNS]; counts1[index(0, 0, player1)] += 1; counts2[index(0, 0, player2)] += 1; for turn in 1..TURNS { for score in 0..21 { for position in 0..10 { if score > position { let i = index(turn, score, position); let old_score = score - (position + 1); for a in [1, 2, 3].iter() { for b in [1, 2, 3].iter() { for c in [1, 2, 3].iter() { let old_position = (position + 10 - (a + b + c)) % 10; let j = index(turn - 1, old_score, old_position); counts1[i] += counts1[j]; counts2[i] += counts2[j]; } } } } } } for position in 0..10 { for old_score in (21 - (position + 1))..21 { for a in [1, 2, 3].iter() { for b in [1, 2, 3].iter() { for c in [1, 2, 3].iter() { let old_position = (position + 10 - (a + b + c)) % 10; let j = index(turn - 1, old_score, old_position); finishes1[turn] += counts1[j]; finishes2[turn] += counts2[j]; } } } } } } // the two players can play their games independently and just // multiply their universes in the end let mut open1: u64 = 1; let mut wins1: u64 = 0; let mut open2: u64 = 1; let mut wins2: u64 = 0; for turn in 1..TURNS { open1 *= 27; open1 -= finishes1[turn]; wins1 += finishes1[turn] * open2; open2 *= 27; open2 -= finishes2[turn]; wins2 += finishes2[turn] * open1; } if wins1 > wins2 { println!("{}", wins1); } else { println!("{}", wins2); } }