solution: day6
This commit is contained in:
		
							
								
								
									
										27
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										27
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -2,6 +2,15 @@ | |||||||
| # It is not intended for manual editing. | # It is not intended for manual editing. | ||||||
| version = 3 | version = 3 | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "aho-corasick" | ||||||
|  | version = "0.7.20" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" | ||||||
|  | dependencies = [ | ||||||
|  |  "memchr", | ||||||
|  | ] | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "aoc" | name = "aoc" | ||||||
| version = "0.1.0" | version = "0.1.0" | ||||||
| @@ -11,6 +20,7 @@ dependencies = [ | |||||||
|  "itertools", |  "itertools", | ||||||
|  "lazy_static", |  "lazy_static", | ||||||
|  "pico-args", |  "pico-args", | ||||||
|  |  "regex", | ||||||
|  "reqwest", |  "reqwest", | ||||||
|  "rust-crypto", |  "rust-crypto", | ||||||
| ] | ] | ||||||
| @@ -591,6 +601,23 @@ dependencies = [ | |||||||
|  "bitflags", |  "bitflags", | ||||||
| ] | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "regex" | ||||||
|  | version = "1.7.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" | ||||||
|  | dependencies = [ | ||||||
|  |  "aho-corasick", | ||||||
|  |  "memchr", | ||||||
|  |  "regex-syntax", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "regex-syntax" | ||||||
|  | version = "0.6.28" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "remove_dir_all" | name = "remove_dir_all" | ||||||
| version = "0.5.3" | version = "0.5.3" | ||||||
|   | |||||||
| @@ -13,5 +13,6 @@ hex-literal = "0.3.4" | |||||||
| itertools = "0.10.5" | itertools = "0.10.5" | ||||||
| lazy_static = "1.4.0" | lazy_static = "1.4.0" | ||||||
| pico-args = "0.5.0" | pico-args = "0.5.0" | ||||||
|  | regex = "1.7.0" | ||||||
| reqwest = { version = "0.11.13", features = ["blocking"] } | reqwest = { version = "0.11.13", features = ["blocking"] } | ||||||
| rust-crypto = "0.2.36" | rust-crypto = "0.2.36" | ||||||
|   | |||||||
							
								
								
									
										139
									
								
								src/bin/06.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								src/bin/06.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,139 @@ | |||||||
|  | use std::collections::HashMap; | ||||||
|  |  | ||||||
|  | use lazy_static::lazy_static; | ||||||
|  | use regex::Regex; | ||||||
|  | use Instruction::*; | ||||||
|  |  | ||||||
|  | #[derive(Debug)] | ||||||
|  | struct Point { | ||||||
|  |     x: u32, | ||||||
|  |     y: u32, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl FromIterator<u32> for Point { | ||||||
|  |     fn from_iter<T: IntoIterator<Item = u32>>(iter: T) -> Self { | ||||||
|  |         let mut it = iter.into_iter(); | ||||||
|  |         Point { | ||||||
|  |             x: it.next().unwrap(), | ||||||
|  |             y: it.next().unwrap(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Debug)] | ||||||
|  | enum Instruction { | ||||||
|  |     On, | ||||||
|  |     Off, | ||||||
|  |     Toggle, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Debug)] | ||||||
|  | struct Command { | ||||||
|  |     instruction: Instruction, | ||||||
|  |     from: Point, | ||||||
|  |     to: Point, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl From<&str> for Command { | ||||||
|  |     fn from(value: &str) -> Self { | ||||||
|  |         lazy_static! { | ||||||
|  |             static ref RE: Regex = Regex::new( | ||||||
|  |                 r"(turn on|turn off|toggle) (\d{1,3},\d{1,3}) through (\d{1,3},\d{1, 3})" | ||||||
|  |             ) | ||||||
|  |             .unwrap(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         let capture = RE.captures(value).unwrap(); | ||||||
|  |  | ||||||
|  |         let instruction = match capture[1].as_ref() { | ||||||
|  |             "turn on" => On, | ||||||
|  |             "turn off" => Off, | ||||||
|  |             "toggle" => Toggle, | ||||||
|  |             _ => unreachable!(), | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         let from: Point = capture[2] | ||||||
|  |             .split(',') | ||||||
|  |             .map(|x| x.parse::<u32>().unwrap()) | ||||||
|  |             .collect(); | ||||||
|  |  | ||||||
|  |         let to: Point = capture[3] | ||||||
|  |             .split(',') | ||||||
|  |             .map(|x| x.parse::<u32>().unwrap()) | ||||||
|  |             .collect(); | ||||||
|  |  | ||||||
|  |         Command { | ||||||
|  |             instruction, | ||||||
|  |             from, | ||||||
|  |             to, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | pub fn part_one(input: &str) -> Option<u32> { | ||||||
|  |     let mut map = HashMap::<(u32, u32), bool>::new(); | ||||||
|  |     for line in input.trim().split('\n') { | ||||||
|  |         let Command { | ||||||
|  |             instruction, | ||||||
|  |             from, | ||||||
|  |             to, | ||||||
|  |         } = Command::from(line); | ||||||
|  |         for x in from.x..=to.x { | ||||||
|  |             for y in from.y..=to.y { | ||||||
|  |                 match instruction { | ||||||
|  |                     On => *map.entry((x, y)).or_default() = true, | ||||||
|  |                     Off => *map.entry((x, y)).or_default() = false, | ||||||
|  |                     Toggle => { | ||||||
|  |                         map.entry((x, y)).or_default(); | ||||||
|  |                         map.insert((x, y), !map[&(x, y)]); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     Some(map.values().filter(|&x| *x).count() as u32) | ||||||
|  | } | ||||||
|  | pub fn part_two(input: &str) -> Option<u32> { | ||||||
|  |     let mut map = HashMap::<(u32, u32), u32>::new(); | ||||||
|  |     for line in input.trim().split('\n') { | ||||||
|  |         let Command { | ||||||
|  |             instruction, | ||||||
|  |             from, | ||||||
|  |             to, | ||||||
|  |         } = Command::from(line); | ||||||
|  |         for x in from.x..=to.x { | ||||||
|  |             for y in from.y..=to.y { | ||||||
|  |                 match instruction { | ||||||
|  |                     On => *map.entry((x, y)).or_default() += 1, | ||||||
|  |                     Toggle => *map.entry((x, y)).or_default() += 2, | ||||||
|  |                     Off => { | ||||||
|  |                         map.entry((x, y)).or_default(); | ||||||
|  |                         if map[&(x, y)] > 0 { | ||||||
|  |                             *map.entry((x, y)).or_default() -= 1; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     Some(map.values().into_iter().sum()) | ||||||
|  | } | ||||||
|  | fn main() { | ||||||
|  |     let input = &aoc::read_file("inputs", 6); | ||||||
|  |     aoc::solve!(1, part_one, input); | ||||||
|  |     aoc::solve!(2, part_two, input); | ||||||
|  | } | ||||||
|  | #[cfg(test)] | ||||||
|  | mod tests { | ||||||
|  |     use super::*; | ||||||
|  |     #[test] | ||||||
|  |     fn test_part_one() { | ||||||
|  |         let input = aoc::read_file("test_inputs", 6); | ||||||
|  |         assert_eq!(part_one(&input), Some(998996)); | ||||||
|  |     } | ||||||
|  |     #[test] | ||||||
|  |     fn test_part_two() { | ||||||
|  |         let input = aoc::read_file("test_inputs", 6); | ||||||
|  |         assert_eq!(part_two(&input), Some(1001996)); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								src/test_inputs/06.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/test_inputs/06.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | turn on 0,0 through 999,999 | ||||||
|  | toggle 0,0 through 999,0 | ||||||
|  | turn off 499,499 through 500,500 | ||||||
		Reference in New Issue
	
	Block a user