Day 1-6
This commit is contained in:
		
							parent
							
								
									47680488e1
								
							
						
					
					
						commit
						8b34e1bb1e
					
				
					 11 changed files with 504 additions and 2 deletions
				
			
		
							
								
								
									
										4
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -3,11 +3,11 @@ | |||
| # will have compiled files and executables | ||||
| debug/ | ||||
| target/ | ||||
| 
 | ||||
| .history/ | ||||
| # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries | ||||
| # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html | ||||
| Cargo.lock | ||||
| 
 | ||||
| # These are backup files generated by rustfmt | ||||
| **/*.rs.bk | ||||
| 
 | ||||
| /input | ||||
							
								
								
									
										12
									
								
								Cargo.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								Cargo.toml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | |||
| [package] | ||||
| name = "aoc_2021" | ||||
| version = "0.1.0" | ||||
| authors = ["Daniel Seiller <earthnuker@gmail.com>"] | ||||
| edition = "2021" | ||||
| 
 | ||||
| # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||
| 
 | ||||
| [dependencies] | ||||
| aoc-runner = "0.3.0" | ||||
| aoc-runner-derive = "0.3.0" | ||||
| itertools = "0.10.1" | ||||
							
								
								
									
										25
									
								
								src/day01.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/day01.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | |||
| use aoc_runner_derive::{aoc, aoc_generator}; | ||||
| #[aoc_generator(day1)] | ||||
| pub fn input_generator(input: &str) -> Vec<usize> { | ||||
|     input | ||||
|         .lines() | ||||
|         .map(|l| l.trim().parse()) | ||||
|         .collect::<Result<Vec<usize>, _>>() | ||||
|         .unwrap() | ||||
| } | ||||
| 
 | ||||
| #[aoc(day1, part1)] | ||||
| pub fn solve_part1(input: &[usize]) -> usize { | ||||
|     return input.windows(2).filter(|v| v[1] > v[0]).count(); | ||||
| } | ||||
| #[aoc(day1, part2)] | ||||
| pub fn solve_part2(input: &[usize]) -> usize { | ||||
|     input | ||||
|         .windows(3) | ||||
|         .map(|w| w.iter().sum()) | ||||
|         .collect::<Vec<usize>>() | ||||
|         .as_slice() | ||||
|         .windows(2) | ||||
|         .filter(|v| v[1] > v[0]) | ||||
|         .count() | ||||
| } | ||||
							
								
								
									
										115
									
								
								src/day02.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								src/day02.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,115 @@ | |||
| use aoc_runner_derive::{aoc, aoc_generator}; | ||||
| use std::{error::Error, str::FromStr}; | ||||
| 
 | ||||
| #[derive(Debug, Copy, Clone)] | ||||
| enum Direction { | ||||
|     Forward, | ||||
|     Down, | ||||
|     Up, | ||||
| } | ||||
| #[derive(Debug, Copy, Clone)] | ||||
| pub struct Instruction { | ||||
|     direction: Direction, | ||||
|     amount: usize, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Copy, Clone, Default)] | ||||
| pub struct Submarine{ | ||||
|     depth: i64, | ||||
|     pos: i64, | ||||
|     aim: i64 | ||||
| } | ||||
| 
 | ||||
| impl Submarine { | ||||
|     fn new() -> Self { | ||||
|         Default::default() | ||||
|     } | ||||
|     fn run_p1(&mut self, inst: &Instruction) { | ||||
|         let d = inst.direction; | ||||
|         let a = inst.amount as i64; | ||||
|         match d { | ||||
|             Direction::Forward => { | ||||
|                 self.pos += a; | ||||
|             } | ||||
|             Direction::Down => { | ||||
|                 self.depth += a; | ||||
|             } | ||||
|             Direction::Up => { | ||||
|                 self.depth -= a; | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|     fn run_p2(&mut self, inst: &Instruction) { | ||||
|         let d = inst.direction; | ||||
|         let a = inst.amount as i64; | ||||
|         match d { | ||||
|             Direction::Forward => { | ||||
|                 self.pos += a; | ||||
|                 self.depth += self.aim*a; | ||||
|             } | ||||
|             Direction::Down => { | ||||
|                 self.aim += a; | ||||
|             } | ||||
|             Direction::Up => { | ||||
|                 self.aim -= a; | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl FromStr for Instruction { | ||||
|     type Err = Box<dyn Error>; | ||||
| 
 | ||||
|     fn from_str(s: &str) -> Result<Self, Self::Err> { | ||||
|         let mut s = s.split_ascii_whitespace(); | ||||
|         let inst = s.next().unwrap(); | ||||
|         let amount: usize = s.next().unwrap().parse().unwrap(); | ||||
|         let ret = match inst { | ||||
|             "forward" => Self { | ||||
|                 direction: Direction::Forward, | ||||
|                 amount, | ||||
|             }, | ||||
|             "up" => Self { | ||||
|                 direction: Direction::Up, | ||||
|                 amount, | ||||
|             }, | ||||
|             "down" => Self { | ||||
|                 direction: Direction::Down, | ||||
|                 amount, | ||||
|             }, | ||||
|             other => { | ||||
|                 panic!("Invalid instruction: {}", other) | ||||
|             } | ||||
|         }; | ||||
|         Ok(ret) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub type Data = Vec<Instruction>; | ||||
| 
 | ||||
| #[aoc_generator(day02)] | ||||
| pub fn input_generator(input: &str) -> Data { | ||||
|     input | ||||
|         .lines() | ||||
|         .map(Instruction::from_str) | ||||
|         .collect::<Result<Vec<_>, _>>() | ||||
|         .unwrap() | ||||
| } | ||||
| 
 | ||||
| #[aoc(day02, part1)] | ||||
| pub fn solve_part1(input: &Data) -> usize { | ||||
|     let mut sm = Submarine::new(); | ||||
|     for inst in input { | ||||
|         sm.run_p1(inst); | ||||
|     } | ||||
|     (sm.pos * sm.depth) as usize | ||||
| } | ||||
| 
 | ||||
| #[aoc(day02, part2)] | ||||
| pub fn solve_part2(input: &Data) -> usize { | ||||
|     let mut sm = Submarine::new(); | ||||
|     for inst in input { | ||||
|         sm.run_p2(inst); | ||||
|     } | ||||
|     (sm.pos * sm.depth) as usize | ||||
| } | ||||
							
								
								
									
										91
									
								
								src/day03.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/day03.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,91 @@ | |||
| use aoc_runner_derive::{aoc, aoc_generator}; | ||||
| 
 | ||||
| type Data = Vec<u16>; | ||||
| 
 | ||||
| fn make_histogram(input: &[u16]) -> Vec<(usize, i64)> { | ||||
|     let counts: &mut [Option<i64>] = &mut [None; 64]; | ||||
|     input.iter().for_each(|val| { | ||||
|         for (n, count) in counts.iter_mut().enumerate().take(12) { | ||||
|             let v = count.get_or_insert(0); | ||||
|             if ((val >> n) & 1) == 1 { | ||||
|                 *v += 1; | ||||
|             } else { | ||||
|                 *v -= 1; | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
|     counts.reverse(); | ||||
|     counts | ||||
|         .iter() | ||||
|         .enumerate() | ||||
|         .filter_map(|(a, b)| b.map(|b| (a, b))) | ||||
|         .collect::<Vec<_>>() | ||||
| } | ||||
| 
 | ||||
| #[aoc_generator(day03)] | ||||
| pub fn input_generator(input: &str) -> Vec<u16> { | ||||
|     input | ||||
|         .lines() | ||||
|         .map(|l| u16::from_str_radix(l, 2).unwrap()) | ||||
|         .collect() | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| enum Mode { | ||||
|     MostCommon, | ||||
|     LeastCommon, | ||||
| } | ||||
| 
 | ||||
| fn tree_filter(data: &[u16], pos: usize, mode: Mode) -> u16 { | ||||
|     let (zero, one) = data | ||||
|         .iter() | ||||
|         .partition::<Vec<u16>, _>(|&v| ((v >> pos) & 1) == 0); | ||||
|      if data.is_empty() { | ||||
|         panic!("Uh Oh!"); | ||||
|     } | ||||
|     if data.len() == 1 { | ||||
|         return data[0]; | ||||
|     } | ||||
|     if zero.len() == one.len() { | ||||
|         match mode { | ||||
|             Mode::MostCommon => tree_filter(&one, pos - 1, mode), | ||||
|             Mode::LeastCommon => tree_filter(&zero, pos - 1, mode), | ||||
|         } | ||||
|     } else { | ||||
|         let mut srt = vec![zero, one]; | ||||
|         srt.sort_by_key(|v| v.len()); | ||||
|         match mode { | ||||
|             Mode::MostCommon => tree_filter(&srt[1], pos - 1, mode), | ||||
|             Mode::LeastCommon => tree_filter(&srt[0], pos - 1, mode), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| const ASCII_ZERO: u8 = 0x30; | ||||
| 
 | ||||
| #[aoc(day03, part1)] // 1997414
 | ||||
| pub fn solve_part1(input: &Data) -> usize { | ||||
|     let counts = make_histogram(input); | ||||
|     let (gamma, epsilon): (String, String) = counts | ||||
|         .iter() | ||||
|         .map(|(_, v)| { | ||||
|             ( | ||||
|                 (ASCII_ZERO + (*v >= 0) as u8) as char, | ||||
|                 (ASCII_ZERO + (*v < 0) as u8) as char, | ||||
|             ) | ||||
|         }) | ||||
|         .unzip(); | ||||
|     let gamma = usize::from_str_radix(&gamma, 2).unwrap(); | ||||
|     let epsilon = usize::from_str_radix(&epsilon, 2).unwrap(); | ||||
|     gamma * epsilon | ||||
| } | ||||
| 
 | ||||
| #[aoc(day03, part2)] | ||||
| pub fn solve_part2(input: &[u16]) -> usize { | ||||
|     // let input: Vec<bool> = input.iter().for_each(|v| v[0]).collect();
 | ||||
|     let a = tree_filter(input, 11, Mode::MostCommon) as usize; | ||||
|     let b = tree_filter(input, 11, Mode::LeastCommon) as usize; | ||||
|     a * b | ||||
| } | ||||
							
								
								
									
										92
									
								
								src/day04.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/day04.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,92 @@ | |||
| use aoc_runner_derive::{aoc, aoc_generator}; | ||||
| 
 | ||||
| #[derive(Debug,Clone)] | ||||
| pub struct Data { | ||||
|     pub numbers: Vec<u8>, | ||||
|     pub boards: Vec<[[(u8,bool); 5]; 5]>, | ||||
| } | ||||
| 
 | ||||
| #[aoc_generator(day04)] | ||||
| pub fn input_generator(input: &str) -> Data { | ||||
|     let mut lines = input.lines(); | ||||
|     let mut boards = vec![]; | ||||
|     let numbers = lines | ||||
|         .next() | ||||
|         .unwrap() | ||||
|         .split(',') | ||||
|         .map(|s| s.parse()) | ||||
|         .collect::<Result<Vec<u8>, _>>() | ||||
|         .unwrap(); | ||||
|     let mut row = 0; | ||||
|     let mut board = [[(0u8,false); 5]; 5]; | ||||
|     for line in lines { | ||||
|         if line.is_empty() { | ||||
|             continue; | ||||
|         } | ||||
|         let line = line | ||||
|             .split_ascii_whitespace() | ||||
|             .map(|s| s.parse()) | ||||
|             .collect::<Result<Vec<u8>, _>>() | ||||
|             .unwrap(); | ||||
|         line.iter().enumerate().for_each(|(i, v)| { | ||||
|             board[row][i] = (*v,false); | ||||
|         }); | ||||
|         row = (row + 1) % 5; | ||||
|         if row == 0 { | ||||
|             boards.push(board); | ||||
|             board = [[(0u8,false); 5]; 5]; | ||||
|         } | ||||
|     } | ||||
|     Data { numbers, boards } | ||||
| } | ||||
| 
 | ||||
| #[aoc(day04, part1)] | ||||
| pub fn solve_part1(input: &Data) -> usize { | ||||
|     let Data {numbers,mut boards} =input.clone(); | ||||
|     for number in numbers.iter() { | ||||
|         for board in &mut boards { | ||||
|             for row in board.iter_mut() { | ||||
|                 for (n,b) in row { | ||||
|                     if n==number { | ||||
|                         *b=true; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             let win=(0..5).map(|v| { | ||||
|                 [board[v][0],board[v][1],board[v][2],board[v][3],board[v][4]].iter().all(|v| v.1)| | ||||
|                 [board[0][v],board[1][v],board[2][v],board[3][v],board[4][v]].iter().all(|v| v.1) | ||||
|             }).any(|v| v); | ||||
|             if win { | ||||
|                 return board.iter().flatten().filter_map(|(v,b)| (!*b).then(|| *v as usize)).sum::<usize>()*(*number as usize) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     unreachable!() | ||||
| } | ||||
| 
 | ||||
| #[aoc(day04, part2)] | ||||
| pub fn solve_part2(input: &Data) -> usize { | ||||
|     let mut ret=None; | ||||
|     let Data {numbers,mut boards} =input.clone(); | ||||
|     let mut board_wins: Vec<bool> = vec![false;boards.len()]; | ||||
|     for number in numbers.iter() { | ||||
|         for (board_n,board) in boards.iter_mut().enumerate() { | ||||
|             for row in board.iter_mut() { | ||||
|                 for (n,b) in row { | ||||
|                     if n==number { | ||||
|                         *b=true; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             let win=(0..5).map(|v| { | ||||
|                 [board[v][0],board[v][1],board[v][2],board[v][3],board[v][4]].iter().all(|v| v.1)| | ||||
|                 [board[0][v],board[1][v],board[2][v],board[3][v],board[4][v]].iter().all(|v| v.1) | ||||
|             }).any(|v| v); | ||||
|             if win && !board_wins[board_n] { | ||||
|                 ret=Some(board.iter().flatten().filter(|(_,b)| !*b).map(|(v,_)| *v as usize).sum::<usize>()*(*number as usize)); | ||||
|                 board_wins[board_n]=true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return ret.unwrap(); | ||||
| } | ||||
							
								
								
									
										106
									
								
								src/day05.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								src/day05.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,106 @@ | |||
| use aoc_runner_derive::{aoc, aoc_generator}; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct Line { | ||||
|     x: (i64, i64), | ||||
|     y: (i64, i64), | ||||
| } | ||||
| 
 | ||||
| impl Line { | ||||
|     fn iter(&self) -> LineIterator { | ||||
|         let ret= LineIterator { | ||||
|             line: self, | ||||
|             px: self.x.0, | ||||
|             py: self.y.0, | ||||
|             sx: match self.x.0.cmp(&self.x.1) { | ||||
|                 std::cmp::Ordering::Less => 1, | ||||
|                 std::cmp::Ordering::Equal => 0, | ||||
|                 std::cmp::Ordering::Greater => -1, | ||||
|             }, | ||||
|             sy: match self.y.0.cmp(&self.y.1) { | ||||
|                 std::cmp::Ordering::Less => 1, | ||||
|                 std::cmp::Ordering::Equal => 0, | ||||
|                 std::cmp::Ordering::Greater => -1, | ||||
|             }, | ||||
|         }; | ||||
|         assert!(ret.sx!=0||ret.sy!=0); | ||||
|         ret | ||||
|     } | ||||
| } | ||||
| #[derive(Debug)] | ||||
| struct LineIterator<'a> { | ||||
|     line: &'a Line, | ||||
|     px: i64, | ||||
|     py: i64, | ||||
|     sx: i64, | ||||
|     sy: i64, | ||||
| } | ||||
| 
 | ||||
| impl<'a> Iterator for LineIterator<'a> { | ||||
|     type Item = (i64, i64); | ||||
| 
 | ||||
|     fn next(&mut self) -> Option<Self::Item> { | ||||
|         let ret = (self.px,self.py); | ||||
|         if self.sx>0 && self.px>self.line.x.1 { | ||||
|             return None; | ||||
|         } | ||||
|         if self.sx<0 && self.px<self.line.x.1 { | ||||
|             return None; | ||||
|         } | ||||
|         if self.sy>0 && self.py>self.line.y.1 { | ||||
|             return None; | ||||
|         } | ||||
|         if self.sy<0 && self.py<self.line.y.1 { | ||||
|             return None; | ||||
|         } | ||||
|         self.px+=self.sx; | ||||
|         self.py+=self.sy; | ||||
|         Some(ret) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| type Data = Vec<Line>; | ||||
| 
 | ||||
| #[aoc_generator(day05)] | ||||
| pub fn input_generator(input: &str) -> Data { | ||||
|     input | ||||
|         .lines() | ||||
|         .map(|line| { | ||||
|             let  parts= line.split(" -> ").collect::<Vec<_>>(); | ||||
|             let start = parts[0] | ||||
|                 .split(',') | ||||
|                 .map(|v| v.parse().unwrap()) | ||||
|                 .collect::<Vec<i64>>(); | ||||
|             let end = parts[1] | ||||
|                 .split(',') | ||||
|                 .map(|v| v.parse().unwrap()) | ||||
|                 .collect::<Vec<i64>>(); | ||||
|             Line { | ||||
|                 x: (start[0], end[0]), | ||||
|                 y: (start[1], end[1]), | ||||
|             } | ||||
|         }) | ||||
|         .collect() | ||||
| } | ||||
| 
 | ||||
| #[aoc(day05, part1)] | ||||
| pub fn solve_part1(input: &Data) -> usize { | ||||
|     let mut grid = vec![vec![0u8; 1000]; 1000]; | ||||
|     for (x,y) in input.iter().filter(|l| l.x.0==l.x.1||l.y.0==l.y.1).flat_map(|v| v.iter()) { | ||||
|         let x: usize=x.try_into().unwrap(); | ||||
|         let y: usize=y.try_into().unwrap(); | ||||
|         grid[x][y] += 1; | ||||
|     } | ||||
|     return grid.iter().flatten().filter(|&v| *v > 1).count(); | ||||
| } | ||||
| 
 | ||||
| #[aoc(day05, part2)] | ||||
| pub fn solve_part2(input: &Data) -> usize { | ||||
|     let mut grid = vec![vec![0u8; 1000]; 1000]; | ||||
|     for (x,y) in input.iter().flat_map(|v| v.iter()) { | ||||
|         let x: usize=x.try_into().unwrap(); | ||||
|         let y: usize=y.try_into().unwrap(); | ||||
|         grid[x][y] += 1; | ||||
|     } | ||||
|     return grid.iter().flatten().filter(|&v| *v > 1).count(); | ||||
| } | ||||
							
								
								
									
										32
									
								
								src/day06.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/day06.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,32 @@ | |||
| use aoc_runner_derive::{aoc, aoc_generator}; | ||||
| 
 | ||||
| type Data = Vec<u8>; | ||||
| 
 | ||||
| #[aoc_generator(day06)] | ||||
| pub fn input_generator(input: &str) -> Data { | ||||
|     input.trim().split(',').map(|v| v.parse().unwrap()).collect() | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| fn simulate(input: &Data,n: usize) -> usize { | ||||
|     let mut state: [usize;9] = [0;9]; | ||||
|     for v in input { | ||||
|         state[*v as usize]+=1; | ||||
|     } | ||||
|     for _ in 0..n { | ||||
|         state[7]+=state[0]; | ||||
|         state.rotate_left(1); | ||||
|     } | ||||
|     state.iter().sum() | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #[aoc(day06, part1)] | ||||
| pub fn solve_part1(input: &Data) -> usize { | ||||
|     simulate(input,80) | ||||
| } | ||||
| 
 | ||||
| #[aoc(day06, part2)] | ||||
| pub fn solve_part2(input: &Data) -> usize { | ||||
|     simulate(input,256) | ||||
| } | ||||
							
								
								
									
										9
									
								
								src/lib.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/lib.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| #![allow(clippy::clippy::needless_return)] | ||||
| use aoc_runner_derive::aoc_lib; | ||||
| pub mod day01; | ||||
| pub mod day02; | ||||
| pub mod day03; | ||||
| pub mod day04; | ||||
| pub mod day05; | ||||
| pub mod day06; | ||||
| aoc_lib! { year = 2021 } | ||||
							
								
								
									
										2
									
								
								src/main.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								src/main.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | |||
| use aoc_runner_derive::aoc_main; | ||||
| aoc_main! { lib  = aoc_2021 } | ||||
							
								
								
									
										18
									
								
								src/template.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/template.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | |||
| use aoc_runner_derive::{aoc, aoc_generator}; | ||||
| 
 | ||||
| type Data = (); | ||||
| 
 | ||||
| #[aoc_generator(dayXX)] | ||||
| pub fn input_generator(input: &str) -> Data { | ||||
|     todo!(); | ||||
| } | ||||
| 
 | ||||
| #[aoc(dayXX, part1)] | ||||
| pub fn solve_part1(input: &Data) -> usize { | ||||
|     todo!(); | ||||
| } | ||||
| 
 | ||||
| #[aoc(dayXX, part2)] | ||||
| pub fn solve_part2(input: &Data) -> usize { | ||||
|     todo!() | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue