Add solution for 2021 day 15 part 2

This commit is contained in:
Patrick Auernig 2021-12-16 16:10:29 +01:00
parent 622c739c81
commit 491e2f3afa
4 changed files with 115 additions and 3 deletions

View File

@ -18,7 +18,7 @@
| 12 | ✓ | ✓ | [Python] |
| 13 | ✓ | ✓ | [C++] |
| 14 | ✓ | ✓ | [Erlang] |
| 15 | ✓ | | [D] |
| 15 | ✓ | | [D] |
| 16 | | | |
| 17 | | | |
| 18 | | | |

View File

@ -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;

13
2021/day-15/part_two.d Normal file
View File

@ -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());
}

View File

@ -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)