day08: rust

This commit is contained in:
matthias@arch 2023-12-08 13:52:36 +01:00
parent adc6e0d0a7
commit 3a333dee53
2 changed files with 126 additions and 0 deletions

12
08/README.md Normal file
View File

@ -0,0 +1,12 @@
# [Day 8](https://adventofcode.com/2023/day/8)
:gift::gift::gift::gift::gift::gift::gift::gift:
Today's language: **Rust**
Execution time: **0,039 s**
Next time, I should just use 64 bit right from the start...
```shell
rustc day08.rs
./day08
```

114
08/day08.rs Normal file
View File

@ -0,0 +1,114 @@
use std::io::{self, BufRead};
use std::collections::HashMap;
struct Junction(u32, u32);
fn hash(s: &str) -> u32 {
let mut h: u32 = 0;
for (i, c) in s.as_bytes().iter().enumerate() {
h |= (*c as u32) << (8 * i);
// println!("i: {}, s={}, Char: {:8b}, h: {:32b}", i, s, c, h);
}
return h;
}
fn ends_with(h: &u32, c: char) -> bool {
return (h >> (8 * 2)) == (c as u32);
}
fn gcd(mut x: u64, mut y: u64) -> u64 {
let mut d: u64;
assert!(x != 0 && y != 0);
while y != 0 {
d = y;
y = x % y;
x = d;
}
return x
}
fn lcm(a: u64, b: u64) -> u64 {
return (a * b) / gcd(a, b);
}
fn main() {
let input = "input.txt";
// let input = "example.txt";
let mut lines = read_lines(&input);
let Ok(instructions) = lines.next().expect("No line found") else { panic!("No line found") };
lines.next();
let mut junctions = HashMap::new();
let mut junctions_a = Vec::new();
for line in lines.map(|r| r.ok().unwrap()) {
let junction = hash(&line[0..3]);
junctions.insert(junction, Junction(hash(&line[7..10]), hash(&line[12..15])));
if ends_with(&junction, 'A') {
junctions_a.push(junction);
}
}
let match_junction = |junction: &u32, instruction: &char| -> u32 {
match instruction {
'R' => junctions[&junction].1,
'L' => junctions[&junction].0,
_ => panic!("Unknown instruction {}", instruction),
}
};
// task 1
let mut steps: u32 = 0;
let target = hash("ZZZ");
let mut junction = hash("AAA");
println!("Check endswidth {} {} {} {}", ends_with(&hash("AAA"), 'A'), ends_with(&hash("BFZ"), 'Z'), ends_with(&hash("AVD"), 'A'), ends_with(&hash("ZZS"), 'Z'));
'outer: loop {
for instruction in instructions.chars() {
if junction == target { break 'outer; }
steps += 1;
junction = match_junction(&junction, &instruction);
}
}
println!("Required steps(1): {}", steps);
let mut steps_to_z = vec![0 as u32; junctions_a.len()];
let mut steps_cycle = vec![0 as u32; junctions_a.len()];
let mut first_z = vec![0 as u32; junctions_a.len()];
for i in 0..junctions_a.len() {
steps = 0;
'outer: loop {
for instruction in instructions.chars() {
if ends_with(&junctions_a[i], 'Z') {
if steps_to_z[i] == 0 {
steps_to_z[i] = steps;
first_z[i] = junctions_a[i];
steps = 0;
}
else {
assert_eq!(first_z[i], junctions_a[i], "Z->Z is not a cycle!");
steps_cycle[i] = steps;
break 'outer;
}
}
// print!("Step {:012}: junction[{}]={:024b}\r", steps, i, junctions_a[i]);
junctions_a[i] = match_junction(&junctions_a[i], &instruction);
steps += 1;
}
}
}
for i in 0..junctions_a.len() {
println!("A-Z: {}, Z->Z: {}", steps_to_z[i], steps_cycle[i]);
}
let mut steps: u64 = steps_cycle[0] as u64;
for i in 1..steps_cycle.len() {
print!("lcm({:12}, {:8})", steps, steps_cycle[i]);
steps = lcm(steps, steps_cycle[i] as u64);
println!("={}", steps);
}
println!("Required steps(2): {}", steps);
}
fn read_lines<P>(filename: P) -> io::Lines<io::BufReader<std::fs::File>>
where P: AsRef<std::path::Path>, {
return match std::fs::File::open(filename) {
Err(why) => panic!("Could not open file. {}", why),
Ok(file) => std::io::BufReader::new(file).lines()
};
}