sotolf2 a révisé ce gist . Aller à la révision
1 file changed, 184 insertions
aoc2015day14.zig(fichier créé)
@@ -0,0 +1,184 @@ | |||
1 | + | const std = @import("std"); | |
2 | + | const mem = std.mem; | |
3 | + | const fs = std.fs; | |
4 | + | const print = std.debug.print; | |
5 | + | ||
6 | + | const ParseError = error{ | |
7 | + | RanOutOfWords, | |
8 | + | }; | |
9 | + | ||
10 | + | const Parser = struct { | |
11 | + | it: mem.SplitIterator(u8, .scalar), | |
12 | + | ||
13 | + | fn fromString(str: []const u8) Parser { | |
14 | + | return Parser{ | |
15 | + | .it = mem.splitScalar(u8, str, ' '), | |
16 | + | }; | |
17 | + | } | |
18 | + | ||
19 | + | fn take(self: *Parser) ![]const u8 { | |
20 | + | const wordo = self.it.next(); | |
21 | + | if (wordo) |word| { | |
22 | + | return word; | |
23 | + | } else { | |
24 | + | return ParseError.RanOutOfWords; | |
25 | + | } | |
26 | + | } | |
27 | + | ||
28 | + | fn skip(self: *Parser, cnt: usize) void { | |
29 | + | for (0..cnt) |_| { | |
30 | + | _ = self.it.next(); | |
31 | + | } | |
32 | + | } | |
33 | + | ||
34 | + | fn takeAsNumber(self: *Parser, Type: type) !Type { | |
35 | + | const wordo = self.it.next(); | |
36 | + | if (wordo) |word| { | |
37 | + | return std.fmt.parseInt(Type, word, 10); | |
38 | + | } else { | |
39 | + | return ParseError.RanOutOfWords; | |
40 | + | } | |
41 | + | } | |
42 | + | }; | |
43 | + | ||
44 | + | const Raindeer = struct { | |
45 | + | speed: usize, | |
46 | + | flight: usize, | |
47 | + | rest: usize, | |
48 | + | ||
49 | + | fn distanceAfter(self: Raindeer, sec: usize) usize { | |
50 | + | const chunk_time = self.flight + self.rest; | |
51 | + | const chunk_dist = self.speed * self.flight; | |
52 | + | const chunked = chunk_dist * (sec / chunk_time); | |
53 | + | const left = @mod(sec, chunk_time); | |
54 | + | const rest = if (left > self.flight) self.speed * self.flight else self.speed * left; | |
55 | + | return chunked + rest; | |
56 | + | } | |
57 | + | }; | |
58 | + | ||
59 | + | fn getLines(path: []const u8, alloc: mem.Allocator) !std.ArrayList(Raindeer) { | |
60 | + | const file = fs.cwd().openFile(path, .{}) catch |err| { | |
61 | + | std.log.err("Failed to open file {s}", .{@errorName(err)}); | |
62 | + | return err; | |
63 | + | }; | |
64 | + | defer file.close(); | |
65 | + | ||
66 | + | var raindeer = std.ArrayList(Raindeer).init(alloc); | |
67 | + | ||
68 | + | while (file.reader().readUntilDelimiterOrEofAlloc(alloc, '\n', std.math.maxInt(usize)) catch |err| { | |
69 | + | std.log.err("Failed to read line: {s}", .{@errorName(err)}); | |
70 | + | return err; | |
71 | + | }) |line| { | |
72 | + | defer alloc.free(line); | |
73 | + | var words = Parser.fromString(line); | |
74 | + | words.skip(3); | |
75 | + | const speed = try words.takeAsNumber(usize); | |
76 | + | words.skip(2); | |
77 | + | const flight = try words.takeAsNumber(usize); | |
78 | + | words.skip(6); | |
79 | + | const rest = try words.takeAsNumber(usize); | |
80 | + | try raindeer.append(.{ | |
81 | + | .speed = speed, | |
82 | + | .flight = flight, | |
83 | + | .rest = rest, | |
84 | + | }); | |
85 | + | } | |
86 | + | return raindeer; | |
87 | + | } | |
88 | + | ||
89 | + | fn part1(raindeer: std.ArrayList(Raindeer)) !void { | |
90 | + | var score: usize = 0; | |
91 | + | ||
92 | + | for (raindeer.items) |rd| { | |
93 | + | score = @max(score, rd.distanceAfter(2503)); | |
94 | + | } | |
95 | + | ||
96 | + | print("Part1: {d}\n", .{score}); | |
97 | + | } | |
98 | + | ||
99 | + | const RaindeerState = struct { | |
100 | + | raindeer: Raindeer, | |
101 | + | running: bool, | |
102 | + | time: usize, | |
103 | + | distance: usize, | |
104 | + | points: usize, | |
105 | + | ||
106 | + | fn fromRaindeer(rnd: Raindeer) RaindeerState { | |
107 | + | return .{ | |
108 | + | .raindeer = rnd, | |
109 | + | .running = true, | |
110 | + | .time = 0, | |
111 | + | .distance = 0, | |
112 | + | .points = 0, | |
113 | + | }; | |
114 | + | } | |
115 | + | ||
116 | + | fn tick(self: *RaindeerState) void { | |
117 | + | if (self.running) { | |
118 | + | self.distance += self.raindeer.speed; | |
119 | + | self.time += 1; | |
120 | + | if (self.time >= self.raindeer.flight) { | |
121 | + | self.time = 0; | |
122 | + | self.running = false; | |
123 | + | } | |
124 | + | } else { | |
125 | + | self.time += 1; | |
126 | + | if (self.time >= self.raindeer.rest) { | |
127 | + | self.time = 0; | |
128 | + | self.running = true; | |
129 | + | } | |
130 | + | } | |
131 | + | } | |
132 | + | }; | |
133 | + | ||
134 | + | fn run(raindeer: std.ArrayList(Raindeer), alloc: mem.Allocator, sec: usize) !usize { | |
135 | + | var states = std.ArrayList(*RaindeerState).init(alloc); | |
136 | + | defer { | |
137 | + | for (states.items) |state| { | |
138 | + | alloc.destroy(state); | |
139 | + | } | |
140 | + | states.deinit(); | |
141 | + | } | |
142 | + | ||
143 | + | for (raindeer.items) |rnd| { | |
144 | + | const state = try alloc.create(RaindeerState); | |
145 | + | state.* = RaindeerState.fromRaindeer(rnd); | |
146 | + | try states.append(state); | |
147 | + | } | |
148 | + | ||
149 | + | for (0..sec) |_| { | |
150 | + | var max_dist: usize = 0; | |
151 | + | for (states.items) |state| { | |
152 | + | state.tick(); | |
153 | + | max_dist = @max(max_dist, state.distance); | |
154 | + | } | |
155 | + | ||
156 | + | for (states.items) |state| { | |
157 | + | if (state.distance == max_dist) | |
158 | + | state.points += 1; | |
159 | + | } | |
160 | + | } | |
161 | + | var max_points: usize = 0; | |
162 | + | for (states.items) |state| { | |
163 | + | max_points = @max(max_points, state.points); | |
164 | + | } | |
165 | + | return max_points; | |
166 | + | } | |
167 | + | ||
168 | + | fn part2(raindeer: std.ArrayList(Raindeer), alloc: mem.Allocator) !void { | |
169 | + | const score = try run(raindeer, alloc, 2503); | |
170 | + | print("Part2: {d}\n", .{score}); | |
171 | + | } | |
172 | + | ||
173 | + | pub fn main() !void { | |
174 | + | var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | |
175 | + | defer _ = gpa.deinit(); | |
176 | + | const alloc = gpa.allocator(); | |
177 | + | ||
178 | + | const filename = "day14.txt"; | |
179 | + | var raindeer = try getLines(filename, alloc); | |
180 | + | defer raindeer.deinit(); | |
181 | + | ||
182 | + | try part1(raindeer); | |
183 | + | try part2(raindeer, alloc); | |
184 | + | } |
Plus récent
Plus ancien