CameronDev

joined 2 years ago
MODERATOR OF

Rust

Not an easy one, mostly because I messed up my merge circuits function (Pop/remove first circuit, load into second, but the pop/remove messed up the indexes, so I was merging the wrong thing).

After getting that it was all good. Pt2 was trivial once pt1 was solved.

spoiler

    #[derive(Debug)]
    struct Circuits {
        circuits: Vec<Vec<usize>>,
    }

    impl Circuits {
        fn find_circuit(&mut self, i: usize) -> Option<usize> {
            for (j, c) in &mut self.circuits.iter().enumerate() {
                if c.contains(&i) {
                    return Some(j);
                }
            }
            None
        }

        fn new_circuit(&mut self, i: usize, j: usize) {
            self.circuits.push(vec![i, j]);
        }

        fn join_circuits(&mut self, i: usize, j: usize) {
            let mut other = self.circuits.get(j).unwrap().clone();
            self.circuits.get_mut(i).unwrap().append(&mut other);
            self.circuits.remove(j);
        }

        fn append_circuit(&mut self, c: usize, x: usize) {
            self.circuits.get_mut(c).unwrap().push(x);
        }

        fn top_three(&mut self) -> Vec<usize> {
            let mut sizes = self
                .circuits
                .iter()
                .map(|c| c.len())
                .collect::<Vec<usize>>();
            sizes.sort();
            sizes.reverse();
            sizes[0..3].to_vec()
        }
    }

    type Pole = (isize, isize, isize);

    fn dist_poles(p1: &Pole, p2: &Pole) -> f32 {
        sqrt(
            ((p1.0 - p2.0) * (p1.0 - p2.0)) as f32
                + ((p1.1 - p2.1) * (p1.1 - p2.1)) as f32
                + ((p1.2 - p2.2) * (p1.2 - p2.2)) as f32,
        )
    }

    #[test]
    fn test_y2025_day8_part1() {
        let input = include_str!("../../input/2025/day_8.txt");
        let poles = input
            .lines()
            .map(|l| {
                let [x, y, z] = l
                    .splitn(3, ",")
                    .map(|c| c.parse::<isize>().unwrap())
                    .collect::<Vec<isize>>()[..]
                else {
                    panic!();
                };
                (x, y, z)
            })
            .collect::<Vec<Pole>>();
        let len = poles.len();

        let mut circuits: Circuits = Circuits { circuits: vec![] };

        let mut pairs = vec![];

        for i in 0..len {
            let first = poles.get(i).unwrap();
            for j in i + 1..len {
                if i == j {
                    continue;
                }
                let second = poles.get(j).unwrap();
                let dist = dist_poles(first, second);
                pairs.push((dist, i, j));
            }
        }

        pairs.sort_by(|a, b| {
            if a.0 < b.0 {
                Ordering::Less
            } else {
                Ordering::Greater
            }
        });

        for (dist, a, b) in pairs[0..1000].iter() {
            let first_circuit = circuits.find_circuit(*a);
            let second_circuit = circuits.find_circuit(*b);

            match (first_circuit, second_circuit) {
                (None, None) => {
                    circuits.new_circuit(*a, *b);
                }
                (Some(c), None) => {
                    circuits.append_circuit(c, *b);
                }
                (None, Some(c)) => {
                    circuits.append_circuit(c, *a);
                }
                (Some(c1), Some(c2)) => {
                    if c1 != c2 {
                        circuits.join_circuits(c1, c2);
                    }
                }
            }
        }

        assert_eq!(circuits.top_three().iter().product::<usize>(), 66640)
    }

[โ€“] CameronDev@programming.dev 1 points 2 weeks ago (2 children)

I used a u8, one bit per level to do mine, but because not all bits correspond to a splitter, it ends up duplicating a lot of the paths. Which is why I made the lowest bit at the top, so it flip-flops a lot, giving the appearance of multiple different paths :D

[โ€“] CameronDev@programming.dev 2 points 2 weeks ago (4 children)

That's awesome, is it just random paths?

[โ€“] CameronDev@programming.dev 2 points 2 weeks ago (1 children)

Its very festive :)

Showing the of it filling in a bit clearer (or less clearer, i dunno): https://youtube.com/shorts/dBYAdRyhCLU

[โ€“] CameronDev@programming.dev 1 points 2 weeks ago (1 children)

Colorised, but filling in from least photons to most: https://youtube.com/shorts/McM1yIn5UCw

[โ€“] CameronDev@programming.dev 6 points 2 weeks ago (2 children)

I use usize by default, but last year there was a challenge that significantly improved performance when I switched from usize to u8 (don't recall which one though).

Video of each path (for the short example, dont think i can do the long one) https://youtube.com/shorts/jLpiUOSIiNw

[โ€“] CameronDev@programming.dev 1 points 2 weeks ago* (last edited 2 weeks ago) (2 children)
[โ€“] CameronDev@programming.dev 4 points 2 weeks ago* (last edited 2 weeks ago) (6 children)

Day 7 - Colourised, single image.

Rust

Not too difficult, but my pt1 approach didnt work for pt2. Small amount of tweaking and it was back in action. This should be a really good one for visualisations, so I am definitely going to try do something. Maybe colorise the nodes based on how many paths go through it? Definitely an animation of the trickle down. Looking forward to seeing everyone elses visualisations as well!

spoiler

    #[test]
    fn test_y2025_day7_part2() {
        let input = include_str!("../../input/2025/day_7.txt");
        let mut rows = input
            .lines()
            .map(|l| {
                l.chars()
                    .map(|c| match c {
                        'S' | '|' => 1isize,
                        '^' => -1isize,
                        _ => 0isize,
                    })
                    .collect::<Vec<isize>>()
            })
            .collect::<Vec<Vec<isize>>>();
        let width = rows[0].len();
        for i in 1..rows.len() {
            for j in 0..width {
                if rows[i - 1][j] >= 1 {
                    if rows[i][j] == -1 {
                        rows[i][j - 1] += rows[i - 1][j];
                        rows[i][j + 1] += rows[i - 1][j];
                    } else {
                        rows[i][j] += rows[i - 1][j];
                    }
                }
            }
        }
        print_tree(&rows);
        let total: isize = rows.pop().unwrap().iter().sum();
        println!("Total: {}", total);
    }

view more: โ€น prev next โ€บ