-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path16.zig
129 lines (116 loc) · 4.84 KB
/
16.zig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
const std = @import("std");
const stdin = std.io.getStdIn().reader();
const print = std.debug.print;
const page_allocator = std.heap.page_allocator;
pub fn main() !void {
const input = try clean_up_input();
const width = input.width;
const height = input.height;
const chars = input.chars;
var max: usize = 0;
for (0..width) |i| {
max = @max(max, try energized_tiles(Beam{ .dir = Direction.Down, .pos = i }, chars, width, height));
max = @max(max, try energized_tiles(Beam{ .dir = Direction.Up, .pos = width * height - 1 - i }, chars, width, height));
max = @max(max, try energized_tiles(Beam{ .dir = Direction.Right, .pos = i * width }, chars, width, height));
max = @max(max, try energized_tiles(Beam{ .dir = Direction.Left, .pos = i * width + width - 1 }, chars, width, height));
}
print("Day 16 >> {d}\n", .{max});
}
pub fn energized_tiles(start_beam: Beam, chars: []const u8, width: usize, height: usize) !usize {
const energized = try page_allocator.alloc(bool, chars.len);
for (energized) |*e| {
e.* = false;
}
var beams = std.ArrayList(Beam).init(page_allocator);
var cached_beams = std.AutoHashMap(Beam, void).init(page_allocator);
try beams.append(start_beam);
var beams_to_delete = std.ArrayList(usize).init(page_allocator);
while (beams.items.len > 0) {
for (beams.items, 0..) |beam, i| {
if (try cached_beams.fetchPut(beam, void{})) |_| {
try beams_to_delete.append(i);
continue;
} else {
energized[beam.pos] = true;
}
switch (chars[beams.items[i].pos]) {
'|' => if (beam.dir == Direction.Left or beam.dir == Direction.Right) {
beams.items[i].dir = Direction.Up;
try beams.append(Beam{ .dir = Direction.Down, .pos = beams.items[i].pos });
},
'-' => if (beam.dir == Direction.Up or beam.dir == Direction.Down) {
beams.items[i].dir = Direction.Left;
try beams.append(Beam{ .dir = Direction.Right, .pos = beams.items[i].pos });
},
'/' => switch (beam.dir) {
.Up => beams.items[i].dir = Direction.Right,
.Down => beams.items[i].dir = Direction.Left,
.Left => beams.items[i].dir = Direction.Down,
.Right => beams.items[i].dir = Direction.Up,
},
'\\' => switch (beam.dir) {
.Up => beams.items[i].dir = Direction.Left,
.Down => beams.items[i].dir = Direction.Right,
.Left => beams.items[i].dir = Direction.Up,
.Right => beams.items[i].dir = Direction.Down,
},
else => {},
}
}
for (beams.items, 0..) |beam, i| {
if (walk_beam(beam.pos, beam.dir, width, height)) |new_pos| {
beams.items[i].pos = new_pos;
} else if (std.mem.count(usize, beams_to_delete.items, &.{i}) == 0) {
try beams_to_delete.append(i);
}
//
// for (chars, 0..) |c, j| {
// if (energized[j]) {
// print("\x1b[31m{c}\x1b[0m", .{c});
// } else {
// print("{c}", .{c});
// }
// if (j % width == width - 1) {
// print("\n", .{});
// }
// }
//
// _ = try stdin.readByte();
}
std.mem.sort(usize, beams_to_delete.items, {}, comptime std.sort.asc(usize));
while (beams_to_delete.popOrNull()) |del_index| {
_ = beams.orderedRemove(del_index);
}
}
return std.mem.count(bool, energized, &.{true});
}
const Beam = struct {
dir: Direction,
pos: usize,
};
pub fn walk_beam(beam_pos: usize, dir: Direction, width: usize, height: usize) ?usize {
return switch (dir) {
.Up => if (beam_pos < width) null else beam_pos - width,
.Down => if (beam_pos + width >= width * height) null else beam_pos + width,
.Left => if (beam_pos % width == 0) null else beam_pos - 1,
.Right => if (beam_pos % width == width - 1) null else beam_pos + 1,
};
}
const Direction = enum {
Up,
Down,
Left,
Right,
};
pub fn clean_up_input() !struct { chars: []const u8, width: usize, height: usize } {
const input = @embedFile("16.txt");
const width = std.mem.indexOfScalar(u8, input, '\n').?;
const height = (input.len + 1) / (width + 1);
var chars = try page_allocator.alloc(u8, width * height);
for (0..width) |x| {
for (0..height) |y| {
chars[y * width + x] = input[x + y * (width + 1)];
}
}
return .{ .chars = chars, .width = width, .height = height };
}