Zuletzt aktiv 1720089306

sotolf2 hat die Gist bearbeitet 1720089306. Zu Änderung gehen

1 file changed, 184 insertions

aoc2015day14.zig(Datei erstellt)

@@ -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 + }
Neuer Älter