diff --git a/day10/Cargo.toml b/day10/Cargo.toml new file mode 100644 index 0000000..d275052 --- /dev/null +++ b/day10/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "day10" +version = "0.1.0" +authors = ["Avril "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[features] +test=[] + +[dependencies] +ad-hoc-iter = "0.2.2" +cfg-if = "1.0.0" +smallmap = "1.2.1" diff --git a/day10/src/main.rs b/day10/src/main.rs new file mode 100644 index 0000000..65f18d5 --- /dev/null +++ b/day10/src/main.rs @@ -0,0 +1,144 @@ +#![allow(dead_code)] + +#[macro_use] extern crate ad_hoc_iter; +#[macro_use] extern crate cfg_if; + +use std::{ + io, + io::BufReader, + fs::OpenOptions, + num::NonZeroU8, + ops, + iter, +}; +use smallmap::Map; +mod input; + +const INPUT: &str = "input"; + +type Adaptors = Map; + + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)] +struct Diffs([usize; 3]); + +impl ops::Add for Diffs +{ + type Output = Self; + fn add(self, other: Self) -> Self::Output{ + Self([ + self.0[0] + other.0[0], + self.0[1] + other.0[1], + self.0[2] + other.0[2], + ]) + } +} + +impl ops::AddAssign for Diffs +{ + fn add_assign(&mut self, rhs: Self) { + self.0[0] += rhs.0[0]; + self.0[1] += rhs.0[1]; + self.0[2] += rhs.0[2]; + } +} + +impl Diffs +{ + pub fn jd1(&self) -> usize + { + self.0[0] + } + pub fn jd2(&self) -> usize + { + self.0[1] + } + pub fn jd3(&self) -> usize + { + self.0[2] + } +} + +fn parse_input(file: &str) -> Result, io::Error> +{ + let file = OpenOptions::new().read(true).open(file)?; + Ok(input::read_input(BufReader::new(file))) +} + +fn find_smallest(map: &Adaptors, finding: impl Into) -> (Option, Diffs) +{ + #![allow(unused_assignments)] + + let finding = finding.into(); + let mut diffs = Diffs::default(); + let mut set=false; + macro_rules! find { + ($l:literal) => { + { + let shim = finding + $l; + debug_assert!(shim > 0); + //eprintln!("Looking up {}", shim); + match map.get(&unsafe { + NonZeroU8::new_unchecked(shim) + }).map(|_| shim) { + Some(yes) if !set => { + set = true; + diffs.0[($l-1)] += 1; + Some(yes) + }, + x => x + } + } + } + }; + (iter![ + find!(1), + find!(2), + find!(3) + ].filter_map(std::convert::identity) + .min(), diffs) +} + +#[inline(always)] fn conv_input(input: impl Iterator) -> impl Iterator +{ + input.filter_map(NonZeroU8::new).zip(iter::repeat(())) +} + +#[inline(always)] fn get_input() -> impl Iterator +{ + cfg_if!{ + if #[cfg(feature="test")] { + input::test_input() + } else { + parse_input(INPUT).unwrap() + } + } +} +fn main() -> Result<(), Box> +{ + let all_jolts = { + let mut map: Adaptors = conv_input(get_input()).collect(); + unsafe { + map.insert(NonZeroU8::new_unchecked(map.iter().map(|&(x, _)| x).max().unwrap().get() + 3), ()); + } + map + }; + debug_assert_eq!(all_jolts.num_pages(), 1); // Assert we have space efficiency. + + let mut current = 0; + #[allow(unused_variables)] + let mut sum=0; + let mut whole_diffs = Diffs::default(); + loop { + if let (Some(next), diffs) = find_smallest(&all_jolts, current) { + current = next; + sum+=1; + whole_diffs += diffs; + } else { + break; + } + } + + println!("{}", whole_diffs.jd1() * whole_diffs.jd3()); + Ok(()) +}