Skip to content

Commit e9c60f4

Browse files
committed
Day 15 part 1-2
1 parent 892a788 commit e9c60f4

File tree

3 files changed

+370
-0
lines changed

3 files changed

+370
-0
lines changed

day15/input_test

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
1163751742
2+
1381373672
3+
2136511328
4+
3694931569
5+
7463417111
6+
1319128137
7+
1359912421
8+
3125421639
9+
1293138521
10+
2311944581

day15/part1.zig

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
const std = @import("std");
2+
3+
pub fn main() !void {
4+
var file = try std.fs.cwd().openFile("input", .{});
5+
defer file.close();
6+
7+
var buf_reader = std.io.bufferedReader(file.reader());
8+
var in_stream = buf_reader.reader();
9+
10+
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
11+
defer arena.deinit();
12+
13+
const allocator = &arena.allocator;
14+
15+
var map_list = std.ArrayList(u8).init(allocator);
16+
map_list.deinit();
17+
18+
const map = blk: {
19+
var i: u32 = 0;
20+
var read_buf: [1024]u8 = undefined;
21+
22+
const first_line = (try in_stream.readUntilDelimiterOrEof(&read_buf, '\n')).?;
23+
for (first_line) |point| {
24+
try map_list.append(point - '0');
25+
i += 1;
26+
}
27+
const x_len = i;
28+
29+
while (try in_stream.readUntilDelimiterOrEof(&read_buf, '\n')) |line| {
30+
for (first_line) |point| {
31+
try map_list.append(point - '0');
32+
i += 1;
33+
}
34+
}
35+
const y_len = i / x_len;
36+
break :blk Map{ .map = map_list.items, .x_len = x_len, .y_len = y_len };
37+
};
38+
39+
// map.print();
40+
const len = map.map.len;
41+
42+
const inf = std.math.maxInt(u32);
43+
44+
var dist: []u32 = try allocator.alloc(u32, len);
45+
defer allocator.free(dist);
46+
47+
var q = std.PriorityQueue(u64).init(allocator, compare);
48+
defer q.deinit();
49+
50+
{
51+
dist[0] = 0;
52+
try q.add((Vertex{ .v = 0, .dist = 0 }).toLong());
53+
54+
var v: u32 = 1;
55+
while (v < map.map.len) : (v += 1) {
56+
dist[v] = inf;
57+
try q.add((Vertex{ .v = v, .dist = std.math.maxInt(u32) }).toLong());
58+
}
59+
}
60+
61+
while (q.len > 0) {
62+
const u_vert = Vertex.fromLong(q.remove());
63+
const u = u_vert.v;
64+
if (u == len - 1) {
65+
break;
66+
}
67+
68+
const ns = map.neighbors(u);
69+
for (ns.get()) |v| {
70+
const alt = dist[u] + map.map[v];
71+
if (alt < dist[v]) {
72+
try q.update((Vertex{ .v = v, .dist = dist[v] }).toLong(), (Vertex{ .v = v, .dist = alt }).toLong());
73+
dist[v] = alt;
74+
}
75+
}
76+
}
77+
const stdout = std.io.getStdOut().writer();
78+
try stdout.print("{d}\n", .{dist[len - 1]});
79+
}
80+
81+
const Neighbors = struct {
82+
len: u8 = 0,
83+
ns: [4]u32 = undefined,
84+
85+
fn add(self: *Neighbors, x: u32, y: u32, x_len: u32) void {
86+
self.ns[self.len] = y * x_len + x;
87+
self.len += 1;
88+
}
89+
90+
fn get(self: Neighbors) []const u32 {
91+
return self.ns[0..self.len];
92+
}
93+
};
94+
95+
const Vertex = struct {
96+
v: u32,
97+
dist: u32,
98+
99+
fn toLong(self: Vertex) u64 {
100+
var x: u64 = @as(u64, self.dist) << 32;
101+
x += self.v;
102+
return x;
103+
}
104+
105+
fn fromLong(x: u64) Vertex {
106+
const dist_mask: u64 = 0xFFFFFFFF00000000;
107+
const v = @intCast(u32, x & ~dist_mask);
108+
const dist = @intCast(u32, (x & dist_mask) >> 32);
109+
return Vertex{ .v = v, .dist = dist };
110+
}
111+
};
112+
113+
fn compare(a: u64, b: u64) std.math.Order {
114+
return std.math.order(a, b);
115+
}
116+
117+
const Map = struct {
118+
map: []u8,
119+
x_len: u32,
120+
y_len: u32,
121+
122+
fn setXLen(self: *Map, x_len: u32) void {
123+
self.x_len = x_len;
124+
}
125+
126+
fn setYLen(self: *Map, y_len: u32) void {
127+
self.y_len = y_len;
128+
}
129+
130+
fn set(self: *Map, x: u8, y: u8, val: u8) void {
131+
self.map[y * self.x_len + x] = val;
132+
}
133+
134+
fn get(self: Map, x: u8, y: u8) u8 {
135+
return self.map[y * self.x_len + x];
136+
}
137+
138+
fn neighbors(self: Map, i: u32) Neighbors {
139+
const x_len = self.x_len;
140+
const y_len = self.y_len;
141+
const x = i % x_len;
142+
const y = i / x_len;
143+
var ns = Neighbors{};
144+
145+
if (x > 0) {
146+
ns.add(x - 1, y, x_len);
147+
}
148+
if (x + 1 < x_len) {
149+
ns.add(x + 1, y, x_len);
150+
}
151+
if (y > 0) {
152+
ns.add(x, y - 1, x_len);
153+
}
154+
if (y + 1 < y_len) {
155+
ns.add(x, y + 1, x_len);
156+
}
157+
158+
return ns;
159+
}
160+
161+
fn print(self: Map) void {
162+
var i: u32 = 0;
163+
while (i < self.x_len) : (i += 1) {
164+
var j: u32 = 0;
165+
while (j < self.y_len) : (j += 1) {
166+
const val = self.get(i, j);
167+
const c: u8 = if (val == 0) '-' else val + '0';
168+
std.debug.print("{c}", .{c});
169+
}
170+
std.debug.print("\n", .{});
171+
}
172+
std.debug.print("\n", .{});
173+
}
174+
};

day15/part2.zig

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
const std = @import("std");
2+
3+
pub fn main() !void {
4+
var file = try std.fs.cwd().openFile("input", .{});
5+
defer file.close();
6+
7+
var buf_reader = std.io.bufferedReader(file.reader());
8+
var in_stream = buf_reader.reader();
9+
10+
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
11+
defer arena.deinit();
12+
13+
const allocator = &arena.allocator;
14+
15+
var map_list = std.ArrayList(u8).init(allocator);
16+
map_list.deinit();
17+
18+
const map = blk: {
19+
var i: u32 = 0;
20+
var read_buf: [1024]u8 = undefined;
21+
22+
const first_line = (try in_stream.readUntilDelimiterOrEof(&read_buf, '\n')).?;
23+
for (first_line) |point| {
24+
try map_list.append(point - '0');
25+
i += 1;
26+
}
27+
const x_len = i;
28+
29+
while (try in_stream.readUntilDelimiterOrEof(&read_buf, '\n')) |line| {
30+
for (first_line) |point| {
31+
try map_list.append(point - '0');
32+
i += 1;
33+
}
34+
}
35+
const y_len = i / x_len;
36+
37+
var small_map = Map{ .map = map_list.items, .x_len = x_len, .y_len = y_len };
38+
var map_items = try allocator.alloc(u8, 25 * x_len * y_len);
39+
var map = Map{ .map = map_items, .x_len = 5 * x_len, .y_len = 5 * y_len };
40+
41+
var tile_y: u8 = 0;
42+
while (tile_y < 5) : (tile_y += 1) {
43+
var tile_x: u8 = 0;
44+
while (tile_x < 5) : (tile_x += 1) {
45+
var y: u32 = 0;
46+
while (y < y_len) : (y += 1) {
47+
var x: u32 = 0;
48+
while (x < x_len) : (x += 1) {
49+
const original: u8 = small_map.get(x, y);
50+
const val: u8 = (original - 1 + tile_x + tile_y) % 9 + 1;
51+
map.set(tile_x * x_len + x, tile_y * y_len + y, val);
52+
}
53+
}
54+
}
55+
}
56+
break :blk map;
57+
};
58+
defer allocator.free(map.map);
59+
60+
const len = map.map.len;
61+
62+
const inf = std.math.maxInt(u32);
63+
64+
var dist: []u32 = try allocator.alloc(u32, len);
65+
defer allocator.free(dist);
66+
67+
var q = std.PriorityQueue(u64).init(allocator, compare);
68+
defer q.deinit();
69+
70+
{
71+
dist[0] = 0;
72+
try q.add((Vertex{ .v = 0, .dist = 0 }).toLong());
73+
74+
var v: u32 = 1;
75+
while (v < map.map.len) : (v += 1) {
76+
dist[v] = inf;
77+
try q.add((Vertex{ .v = v, .dist = std.math.maxInt(u32) }).toLong());
78+
}
79+
}
80+
81+
while (q.len > 0) {
82+
const u_vert = Vertex.fromLong(q.remove());
83+
const u = u_vert.v;
84+
if (u == len - 1) {
85+
break;
86+
}
87+
88+
const ns = map.neighbors(u);
89+
for (ns.get()) |v| {
90+
const alt = dist[u] + map.map[v];
91+
if (alt < dist[v]) {
92+
try q.update((Vertex{ .v = v, .dist = dist[v] }).toLong(), (Vertex{ .v = v, .dist = alt }).toLong());
93+
dist[v] = alt;
94+
}
95+
}
96+
}
97+
const stdout = std.io.getStdOut().writer();
98+
try stdout.print("{d}\n", .{dist[len - 1]});
99+
}
100+
101+
const Neighbors = struct {
102+
len: u8 = 0,
103+
ns: [4]u32 = undefined,
104+
105+
fn add(self: *Neighbors, x: u32, y: u32, x_len: u32) void {
106+
self.ns[self.len] = y * x_len + x;
107+
self.len += 1;
108+
}
109+
110+
fn get(self: Neighbors) []const u32 {
111+
return self.ns[0..self.len];
112+
}
113+
};
114+
115+
const Vertex = struct {
116+
v: u32,
117+
dist: u32,
118+
119+
fn toLong(self: Vertex) u64 {
120+
var x: u64 = @as(u64, self.dist) << 32;
121+
x += self.v;
122+
return x;
123+
}
124+
125+
fn fromLong(x: u64) Vertex {
126+
const dist_mask: u64 = 0xFFFFFFFF00000000;
127+
const v = @intCast(u32, x & ~dist_mask);
128+
const dist = @intCast(u32, (x & dist_mask) >> 32);
129+
return Vertex{ .v = v, .dist = dist };
130+
}
131+
};
132+
133+
fn compare(a: u64, b: u64) std.math.Order {
134+
return std.math.order(a, b);
135+
}
136+
137+
const Map = struct {
138+
map: []u8,
139+
x_len: u32,
140+
y_len: u32,
141+
142+
fn set(self: *Map, x: u32, y: u32, val: u8) void {
143+
self.map[y * self.x_len + x] = val;
144+
}
145+
146+
fn get(self: Map, x: u32, y: u32) u8 {
147+
return self.map[y * self.x_len + x];
148+
}
149+
150+
fn neighbors(self: Map, i: u32) Neighbors {
151+
const x_len = self.x_len;
152+
const y_len = self.y_len;
153+
const x = i % x_len;
154+
const y = i / x_len;
155+
var ns = Neighbors{};
156+
157+
if (x > 0) {
158+
ns.add(x - 1, y, x_len);
159+
}
160+
if (x + 1 < x_len) {
161+
ns.add(x + 1, y, x_len);
162+
}
163+
if (y > 0) {
164+
ns.add(x, y - 1, x_len);
165+
}
166+
if (y + 1 < y_len) {
167+
ns.add(x, y + 1, x_len);
168+
}
169+
170+
return ns;
171+
}
172+
173+
fn print(self: Map) void {
174+
var y: u32 = 0;
175+
while (y < self.y_len) : (y += 1) {
176+
var x: u32 = 0;
177+
while (x < self.x_len) : (x += 1) {
178+
const val = self.get(x, y);
179+
const c: u8 = if (val == 0) '-' else val + '0';
180+
std.debug.print("{c}", .{c});
181+
}
182+
std.debug.print("\n", .{});
183+
}
184+
std.debug.print("\n", .{});
185+
}
186+
};

0 commit comments

Comments
 (0)