From 3a333dee53ee5e652e13d4fc3a26fdd00b1b99c5 Mon Sep 17 00:00:00 2001 From: "matthias@arch" Date: Fri, 8 Dec 2023 13:52:36 +0100 Subject: [PATCH] day08: rust --- 08/README.md | 12 ++++++ 08/day08.rs | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 08/README.md create mode 100644 08/day08.rs diff --git a/08/README.md b/08/README.md new file mode 100644 index 0000000..5d5d6d0 --- /dev/null +++ b/08/README.md @@ -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 +``` diff --git a/08/day08.rs b/08/day08.rs new file mode 100644 index 0000000..fd3a940 --- /dev/null +++ b/08/day08.rs @@ -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

(filename: P) -> io::Lines> +where P: AsRef, { + return match std::fs::File::open(filename) { + Err(why) => panic!("Could not open file. {}", why), + Ok(file) => std::io::BufReader::new(file).lines() + }; +}