Finish day 9

This commit is contained in:
Kienan Stewart 2020-12-11 21:23:11 -05:00
parent b38bd5f0ac
commit ebbc0931b7
3 changed files with 1190 additions and 0 deletions

27
day9/build.zig Normal file
View File

@ -0,0 +1,27 @@
const Builder = @import("std").build.Builder;
pub fn build(b: *Builder) void {
// Standard target options allows the person running `zig build` to choose
// what target to build for. Here we do not override the defaults, which
// means any target is allowed, and the default is native. Other options
// for restricting supported target set are available.
const target = b.standardTargetOptions(.{});
// Standard release options allow the person running `zig build` to select
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
const mode = b.standardReleaseOptions();
const exe = b.addExecutable("day9", "src/main.zig");
exe.setTarget(target);
exe.setBuildMode(mode);
exe.install();
const run_cmd = exe.run();
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}

1000
day9/input Normal file

File diff suppressed because it is too large Load Diff

163
day9/src/main.zig Normal file
View File

@ -0,0 +1,163 @@
const std = @import("std");
pub fn main() anyerror!void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
var gpa = &arena.allocator;
var stream = std.ArrayList(u64).init(gpa);
var f = try std.fs.cwd().openFile("input", .{});
var contents = try f.readToEndAlloc(gpa, std.math.maxInt(u32));
var it = std.mem.tokenize(contents, "\n");
while (it.next()) |line| {
//std.log.debug("{}", .{atoi(line)});
try stream.append(atoi(line));
}
var first_not_matching = find_first_with_no_sum_property(stream.items[0..], 25);
std.log.info("First with no sum property: {} (at index {})",
.{stream.items[first_not_matching.?], first_not_matching.?});
// Part 2
// 22406676
var ranges = std.ArrayList(Range).init(gpa);
try find_contiguous_sets_matching(stream.items[0..], 22406676, &ranges);
std.log.debug("Found {} ranges summing to {}", .{ranges.items.len, 22406676});
for (ranges.items) |r| {
std.log.info("Range: {}, len {}. Sum of edge indices: {}",
.{r, r.y - r.x + 1, stream.items[r.x] + stream.items[r.y-1]});
var s : u64 = 0;
var min: u64 = std.math.maxInt(u64);
var max: u64 = 0;
for (stream.items[r.x..r.y]) |v| {
std.log.debug("{}", .{v});
s += v;
min = std.math.min(v, min);
max = std.math.max(v, max);
}
std.log.debug("Sum of items in range: {}, min: {}, max: {}; sum min+max {}",
.{s, min, max, min+max});
}
}
const Range = struct {
x : usize = 0,
y : usize = 0,
};
pub fn find_contiguous_sets_matching(stream: []u64, match: u64, ranges: *std.ArrayList(Range)) !void {
var i : usize = 0;
// start create a window from 0 ... end of list breaking when
// the sum is greater than the match value
// then go on 1 ... end of list
while (i < stream.len) : (i += 1) {
var j : usize = i+1;
while (j < stream.len) : (j += 1) {
std.log.debug("Checking range {}..{}", .{i, j});
var sum : u64 = 0;
for (stream[i..j]) |v| {
sum += v;
}
if (sum > match) {
break;
}
if (sum == match) {
try ranges.append(Range{.x = i, .y = j});
break;
}
}
}
}
/// returns the INDEX of the first non-matching
pub fn find_first_with_no_sum_property(stream: []u64, preamble: u64) ?u64 {
var i : u64 = preamble;
while (i < stream.len) : (i += 1) {
//std.log.debug("Searching for match for {} in indicess {} to {}: {}",
// .{stream[i], i-preamble, i, stream[i-preamble..i]});
if (!has_sum_property(stream[i], stream[i-preamble..i])) {
return i;
}
}
return null;
}
pub fn has_sum_property(value: u64, preceding_values: []u64) bool {
for (preceding_values) |v, k| {
for (preceding_values) |w, k2| {
if (k == k2) {
continue; // don't sum against our selves
}
//std.log.debug("[{}, {}] -> {} + {} => {} (searching for {})",
// .{k, k2, v, w, v+w, value});
if ((v+w) == value) {
return true;
}
}
}
return false;
}
test "first not having a sum of 5 preamble" {
const preamble : u64 = 5;
var stream = [_]u64 {
35,
20,
15,
25,
47,
40,
62,
55,
65,
95,
102,
117,
150,
182,
127,
219,
299,
277,
309,
576,
};
var idx_not_matching = find_first_with_no_sum_property(stream[0..], preamble);
var i = stream[idx_not_matching.?];
std.testing.expectEqual(i, 127);
}
fn atoi(a: []const u8) u64 {
var i : u64 = 0;
var mul : u64 = 1;
var start : usize = 0;
if (a[0] == '-' or a[0] == '+') {
start = 1;
if (a[0] == '-') {
//mul *= -1;
unreachable;
}
}
for(a[start..]) |v, k| {
if (! std.ascii.isDigit(v)) {
std.log.warn("Byte {x} is not a digit", .{v});
continue;
}
// 48 is '0' in ascii
std.debug.assert(v >= 48 and v < 58);
i += @as(u64, @as(u64, (v - 48)) * std.math.pow(u64, 10, @intCast(u64, a.len - k - 1 - start)));
}
//std.log.debug("0x{x} --> {}", .{a, i});
return i * mul;
}
test "atoi_regular" {
var i = atoi("1234");
std.testing.expectEqual(i, 1234);
}
test "atoi_pos" {
var i = atoi("+1234");
std.testing.expectEqual(i, 1234);
}