Advertisement
Guest User

Untitled

a guest
Dec 21st, 2024
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 12.82 KB | None | 0 0
  1. use std::collections;
  2. use std::collections::HashMap;
  3. use std::hash::Hash;
  4. use std::io;
  5. use std::fs;
  6. use std::fmt;
  7. use std::collections::BinaryHeap;
  8. use std::cmp::Ordering;
  9.  
  10. use crate::advent_of_code::Day;
  11. use crate::advent_of_code::UDLRIterator;
  12. use crate::advent_of_code::Direction;
  13.  
  14. pub struct Day21 { }
  15.  
  16. impl Day for Day21 {
  17.  
  18.     fn puzzle_1(input: io::Lines<io::BufReader<fs::File>>) -> String {
  19.  
  20.         use std::time::Instant;
  21.         let now = Instant::now();    
  22.         let (graph, edges) = generate_graph(1);
  23.         let mut complexity: u64 = 0;
  24.         let elapsed = now.elapsed();
  25.         println!("Elapsed: {:.2?}", elapsed);
  26.  
  27.         for line in input {
  28.             let code: String = line.unwrap();
  29.             let mut prev_char = 'A';
  30.             let mut shortest_sequence: u64 = 0;
  31.             for char in code.chars() {
  32.                 shortest_sequence += dijkstra(&graph, &edges, (prev_char, Button::ACTIVATE), (char, Button::ACTIVATE)).unwrap();
  33.                 prev_char = char;
  34.             }
  35.            
  36.             let mut numeric_code: u64 = 0;
  37.             let mut multiplier: u64 = 1;
  38.             for char in code.chars().rev() {
  39.                 if char != 'A' {
  40.                     numeric_code += char.to_digit(10).unwrap() as u64 * multiplier;
  41.                     multiplier *= 10;
  42.                 }
  43.             }
  44.             complexity += numeric_code * shortest_sequence;
  45.         }
  46.  
  47.         let elapsed = now.elapsed();
  48.         println!("Elapsed: {:.2?}", elapsed);
  49.         dbg!(complexity);
  50.         complexity.to_string()
  51.     }
  52.  
  53.  
  54.     fn puzzle_2(input: io::Lines<io::BufReader<fs::File>>) -> String {
  55.  
  56.         use std::time::Instant;
  57.         let now = Instant::now();    
  58.         let (graph, edges) = generate_graph(24);
  59.         let mut complexity: u64 = 0;
  60.  
  61.         for line in input {
  62.             let code: String = line.unwrap();
  63.             let mut prev_char = 'A';
  64.             let mut shortest_sequence: u64 = 0;
  65.             for char in code.chars() {
  66.                 shortest_sequence += dijkstra(&graph, &edges, (prev_char, Button::ACTIVATE), (char, Button::ACTIVATE)).unwrap();
  67.                 prev_char = char;
  68.             }
  69.            
  70.             let mut numeric_code: u64 = 0;
  71.             let mut multiplier: u64 = 1;
  72.             for char in code.chars().rev() {
  73.                 if char != 'A' {
  74.                     numeric_code += char.to_digit(10).unwrap() as u64 * multiplier;
  75.                     multiplier *= 10;
  76.                 }
  77.             }
  78.             complexity += numeric_code * shortest_sequence;
  79.         }
  80.         let elapsed = now.elapsed();
  81.         println!("Elapsed: {:.2?}", elapsed);
  82.    
  83.         dbg!(complexity);
  84.         complexity.to_string()    }
  85. }
  86.  
  87. #[derive(Hash, Clone, Eq, PartialEq, Debug, Copy)]
  88. enum Button {
  89.     UP,
  90.     DOWN,
  91.     LEFT,
  92.     RIGHT,
  93.     ACTIVATE
  94. }
  95.  
  96. // TODO: why doesnt this work with dbg! ?
  97. impl fmt::Display for Button {
  98.     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  99.        match self {
  100.            Button::UP => write!(f, "^"),
  101.            Button::DOWN => write!(f, "v"),
  102.            Button::LEFT => write!(f, "<"),
  103.            Button::RIGHT => write!(f, ">"),
  104.            Button::ACTIVATE => write!(f, "A"),
  105.            _ => panic!()
  106.        }
  107.    }
  108. }
  109.  
  110. #[derive(Copy, Clone, Eq, PartialEq)]
  111. struct State {
  112.    cost: u64,
  113.    node: (char, Button),
  114. }
  115.  
  116. // The priority queue depends on `Ord`.
  117. // Explicitly implement the trait so the queue becomes a min-heap
  118. // instead of a max-heap.
  119. impl Ord for State {
  120.    fn cmp(&self, other: &Self) -> Ordering {
  121.        // Notice that we flip the ordering on costs.
  122.        // In case of a tie we compare positions - this step is necessary
  123.        // to make implementations of `PartialEq` and `Ord` consistent.
  124.        other.cost.cmp(&self.cost)
  125.    }
  126. }
  127.  
  128. // `PartialOrd` needs to be implemented as well.
  129. impl PartialOrd for State {
  130.    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
  131.        Some(self.cmp(other))
  132.    }
  133. }
  134.  
  135.  
  136. type Graph = HashMap<Node, Vec<Node>>;
  137. type Edges = HashMap<(Node, Node), u64>;
  138. type Node = (char, Button);
  139.  
  140. fn generate_graph(depth: u32) -> (Graph, Edges) {
  141.  
  142.    let keypad: Vec<Vec<char>> = Vec::from([
  143.        Vec::from(['💀','0','A']),
  144.        Vec::from(['1','2','3']),
  145.        Vec::from(['4','5','6']),
  146.        Vec::from(['7','8','9']),
  147.    ]);
  148.  
  149.    let instructions: HashMap<(Button, Button), Vec<Button>> = HashMap::from([
  150.        ((Button::LEFT, Button::UP), Vec::from([Button::RIGHT, Button::UP, Button::ACTIVATE])),
  151.        ((Button::LEFT, Button::RIGHT), Vec::from([Button::RIGHT, Button::RIGHT, Button::ACTIVATE])),
  152.        ((Button::LEFT, Button::DOWN), Vec::from([Button::RIGHT, Button::ACTIVATE])),
  153.        ((Button::LEFT, Button::ACTIVATE), Vec::from([Button::RIGHT, Button::RIGHT, Button::UP, Button::ACTIVATE])),
  154.        ((Button::LEFT, Button::LEFT), Vec::from([Button::ACTIVATE])),
  155.  
  156.        ((Button::RIGHT, Button::UP), Vec::from([Button::LEFT, Button::UP, Button::ACTIVATE])),
  157.        ((Button::RIGHT, Button::LEFT), Vec::from([Button::LEFT, Button::LEFT, Button::ACTIVATE])),
  158.        ((Button::RIGHT, Button::DOWN), Vec::from([Button::LEFT, Button::ACTIVATE])),
  159.        ((Button::RIGHT, Button::ACTIVATE), Vec::from([Button::UP, Button::ACTIVATE])),
  160.        ((Button::RIGHT, Button::RIGHT), Vec::from([Button::ACTIVATE])),
  161.  
  162.        ((Button::UP, Button::RIGHT), Vec::from([Button::DOWN, Button::RIGHT, Button::ACTIVATE])),
  163.        ((Button::UP, Button::LEFT), Vec::from([Button::DOWN, Button::LEFT, Button::ACTIVATE])),
  164.        ((Button::UP, Button::DOWN), Vec::from([Button::DOWN, Button::ACTIVATE])),
  165.        ((Button::UP, Button::ACTIVATE), Vec::from([Button::RIGHT, Button::ACTIVATE])),
  166.        ((Button::UP, Button::UP), Vec::from([Button::ACTIVATE])),
  167.  
  168.        ((Button::DOWN, Button::RIGHT), Vec::from([Button::RIGHT, Button::ACTIVATE])),
  169.        ((Button::DOWN, Button::LEFT), Vec::from([Button::LEFT, Button::ACTIVATE])),
  170.        ((Button::DOWN, Button::UP), Vec::from([Button::UP, Button::ACTIVATE])),
  171.        ((Button::DOWN, Button::ACTIVATE), Vec::from([Button::UP, Button::RIGHT, Button::ACTIVATE])),
  172.        ((Button::DOWN, Button::DOWN), Vec::from([Button::ACTIVATE])),
  173.  
  174.        ((Button::ACTIVATE, Button::RIGHT), Vec::from([Button::DOWN, Button::ACTIVATE])),
  175.        ((Button::ACTIVATE, Button::LEFT), Vec::from([Button::DOWN, Button::LEFT, Button::LEFT, Button::ACTIVATE])),
  176.        ((Button::ACTIVATE, Button::UP), Vec::from([Button::LEFT, Button::ACTIVATE])),
  177.        ((Button::ACTIVATE, Button::DOWN), Vec::from([Button::LEFT, Button::DOWN, Button::ACTIVATE])),
  178.        ((Button::ACTIVATE, Button::ACTIVATE), Vec::from([Button::ACTIVATE])),
  179.    ]);
  180.  
  181.  
  182.    fn calculate_cost(from_state: Button, to_state: Button, depth: u32, instructions: &HashMap<(Button, Button), Vec<Button>>, memo: &mut HashMap<(Button, Button, u32), u64>) -> u64 {
  183.        if depth == 0 {
  184.            return (&instructions[&(from_state, to_state)]).len() as u64;
  185.        } else {
  186.            let mut new_instr: u64 = 0;
  187.            if memo.contains_key(&(from_state, to_state, depth)) {
  188.                return memo[&(from_state, to_state, depth)];
  189.            }
  190.  
  191.            let steps = &instructions[&(from_state, to_state)];
  192.            if steps.len() == 1 {
  193.                new_instr += 1;
  194.            } else {
  195.                // example, if from < to >, then steps are  > > a, so need, from next keypad: (a, >), (>, >), (>, a), ie: v A A ^ A
  196.                let mut step_iter = steps.iter().peekable();
  197.                let mut prev_robot_position = Button::ACTIVATE;
  198.                while let Some(step) = step_iter.next() {
  199.                    new_instr += calculate_cost(prev_robot_position.clone(), step.clone(), depth - 1, instructions, memo);
  200.                    prev_robot_position = step.clone();
  201.                }  
  202.            }
  203.            memo.entry((from_state, to_state, depth))
  204.                .or_insert(new_instr);
  205.            //dbg!(depth);
  206.            new_instr
  207.        }
  208.    }
  209.  
  210.    let mut graph: Graph = Graph::new();
  211.    let mut edges: Edges = Edges::new();
  212.    let mut memo: HashMap<(Button, Button, u32), u64> = HashMap::new();
  213.  
  214.    // generate the graph
  215.    for y in 0..keypad.len() {
  216.        for x in 0..keypad[y].len() {
  217.            if keypad[y][x] == '💀' {
  218.                continue;
  219.            }
  220.            let mut new_nodes: Vec<(char, Button)> = Vec::new();
  221.  
  222.            // insert ('key', ACTIVATE), node, that represents actually pressing the key
  223.            let activate_node =  (keypad[y][x], Button::ACTIVATE);
  224.            graph.insert(activate_node.clone(), Vec::new());
  225.            new_nodes.push(activate_node.clone());
  226.  
  227.            for pos_data in (UDLRIterator { center: (x as i32, y as i32),
  228.                                                                dist_from_center: 1,
  229.                                                                index: 0,
  230.                                                                x_bound: keypad[y].len() as i32,
  231.                                                                y_bound: keypad.len() as i32 }) {
  232.                let pos = pos_data.0;
  233.                if keypad[pos.1 as usize][pos.0 as usize] == '💀' {
  234.                    continue;
  235.                }
  236.                                                                        
  237.                let keypad_state = match pos_data.1 {
  238.                    Direction::UP => Button::DOWN,
  239.                    Direction::DOWN => Button::UP,
  240.                    Direction::LEFT => Button::RIGHT,
  241.                    Direction::RIGHT => Button::LEFT
  242.                };
  243.                let node = (keypad[y][x], keypad_state);
  244.                graph.insert(node.clone(), Vec::new());
  245.                new_nodes.push(node);
  246.            }
  247.  
  248.            //let mut activation_node_dont
  249.            for node in new_nodes {
  250.  
  251.                for pos_data in (UDLRIterator { center: (x as i32, y as i32),
  252.                    dist_from_center: 1,
  253.                    index: 0,
  254.                    x_bound: keypad[y].len() as i32,
  255.                    y_bound: keypad.len() as i32 }) {
  256.  
  257.                    let pos: (i32, i32) = pos_data.0;
  258.                    if keypad[pos.1 as usize][pos.0 as usize] == '💀' {
  259.                        continue;
  260.                    }
  261.    
  262.                    let keypad_dest = match pos_data.1 {
  263.                        Direction::UP => Button::UP,
  264.                        Direction::DOWN => Button::DOWN,
  265.                        Direction::LEFT => Button::LEFT,
  266.                        Direction::RIGHT => Button::RIGHT
  267.                    };
  268.  
  269.                    let end_node = (keypad[pos.1 as usize][pos.0 as usize], keypad_dest.clone());
  270.  
  271.                    graph.entry(node.clone())
  272.                        .and_modify(|conn_nodes| {
  273.                            conn_nodes.push(end_node.clone());
  274.                        });
  275.                    let edge_cost: u64 = calculate_cost(node.clone().1, keypad_dest.clone(), depth, &instructions, &mut memo);
  276.                    edges.insert((node.clone(), end_node.clone()), edge_cost);
  277.  
  278.                }
  279.  
  280.                // node to activate node edge represents pressing the button once you get there
  281.                graph.entry(node.clone())
  282.                .and_modify(|conn_nodes| {
  283.                    conn_nodes.push(activate_node.clone());
  284.                });
  285.  
  286.                let edge_cost: u64 = calculate_cost(node.clone().1, activate_node.clone().1, depth, &instructions, &mut memo);
  287.                edges.insert((node.clone(), activate_node.clone()), edge_cost);
  288.                                
  289.            }
  290.        }
  291.    }
  292.  
  293.    (graph, edges)
  294. }
  295.  
  296.  
  297. fn dijkstra(graph: &Graph,
  298.            edges: &Edges,
  299.            souce: (char, Button),
  300.            goal: (char, Button)) -> Option<u64> {
  301.  
  302.    let mut heap: BinaryHeap<State> = collections::BinaryHeap::new();
  303.    let mut dist: HashMap<(char, Button), u64> = HashMap::new();
  304.  
  305.    for node in graph.keys() {
  306.        if *node != souce {
  307.            heap.push(State { cost: u64::max_value(), node: node.clone() });
  308.            dist.insert(node.clone(), u64::max_value());
  309.        }
  310.    }
  311.  
  312.    dist.insert(souce.clone(), 0);
  313.    heap.push(State { cost: 0, node: souce });
  314.  
  315.    while let Some(State { cost, node }) = heap.pop() {
  316.        if node == goal {
  317.            return Some(cost);
  318.        }
  319.  
  320.        if cost > dist[&node] {
  321.            continue;
  322.        }
  323.  
  324.        let neighbors = &graph[&node];
  325.        for neighbor in neighbors {
  326.            let alt = dist[&node] + edges[&(node, neighbor.clone())];
  327.  
  328.            if alt < dist[&neighbor] {
  329.                heap.push(State { cost: alt, node: neighbor.clone() });
  330.                dist.insert(*neighbor, alt);
  331.            }
  332.        }
  333.    }
  334.    None
  335. }
  336.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement