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 day11;
|
||||||
pub mod day12;
|
pub mod day12;
|
||||||
pub mod day13;
|
pub mod day13;
|
||||||
|
pub mod day14;
|
||||||
aoc_lib! { year = 2020 }
|
aoc_lib! { year = 2020 }
|
||||||
|
|
Loading…
Reference in a new issue