1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
use crate::input::Input; use std::collections::HashSet; struct Action { write_one: bool, move_direction: i8, next_state: u8, } struct State { if_zero_action: Action, if_one_action: Action, } pub fn solve(input: &mut Input) -> Result<usize, String> { let mut tape = HashSet::new(); let mut target_steps = 0; let mut states: Vec<State> = Vec::new(); let on_error = || "Invalid input".to_string(); for (count, text) in input.text.split("\n\n").enumerate() { if count == 0 { target_steps = text .split(' ') .nth(8) .ok_or_else(on_error)? .parse::<u32>() .map_err(|_| on_error())?; } else { let words: Vec<&str> = text.split(' ').collect(); if words.len() < 69 { return Err(on_error()); } let if_zero_action = Action { write_one: words[17] == "1.\n", move_direction: if words[27] == "right.\n" { 1 } else { -1 }, next_state: words[35].bytes().next().ok_or_else(on_error)? - b'A', }; let if_one_action = Action { write_one: words[50] == "1.\n", move_direction: if words[60] == "right.\n" { 1 } else { -1 }, next_state: words[68].bytes().next().ok_or_else(on_error)? - b'A', }; states.push(State { if_zero_action, if_one_action, }); } } let mut current_state = 0; let mut current_position = 0_i32; for _ in 0..target_steps { let current_action = if tape.contains(¤t_position) { &states[current_state].if_one_action } else { &states[current_state].if_zero_action }; if current_action.write_one { tape.insert(current_position); } else { tape.remove(¤t_position); } current_position += i32::from(current_action.move_direction); current_state = current_action.next_state as usize; } Ok(tape.len()) } #[test] pub fn tests() { use crate::test_part_one; let real_input = include_str!("day25_input.txt"); test_part_one!(real_input => 633); }