diff --git a/progress.png b/progress.png index d44bc71..b623c25 100644 Binary files a/progress.png and b/progress.png differ diff --git a/progress.yaml b/progress.yaml index 31d7af7..5a141eb 100644 --- a/progress.yaml +++ b/progress.yaml @@ -31,4 +31,6 @@ 16: stars: 0 17: + stars: 1 +18: stars: 1 \ No newline at end of file diff --git a/res/examples/day18.txt b/res/examples/day18.txt new file mode 100644 index 0000000..0371b23 --- /dev/null +++ b/res/examples/day18.txt @@ -0,0 +1,25 @@ +5,4 +4,2 +4,5 +3,0 +2,1 +6,3 +2,4 +1,5 +0,6 +3,3 +2,6 +5,1 +1,2 +5,5 +2,5 +6,5 +1,4 +0,4 +6,4 +1,1 +6,1 +1,0 +0,5 +1,6 +2,0 \ No newline at end of file diff --git a/src/day18/puzzle1.typ b/src/day18/puzzle1.typ new file mode 100644 index 0000000..efcdd4d --- /dev/null +++ b/src/day18/puzzle1.typ @@ -0,0 +1,148 @@ +#import "/src/utils.typ": * + +#let offsets = ( + (1, 0), + (0, 1), + (-1, 0), + (0, -1) +) + +#let get-coords(x, y) = { + return str(x) + "/" + str(y) +} + +#let get-lowest(nodes, scores) = { + let lowest-score = none + let lowest-i = none + for (i, (x, y)) in nodes.enumerate() { + let score = scores.at(y).at(x) + + if lowest-i == none or score < lowest-score { + lowest-score = score + lowest-i = i + } + } + + if lowest-i == none { + panic() + } + return lowest-i +} + +#let make-path(parents, end) = { + let path = (end,) + let (x, y) = end + let pos = parents.at(y).at(x) + while pos != none { + (x, y) = pos + path.insert(0, pos) + pos = parents.at(y).at(x) + } + return path +} + +#let find-path(w, h, grid, start: (0, 0), end: auto) = { + let end = if end == auto {(w - 1, h - 1)} else {end} + let end = (w - 1, h - 1) + let (x, y) = (0, 0) + let open = ((x, y),) + let closed = () + let g-scores = ((0,) * w,) * h + let f-scores = ((calc.inf,) * w,) * h + let parents = ((none,)*w,)*h + while open.len() != 0 { + let cur = open.remove(get-lowest(open, f-scores)) + + if cur == end { + return make-path(parents, cur) + } + + let g-score = g-scores.at(y).at(x) + let f-score = f-scores.at(y).at(x) + + let (x, y) = cur + for (dx, dy) in offsets { + let (x2, y2) = (x + dx, y + dy) + if x2 < 0 or x2 >= w or y2 < 0 or y2 >= h { + continue + } + if grid.at(y2).at(x2) { + continue + } + if (x2, y2) in closed { + continue + } + let g = x2 + y2 + let h = calc.abs(end.first() - x2) + calc.abs(end.last() - y2) + let f = g + h + + if f < f-scores.at(y2).at(x2) { + g-scores.at(y2).at(x2) = g + f-scores.at(y2).at(x2) = f + parents.at(y2).at(x2) = (x, y) + open.push((x2, y2)) + } + } + closed.push(cur) + } + panic("No path was found") +} + +#let solve(input, w: 0, h: 0, n-bytes: 0) = { + assert(w != 0, message: "Width cannot be 0") + assert(h != 0, message: "Height cannot be 0") + let grid = ((false,) * w,) * h + + let obstacles = input.split("\n") + for obs in obstacles.slice(0, n-bytes) { + let (x, y) = obs.split(",").map(int) + grid.at(y).at(x) = true + } + + let path = find-path(w, h, grid) + return path.len() - 1 +} + +#let visualize(input, w: 0, h: 0, n-bytes: 0, s: 2em) = { + let grid_ = ((false,) * w,) * h + + let obstacles = input.split("\n") + for obs in obstacles.slice(0, n-bytes) { + let (x, y) = obs.split(",").map(int) + grid_.at(y).at(x) = true + } + + let path = find-path(w, h, grid_) + for (x, y) in path { + grid_.at(y).at(x) = grid.cell(fill: green.lighten(60%))[O] + } + + let cells = grid_.flatten().map(c => { + if c == false [] + else if c == true {grid.cell(fill: red.lighten(60%))[\#]} + else {c} + }) + + grid( + columns: (s,) * w, + rows: (s,) * h, + align: center + horizon, + stroke: black, + ..cells + ) +} + +#show-puzzle( + 18, 1, + solve.with(w: 71, h: 71, n-bytes: 1024), + example: ( + (result: 22, args: (w: 7, h: 7, n-bytes: 12)), + ), + visualize: visualize.with(w: 7, h: 7, n-bytes: 12) +) + +/* +#pagebreak() +#set page(width: auto, height: auto) +#visualize(get-input(18), w: 71, h: 71, n-bytes: 1024, s: 1em) +*/ \ No newline at end of file diff --git a/src/day18/puzzle2.typ b/src/day18/puzzle2.typ new file mode 100644 index 0000000..e69de29 diff --git a/src/main.pdf b/src/main.pdf index 62d3fc1..5b16261 100644 Binary files a/src/main.pdf and b/src/main.pdf differ