diff --git a/day14/Cargo.toml b/day14/Cargo.toml new file mode 100644 index 0000000..4984a1c --- /dev/null +++ b/day14/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "day14" +version = "0.1.0" +authors = ["inga-lovinde <52715130+inga-lovinde@users.noreply.github.com>"] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +lazy_static = "1.4.0" +regex = "1" diff --git a/day14/src/main.rs b/day14/src/main.rs new file mode 100644 index 0000000..e93f847 --- /dev/null +++ b/day14/src/main.rs @@ -0,0 +1,90 @@ +use std::collections::HashSet; +use std::io::{self, BufRead}; +use std::error::Error; +use std::str::FromStr; + +#[macro_use] extern crate lazy_static; +use regex::Regex; + +#[derive(Clone, Copy, Debug)] +struct Mask { + and: u64, + or: u64, +} + +impl Mask { + fn from(and: u64, or: u64) -> Mask { + Mask { + and, + or, + } + } +} + +#[derive(Clone, Copy, Debug)] +enum Instruction { + SetMask(Mask), + SetValue{ address: usize, value: u64 }, +} + +impl FromStr for Instruction { + type Err = Box; + + fn from_str(s: &str) -> Result { + lazy_static! { + static ref MASK_RE: Regex = Regex::new(r"^mask\s*=\s*([01X]+)$").unwrap(); + static ref MEM_RE: Regex = Regex::new(r"^mem\[(\d+)\]\s*=\s*(\d+)$").unwrap(); + } + + match (MASK_RE.captures(s), MEM_RE.captures(s)) { + (Some(mask_captures), None) => Ok(Self::SetMask(Mask::from( + u64::from_str_radix(&mask_captures[1].replace("X", "1"), 2)?, + u64::from_str_radix(&mask_captures[1].replace("X", "0"), 2)?, + ))), + (None, Some(mem_re)) => Ok(Self::SetValue { + address: mem_re[1].parse()?, + value: mem_re[2].parse()?, + }), + _ => Err(Box::from("Wrong string format")), + } + } +} + +struct ProgramState { + mask: Mask, + memory: Vec, +} + +impl ProgramState { + pub fn new() -> ProgramState { + ProgramState { + mask: Mask::from(!0, 0), + memory: vec![0; 1 << 16], + } + } + + pub fn apply_instruction(&mut self, instruction: Instruction) -> () { + match instruction { + Instruction::SetMask(mask) => self.mask = mask, + Instruction::SetValue{ address, value } => self.memory[address] = (value | self.mask.or) & self.mask.and, + } + } + + pub fn get_sum(&self) -> u64 { + self.memory.iter().sum() + } +} + +fn main() { + let stdin = io::stdin(); + let instructions: Vec<_> = stdin.lock().lines().into_iter() + .map(|line| line.unwrap().parse::().unwrap()) + .collect(); + + let mut program_state = ProgramState::new(); + for instruction in instructions { + program_state.apply_instruction(instruction); + } + + println!("{}", program_state.get_sum()); +}