summaryrefslogtreecommitdiff
path: root/2023/day17.rs
diff options
context:
space:
mode:
Diffstat (limited to '2023/day17.rs')
-rw-r--r--2023/day17.rs169
1 files changed, 114 insertions, 55 deletions
diff --git a/2023/day17.rs b/2023/day17.rs
index 37aff45..57a4577 100644
--- a/2023/day17.rs
+++ b/2023/day17.rs
@@ -5,86 +5,145 @@ use num::complex::Complex as c;
use num::Complex;
use std::cmp::min;
use std::collections::HashMap;
+use std::collections::HashSet;
use std::fs::File;
use std::io::Read;
type Matrix<T> = Vec<Vec<T>>;
-fn rec(
- pos: Complex<i32>,
- dir: Complex<i32>,
- conti: u32,
- mut hl: i32,
- s: &mut HashMap<(Complex<i32>, Complex<i32>, u32), i32>,
- m: &Matrix<i32>,
-) -> i32 {
- if !(0 <= pos.re && pos.re < m[0].len() as i32 && 0 <= pos.im && pos.im < m.len() as i32) {
- return 999999999;
- }
- hl += m[pos.im as usize][pos.re as usize];
-
- if conti > 3 {
- return 999999999;
- }
-
- // println!("{}", pos);
- if let Some(hl_) = s.get(&(pos, dir, conti)) {
- if hl_ <= &hl {
- return 999999999;
+fn bfs1(m: &Matrix<u32>) -> u32 {
+ let mut s: HashMap<(Complex<i32>, Complex<i32>, u32), u32> = HashMap::new();
+ let mut hs: HashSet<(Complex<i32>, Complex<i32>, u32, u32)> = HashSet::new();
+ let mut hs_next: HashSet<(Complex<i32>, Complex<i32>, u32, u32)> = HashSet::new();
+
+ hs.insert((c::new(0, 0), c::new(1, 0), 0, 0));
+
+ let mut res: Vec<u32> = Vec::new();
+ while hs.len() > 0 {
+ for (pos, dir, conti, mut hl) in hs {
+ if conti > 2 {
+ continue;
+ }
+
+ if !(0 <= pos.re
+ && pos.re < m[0].len() as i32
+ && 0 <= pos.im
+ && pos.im < m.len() as i32)
+ {
+ continue;
+ }
+
+ hl += m[pos.im as usize][pos.re as usize];
+
+ if pos == c::new(m[0].len() as i32 - 1, m.len() as i32 - 1) {
+ res.push(hl);
+ continue;
+ }
+
+ if let Some(hl_) = s.get(&(pos, dir, conti)) {
+ if hl_ <= &hl {
+ continue;
+ }
+ }
+ s.insert((pos, dir, conti), hl);
+
+ let new_dir = dir;
+ let new_pos = pos + new_dir;
+ hs_next.insert((new_pos, new_dir, conti + 1, hl));
+
+ let new_dir = dir * c::i();
+ let new_pos = pos + new_dir;
+ hs_next.insert((new_pos, new_dir, 0, hl));
+
+ let new_dir = dir * (-c::i());
+ let new_pos = pos + new_dir;
+ hs_next.insert((new_pos, new_dir, 0, hl));
}
+ hs = hs_next;
+ hs_next = HashSet::new();
}
- s.insert((pos, dir, conti), hl);
+ return res.into_iter().fold(999999999, min) - m[0][0];
+}
- if pos == c::new(m[0].len() as i32 - 1, m.len() as i32 - 1) {
- return hl;
+fn bfs2(m: &Matrix<u32>) -> u32 {
+ let mut s: HashMap<(Complex<i32>, Complex<i32>, u32), u32> = HashMap::new();
+ let mut hs: HashSet<(Complex<i32>, Complex<i32>, u32, u32)> = HashSet::new();
+ let mut hs_next: HashSet<(Complex<i32>, Complex<i32>, u32, u32)> = HashSet::new();
+
+ hs.insert((c::new(0, 0), c::new(1, 0), 0, 0));
+
+ let mut res: Vec<u32> = Vec::new();
+ while hs.len() > 0 {
+ for (pos, dir, conti, mut hl) in hs {
+ if conti > 9 {
+ continue;
+ }
+
+ if !(0 <= pos.re
+ && pos.re < m[0].len() as i32
+ && 0 <= pos.im
+ && pos.im < m.len() as i32)
+ {
+ continue;
+ }
+
+ hl += m[pos.im as usize][pos.re as usize];
+
+ if conti > 2 && pos == c::new(m[0].len() as i32 - 1, m.len() as i32 - 1) {
+ res.push(hl);
+ continue;
+ }
+
+ if let Some(hl_) = s.get(&(pos, dir, conti)) {
+ if hl_ <= &hl {
+ continue;
+ }
+ }
+ s.insert((pos, dir, conti), hl);
+
+ let new_dir = dir;
+ let new_pos = pos + new_dir;
+ hs_next.insert((new_pos, new_dir, conti + 1, hl));
+
+ if conti > 2 {
+ let new_dir = dir * c::i();
+ let new_pos = pos + new_dir;
+ hs_next.insert((new_pos, new_dir, 0, hl));
+
+ let new_dir = dir * (-c::i());
+ let new_pos = pos + new_dir;
+ hs_next.insert((new_pos, new_dir, 0, hl));
+ }
+ }
+ hs = hs_next;
+ hs_next = HashSet::new();
}
-
- let mut ret = 999999999;
- let new_pos = pos + dir;
- let new_dir = dir;
- ret = min(ret, rec(new_pos, new_dir, conti + 1, hl, s, m));
-
- let new_pos = pos + dir;
- let new_dir = dir * c::i();
- ret = min(ret, rec(new_pos, new_dir, 0, hl, s, m));
-
- let new_pos = pos + dir;
- let new_dir = dir * (-c::i());
- ret = min(ret, rec(new_pos, new_dir, 0, hl, s, m));
-
- return ret;
+ return res.into_iter().fold(999999999, min) - m[0][0];
}
fn main() {
- let filename = "in/day17.ref";
- // let filename = "in/day17.pzl";
+ // let filename = "in/day17.ref";
+ let filename = "in/day17.pzl";
let mut f = File::open(filename).expect("cannot open file");
let mut content = String::new();
f.read_to_string(&mut content).expect("cannot read file");
let lines = content.trim_end().split('\n');
- // println!("{:?}", lines);
- let mut m: Matrix<i32> = Vec::new();
+ let mut m: Matrix<u32> = Vec::new();
for line in lines {
- let mut mr: Vec<i32> = Vec::new();
+ let mut mr: Vec<u32> = Vec::new();
for c in line.chars() {
- mr.push(c.to_digit(10).unwrap() as i32);
+ mr.push(c.to_digit(10).unwrap());
}
m.push(mr);
}
- // println!("{:?}", m);
-
- let mut state: HashMap<(Complex<i32>, Complex<i32>, u32), i32> = HashMap::new();
- let mut pos = c::new(0, 0);
- let mut dir = c::new(1, 0);
-
- let res1 = rec(pos, dir, 0, 0, &mut state, &m);
- // println!("{:?}", state);
- let mut res2 = 0;
+ let res1 = bfs1(&m);
+ let res2 = bfs2(&m);
println!("res1: {}", res1);
println!("res2: {}", res2);
+ assert_eq!(res1, 635);
+ assert_eq!(res2, 734);
}
-// 612 too low