Compare commits
2 Commits
77ff15f997
...
8f9891cdde
Author | SHA1 | Date | |
---|---|---|---|
8f9891cdde | |||
676dceec14 |
@ -1,6 +1,5 @@
|
||||
const aoc = @import("./aoc.zig");
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
|
||||
const MappingRange = struct {
|
||||
src_start: u64,
|
||||
|
115
src/day6.zig
Normal file
115
src/day6.zig
Normal file
@ -0,0 +1,115 @@
|
||||
const std = @import("std");
|
||||
const aoc = @import("./aoc.zig");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
const BoundedU32 = std.BoundedArray(u32, 32);
|
||||
|
||||
const Input = struct {
|
||||
time: BoundedU32,
|
||||
distance: BoundedU32,
|
||||
};
|
||||
|
||||
fn parse_numbers(result: *BoundedU32, text: []const u8) !void {
|
||||
var i: usize = 0;
|
||||
var tokens = std.mem.tokenizeScalar(u8, text, ' ');
|
||||
while (tokens.next()) |token| : (i += 1) {
|
||||
const number = try std.fmt.parseInt(u32, token, 10);
|
||||
try result.append(number);
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_input(lines: []const []const u8) !Input {
|
||||
var time = try BoundedU32.init(0);
|
||||
var distance = try BoundedU32.init(0);
|
||||
try parse_numbers(&time, lines[0][9..]);
|
||||
try parse_numbers(&distance, lines[1][9..]);
|
||||
assert(time.len == distance.len);
|
||||
return Input{ .time = time, .distance = distance };
|
||||
}
|
||||
|
||||
pub fn part1(input: *aoc.Input) !aoc.Result {
|
||||
var parsed = try parse_input(input.lines);
|
||||
|
||||
var answer: u32 = 1;
|
||||
for (0..parsed.time.len) |i| {
|
||||
const required_distance = parsed.distance.get(i);
|
||||
const max_allowed_time = parsed.time.get(i);
|
||||
|
||||
var min_time: u32 = 0;
|
||||
var max_time: u32 = 0;
|
||||
for (1..(max_allowed_time+1)) |speed_usize| {
|
||||
const speed: u32 = @intCast(speed_usize);
|
||||
const distance = speed*(max_allowed_time - speed);
|
||||
if (distance <= required_distance) continue;
|
||||
|
||||
if (max_time == 0) {
|
||||
min_time = speed;
|
||||
max_time = speed;
|
||||
} else {
|
||||
max_time = @max(max_time, speed);
|
||||
}
|
||||
}
|
||||
|
||||
const margin = max_time - min_time + 1;
|
||||
answer *= margin;
|
||||
}
|
||||
|
||||
return .{ .uint = answer };
|
||||
}
|
||||
|
||||
pub fn part2(input: *aoc.Input) !aoc.Result {
|
||||
var parsed = try parse_input(input.lines);
|
||||
|
||||
var allowed_time: u64 = 0;
|
||||
var required_distance: u64 = 0;
|
||||
for (0..parsed.time.len) |i| {
|
||||
const time = parsed.time.get(i);
|
||||
if (allowed_time > 0) {
|
||||
allowed_time *= try std.math.powi(u32, 10, std.math.log10(time)+1);
|
||||
}
|
||||
allowed_time += time;
|
||||
|
||||
const distance = parsed.distance.get(i);
|
||||
if (required_distance > 0) {
|
||||
required_distance *= try std.math.powi(u32, 10, std.math.log10(distance)+1);
|
||||
}
|
||||
required_distance += distance;
|
||||
}
|
||||
|
||||
var min_time: u64 = 0;
|
||||
var max_time: u64 = 0;
|
||||
for (1..(allowed_time+1)) |speed_usize| {
|
||||
const speed: u64 = @intCast(speed_usize);
|
||||
const distance = speed*(allowed_time - speed);
|
||||
if (distance <= required_distance) continue;
|
||||
|
||||
if (max_time == 0) {
|
||||
min_time = speed;
|
||||
max_time = speed;
|
||||
} else {
|
||||
max_time = @max(max_time, speed);
|
||||
}
|
||||
}
|
||||
|
||||
var answer = max_time - min_time + 1;
|
||||
return .{ .uint = @intCast(answer) };
|
||||
}
|
||||
|
||||
const example_input = [_][]const u8{
|
||||
"Time: 7 15 30",
|
||||
"Distance: 9 40 200"
|
||||
};
|
||||
|
||||
test "part 1 example" {
|
||||
var input = aoc.Input{ .lines = &example_input, .allocator = std.testing.allocator };
|
||||
var actual = try part1(&input);
|
||||
var expected: u32 = 288;
|
||||
try std.testing.expectEqual(expected, actual.uint);
|
||||
}
|
||||
|
||||
test "part 2 example" {
|
||||
var input = aoc.Input{ .lines = &example_input, .allocator = std.testing.allocator };
|
||||
var actual = try part2(&input);
|
||||
var expected: u32 = 71503;
|
||||
try std.testing.expectEqual(expected, actual.uint);
|
||||
}
|
@ -26,6 +26,7 @@ const Days = [_]aoc.Day{
|
||||
create_day(@import("day3.zig")),
|
||||
create_day(@import("day4.zig")),
|
||||
create_day(@import("day5.zig")),
|
||||
create_day(@import("day6.zig")),
|
||||
};
|
||||
|
||||
fn kilobytes(count: u32) u32 {
|
||||
@ -72,6 +73,7 @@ fn run(allocator: Allocator, args: *cli) !u8 {
|
||||
|
||||
var input = aoc.Input{ .allocator = allocator, .lines = lines.items };
|
||||
|
||||
var start_time = std.time.microTimestamp();
|
||||
var result: aoc.Result = undefined;
|
||||
if (args.part == 1) {
|
||||
result = try day.part1.?(&input);
|
||||
@ -80,6 +82,7 @@ fn run(allocator: Allocator, args: *cli) !u8 {
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
const end_time = std.time.microTimestamp();
|
||||
|
||||
switch (result) {
|
||||
.uint => std.debug.print("{}\n", .{result.uint}),
|
||||
@ -88,6 +91,9 @@ fn run(allocator: Allocator, args: *cli) !u8 {
|
||||
.text => std.debug.print("{s}\n", .{result.text}),
|
||||
}
|
||||
|
||||
const duration = end_time - start_time;
|
||||
std.debug.print("Time taken: {}ms ({}us)\n", .{@divTrunc(duration, std.time.us_per_ms), duration});
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -135,7 +141,7 @@ fn get_input(allocator: Allocator, args: *cli) !u8 {
|
||||
return 255;
|
||||
}
|
||||
|
||||
const body = try request.reader().readAllAlloc(allocator, kilobytes(8));
|
||||
const body = try request.reader().readAllAlloc(allocator, kilobytes(128));
|
||||
defer allocator.free(body);
|
||||
|
||||
var file = try std.fs.cwd().createFile(args.input_file, .{ });
|
||||
@ -172,4 +178,5 @@ test {
|
||||
_ = @import("day3.zig");
|
||||
_ = @import("day4.zig");
|
||||
_ = @import("day5.zig");
|
||||
_ = @import("day6.zig");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user