parent
5e246a1567
commit
d9b5a89702
@ -0,0 +1,11 @@ |
||||
[package] |
||||
name = "day14-hard" |
||||
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" |
@ -0,0 +1,97 @@ |
||||
use std::collections::HashMap; |
||||
use std::error::Error; |
||||
use std::io::{self, BufRead}; |
||||
use std::str::FromStr; |
||||
|
||||
#[macro_use] extern crate lazy_static; |
||||
use regex::Regex; |
||||
|
||||
#[derive(Clone, Copy, Debug)] |
||||
struct Mask { |
||||
pub bypass: u64, |
||||
pub floating: u64, |
||||
pub ones: u64, |
||||
} |
||||
|
||||
#[derive(Clone, Copy, Debug)] |
||||
enum Instruction { |
||||
SetMask(Mask), |
||||
SetValue{ address: u64, value: u128 }, |
||||
} |
||||
|
||||
impl FromStr for Instruction { |
||||
type Err = Box<dyn Error>; |
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> { |
||||
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 { |
||||
bypass: u64::from_str_radix(&mask_captures[1].replace("1", "X").replace("0", "1").replace("X", "0"), 2)?, |
||||
floating: u64::from_str_radix(&mask_captures[1].replace("1", "0").replace("X", "1"), 2)?, |
||||
ones: 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: HashMap<u64, u128>, |
||||
} |
||||
|
||||
impl ProgramState { |
||||
pub fn new() -> ProgramState { |
||||
ProgramState { |
||||
mask: Mask { |
||||
bypass: !0, |
||||
floating: 0, |
||||
ones: 0, |
||||
}, |
||||
memory: HashMap::new(), |
||||
} |
||||
} |
||||
|
||||
pub fn apply_instruction(&mut self, instruction: Instruction) -> () { |
||||
match instruction { |
||||
Instruction::SetMask(mask) => self.mask = mask, |
||||
Instruction::SetValue{ address, value } => { |
||||
let address_min = (address & self.mask.bypass) | self.mask.ones; |
||||
let address_max = address_min | self.mask.floating; |
||||
for i in address_min..=address_max { // insanely slow, could be optimized, but I'm lazy :(
|
||||
if (i & address_min) == address_min && (i & address_max) == i { |
||||
self.memory.insert(i, value); |
||||
println!("Inserting {} into {}", value, i); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub fn get_sum(&self) -> u128 { |
||||
self.memory.values().sum() |
||||
} |
||||
} |
||||
|
||||
fn main() { |
||||
let stdin = io::stdin(); |
||||
let instructions: Vec<_> = stdin.lock().lines().into_iter() |
||||
.map(|line| line.unwrap().parse::<Instruction>().unwrap()) |
||||
.collect(); |
||||
|
||||
let mut program_state = ProgramState::new(); |
||||
for instruction in instructions { |
||||
program_state.apply_instruction(instruction); |
||||
println!("Processed instruction"); |
||||
} |
||||
|
||||
println!("{}", program_state.get_sum()); |
||||
} |
Loading…
Reference in new issue