You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
3.3 KiB
Zig

const std = @import("std");
const Lens = struct { label: []const u8, focalLength: u8 };
pub fn main() !void {
var content = @embedFile("data.txt");
var words = std.mem.split(u8, content, ",");
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
var boxes = std.AutoHashMap(u32, std.ArrayList(Lens)).init(allocator);
defer boxes.deinit();
var part1: u32 = 0;
while (words.next()) |w| {
// stupid last char thing
const word = if (w[w.len - 1] == 10) w[0 .. w.len - 2] else w;
// Part 1
part1 += hash(word);
// Part 2
const dash = std.mem.indexOf(u8, word, "-");
const equals = std.mem.indexOf(u8, word, "=");
const idx = dash orelse equals orelse unreachable;
const label = word[0..idx];
const box = hash(label);
std.debug.print("\nAfter \"{s}\":\n", .{word});
if (dash != null) {
// if dash, find the box
if (boxes.getPtr(box)) |list| {
// get the list, and find a lens with this label in it
var indexToRemove: ?usize = null;
for (list.items, 0..) |l, i| {
if (std.mem.eql(u8, l.label, label)) {
indexToRemove = i;
}
}
// if it's there, remove it
if (indexToRemove) |i| {
_ = list.orderedRemove(i);
}
}
} else {
// if equals, parse out parts, put it in the box
const focalLength = try std.fmt.parseInt(u8, word[idx + 1 ..], 10);
const lens = Lens{ .focalLength = focalLength, .label = label };
// does this list exist? use it. otherwise make a new one
var list = boxes.get(box) orelse std.ArrayList(Lens).init(allocator);
// find if this lens is already in the list
var dupIdx: ?usize = null;
for (list.items, 0..) |l, i| {
if (std.mem.eql(u8, l.label, label)) {
dupIdx = i;
}
}
// if it is, replace it with the new lens
if (dupIdx) |i| {
try list.replaceRange(i, 1, &[_]Lens{lens});
} else {
try list.append(lens);
}
try boxes.put(box, list);
}
printBoxes(boxes);
}
std.debug.print("Part 1: {d}\n", .{part1});
var part2: usize = 0;
var it = boxes.iterator();
while (it.next()) |box| {
const boxNumber = box.key_ptr.*;
for (box.value_ptr.items, 0..) |lens, slotNumber| {
part2 += (boxNumber + 1) * (slotNumber + 1) * lens.focalLength;
}
}
std.debug.print("Part 2: {d}\n", .{part2});
}
fn hash(word: []const u8) u32 {
var sum: u32 = 0;
for (word) |c| {
if (c == 10) {
break;
}
sum += c;
sum *= 17;
sum = sum % 256;
}
return sum;
}
fn printBoxes(boxes: std.AutoHashMap(u32, std.ArrayList(Lens))) void {
var it = boxes.iterator();
while (it.next()) |list| {
std.debug.print("Box {d}: ", .{list.key_ptr.*});
for (list.value_ptr.items) |lens| {
std.debug.print("[{s} {d}] ", .{ lens.label, lens.focalLength });
}
std.debug.print("\n", .{});
}
}