From 00000090cff5bf14143a2c94ef3ce566ae9f14f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Jane=C5=BEi=C4=8D?= Date: Sat, 3 Dec 2022 20:10:45 +0100 Subject: [PATCH] solution: day6 --- Cargo.lock | 27 ++++++++ Cargo.toml | 1 + src/bin/06.rs | 139 +++++++++++++++++++++++++++++++++++++++++ src/test_inputs/06.txt | 3 + 4 files changed, 170 insertions(+) create mode 100644 src/bin/06.rs create mode 100644 src/test_inputs/06.txt diff --git a/Cargo.lock b/Cargo.lock index 021e978..c188d77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. 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]] name = "aoc" version = "0.1.0" @@ -11,6 +20,7 @@ dependencies = [ "itertools", "lazy_static", "pico-args", + "regex", "reqwest", "rust-crypto", ] @@ -591,6 +601,23 @@ dependencies = [ "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]] name = "remove_dir_all" version = "0.5.3" diff --git a/Cargo.toml b/Cargo.toml index b5a7d7b..dffc2e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,5 +13,6 @@ hex-literal = "0.3.4" itertools = "0.10.5" lazy_static = "1.4.0" pico-args = "0.5.0" +regex = "1.7.0" reqwest = { version = "0.11.13", features = ["blocking"] } rust-crypto = "0.2.36" diff --git a/src/bin/06.rs b/src/bin/06.rs new file mode 100644 index 000000000..5cd82a4 --- /dev/null +++ b/src/bin/06.rs @@ -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 for Point { + fn from_iter>(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::().unwrap()) + .collect(); + + let to: Point = capture[3] + .split(',') + .map(|x| x.parse::().unwrap()) + .collect(); + + Command { + instruction, + from, + to, + } + } +} + +pub fn part_one(input: &str) -> Option { + 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 { + 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)); + } +} diff --git a/src/test_inputs/06.txt b/src/test_inputs/06.txt new file mode 100644 index 000000000..4506a12 --- /dev/null +++ b/src/test_inputs/06.txt @@ -0,0 +1,3 @@ +turn on 0,0 through 999,999 +toggle 0,0 through 999,0 +turn off 499,499 through 500,500