Day 14
This commit is contained in:
parent
d9e4bf6ad3
commit
849cc76034
2 changed files with 171 additions and 0 deletions
170
src/day14.rs
Normal file
170
src/day14.rs
Normal file
|
@ -0,0 +1,170 @@
|
|||
use aoc_runner_derive::{aoc, aoc_generator};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Command {
|
||||
Mask { and: u64, or: u64, raw: Vec<char> },
|
||||
Write { val: u64, addr: u64 },
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_bit(v: u64, bit: usize, val: bool) -> u64 {
|
||||
let mut v = v;
|
||||
let bv = 1 << bit;
|
||||
if val {
|
||||
v |= bv;
|
||||
} else {
|
||||
v &= !bv;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
impl Command {
|
||||
fn apply_mask_v1(&self, val: u64) -> u64 {
|
||||
if let Command::Mask { and, or, .. } = self {
|
||||
return (val & and) | or;
|
||||
};
|
||||
panic!("Can't apply non-mask command");
|
||||
}
|
||||
|
||||
fn apply_mask_v2_inner(&self, addr: &mut u64, s: &Vec<char>, ret: &mut Vec<u64>) {
|
||||
let mut s_c = s.clone();
|
||||
for (idx, c) in s.iter().enumerate() {
|
||||
match *c {
|
||||
'0' => (),
|
||||
'1' => {
|
||||
*addr = set_bit(*addr, idx, true);
|
||||
}
|
||||
'X' => {
|
||||
s_c[idx] = '0';
|
||||
*addr = set_bit(*addr, idx, true);
|
||||
self.apply_mask_v2_inner(addr, &s_c, ret);
|
||||
*addr = set_bit(*addr, idx, false);
|
||||
self.apply_mask_v2_inner(addr, &s_c, ret);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
ret.push(*addr);
|
||||
}
|
||||
|
||||
fn apply_mask_v2(&self, addr: u64) -> Vec<u64> {
|
||||
let mut addr = addr;
|
||||
if let Command::Mask { raw, .. } = self {
|
||||
let mut raw = raw.clone();
|
||||
raw.reverse();
|
||||
let mut ret = vec![];
|
||||
self.apply_mask_v2_inner(&mut addr, &raw, &mut ret);
|
||||
ret.sort();
|
||||
ret.dedup();
|
||||
return ret;
|
||||
};
|
||||
panic!("Can't apply non-mask command");
|
||||
}
|
||||
}
|
||||
|
||||
type Data = Vec<Command>;
|
||||
|
||||
#[aoc_generator(day14)]
|
||||
pub fn input_generator(input: &str) -> Data {
|
||||
let mut ret = vec![];
|
||||
for line in input.lines() {
|
||||
if line.starts_with("mask") {
|
||||
let mut mask_and = 0;
|
||||
let mut mask_or = 0;
|
||||
let mut char_buf = vec![];
|
||||
for (n, c) in line.split("=").nth(1).unwrap().trim().chars().enumerate() {
|
||||
char_buf.push(c);
|
||||
mask_and <<= 1;
|
||||
mask_or <<= 1;
|
||||
match c {
|
||||
'X' => {
|
||||
mask_and |= 1;
|
||||
mask_or |= 0;
|
||||
}
|
||||
'1' => {
|
||||
mask_and |= 1;
|
||||
mask_or |= 1;
|
||||
}
|
||||
'0' => {
|
||||
mask_and |= 0;
|
||||
mask_or |= 0;
|
||||
}
|
||||
c => {
|
||||
panic!("Invalid char in mask: {}", c);
|
||||
}
|
||||
}
|
||||
}
|
||||
ret.push(Command::Mask {
|
||||
and: mask_and,
|
||||
or: mask_or,
|
||||
raw: char_buf,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
if line.starts_with("mem") {
|
||||
let addr: u64 = line
|
||||
.chars()
|
||||
.skip_while(|&c| c != '[')
|
||||
.skip(1)
|
||||
.take_while(|&c| c != ']')
|
||||
.collect::<String>()
|
||||
.parse()
|
||||
.unwrap();
|
||||
let val: u64 = line
|
||||
.chars()
|
||||
.skip_while(|&c| c != '=')
|
||||
.skip(1)
|
||||
.skip_while(|&c| c.is_whitespace())
|
||||
.collect::<String>()
|
||||
.parse()
|
||||
.unwrap();
|
||||
ret.push(Command::Write { addr, val });
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
#[aoc(day14, part1)]
|
||||
pub fn solve_part1(input: &Data) -> u64 {
|
||||
let mut mem = HashMap::new();
|
||||
let mut mask = Command::Mask {
|
||||
and: std::u64::MAX,
|
||||
or: 0u64,
|
||||
raw: vec![],
|
||||
};
|
||||
for inst in input {
|
||||
match inst {
|
||||
Command::Write { val, addr } => {
|
||||
mem.insert(*addr, mask.apply_mask_v1(*val));
|
||||
}
|
||||
m => {
|
||||
mask = m.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
return mem.values().copied().sum();
|
||||
}
|
||||
|
||||
#[aoc(day14, part2)]
|
||||
pub fn solve_part2(input: &Data) -> u64 {
|
||||
let mut mem = HashMap::new();
|
||||
let mut mask = Command::Mask {
|
||||
and: std::u64::MAX,
|
||||
or: 0u64,
|
||||
raw: vec![],
|
||||
};
|
||||
for inst in input {
|
||||
match inst {
|
||||
Command::Write { val, addr } => {
|
||||
for addr in mask.apply_mask_v2(*addr) {
|
||||
mem.insert(addr, val);
|
||||
}
|
||||
}
|
||||
m => {
|
||||
mask = m.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
return mem.values().copied().sum();
|
||||
}
|
|
@ -12,4 +12,5 @@ pub mod day10;
|
|||
pub mod day11;
|
||||
pub mod day12;
|
||||
pub mod day13;
|
||||
pub mod day14;
|
||||
aoc_lib! { year = 2020 }
|
||||
|
|
Loading…
Reference in a new issue