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
|
const std = @import("std");
const aoc = @import("aoc");
const Entry = []u1;
const Vector = struct { x: u16, y: u16 };
fn freeEntries(allocator: std.mem.Allocator, entries: *const std.ArrayList(Entry)) void {
for (entries.items) |entry| {
allocator.free(entry);
}
entries.deinit();
}
fn parse(allocator: std.mem.Allocator, input: []u8) !std.ArrayList(Entry) {
var entries = std.ArrayList(Entry).init(allocator);
errdefer freeEntries(allocator, &entries);
var lineit = std.mem.tokenize(u8, input, "\n");
while (lineit.next()) |line| {
var linemap: []u1 = try allocator.alloc(u1, line.len);
errdefer allocator.free(linemap);
for (line) |c, i| {
linemap[i] = @boolToInt(c == '#');
}
try entries.append(linemap);
}
return entries;
}
fn treesHit(map: std.ArrayList(Entry), slope: Vector) u16 {
var count: u16 = 0;
var pos = Vector{ .x = 0, .y = 0 };
while (pos.y < map.items.len - 1) {
pos.x += slope.x;
pos.y += slope.y;
count += map.items[pos.y][pos.x % map.items[0].len];
}
return count;
}
fn part1(allocator: std.mem.Allocator, input: []u8, args: [][]u8) !?[]u8 {
_ = args;
const map = try parse(allocator, input);
defer freeEntries(allocator, &map);
const answer = treesHit(map, Vector{ .x = 3, .y = 1 });
return try std.fmt.allocPrint(allocator, "{d}", .{answer});
}
fn part2(allocator: std.mem.Allocator, input: []u8, args: [][]u8) !?[]u8 {
_ = args;
const map = try parse(allocator, input);
defer freeEntries(allocator, &map);
const slopes = [_]Vector{
Vector{ .x = 1, .y = 1 },
Vector{ .x = 3, .y = 1 },
Vector{ .x = 5, .y = 1 },
Vector{ .x = 7, .y = 1 },
Vector{ .x = 1, .y = 2 },
};
var answer: u32 = 1;
for (slopes) |slope| {
answer *= treesHit(map, slope);
}
return try std.fmt.allocPrint(allocator, "{d}", .{answer});
}
pub const main = aoc.main(part1, part2, .{ "282", "958815792" });
|