• 1 Post
  • 9 Comments
Joined 2 months ago
cake
Cake day: October 26th, 2024

help-circle

  • Rust

    Pretty happy with my solution today. I took my time today as it was a bit of a slow day and did it in Rust instead of python. Having proper Vec2 types is very nice.

    Tap for spoiler
    use std::{collections::HashMap, error::Error, io::Read};
    
    use glam::{IVec2, Vec2};
    
    fn permutations_of_size_two(antennas: &[Vec2]) -> Vec<[&Vec2; 2]> {
        let mut permutations = vec![];
        for (i, antenna) in antennas.iter().enumerate() {
            for j in 0..antennas.len() {
                if i == j {
                    continue;
                }
                permutations.push([antenna, &antennas[j]])
            }
        }
        permutations
    }
    
    fn main() -> Result<(), Box<dyn Error>> {
        let mut input = String::new();
        std::io::stdin().read_to_string(&mut input)?;
    
        let height = input.lines().count() as i32;
        let width = input.lines().next().unwrap().len() as i32;
    
        let antenna_positions = input
            .lines()
            .enumerate()
            .flat_map(|(y, l)| 
                l.chars().enumerate().map(move |(x, c)| (Vec2::new(x as f32, y as f32), c))
            )
            .filter(|(_v, c)| *c != '.')
            .fold(HashMap::new(), |mut acc: HashMap<char, Vec<_>> , current| {
                acc.entry(current.1).or_default().push(current.0);
                acc
            });
    
        let mut antinodes = vec![];
        for (_c, antennas) in antenna_positions {
            let perms = permutations_of_size_two(&antennas);
            for [first, second] in perms {
                let mut i = 1.;
                loop {
                    let antinode = (first + (second-first) * i).round();
                    if (0..height).contains(&(antinode.x as i32)) &&
                        (0..width).contains(&(antinode.y as i32)) {
                            antinodes.push(antinode);
                    } else {
                        break;
                    }
                    i += 1.;
                }
            }
        }
    
        let mut antinode_count = 0;
        let map = input
            .lines()
            .enumerate()
            .map(|(y, l)| 
                l.chars().enumerate().map(|(x, c)| {
                    if antinodes.contains(&Vec2::new(x as f32, y as f32)) {
                        println!("({x},{y})");
                        antinode_count += 1;
                        return '#';
                    }
                    c
                }).collect::<String>()
            )
            .collect::<Vec<_>>()
            .join("\n");
    
        println!("{map}");
        println!("{antinode_count}");
    
        Ok(())
    }
    

  • My initial comment was a bit harsh, I’m sorry for that. It was meant to be a bit of a joke. Anyway here’s my code. Do note that I don’t do the challenges timed so I have a bit more time to name my variables accordingly. Takes 35 seconds to run on a pc with a AMD Ryzen 5 5600

    import sys
    from tqdm import tqdm
    
    
    input = sys.stdin.read()
    
    def all_operator_permutations(operator_count):
        if operator_count == 0:
            return [[]]
    
        smaller_permutations = all_operator_permutations(operator_count-1)
        return [
                *[['+', *ops] for ops in smaller_permutations],
                *[['*', *ops] for ops in smaller_permutations],
                *[['||', *ops] for ops in smaller_permutations],
                ]
    
    def test_operators(ops, values):
        res = values.pop(0)
        for op in ops:
            match op:
                case '*':
                    res *= values.pop(0)
                case '+':
                    res += values.pop(0)
                case '||':
                    res = int(f"{res}{values.pop(0)}")
        return res
    
    
    total_calibration_result = 0
    
    for line in tqdm(input.splitlines()[:]):
        target, *tail = line.split(':')
        target = int(target)
        values = [int(val) for val in tail[0].split()]
    
        all_perms = all_operator_permutations(len(values) - 1)
        ops = all_perms.pop()
        while True:
            res = test_operators(ops, values.copy())
            if res == target:
                total_calibration_result += target
                break
            if not all_perms:
                break
            ops = all_perms.pop()
    
    print(total_calibration_result)