diff --git a/2021/README.md b/2021/README.md index 44049f8..d240098 100644 --- a/2021/README.md +++ b/2021/README.md @@ -18,7 +18,7 @@ | 12 | ✓ | ✓ | [Python] | | 13 | ✓ | ✓ | [C++] | | 14 | ✓ | ✓ | [Erlang] | -| 15 | ✓ | | [D] | +| 15 | ✓ | ✓ | [D] | | 16 | | | | | 17 | | | | | 18 | | | | diff --git a/2021/day-15/common.d b/2021/day-15/common.d index a76815c..656c425 100644 --- a/2021/day-15/common.d +++ b/2021/day-15/common.d @@ -4,6 +4,8 @@ import std.algorithm.iteration : filter, map; import std.algorithm.searching : minElement, canFind; import std.array : split; import std.container.array : Array; +import std.container.rbtree : redBlackTree; +import std.container.binaryheap : BinaryHeap; import std.conv : to; import std.stdio; import std.string : stripRight; @@ -14,12 +16,64 @@ private alias Buffer = Array!(Array!(uint)); struct CaveMap { private Buffer positions; + private const ulong tile_width; + private const ulong tile_height; this(string path) { positions = parseFile(path); } + this(string path, uint tiles) + { + auto buffer = parseFile(path); + tile_height = buffer.length; + tile_width = buffer[0].length; + + tileRight(buffer, tiles); + tileDown(buffer, tiles); + + positions = buffer; + } + + private void tileRight(Buffer buffer, uint tiles) + { + foreach (tile_x; 1 .. tiles) + { + foreach (y; 0 .. tile_height) + { + foreach (x; 0 .. tile_width) + { + auto next_val = (buffer[y][x] + tile_x - 1) % 9; + next_val = next_val == 0 ? 1 : next_val + 1; + buffer[y].insertBack(next_val); + } + } + } + } + + private void tileDown(Buffer buffer, uint tiles) + { + foreach (tile_y; 1 .. tiles) + { + const tile_y_begin = tile_y * tile_height; + foreach (y; 0 .. tile_height) + { + buffer.insertBack(Array!uint()); + foreach (tile_x; 0 .. tiles) + { + const tile_x_begin = tile_x * tile_width; + foreach (x; 0 .. tile_width) + { + auto next_val = (buffer[y][tile_x_begin + x] + tile_y - 1) % 9; + next_val = next_val == 0 ? 1 : next_val + 1; + buffer[tile_y_begin + y].insertBack(next_val); + } + } + } + } + } + private Array!(Array!uint) parseFile(string path) { auto file = File(path, "r"); @@ -41,6 +95,16 @@ struct CaveMap return buffer; } + + void toString(scope void delegate(const(char)[]) sink) const + { + foreach (y; 0 .. positions.length) + { + foreach (x; 0 .. positions[y].length) + sink(to!string(positions[y][x])); + sink("\n"); + } + } } private alias NodeId = Tuple!(uint, uint); @@ -93,10 +157,45 @@ struct Cave uint lowestRisk() { - auto safest_path = dijkstraSlow(); + auto safest_path = dijkstraFaster(); return safest_path[1][end_node]; } + private Tuple!(NodeId[NodeId], uint[NodeId]) dijkstraFaster() + { + uint[NodeId] distance; + NodeId[NodeId] previous; + + foreach (node_id; nodes.byKey()) + distance[node_id] = uint.max; + + distance[start_node] = 0; + + auto queue = redBlackTree(tuple(distance[start_node], start_node)); + + foreach (_, node; queue) + { + if (node == end_node) + break; + + foreach (neighbor; nodes[node]) + { + auto total_distance = distance[node] + neighbor.weight; + + if (total_distance < distance[neighbor.id]) + { + queue.removeKey(tuple(distance[neighbor.id], neighbor.id)); + distance[neighbor.id] = total_distance; + previous[neighbor.id] = node; + queue.insert(tuple(distance[neighbor.id], neighbor.id)); + } + + } + } + + return tuple(previous, distance); + } + private Tuple!(NodeId[NodeId], uint[NodeId]) dijkstraSlow() { bool[NodeId] unvisited; diff --git a/2021/day-15/part_two.d b/2021/day-15/part_two.d new file mode 100644 index 0000000..5f5d650 --- /dev/null +++ b/2021/day-15/part_two.d @@ -0,0 +1,13 @@ +import std.stdio; +import common : CaveMap, Cave; + +void main(string[] args) +{ + auto immutable path = args[1]; + + auto cave_map = CaveMap(path, 5); + + auto graph = Cave(cave_map); + + writeln(graph.lowestRisk()); +} diff --git a/README.md b/README.md index 492e284..b1650df 100644 --- a/README.md +++ b/README.md @@ -8,4 +8,4 @@ - [2018](2018/README.md) (0% completed) - [2019](2019/README.md) (0% completed) - [2020](2020/README.md) (20% completed) -- [2021](2021/README.md) (58% completed) +- [2021](2021/README.md) (60% completed)