Day 13: Claw Contraption

Megathread guidelines

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

FAQ

  • CameronDev@programming.devOPM
    link
    fedilink
    arrow-up
    2
    ·
    15 days ago

    Rust

    Hardest part was parsing the input, i somehow forgot how regexes work and wasted hours.

    Learning how to do matrix stuff in rust was a nice detour as well.

    #[cfg(test)]
    mod tests {
        use nalgebra::{Matrix2, Vector2};
        use regex::Regex;
    
        fn play_game(ax: i128, ay: i128, bx: i128, by: i128, gx: i128, gy: i128) -> i128 {
            for a_press in 0..100 {
                let rx = gx - ax * a_press;
                let ry = gy - ay * a_press;
                if rx % bx == 0 && ry % by == 0 && rx / bx == ry / by {
                    return a_press * 3 + ry / by;
                }
            }
            0
        }
    
        fn play_game2(ax: i128, ay: i128, bx: i128, by: i128, gx: i128, gy: i128) -> i128 {
            // m * p = g
            // p = m' * g
            // |ax bx|.|a_press| = |gx|
            // |ay by| |b_press|   |gy|
            let m = Matrix2::new(ax as f64, bx as f64, ay as f64, by as f64);
            match m.try_inverse() {
                None => return 0,
                Some(m_inv) => {
                    let g = Vector2::new(gx as f64, gy as f64);
                    let p = m_inv * g;
                    let pa = p[0].round() as i128;
                    let pb = p[1].round() as i128;
                    if pa * ax + pb * bx == gx && pa * ay + pb * by == gy {
                        return pa * 3 + pb;
                    }
                }
            };
            0
        }
    
        #[test]
        fn day13_part1_test() {
            let input = std::fs::read_to_string("src/input/day_13.txt").unwrap();
            let re = Regex::new(r"[0-9]+").unwrap();
    
            let games = input
                .trim()
                .split("\n\n")
                .map(|line| {
                    re.captures_iter(line)
                        .map(|x| {
                            let first = x.get(0).unwrap().as_str();
                            first.parse::<i128>().unwrap()
                        })
                        .collect::<Vec<i128>>()
                })
                .collect::<Vec<Vec<i128>>>();
    
            let mut total = 0;
            for game in games {
                let cost = play_game2(game[0], game[1], game[2], game[3], game[4], game[5]);
                total += cost;
            }
            // 36870
            println!("{}", total);
        }
    
        #[test]
        fn day12_part2_test() {
            let input = std::fs::read_to_string("src/input/day_13.txt").unwrap();
            let re = Regex::new(r"[0-9]+").unwrap();
    
            let games = input
                .trim()
                .split("\n\n")
                .map(|line| {
                    re.captures_iter(line)
                        .map(|x| {
                            let first = x.get(0).unwrap().as_str();
                            first.parse::<i128>().unwrap()
                        })
                        .collect::<Vec<i128>>()
                })
                .collect::<Vec<Vec<i128>>>();
    
            let mut total = 0;
            for game in games {
                let cost = play_game2(
                    game[0],
                    game[1],
                    game[2],
                    game[3],
                    game[4] + 10000000000000,
                    game[5] + 10000000000000,
                );
                total += cost;
            }
            println!("{}", total);
        }
    }