day20: added p1 and p2
This commit is contained in:
parent
dfdc7ba3c7
commit
fd4b1a1a99
173
src/day20/1.rs
173
src/day20/1.rs
|
@ -1 +1,172 @@
|
||||||
const INPUTS: [&'static str; 2] = [include_str!("./sample.txt"), include_str!("./input.txt")];
|
#![feature(slice_split_once)]
|
||||||
|
#![feature(byte_slice_trim_ascii)]
|
||||||
|
#![feature(test)]
|
||||||
|
|
||||||
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
extern crate test;
|
||||||
|
|
||||||
|
const INPUTS: [&str; 3] = [
|
||||||
|
"broadcaster -> a
|
||||||
|
%a -> inv, con
|
||||||
|
&inv -> b
|
||||||
|
%b -> con
|
||||||
|
&con -> output",
|
||||||
|
include_str!("./sample.txt"),
|
||||||
|
include_str!("./input.txt"),
|
||||||
|
];
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn compress(mut c: &[u8]) -> usize {
|
||||||
|
if c.len() > 3 {
|
||||||
|
c = &c[..3];
|
||||||
|
}
|
||||||
|
let mut out = 0;
|
||||||
|
let mut i = c.len() as i32 - 1;
|
||||||
|
|
||||||
|
let mut pow = 1;
|
||||||
|
while i >= 0 {
|
||||||
|
out += pow * (c[i as usize] - b'a') as usize;
|
||||||
|
|
||||||
|
pow *= 26;
|
||||||
|
|
||||||
|
i -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(data: &str) -> i64 {
|
||||||
|
let data = data.as_bytes();
|
||||||
|
|
||||||
|
let mut map = vec![];
|
||||||
|
|
||||||
|
let mut conjunction_inputs = HashMap::new();
|
||||||
|
|
||||||
|
for line in data.split(|&x| x == b'\n') {
|
||||||
|
if line.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let (src, remain) = line.split_once(|&x| x == b' ').unwrap();
|
||||||
|
|
||||||
|
let (stype, label) = match src[0] {
|
||||||
|
b'%' => (src[0], compress(&src[1..])),
|
||||||
|
b'&' => (src[0], compress(&src[1..])),
|
||||||
|
b'b' => (0, compress(src)),
|
||||||
|
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let remain = &remain[3..];
|
||||||
|
|
||||||
|
let dst: Vec<usize> = remain
|
||||||
|
.split(|&x| x == b',')
|
||||||
|
.map(|x| x.trim_ascii())
|
||||||
|
.map(compress)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if map.len() <= label {
|
||||||
|
map.extend(std::iter::repeat((0, vec![])).take(label - map.len() + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
map[label] = (stype, dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k, (ntype, dst)) in map.iter().enumerate() {
|
||||||
|
let ntype = *ntype;
|
||||||
|
if ntype != b'&' && ntype != b'%' {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for &dst in dst {
|
||||||
|
if let Some(&(dtype, _)) = map.get(dst) {
|
||||||
|
if dtype == b'&' {
|
||||||
|
conjunction_inputs
|
||||||
|
.entry(dst)
|
||||||
|
.or_insert_with(Vec::new)
|
||||||
|
.push(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut button_state = vec![false; map.len()];
|
||||||
|
|
||||||
|
let mut low = 0;
|
||||||
|
let mut high = 0;
|
||||||
|
|
||||||
|
for _ in 0..1000 {
|
||||||
|
let mut q = VecDeque::new(); // Button pressed, send signal to broadcaster
|
||||||
|
|
||||||
|
let (_, broadcast_dst) = &map[compress("broadcaster".as_bytes())]; //map.get(&compress("broadcaster".as_bytes())).unwrap();
|
||||||
|
//
|
||||||
|
low += 1;
|
||||||
|
|
||||||
|
for &dst in broadcast_dst {
|
||||||
|
q.push_back((dst, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
while let Some((node, pulse)) = q.pop_front() {
|
||||||
|
if pulse == 0 {
|
||||||
|
low += 1;
|
||||||
|
} else {
|
||||||
|
high += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (ntype, ndst) = if let Some(o) = map.get(node) {
|
||||||
|
o
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
match *ntype {
|
||||||
|
b'%' => {
|
||||||
|
if pulse == 1 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(state) = button_state.get_mut(node) {
|
||||||
|
*state = !*state;
|
||||||
|
for &dst in ndst {
|
||||||
|
q.push_back((dst, if *state { 1 } else { 0 }));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b'&' => {
|
||||||
|
// Update state
|
||||||
|
|
||||||
|
let new_state = conjunction_inputs
|
||||||
|
.get(&node)
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.all(|&x| *button_state.get(x).unwrap());
|
||||||
|
|
||||||
|
for &dst in ndst {
|
||||||
|
q.push_back((dst, !new_state as i64));
|
||||||
|
}
|
||||||
|
|
||||||
|
*button_state.get_mut(node).unwrap() = !new_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
0 => (),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
low * high
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
for input in INPUTS.iter().skip(2) {
|
||||||
|
println!("answer = {}", process(input));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn part1(b: &mut test::Bencher) {
|
||||||
|
b.iter(|| {
|
||||||
|
let v = process(INPUTS[INPUTS.len() - 1]);
|
||||||
|
test::black_box(v);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
197
src/day20/2.rs
197
src/day20/2.rs
|
@ -1 +1,196 @@
|
||||||
const INPUTS: [&'static str; 2] = [include_str!("./sample.txt"), include_str!("./input.txt")];
|
#![feature(slice_split_once)]
|
||||||
|
#![feature(byte_slice_trim_ascii)]
|
||||||
|
#![feature(test)]
|
||||||
|
|
||||||
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
extern crate test;
|
||||||
|
|
||||||
|
const INPUTS: [&str; 1] = [include_str!("./input.txt")];
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn compress(mut c: &[u8]) -> usize {
|
||||||
|
if c.len() > 3 {
|
||||||
|
c = &c[..3];
|
||||||
|
}
|
||||||
|
let mut out = 0;
|
||||||
|
let mut i = c.len() as i32 - 1;
|
||||||
|
|
||||||
|
let mut pow = 1;
|
||||||
|
while i >= 0 {
|
||||||
|
out += pow * (c[i as usize] - b'a') as usize;
|
||||||
|
|
||||||
|
pow *= 26;
|
||||||
|
|
||||||
|
i -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(data: &str) -> usize {
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
let mut conjunction_inputs = HashMap::new();
|
||||||
|
|
||||||
|
for line in data.lines() {
|
||||||
|
if line.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let (src, remain) = line.split_once(' ').unwrap();
|
||||||
|
|
||||||
|
let src: Vec<char> = src.chars().collect();
|
||||||
|
|
||||||
|
let (stype, label) = match src[0] {
|
||||||
|
'%' => (src[0], (&src[1..])),
|
||||||
|
'&' => (src[0], &src[1..]),
|
||||||
|
'b' => (' ', src.as_slice()),
|
||||||
|
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let remain = &remain[3..];
|
||||||
|
|
||||||
|
let dst: Vec<String> = remain
|
||||||
|
.split(',')
|
||||||
|
.map(|x| x.trim())
|
||||||
|
.map(|x| x.to_string())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let label: String = label.iter().collect();
|
||||||
|
|
||||||
|
map.insert(label, (stype, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k, (ntype, dst)) in map.iter() {
|
||||||
|
let ntype = *ntype;
|
||||||
|
if ntype != '&' && ntype != '%' {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for dst in dst {
|
||||||
|
if let Some(&(dtype, _)) = map.get(&dst.to_string()) {
|
||||||
|
if dtype == '&' {
|
||||||
|
conjunction_inputs
|
||||||
|
.entry(dst.to_string())
|
||||||
|
.or_insert_with(Vec::new)
|
||||||
|
.push(k.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut button_state: HashMap<String, bool> = HashMap::new();
|
||||||
|
|
||||||
|
for k in map.keys() {
|
||||||
|
button_state.insert(k.clone(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut button_presses = vec![];
|
||||||
|
let mut button_press = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
button_press += 1;
|
||||||
|
cycle(
|
||||||
|
button_press,
|
||||||
|
&mut button_state,
|
||||||
|
&mut map,
|
||||||
|
&mut conjunction_inputs,
|
||||||
|
&mut button_presses,
|
||||||
|
);
|
||||||
|
|
||||||
|
if button_presses.len() == conjunction_inputs.get("zh").map_or(0, |x| x.len()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lcm(&button_presses)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lcm(a: &[usize]) -> usize {
|
||||||
|
let mut answer = a[0];
|
||||||
|
|
||||||
|
for &num in a.iter().skip(1) {
|
||||||
|
answer = (num * answer) / (gcd(num, answer));
|
||||||
|
}
|
||||||
|
|
||||||
|
answer
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
const fn gcd(a: usize, b: usize) -> usize {
|
||||||
|
if b == 0 {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
gcd(b, a % b)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cycle(
|
||||||
|
button_press: usize,
|
||||||
|
state: &mut HashMap<String, bool>,
|
||||||
|
map: &mut HashMap<String, (char, Vec<String>)>,
|
||||||
|
conjunction_inputs: &mut HashMap<String, Vec<String>>,
|
||||||
|
button_presses: &mut Vec<usize>,
|
||||||
|
) {
|
||||||
|
let mut q = VecDeque::new();
|
||||||
|
|
||||||
|
let (_, broadcast_dst) = map.get(&"broadcaster".to_string()).unwrap();
|
||||||
|
for dst in broadcast_dst {
|
||||||
|
q.push_back((dst, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
while let Some((dst, pulse)) = q.pop_front() {
|
||||||
|
let (dtype, dnext) = match map.get(dst) {
|
||||||
|
Some(v) => v,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
if pulse && dst == "zh" {
|
||||||
|
button_presses.push(button_press);
|
||||||
|
}
|
||||||
|
|
||||||
|
match dtype {
|
||||||
|
'%' => {
|
||||||
|
if pulse {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(state) = state.get_mut(dst) {
|
||||||
|
*state = !*state;
|
||||||
|
|
||||||
|
for next in dnext.iter() {
|
||||||
|
q.push_back((next, *state));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
'&' => {
|
||||||
|
let new_state = conjunction_inputs
|
||||||
|
.get(dst)
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.all(|x| *state.get(x).unwrap());
|
||||||
|
|
||||||
|
for next in dnext {
|
||||||
|
q.push_back((next, !new_state));
|
||||||
|
}
|
||||||
|
|
||||||
|
*state.get_mut(dst).unwrap() = !new_state;
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
for input in INPUTS.iter() {
|
||||||
|
println!("answer = {}", process(input));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn part1(b: &mut test::Bencher) {
|
||||||
|
b.iter(|| {
|
||||||
|
let v = process(INPUTS[INPUTS.len() - 1]);
|
||||||
|
test::black_box(v);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
1021
src/day20/custom.svg
Normal file
1021
src/day20/custom.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 49 KiB |
58
src/day20/input.txt
Normal file
58
src/day20/input.txt
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
%zl -> zp, cl
|
||||||
|
%vp -> dj, vr
|
||||||
|
%cc -> xp
|
||||||
|
&dj -> lq, mb, dc, ns, gz
|
||||||
|
%md -> ts, zp
|
||||||
|
%fc -> zp
|
||||||
|
%px -> zx
|
||||||
|
&nx -> gl, br, pr, xf, vd, gj, kd
|
||||||
|
%tf -> lt, dj
|
||||||
|
%fj -> pc
|
||||||
|
%mb -> xx
|
||||||
|
%cl -> mj
|
||||||
|
%pm -> fj
|
||||||
|
%dc -> dj, vp
|
||||||
|
%jc -> bz, xm
|
||||||
|
&vd -> zh
|
||||||
|
%pz -> sr, nx
|
||||||
|
&ns -> zh
|
||||||
|
%sr -> nx
|
||||||
|
%gl -> pr
|
||||||
|
%xx -> nt, dj
|
||||||
|
%gp -> md
|
||||||
|
%hb -> jl, nx
|
||||||
|
&zh -> rx
|
||||||
|
%rb -> gz, dj
|
||||||
|
%xm -> bz
|
||||||
|
&zp -> px, gp, cl, bh, fn, ls, hs
|
||||||
|
&bz -> pm, pc, bv, dl, jp, fj, cc
|
||||||
|
%nl -> bz, pm
|
||||||
|
&bh -> zh
|
||||||
|
%hq -> gj, nx
|
||||||
|
%bv -> bz, nl
|
||||||
|
%bj -> jp, bz
|
||||||
|
%gj -> mx
|
||||||
|
%xp -> bz, bj
|
||||||
|
%vr -> dj, mb
|
||||||
|
&dl -> zh
|
||||||
|
%pr -> hb
|
||||||
|
%nt -> dj, lq
|
||||||
|
%mx -> gl, nx
|
||||||
|
%kd -> hq
|
||||||
|
%fn -> px
|
||||||
|
%jp -> xc
|
||||||
|
%zx -> zl, zp
|
||||||
|
%br -> nx, xf
|
||||||
|
%lt -> dj
|
||||||
|
%df -> dj, tf
|
||||||
|
%ts -> zp, fc
|
||||||
|
%jl -> nx, pz
|
||||||
|
%xc -> jc, bz
|
||||||
|
%xf -> kd
|
||||||
|
%lq -> rb
|
||||||
|
%gz -> df
|
||||||
|
%pc -> cc
|
||||||
|
%hs -> fn
|
||||||
|
broadcaster -> ls, bv, dc, br
|
||||||
|
%mj -> zp, gp
|
||||||
|
%ls -> hs, zp
|
5
src/day20/sample.txt
Normal file
5
src/day20/sample.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
broadcaster -> a, b, c
|
||||||
|
%a -> b
|
||||||
|
%b -> c
|
||||||
|
%c -> inv
|
||||||
|
&inv -> a
|
Loading…
Reference in New Issue
Block a user