at main 3.4 kB view raw
1#![allow(dead_code)] 2use anyhow::Context; 3const INPUT: &str = include_str!("input/1/actual.txt"); 4 5pub fn main() -> anyhow::Result<()> { 6 let rotations = Rotation::parse_file(INPUT).context("parsing input")?; 7 8 let mut dial = Dial::new(50, true); 9 10 dial.apply_rotations(&rotations); 11 12 println!("{:?}", dial); 13 14 Ok(()) 15} 16 17#[derive(Debug)] 18struct Dial { 19 value: i32, 20 times_left_at_zero: u32, 21 /// for extra challenge thing 22 extra_mode: bool, 23} 24 25impl Dial { 26 const SIZE: i32 = 100; 27 28 pub fn new(initial_value: i32, extra: bool) -> Dial { 29 Dial { 30 value: initial_value, 31 times_left_at_zero: 0, 32 extra_mode: extra, 33 } 34 } 35 36 pub fn apply_rotations(&mut self, rotations: &Vec<Rotation>) { 37 rotations.iter().for_each(|rotation| { 38 if self.extra_mode { 39 self.times_left_at_zero += self.hits_zero_during(rotation); 40 self.apply_rotation(rotation); 41 } else { 42 self.apply_rotation(rotation); 43 if self.value == 0 { 44 self.times_left_at_zero += 1; 45 } 46 } 47 }); 48 } 49 50 fn apply_rotation(&mut self, rotation: &Rotation) { 51 match rotation.direction { 52 Direction::Left => self.value -= rotation.amount, 53 Direction::Right => self.value += rotation.amount, 54 } 55 56 self.value = self.value.rem_euclid(Self::SIZE); 57 } 58 59 fn hits_zero_during(&self, rotation: &Rotation) -> u32 { 60 if rotation.amount <= 0 { 61 return 0; 62 } 63 64 // how many steps until next hit 0 65 // this gave me a headache. boy do i suck at maths. 66 // this is my punishment for sleeping through every maths class in school. 67 let turns_needed = match rotation.direction { 68 Direction::Right => { 69 if self.value == 0 { 70 Self::SIZE 71 } else { 72 Self::SIZE - self.value 73 } 74 } 75 Direction::Left => { 76 if self.value == 0 { 77 Self::SIZE 78 } else { 79 self.value 80 } 81 } 82 }; 83 84 if rotation.amount < turns_needed { 85 0 86 } else { 87 1 + ((rotation.amount - turns_needed) / Self::SIZE) as u32 88 } 89 } 90} 91 92#[derive(Debug, PartialEq, Eq)] 93enum Direction { 94 Left, 95 Right, 96} 97 98impl Direction { 99 pub fn parse(character: char) -> anyhow::Result<Direction> { 100 match character { 101 'L' => Ok(Self::Left), 102 'R' => Ok(Self::Right), 103 _ => Err(anyhow::anyhow!("unknown direction char '{}'", character)), 104 } 105 } 106} 107 108#[derive(Debug)] 109struct Rotation { 110 direction: Direction, 111 amount: i32, 112} 113 114impl Rotation { 115 pub fn parse_file(text: &str) -> anyhow::Result<Vec<Rotation>> { 116 text.lines().map(Rotation::parse).collect() 117 } 118 119 pub fn parse(line: &str) -> anyhow::Result<Rotation> { 120 let mut chars = line.chars(); 121 122 let direction = Direction::parse(chars.next().context("popping first char")?) 123 .context("parsing direction")?; 124 125 let amount = chars 126 .collect::<String>() 127 .parse::<i32>() 128 .context("parsing remaining number")?; 129 130 Ok(Self { direction, amount }) 131 } 132}