solve day 15
This commit is contained in:
parent
31c2a661c2
commit
ab6a4d4bb9
@ -2,7 +2,6 @@ const std = @import("std");
|
||||
const aoc = @import("./aoc.zig");
|
||||
const assert = std.debug.assert;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const PointU32 = @import("./point.zig").Point(u32);
|
||||
|
||||
const Tile = enum {
|
||||
Empty,
|
||||
|
159
src/day15.zig
Normal file
159
src/day15.zig
Normal file
@ -0,0 +1,159 @@
|
||||
const std = @import("std");
|
||||
const aoc = @import("./aoc.zig");
|
||||
const assert = std.debug.assert;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const Input = struct {
|
||||
parts: std.ArrayList([]const u8),
|
||||
|
||||
fn init(allocator: Allocator) Input {
|
||||
return Input{
|
||||
.parts = std.ArrayList([]const u8).init(allocator)
|
||||
};
|
||||
}
|
||||
|
||||
fn deinit(self: Input) void {
|
||||
self.parts.deinit();
|
||||
}
|
||||
};
|
||||
|
||||
const HashMapItem = struct {
|
||||
key: []const u8,
|
||||
value: u8
|
||||
};
|
||||
|
||||
const HashMap = struct {
|
||||
boxes: [256]std.ArrayList(HashMapItem),
|
||||
|
||||
fn init(allocator: Allocator) HashMap {
|
||||
var boxes: [256]std.ArrayList(HashMapItem) = undefined;
|
||||
for (0..256) |i| {
|
||||
boxes[i] = std.ArrayList(HashMapItem).init(allocator);
|
||||
}
|
||||
|
||||
return HashMap{ .boxes = boxes };
|
||||
}
|
||||
|
||||
fn deinit(self: HashMap) void {
|
||||
for (self.boxes) |box| {
|
||||
box.deinit();
|
||||
}
|
||||
}
|
||||
|
||||
fn put(self: *HashMap, key: []const u8, value: u8) !void {
|
||||
const hash = compute_hash(key);
|
||||
var box = &self.boxes[hash];
|
||||
|
||||
for (box.items) |*item| {
|
||||
if (std.mem.eql(u8, item.key, key)) {
|
||||
item.value = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try box.append(HashMapItem{ .key = key, .value = value });
|
||||
}
|
||||
|
||||
fn remove(self: *HashMap, key: []const u8) void {
|
||||
const hash = compute_hash(key);
|
||||
var box = &self.boxes[hash];
|
||||
for (0.., box.items) |i, item| {
|
||||
if (std.mem.eql(u8, item.key, key)) {
|
||||
_ = box.orderedRemove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn debug(self: HashMap) void {
|
||||
for (0.., self.boxes) |i, box| {
|
||||
if (box.items.len == 0) continue;
|
||||
|
||||
std.debug.print("Box {}:", .{i});
|
||||
for (box.items) |item| {
|
||||
std.debug.print(" [{s} {}]", .{item.key, item.value});
|
||||
}
|
||||
std.debug.print("\n", .{});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fn parse_input(allocator: Allocator, lines: []const []const u8) !Input {
|
||||
var result = Input.init(allocator);
|
||||
errdefer result.deinit();
|
||||
|
||||
var iter = std.mem.splitScalar(u8, lines[0], ',');
|
||||
while (iter.next()) |part| {
|
||||
try result.parts.append(part);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fn compute_hash(text: []const u8) u8 {
|
||||
var current: u16 = 0;
|
||||
for (text) |symbol| {
|
||||
current += symbol;
|
||||
current *= 17;
|
||||
current %= 256;
|
||||
}
|
||||
return @intCast(current);
|
||||
}
|
||||
|
||||
pub fn part1(input: *aoc.Input) !aoc.Result {
|
||||
const parsed = try parse_input(input.allocator, input.lines);
|
||||
defer parsed.deinit();
|
||||
|
||||
var result: u64 = 0;
|
||||
for (parsed.parts.items) |item| {
|
||||
result += compute_hash(item);
|
||||
}
|
||||
|
||||
return .{ .uint = result };
|
||||
}
|
||||
|
||||
pub fn part2(input: *aoc.Input) !aoc.Result {
|
||||
const allocator = input.allocator;
|
||||
const parsed = try parse_input(input.allocator, input.lines);
|
||||
defer parsed.deinit();
|
||||
|
||||
var hash_map = HashMap.init(allocator);
|
||||
defer hash_map.deinit();
|
||||
|
||||
for (parsed.parts.items) |inst| {
|
||||
if (inst[inst.len - 1] == '-') {
|
||||
const key = inst[0..(inst.len-1)];
|
||||
hash_map.remove(key);
|
||||
} else {
|
||||
const equal_pos = std.mem.indexOfScalar(u8, inst, '=') orelse return error.InvalidInstruction;
|
||||
const key = inst[0..equal_pos];
|
||||
const value = inst[(equal_pos+1)] - '0';
|
||||
try hash_map.put(key, value);
|
||||
}
|
||||
|
||||
// std.debug.print("After \"{s}\":\n", .{inst});
|
||||
// hash_map.debug();
|
||||
// std.debug.print("\n", .{});
|
||||
}
|
||||
|
||||
var result: u64 = 0;
|
||||
for (1.., hash_map.boxes) |box_idx, box| {
|
||||
for (1.., box.items) |item_idx, item| {
|
||||
result += box_idx * item_idx * item.value;
|
||||
}
|
||||
}
|
||||
|
||||
return .{ .uint = result };
|
||||
}
|
||||
|
||||
const example_input = [_][]const u8{
|
||||
"rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7"
|
||||
};
|
||||
|
||||
test "part 1 example" {
|
||||
try aoc.expectAnswerUInt(part1, 1320, &example_input);
|
||||
}
|
||||
|
||||
test "part 2 example" {
|
||||
try aoc.expectAnswerUInt(part2, 145, &example_input);
|
||||
}
|
@ -35,6 +35,7 @@ const Days = [_]aoc.Day{
|
||||
create_day(@import("./day12.zig")),
|
||||
create_day(@import("./day13.zig")),
|
||||
create_day(@import("./day14.zig")),
|
||||
create_day(@import("./day15.zig")),
|
||||
};
|
||||
|
||||
fn kilobytes(count: u32) u32 {
|
||||
@ -73,10 +74,8 @@ fn run(allocator: Allocator, args: *cli) !u8 {
|
||||
lines.deinit();
|
||||
}
|
||||
|
||||
var line_buf: [1024]u8 = undefined;
|
||||
while (try reader.readUntilDelimiterOrEof(&line_buf, '\n')) |line| {
|
||||
var trimmed_line = std.mem.trimRight(u8, line, &.{'\r'});
|
||||
try lines.append(try allocator.dupe(u8, trimmed_line));
|
||||
while (try reader.readUntilDelimiterOrEofAlloc(allocator, '\n', kilobytes(32))) |line| {
|
||||
try lines.append(std.mem.trimRight(u8, line, &.{'\r'}));
|
||||
}
|
||||
|
||||
var input = aoc.Input{ .allocator = allocator, .lines = lines.items };
|
||||
@ -193,4 +192,5 @@ test {
|
||||
_ = @import("./day12.zig");
|
||||
_ = @import("./day13.zig");
|
||||
_ = @import("./day14.zig");
|
||||
_ = @import("./day15.zig");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user