Finish day 9
This commit is contained in:
parent
b38bd5f0ac
commit
ebbc0931b7
|
@ -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);
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||||
|
}
|
Reference in New Issue