4 files changed
+739
No files matched your search
+141
@@ -0,0 +1,141 @@
|
||||
// ==== day 12
|
||||
|
||||
use crate::utils;
|
||||
use anyhow::Result;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum Instruction {
|
||||
Mask {
|
||||
exes_mask: u64,
|
||||
ones_mask: u64,
|
||||
zeroes_mask: u64,
|
||||
},
|
||||
Write {
|
||||
address: u64,
|
||||
value: u64,
|
||||
},
|
||||
}
|
||||
|
||||
fn parse_mask(s: &str) -> Instruction {
|
||||
let maskstr = &s[s.find(" = ").unwrap() + 3..];
|
||||
let ones_str = maskstr.replace('X', "0");
|
||||
let zeroes_str = maskstr
|
||||
.replace('1', "X")
|
||||
.replace('0', "1")
|
||||
.replace('X', "0");
|
||||
let exes_str = maskstr.replace('1', "0").replace('X', "1");
|
||||
Instruction::Mask {
|
||||
exes_mask: u64::from_str_radix(&exes_str, 2).unwrap(),
|
||||
ones_mask: u64::from_str_radix(&ones_str, 2).unwrap(),
|
||||
zeroes_mask: u64::from_str_radix(&zeroes_str, 2).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_write(s: &str) -> Instruction {
|
||||
Instruction::Write {
|
||||
address: s[4..s.find(']').unwrap()].parse().unwrap(),
|
||||
value: s[s.find(" = ").unwrap() + 3..].parse().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse(input: &str) -> Vec<Instruction> {
|
||||
input
|
||||
.lines()
|
||||
.map(|l| l.trim())
|
||||
.map(|l| match &l[0..4] {
|
||||
"mask" => parse_mask(l),
|
||||
"mem[" => parse_write(l),
|
||||
_ => unreachable!("bad input"),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn simulate1(program: &[Instruction]) -> u64 {
|
||||
let mut memory: HashMap<u64, u64> = HashMap::new();
|
||||
|
||||
let (mut cur_ones, mut cur_zeroes) = (0, 0);
|
||||
program.iter().for_each(|i| {
|
||||
match i {
|
||||
Instruction::Mask {
|
||||
ones_mask,
|
||||
zeroes_mask,
|
||||
..
|
||||
} => {
|
||||
cur_ones = *ones_mask;
|
||||
cur_zeroes = *zeroes_mask;
|
||||
}
|
||||
Instruction::Write { address, value } => {
|
||||
memory.insert(*address, (value | cur_ones) & !cur_zeroes);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
memory.values().sum()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_bit(n: u64, bit: usize, value: bool) -> u64 {
|
||||
if value {
|
||||
n | (1 << bit)
|
||||
} else {
|
||||
n & !(1 << bit)
|
||||
}
|
||||
}
|
||||
|
||||
fn address_masks_from_float_mask(float_mask: u64) -> impl Iterator<Item = u64> {
|
||||
let possibilities = 2_u64.pow(float_mask.count_ones());
|
||||
let one_positions: Vec<usize> = (0..36).filter(|i| float_mask & (1 << i) != 0).collect();
|
||||
(0..possibilities).map(move |i| {
|
||||
one_positions
|
||||
.iter()
|
||||
.enumerate()
|
||||
.fold(0, |result, (j, pos)| {
|
||||
set_bit(result, *pos, (i & (1 << j)) != 0)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn simulate2(program: &[Instruction]) -> u64 {
|
||||
let mut memory: HashMap<u64, u64> = HashMap::new();
|
||||
|
||||
let (mut cur_exes, mut cur_ones, mut cur_zeroes) = (0, 0, 0);
|
||||
program.iter().for_each(|i| {
|
||||
match i {
|
||||
Instruction::Mask {
|
||||
exes_mask,
|
||||
ones_mask,
|
||||
zeroes_mask,
|
||||
} => {
|
||||
cur_exes = *exes_mask;
|
||||
cur_ones = *ones_mask;
|
||||
cur_zeroes = *zeroes_mask;
|
||||
}
|
||||
Instruction::Write { address, value } => {
|
||||
let base_address = (*address | cur_ones) & !cur_exes;
|
||||
address_masks_from_float_mask(cur_exes)
|
||||
.map(|a| a | base_address)
|
||||
.for_each(|a| {
|
||||
memory.insert(a, *value);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
memory.values().sum()
|
||||
}
|
||||
|
||||
// main
|
||||
pub fn run() -> Result<(u64, u64)> {
|
||||
let data = utils::read_file("data/input-14.txt")?;
|
||||
let answers = utils::read_i64s("data/output-14.txt")?;
|
||||
|
||||
let parsed = parse(&data);
|
||||
|
||||
let p1 = simulate1(&parsed);
|
||||
let p2 = simulate2(&parsed);
|
||||
|
||||
assert_eq!(p1, answers[0] as u64);
|
||||
assert_eq!(p2, answers[1] as u64);
|
||||
Ok((p1, p2))
|
||||
}
|
||||
@@ -12,6 +12,7 @@ mod day09;
|
||||
mod day10;
|
||||
mod day11;
|
||||
mod day12;
|
||||
mod day14;
|
||||
mod utils;
|
||||
|
||||
// TODO
|
||||
@@ -37,5 +38,6 @@ fn main() -> Result<()> {
|
||||
println!("Day 10: {:?}", day10::run()?);
|
||||
println!("Day 11: {:?}", day11::run()?);
|
||||
println!("Day 12: {:?}", day12::run()?);
|
||||
println!("Day 14: {:?}", day14::run()?);
|
||||
Ok(())
|
||||
}
|
||||
Reference in new issue
Block a user