• 22 Posts
  • 59 Comments
Joined 8 months ago
cake
Cake day: June 4th, 2025

help-circle








  • I’ll cover item 1: start by writing a document, describing what you want to achieve: what do you mean by package, what do you mean by package manager, what features you want to have, what features you do not want to have, how you’re going to build and distribute the packages.

    The reason why this is important is that a) this will be a useful reference for the implementation, b) you will learn a lot about the subject matter by trying to answer these questions, and c) you’ll learn to write such documents which is a very useful skill.










  • Rust

    #[derive(Default)]
    pub struct Day1Solver {
        input: Vec<i64>,
    }
    
    impl Solver for Day1Solver {
        fn presolve(&mut self, input: &str) {
            self.input = input
                .trim()
                .split("\n")
                .map(|line| {
                    if let Some(n) = line.strip_prefix('L') {
                        -n.parse::<i64>().unwrap()
                    } else if let Some(n) = line.strip_prefix('R') {
                        n.parse().unwrap()
                    } else {
                        panic!("what: {line}");
                    }
                })
                .collect();
        }
    
        fn solve_part_one(&mut self) -> String {
            let mut p = 50;
            let mut count = 0;
            for n in self.input.clone() {
                p += n;
                if p % 100 == 0 {
                    count += 1;
                }
            }
            count.to_string()
        }
    
        fn solve_part_two(&mut self) -> String {
            let mut count = 0;
            let mut p = 1000000000050;
            for i in self.input.clone() {
                if p % 100 == 0 {
                    count += (i / 100).abs();
                } else {
                    count += ((p + i) / 100 - p / 100).abs();
                    if i < 0 && (p + i) % 100 == 0 {
                        count += 1;
                    }
                }
                p += i;
            }
            count.to_string()
        }
    }
    


  • Rust

    use std::collections::{HashSet, VecDeque};
    
    use itertools::Itertools;
    
    fn neighbours_of(i: usize, j: usize, side: usize) -> impl Iterator<Item = (usize, usize)> {
        [
            (i, j.wrapping_sub(1)),
            (i, j + 1),
            (
                if (i + j) % 2 == 0 {
                    i.wrapping_sub(1)
                } else {
                    i + 1
                },
                j,
            ),
        ]
        .into_iter()
        .filter(move |&(i, j)| i < side && j >= i && j < (2 * side - i - 1))
    }
    
    pub fn solve_part_1(input: &str) -> String {
        let data = input
            .lines()
            .map(|l| l.chars().collect::<Vec<_>>())
            .collect::<Vec<_>>();
        let side = data.len();
        let mut queue = VecDeque::new();
        queue.push_back((0, 0));
        let mut pairs = 0;
        let mut visited = HashSet::new();
        while let Some((i, j)) = queue.pop_front() {
            if visited.contains(&(i, j)) {
                continue;
            }
            for (ni, nj) in neighbours_of(i, j, side) {
                if visited.contains(&(ni, nj)) {
                    continue;
                }
                if data[i][j] == 'T' && data[ni][nj] == 'T' {
                    pairs += 1;
                }
                queue.push_back((ni, nj));
            }
            visited.insert((i, j));
        }
        pairs.to_string()
    }
    
    pub fn solve_part_2(input: &str) -> String {
        let data = input
            .lines()
            .map(|l| l.chars().collect::<Vec<_>>())
            .collect::<Vec<_>>();
        let side = data.len();
        let mut front = (0..data.len())
            .cartesian_product(0..data[0].len())
            .filter(|&(i, j)| data[i][j] == 'S')
            .collect::<HashSet<_>>();
        let mut visited = HashSet::new();
        let mut steps = 0;
        while !front.is_empty() {
            let mut next_front = HashSet::new();
            for (i, j) in front.drain() {
                if data[i][j] == 'E' {
                    return steps.to_string();
                }
                visited.insert((i, j));
                for (ni, nj) in neighbours_of(i, j, side) {
                    if (data[ni][nj] == 'T' || data[ni][nj] == 'E') && !visited.contains(&(ni, nj)) {
                        next_front.insert((ni, nj));
                    }
                }
            }
            steps += 1;
            front = next_front;
        }
        panic!("exit not found");
    }
    
    pub fn rotate(data: &[Vec<char>]) -> Vec<Vec<char>> {
        let mut result = vec![vec!['.'; data[0].len()]; data.len()];
        let side = data.len();
        for i in 0..data.len() {
            for j in i..(data[0].len() - i) {
                if (i + j) % 2 == 0 {
                    result[i][j] = data[side - (i + j) / 2 - 1][i * 2 + side - (i + j) / 2 - 1];
                } else {
                    result[i][j] = data[side - (i + j).div_ceil(2) - 1][side - (j - i).div_ceil(2) + i];
                }
            }
        }
        result
    }
    
    pub fn solve_part_3(input: &str) -> String {
        let data = input
            .lines()
            .map(|l| l.chars().collect::<Vec<_>>())
            .collect::<Vec<_>>();
        let side = data.len();
        let data = [data.clone(), rotate(&data), rotate(&rotate(&data))];
        let mut front = (0..data[0].len())
            .cartesian_product(0..data[0][0].len())
            .filter(|&(i, j)| data[0][i][j] == 'S')
            .map(|(i, j)| (i, j, 0))
            .collect::<HashSet<_>>();
        let mut visited = HashSet::new();
        let mut steps = 0;
        while !front.is_empty() {
            let mut next_front = HashSet::new();
            for (i, j, rotation) in front.drain() {
                if data[rotation][i][j] == 'E' {
                    return steps.to_string();
                }
                visited.insert((i, j, rotation));
                let next_rotation = (rotation + 1) % 3;
                for (ni, nj) in neighbours_of(i, j, side) {
                    if (data[next_rotation][ni][nj] == 'T' || data[next_rotation][ni][nj] == 'E')
                        && !visited.contains(&(ni, nj, next_rotation))
                    {
                        next_front.insert((ni, nj, next_rotation));
                    }
                }
                if (data[next_rotation][i][j] == 'T' || data[next_rotation][i][j] == 'E')
                    && !visited.contains(&(i, j, next_rotation))
                {
                    next_front.insert((i, j, next_rotation));
                }
            }
            steps += 1;
            front = next_front;
        }
        panic!("exit not found");
    }