merry christmas, and to all a good AoC!

This commit is contained in:
Shoofle 2024-12-25 09:16:23 -05:00
parent 28f5eb17b0
commit 591f9b5294
5 changed files with 769 additions and 0 deletions

6
day24/Cargo.toml Normal file
View File

@ -0,0 +1,6 @@
[package]
name = "day24"
version = "0.1.0"
edition = "2021"
[dependencies]

545
day24/pbcopy Normal file

File diff suppressed because one or more lines are too long

128
day24/src/main.rs Normal file
View File

@ -0,0 +1,128 @@
use std::collections::HashMap;
use std::env;
use std::fs;
#[derive(Debug, Eq, PartialEq, Hash)]
enum Wire<'a> {
Value(bool),
And(&'a str, &'a str),
Or(&'a str, &'a str),
Xor(&'a str, &'a str),
}
fn main() {
println!("Hello, AoC day 24!");
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
println!("wrong number of arguments!");
std::process::exit(1);
}
let file_path = &args[1];
let file = fs::read_to_string(file_path)
.expect("should be able to read the file");
let (values, connections) = file.split_once("\n\n").expect("failed to split the file?");
let mut wires: HashMap<&str, Wire> = HashMap::new();
values
.lines()
.for_each(|x| {
let (label, val_str) = x.split_once(": ").expect("wires should have a : in them");
wires.insert(label, Wire::Value(val_str == "1"));
});
connections
.lines()
.for_each(|line| {
let (expr, label) = line.split_once(" -> ").expect("connections should have ->");
let expression: Vec<_> = expr.split(" ").collect();
let (a, op, b) = (expression[0], expression[1], expression[2]);
wires.insert(label, match op {
"AND" => Wire::And(a, b),
"OR" => Wire::Or(a, b),
"XOR" => Wire::Xor(a, b),
_ => Wire::Value(false),
});
});
println!("{wires:?}");
// part a
let mut zs: Vec<String> = wires.keys()
.filter(|name| name.starts_with("z"))
.map(|name| name.to_string())
.collect();
zs.sort();
zs = zs.into_iter().rev().collect();
for z in &zs { print!("{z}"); }
print!("\n");
let mut part_a: u64 = 0;
for z in &zs {
part_a = part_a << 1;
let this = get_value(z, &wires);
if this { part_a = part_a + 1; }
}
println!("the resulting z value is {part_a}");
// part b
println!("BEGIN GRAPHVIZ OUTPUT\n\n\n\n");
println!("digraph addingmachine {{");
for (label, wire) in &wires {
match wire {
Wire::Value(_) => print!("{label} [shape=box, color={}];", if label.starts_with("x") { "blue" } else { "red" }),
_ => ()
}
}
for (label, wire) in &wires {
match wire {
Wire::Value(_) => (),
Wire::And(a, b) => {
if label.starts_with("z") { print!("{label} [shape=triangle, color=green];");
} else { print!("{label} [shape=triangle];"); }
print!("{a} -> {label};");
print!("{b} -> {label};");
},
Wire::Or(a, b) => {
if label.starts_with("z") { print!("{label} [shape=egg, color=green];");
} else { print!("{label} [shape=egg];"); }
print!("{a} -> {label};");
print!("{b} -> {label};");
},
Wire::Xor(a, b) => {
if label.starts_with("z") { print!("{label} [shape=star, color=green];");
} else { print!("{label} [shape=star];"); }
print!("{a} -> {label};");
print!("{b} -> {label};");
},
}
}
println!("}}");
println!("\n\n\n\nEND GRAPHVIZ OUTPUT");
println!("by direct inspection of the graph rendered by the above graphviz output,");
println!("we find that the pairs that need to swap are z12+qdg, z19+vvf, z37+nvh, fgn+dck");
let mut answer = vec!["z12", "qdg", "z19", "vvf", "z37", "nvh", "fgn", "dck"];
answer.sort();
print!("or, in order: ");
for x in answer { print!("{x},"); }
print!("\n");
}
fn get_value<'a>(name: &'a str, system: &HashMap<&'a str, Wire>) -> bool {
match system.get(name) {
None => false,
Some(Wire::Value(v)) => *v,
Some(Wire::And(a, b)) => get_value(a, system) && get_value(b, system),
Some(Wire::Or(a, b)) => get_value(a, system) || get_value(b, system),
Some(Wire::Xor(a, b)) => get_value(a, system) ^ get_value(b, system),
}
}

6
day25/Cargo.toml Normal file
View File

@ -0,0 +1,6 @@
[package]
name = "day25"
version = "0.1.0"
edition = "2021"
[dependencies]

84
day25/src/main.rs Normal file
View File

@ -0,0 +1,84 @@
use std::env;
use std::fs;
use std::iter::zip;
fn main() {
println!("Hello, AoC day 24!");
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
println!("wrong number of arguments!");
std::process::exit(1);
}
let file_path = &args[1];
let file = fs::read_to_string(file_path)
.expect("should be able to read the file");
let keys = file.split("\n\n")
.filter(|section| section.starts_with("....."))
.map(string_transpose)
.map(|vec_of_vec_of_char| vec_of_vec_of_char
.into_iter()
.map(|vec_of_char| vec_of_char
.into_iter()
.filter(|c| *c == '#')
.count() - 1
)
.collect::<Vec<_>>()
)
.collect::<Vec<_>>();
let locks = file.split("\n\n")
.filter(|section| section.starts_with("#####"))
.map(string_transpose)
.map(|vec_of_vec_of_char| vec_of_vec_of_char
.into_iter()
.map(|vec_of_char| vec_of_char
.into_iter()
.filter(|c| *c == '#')
.count() - 1
)
.collect::<Vec<_>>()
)
.collect::<Vec<_>>();
println!("{keys:?}, {locks:?}");
let mut sum = 0;
for lock in &locks {
for key in &keys {
if fits(lock, key) {
sum += 1;
}
}
}
println!("the number of unique lock/key pairs is {sum}");
}
fn string_transpose(several_lines: &str) -> Vec<Vec<char>> {
let mut output = Vec::with_capacity(several_lines.lines().next().unwrap().len());
for line in several_lines.lines() {
for (idx, chr) in line.chars().enumerate() {
if idx == output.len() {
output.push(vec![]);
}
output[idx].push(chr);
}
}
return output
}
fn fits(lock: &Vec<usize>, key: &Vec<usize>) -> bool {
//println!("testing {lock:?} against {key:?}");
for (tumbler, tooth) in zip(lock, key) {
//println!("tumbler: {tumbler}; tooth: {tooth}");
if *tumbler + *tooth > 5 {
return false;
}
}
//println!("we good!");
return true;
}