Day 1: Historian Hysteria
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://blocks.programming.dev/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/22323136
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
Zig
const std = @import("std"); const List = std.ArrayList; const Map = std.AutoHashMap; const splitSeq = std.mem.splitSequence; const splitScalar = std.mem.splitScalar; const parseInt = std.fmt.parseInt; const print = std.debug.print; const sort = std.sort.block; var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const alloc = gpa.allocator(); const Answer = struct { distance: u32, similarity: u32, }; fn lessThan(_: void, lhs: []const u8, rhs: []const u8) bool { return std.mem.lessThan(u8, lhs, rhs); } pub fn solve(input: []const u8) !Answer { var rows = splitScalar(u8, input, '\n'); var left_list = List([]const u8).init(alloc); defer left_list.deinit(); var right_list = List([]const u8).init(alloc); defer right_list.deinit(); // PART 1 // split the rows into two lists while (rows.next()) |row| { var sides = splitSeq(u8, row, " "); try left_list.append(sides.next() orelse break); try right_list.append(sides.next() orelse break); } _ = left_list.pop(); // last null // sort both lists sort([]const u8, left_list.items, {}, lessThan); sort([]const u8, right_list.items, {}, lessThan); var distance: u32 = 0; for (left_list.items, right_list.items) |left, right| { distance += @abs(try parseInt(i32, left, 10) - try parseInt(i32, right, 10)); } // PART 2 var right_scores = Map(i32, u32).init(alloc); defer right_scores.deinit(); // count number of item appearances in the right list for (right_list.items) |item| { const value = try parseInt(i32, item, 10); const result = try right_scores.getOrPut(value); if (!result.found_existing) { result.value_ptr.* = 1; } else { result.value_ptr.* += 1; } } // sum up similarity between items in left list and right list scores var similarity: u32 = 0; for (left_list.items) |item| { const value = try parseInt(i32, item, 10); const result = right_scores.get(value) orelse 0; similarity += @as(u32, @intCast(value)) * result; } return Answer{ .distance = distance, .similarity = similarity }; } pub fn main() !void { const answer = try solve(@embedFile("input.txt")); print("Part 1: {d}\n", .{answer.distance}); print("Part 2: {d}\n", .{answer.similarity}); } test "test input" { const answer = try solve(@embedFile("test.txt")); try std.testing.expectEqual(answer.distance, 11); try std.testing.expectEqual(answer.similarity, 31); }