diff --git a/.gitignore b/.gitignore index 680dea4..602df14 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target .history -input \ No newline at end of file +input +src/template.rs \ No newline at end of file diff --git a/src/day12.rs b/src/day12.rs index e41e2a8..1e84dc6 100644 --- a/src/day12.rs +++ b/src/day12.rs @@ -1,156 +1,155 @@ -use aoc_runner_derive::{aoc, aoc_generator}; - -#[derive(Debug)] -pub enum Direction { - North, - East, - South, - West -} - -impl Direction { - fn from_int(n: i64) -> Self { - match n%4 { - 0 => Self::East, - 1 => Self::South, - 2 => Self::West, - 3 => Self::North, - _ => unreachable!() - } - } -} - -#[derive(Debug)] -pub enum Command { - Direction(Direction,i64), - Left(i64), - Right(i64), - Forward(i64) -} - -#[derive(Debug)] -pub struct Ship { - rot: i64, - pos: (i64,i64), - wp: (i64,i64) -} - -impl Ship { - fn new() -> Self { - Self { - rot:0, - pos: (0,0), - wp: (10,1) - } - } - - fn facing(&self) -> Direction { - Direction::from_int(self.rot) - } - - fn cmd_p1(&mut self, cmd: &Command) { - match cmd { - Command::Direction(Direction::North,n) => { - self.pos.1+=n; - } - Command::Direction(Direction::South,n) => { - self.pos.1-=n; - } - Command::Direction(Direction::East,n) => { - self.pos.0+=n; - } - Command::Direction(Direction::West,n) => { - self.pos.0-=n; - } - Command::Left(n) => { - self.rot-=n; - } - Command::Right(n) => { - self.rot+=n; - } - Command::Forward(n) => { - self.cmd_p1(&Command::Direction(self.facing(),*n)) - } - } - } - - fn cmd_p2(&mut self, cmd: &Command) { - match cmd { - Command::Direction(Direction::North,n) => { - self.wp.1+=n; - } - Command::Direction(Direction::South,n) => { - self.wp.1-=n; - } - Command::Direction(Direction::East,n) => { - self.wp.0+=n; - } - Command::Direction(Direction::West,n) => { - self.wp.0-=n; - } - Command::Right(n) => { - let wp=self.wp; - self.wp=match n%4 { - 0 => wp, - 1 => (wp.1,-wp.0), - 2 => (-wp.0,-wp.1), - 3 => (-wp.1,wp.0), - _ => unreachable!() - }; - } - Command::Left(n) => { - let wp=self.wp; - self.wp=match n%4 { - 0 => wp, - 1 => (-wp.1,wp.0), - 2 => (-wp.0,-wp.1), - 3 => (wp.1,-wp.0), - _ => unreachable!() - }; - } - Command::Forward(n) => { - self.pos.0+=self.wp.0*n; - self.pos.1+=self.wp.1*n; - } - } - } -} - -#[aoc_generator(day12)] -pub fn input_generator(input: &str) -> Vec { - input - .lines() - .map(|l| { - let mut chars=l.chars(); - let cmd=chars.next().unwrap(); - let num = chars.collect::().parse().unwrap(); - match cmd { - 'N' => Command::Direction(Direction::North, num), - 'S' => Command::Direction(Direction::South,num), - 'E' => Command::Direction(Direction::East,num), - 'W' => Command::Direction(Direction::West,num), - 'L' if num%90==0 => Command::Left((num/90)%4), - 'R' if num%90==0 => Command::Right((num/90)%4), - 'F' => Command::Forward(num), - _ => panic!("Invalid command: {}",l) - } - }).collect::>() -} - -#[aoc(day12, part1)] -pub fn solve_part1(input: &Vec) -> usize { - let mut ship=Ship::new(); - for cmd in input { - ship.cmd_p1(cmd); - } - return (ship.pos.0.abs() as usize) + (ship.pos.1.abs() as usize); -} - -#[aoc(day12, part2)] -pub fn solve_part2(input: &Vec) -> usize { - let mut ship=Ship::new(); - for cmd in input { - ship.cmd_p2(cmd); - } - return (ship.pos.0.abs() as usize) + (ship.pos.1.abs() as usize); -} \ No newline at end of file +use aoc_runner_derive::{aoc, aoc_generator}; + +#[derive(Debug)] +pub enum Direction { + North, + East, + South, + West, +} + +impl Direction { + fn from_int(n: i64) -> Self { + match n % 4 { + 0 => Self::East, + 1 => Self::South, + 2 => Self::West, + 3 => Self::North, + _ => unreachable!(), + } + } +} + +#[derive(Debug)] +pub enum Command { + Direction(Direction, i64), + Left(i64), + Right(i64), + Forward(i64), +} + +#[derive(Debug)] +pub struct Ship { + rot: i64, + pos: (i64, i64), + wp: (i64, i64), +} + +impl Ship { + fn new() -> Self { + Self { + rot: 0, + pos: (0, 0), + wp: (10, 1), + } + } + + fn facing(&self) -> Direction { + Direction::from_int(self.rot) + } + + fn cmd_p1(&mut self, cmd: &Command) { + match cmd { + Command::Direction(Direction::North, n) => { + self.pos.1 += n; + } + Command::Direction(Direction::South, n) => { + self.pos.1 -= n; + } + Command::Direction(Direction::East, n) => { + self.pos.0 += n; + } + Command::Direction(Direction::West, n) => { + self.pos.0 -= n; + } + Command::Left(n) => { + self.rot -= n; + } + Command::Right(n) => { + self.rot += n; + } + Command::Forward(n) => self.cmd_p1(&Command::Direction(self.facing(), *n)), + } + } + + fn cmd_p2(&mut self, cmd: &Command) { + match cmd { + Command::Direction(Direction::North, n) => { + self.wp.1 += n; + } + Command::Direction(Direction::South, n) => { + self.wp.1 -= n; + } + Command::Direction(Direction::East, n) => { + self.wp.0 += n; + } + Command::Direction(Direction::West, n) => { + self.wp.0 -= n; + } + Command::Right(n) => { + let wp = self.wp; + self.wp = match n % 4 { + 0 => wp, + 1 => (wp.1, -wp.0), + 2 => (-wp.0, -wp.1), + 3 => (-wp.1, wp.0), + _ => unreachable!(), + }; + } + Command::Left(n) => { + let wp = self.wp; + self.wp = match n % 4 { + 0 => wp, + 1 => (-wp.1, wp.0), + 2 => (-wp.0, -wp.1), + 3 => (wp.1, -wp.0), + _ => unreachable!(), + }; + } + Command::Forward(n) => { + self.pos.0 += self.wp.0 * n; + self.pos.1 += self.wp.1 * n; + } + } + } +} + +#[aoc_generator(day12)] +pub fn input_generator(input: &str) -> Vec { + input + .lines() + .map(|l| { + let mut chars = l.chars(); + let cmd = chars.next().unwrap(); + let num = chars.collect::().parse().unwrap(); + match cmd { + 'N' => Command::Direction(Direction::North, num), + 'S' => Command::Direction(Direction::South, num), + 'E' => Command::Direction(Direction::East, num), + 'W' => Command::Direction(Direction::West, num), + 'L' if num % 90 == 0 => Command::Left((num / 90) % 4), + 'R' if num % 90 == 0 => Command::Right((num / 90) % 4), + 'F' => Command::Forward(num), + _ => panic!("Invalid command: {}", l), + } + }) + .collect::>() +} + +#[aoc(day12, part1)] +pub fn solve_part1(input: &Vec) -> usize { + let mut ship = Ship::new(); + for cmd in input { + ship.cmd_p1(cmd); + } + return (ship.pos.0.abs() as usize) + (ship.pos.1.abs() as usize); +} + +#[aoc(day12, part2)] +pub fn solve_part2(input: &Vec) -> usize { + let mut ship = Ship::new(); + for cmd in input { + ship.cmd_p2(cmd); + } + return (ship.pos.0.abs() as usize) + (ship.pos.1.abs() as usize); +} diff --git a/src/day13.rs b/src/day13.rs new file mode 100644 index 0000000..97c49c3 --- /dev/null +++ b/src/day13.rs @@ -0,0 +1,74 @@ +use aoc_runner_derive::{aoc, aoc_generator}; + +#[derive(Debug)] +pub struct BusInfo { + earliest: u64, + busses: Vec, +} + +type Data = BusInfo; + +#[aoc_generator(day13)] +pub fn input_generator(input: &str) -> Data { + let mut l = input.lines(); + let earliest = l.next().unwrap().parse().unwrap(); + let busses = l + .next() + .unwrap() + .split(',') + .map(|c| match c { + "x" => 0, + n => n.parse().unwrap(), + }) + .collect(); + BusInfo { earliest, busses } +} + +#[aoc(day13, part1)] +pub fn solve_part1(input: &Data) -> usize { + let e = input.earliest; + let mut min = std::u64::MAX; + let mut min_id = 0; + for n in &input.busses { + if *n == 0 { + continue; + } + let m = n - (e % n); + if m < min { + min = m; + min_id = *n; + } + } + return min as usize * min_id as usize; +} + +#[aoc(day13, part2)] +pub fn solve_part2(input: &Data) -> i64 { + let b = input + .busses + .iter() + .enumerate() + .filter(|(_, n)| **n != 0) + .map(|(a, b)| (a as i64, *b as i64)) + .collect::>(); + let mut t = 0; + let target = b.iter().map(|(_, b)| b).fold(1, |a, b| a * b); + loop { + let mut cnt = 0; + let dt = b + .iter() + .filter_map(|(i, n)| { + if (t + i) % n == 0 { + cnt += 1; + Some(*n) + } else { + None + } + }) + .fold(1, |a, b| a * b); + if dt == target { + return t % dt; + } + t += dt; + } +} diff --git a/src/lib.rs b/src/lib.rs index 718c884..072a12a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,4 +11,5 @@ pub mod day09; pub mod day10; pub mod day11; pub mod day12; +pub mod day13; aoc_lib! { year = 2020 }