aoc-2021-rust

git clone https://git.sinitax.com/sinitax/aoc-2021-rust
Log | Files | Refs | README | sfeed.txt

commit 2fea9d7c7acdc304f11ebee3fa89362763607388
parent 4c9b5e23a5330203177f7a5902396859f5cfe4db
Author: Louis Burda <quent.burda@gmail.com>
Date:   Wed, 19 Apr 2023 15:12:44 +0200

[Day 23] Calc moved_in and moved_out implicitly

Diffstat:
Msrc/23/src/main.rs | 123++++++++++++++++++++++++++++++++++++++++++-------------------------------------
1 file changed, 66 insertions(+), 57 deletions(-)

diff --git a/src/23/src/main.rs b/src/23/src/main.rs @@ -13,16 +13,9 @@ struct Pos { y: isize } -#[derive(PartialEq,Eq,Hash,Clone,Copy)] -struct DJKAgentState { - moved_out: bool, - moved_in: bool, - pos: Pos -} - #[derive(PartialEq,Eq,Hash,Clone)] struct DJKState { - agents: [Vec<DJKAgentState>; 4] + agents: [Vec<Pos>; 4] } #[derive(Clone)] @@ -37,6 +30,8 @@ struct MapConfig { hallway: Range, slot_x: Range, slot_y: Range, + initial: DJKState, + fixed: [Vec<bool>; 4] } static AGENT_SYMBS: [char; 4] = ['A', 'B', 'C', 'D']; @@ -50,6 +45,18 @@ impl Pos { } impl DJKState { + fn moved_in(&self, at: usize, ai: usize, cfg: &MapConfig) -> bool { + if self.agents[at][ai] == cfg.initial.agents[at][ai] { + return cfg.fixed[at][ai]; + } else { + return self.agents[at][ai].x == idx2slot!(cfg, at); + } + } + + fn moved_out(&self, at: usize, ai: usize, cfg: &MapConfig) -> bool { + return self.agents[at][ai].y == cfg.hallway_y; + } + fn print(&self, map: &HashMap<Pos,char>) { let maxx = map.iter().map(|(p,_)| p.x).max().unwrap(); let maxy = map.iter().map(|(p,_)| p.y).max().unwrap(); @@ -62,7 +69,7 @@ impl DJKState { nc = if *c.unwrap() == '#' { '#' } else { ' ' }; for t in 0..4 { for agent in &self.agents[t] { - if p == agent.pos { + if &p == agent { nc = AGENT_SYMBS[t]; break; } @@ -93,7 +100,9 @@ fn parse_input(input: &str) -> (HashMap<Pos,char>, MapConfig) { hallway_y: 1, hallway: Range { min: 1, max: 12 }, slot_x: Range { min: 3, max: 10 }, - slot_y: Range { min: 1, max: y - 1 } + slot_y: Range { min: 1, max: y - 1 }, + initial: DJKState { agents: [ vec![], vec![], vec![], vec![] ] }, + fixed: [ vec![], vec![], vec![], vec![] ], }; return (map, cfg); @@ -104,8 +113,8 @@ fn heuristic(cfg: &MapConfig, state: &DJKState) -> isize { for t in 0..4 { for agent in &state.agents[t] { let slot_x = idx2slot!(cfg, t); - if agent.pos.x != slot_x { - cost += agent.pos.dist_to(&Pos { x: slot_x, y: cfg.hallway_y }); + if agent.x != slot_x { + cost += agent.dist_to(&Pos { x: slot_x, y: cfg.hallway_y }); } } } @@ -124,13 +133,13 @@ fn try_move_out(map: &HashMap<Pos,char>, cfg: &MapConfig, for (i,agent) in state.agents[t].iter().enumerate() { if t == at && i == ai { continue; } - if agent.pos.x == cur.pos.x && agent.pos.y < cur.pos.y { return; } + if agent.x == cur.x && agent.y < cur.y { return; } - if agent.pos.y == cfg.hallway_y { - if agent.pos.x > cur.pos.x { - maxx = isize::min(maxx, agent.pos.x); + if agent.y == cfg.hallway_y { + if agent.x > cur.x { + maxx = isize::min(maxx, agent.x); } else { - minx = isize::max(minx, agent.pos.x + 1); + minx = isize::max(minx, agent.x + 1); } } } @@ -142,11 +151,10 @@ fn try_move_out(map: &HashMap<Pos,char>, cfg: &MapConfig, && ((x - cfg.slot_x.min) % 2 == 0) { continue; } let mut nstate = state.clone(); - nstate.agents[at][ai].pos.x = x; - nstate.agents[at][ai].pos.y = cfg.hallway_y; - nstate.agents[at][ai].moved_out = true; + nstate.agents[at][ai].x = x; + nstate.agents[at][ai].y = cfg.hallway_y; let ncost_g = cost + MOVE_COST[at] - * state.agents[at][ai].pos.dist_to(&nstate.agents[at][ai].pos); + * state.agents[at][ai].dist_to(&nstate.agents[at][ai]); let ncost_f = ncost_g + heuristic(cfg, &nstate); let res = costmap.get_mut(&nstate); @@ -173,26 +181,25 @@ fn try_move_in(map: &HashMap<Pos,char>, cfg: &MapConfig, for (i,agent) in state.agents[t].iter().enumerate() { if t == at && i == ai { continue; } - if agent.pos.y == cfg.hallway_y { + if agent.y == cfg.hallway_y { /* another agent is in the way */ - if agent.pos.x > state.agents[at][ai].pos.x { - if idx2slot!(cfg, at) > agent.pos.x { return; } + if agent.x > state.agents[at][ai].x { + if idx2slot!(cfg, at) > agent.x { return; } } else { - if idx2slot!(cfg, at) < agent.pos.x { return; } + if idx2slot!(cfg, at) < agent.x { return; } } - } else if agent.pos.x == idx2slot!(cfg, at) { - slot_free_y = isize::min(slot_free_y, agent.pos.y - 1); + } else if agent.x == idx2slot!(cfg, at) { + slot_free_y = isize::min(slot_free_y, agent.y - 1); if slot_free_y == cfg.hallway_y { return; } } } } let mut nstate = state.clone(); - nstate.agents[at][ai].pos.x = idx2slot!(cfg, at); - nstate.agents[at][ai].pos.y = slot_free_y; - nstate.agents[at][ai].moved_in = true; + nstate.agents[at][ai].x = idx2slot!(cfg, at); + nstate.agents[at][ai].y = slot_free_y; let ncost_g = cost + MOVE_COST[at] - * state.agents[at][ai].pos.dist_to(&nstate.agents[at][ai].pos); + * state.agents[at][ai].dist_to(&nstate.agents[at][ai]); let ncost_f = ncost_g + heuristic(cfg, &nstate); let res = costmap.get_mut(&nstate); @@ -212,41 +219,43 @@ fn try_move(map: &HashMap<Pos,char>, cfg: &MapConfig, costmap: &mut HashMap<DJKState,isize>, active: &mut PriorityQueue<DJKState,isize>, state: &DJKState, cost: isize, at: usize, ai: usize) -> bool { - if !state.agents[at][ai].moved_out { - try_move_out(map, cfg, costmap, active, state, cost, at, ai); - return false; - } else if !state.agents[at][ai].moved_in { - try_move_in(map, cfg, costmap, active, state, cost, at, ai); + if !state.moved_in(at, ai, cfg) { + if !state.moved_out(at, ai, cfg) { + try_move_out(map, cfg, costmap, active, state, cost, at, ai); + } else { + try_move_in(map, cfg, costmap, active, state, cost, at, ai); + } return false; } else { - return state.agents.iter().all(|v| v.iter().all(|a| a.moved_in)); + for t in 0..4 { + for i in 0..state.agents[t].len() { + if !state.moved_in(t, i, cfg) { return false; } + } + } + return true; } } -fn organize(map: &HashMap<Pos,char>, cfg: &MapConfig) -> Option<usize> { - let mut active: PriorityQueue<DJKState,isize> = PriorityQueue::new(); - let mut costmap: HashMap<DJKState,isize> = HashMap::new(); +fn organize(map: &HashMap<Pos,char>, cfg: &mut MapConfig) -> Option<usize> { + let mut active: PriorityQueue<DJKState,isize> = PriorityQueue::with_capacity(100000); + let mut costmap: HashMap<DJKState,isize> = HashMap::with_capacity(100000); - let mut initial = DJKState { agents: [vec![], vec![], vec![], vec![]] }; for (p,c) in map.iter() { let idx = AGENT_SYMBS.iter().position(|sc| sc == c); if idx.is_some() { - let mut agent = DJKAgentState { - moved_out: false, - moved_in: false, - pos: p.clone() - }; - if p.x == cfg.slot_x.min + 2 * idx.unwrap() as isize { + if p.x == idx2slot!(cfg, idx.unwrap()) { let fixed = (p.y+1..cfg.slot_y.max) .all(|y| map.get(&Pos { x: p.x, y }).unwrap() == c); - agent.moved_out = fixed; - agent.moved_in = fixed; + aoc::debugln!("{} {} {} -> {}", p.x, p.y, c, fixed); + cfg.fixed[idx.unwrap()].push(fixed); + } else { + cfg.fixed[idx.unwrap()].push(false); } - initial.agents[idx.unwrap()].push(agent); + cfg.initial.agents[idx.unwrap()].push(p.clone()); } } - active.push(initial.clone(), -heuristic(&cfg, &initial)); - costmap.insert(initial, 0); + active.push(cfg.initial.clone(), -heuristic(&cfg, &cfg.initial)); + costmap.insert(cfg.initial.clone(), 0); let mut advanced: usize = 0; while !active.is_empty() { @@ -307,16 +316,16 @@ fn extend_map(s_map: &HashMap<Pos,char>, s_cfg: &MapConfig) } fn part1(aoc: &mut aoc::Info) { - let (map,cfg) = parse_input(&aoc.input); - let answer = organize(&map, &cfg); + let (map, mut cfg) = parse_input(&aoc.input); + let answer = organize(&map, &mut cfg); aoc.answer = Some(format!("{}", answer.unwrap())); aoc.solution = Some("15385"); } fn part2(aoc: &mut aoc::Info) { - let (s_map,s_cfg) = parse_input(&aoc.input); - let (map,cfg) = extend_map(&s_map, &s_cfg); - let answer = organize(&map, &cfg); + let (s_map, s_cfg) = parse_input(&aoc.input); + let (map, mut cfg) = extend_map(&s_map, &s_cfg); + let answer = organize(&map, &mut cfg); aoc.answer = Some(format!("{}", answer.unwrap())); }