From 1df72d9e72c314b3cb19782f833cb15e8a802fa2 Mon Sep 17 00:00:00 2001 From: John Costa Date: Tue, 5 Dec 2023 21:09:13 +0000 Subject: [PATCH] Day 5; --- AdventOfCode2023/.gitignore | 1 + AdventOfCode2023/src/day5/day5.zig | 195 +++++++++++++++++++++++++++++ AdventOfCode2023/src/main.zig | 7 +- 3 files changed, 200 insertions(+), 3 deletions(-) create mode 100644 AdventOfCode2023/src/day5/day5.zig diff --git a/AdventOfCode2023/.gitignore b/AdventOfCode2023/.gitignore index 4c82b07..ddc746a 100644 --- a/AdventOfCode2023/.gitignore +++ b/AdventOfCode2023/.gitignore @@ -1,2 +1,3 @@ zig-cache zig-out +input.txt diff --git a/AdventOfCode2023/src/day5/day5.zig b/AdventOfCode2023/src/day5/day5.zig new file mode 100644 index 0000000..ec4cf74 --- /dev/null +++ b/AdventOfCode2023/src/day5/day5.zig @@ -0,0 +1,195 @@ +const std = @import("std"); +const print = std.debug.print; +const ArrayList = std.ArrayList; +const expect = std.testing.expect; + +const Range = struct { + sourceStart: usize, + destinationStart: usize, + rangeLength: usize, + + pub fn fits(self: Range, input: usize) bool { + return input >= self.sourceStart and input < self.sourceStart + self.rangeLength; + } + + pub fn compute(self: Range, input: usize) usize { + if (self.fits(input)) { + var distanceFromStart = input - self.sourceStart; + return self.destinationStart + distanceFromStart; + } + return input; + } + + pub fn prettyPrint(self: Range) void { + print("Start: {} | Destination Start: {} | Length: {}\n", .{ self.sourceStart, self.destinationStart, self.rangeLength }); + } +}; + +test "Test range" { + var range = Range{ .sourceStart = 50, .destinationStart = 98, .rangeLength = 2 }; + try expect(range.compute(49) == 49); + try expect(range.compute(50) == 98); + try expect(range.compute(51) == 99); + try expect(range.compute(52) == 52); + + try expect(range.fits(51)); + + var otherRange = Range{ .sourceStart = 18, .destinationStart = 25, .rangeLength = 70 }; + try expect(otherRange.fits(40)); +} + +fn getSeeds(input: [][]const u8) ![]usize { + var allocator = std.heap.page_allocator; + + var seedsLine = input[0][7..]; + var seedNumbers = std.mem.tokenizeSequence(u8, seedsLine, " "); + var seedsList = ArrayList(usize).init(allocator); + defer seedsList.deinit(); + + while (seedNumbers.next()) |num| { + try seedsList.append(try std.fmt.parseInt(usize, num, 10)); + } + + var seeds = try seedsList.toOwnedSlice(); + return seeds; +} + +fn parseRange(line: []const u8, reverse: bool) !Range { + var seedNumbers = std.mem.tokenizeSequence(u8, line, " "); + var destinationStart = try std.fmt.parseInt(usize, seedNumbers.next().?, 10); + var sourceStart = try std.fmt.parseInt(usize, seedNumbers.next().?, 10); + var rangeLength = try std.fmt.parseInt(usize, seedNumbers.next().?, 10); + if (reverse) { + return Range{ .sourceStart = destinationStart, .destinationStart = sourceStart, .rangeLength = rangeLength }; + } + return Range{ .sourceStart = sourceStart, .destinationStart = destinationStart, .rangeLength = rangeLength }; +} + +fn traverseMaps(maps: [7]*ArrayList(Range), input: usize) usize { + var mappedValue = input; + for (maps) |map| { + // print("Mapped value: {}\n", .{mappedValue}); + for (map.*.items) |range| { + if (range.fits(mappedValue)) { + mappedValue = range.compute(mappedValue); + break; + } + } + } + return mappedValue; +} + +pub fn solve(input: [][]const u8) !void { + var allocator = std.heap.page_allocator; + + var seeds = try getSeeds(input); + + var seedToSoil = ArrayList(Range).init(allocator); + var soilToFert = ArrayList(Range).init(allocator); + var fertToWater = ArrayList(Range).init(allocator); + var waterToLight = ArrayList(Range).init(allocator); + var lightToTemp = ArrayList(Range).init(allocator); + var tempToHumid = ArrayList(Range).init(allocator); + var humidToLocation = ArrayList(Range).init(allocator); + + var locationToHumid = ArrayList(Range).init(allocator); + var humidToTemp = ArrayList(Range).init(allocator); + var tempToLight = ArrayList(Range).init(allocator); + var lightToWater = ArrayList(Range).init(allocator); + var waterToFert = ArrayList(Range).init(allocator); + var fertToSoil = ArrayList(Range).init(allocator); + var soilToSeed = ArrayList(Range).init(allocator); + + var maps = [7]*ArrayList(Range){ &seedToSoil, &soilToFert, &fertToWater, &waterToLight, &lightToTemp, &tempToHumid, &humidToLocation }; + + var reverseMaps = [7]*ArrayList(Range){ &locationToHumid, &humidToTemp, &tempToLight, &lightToWater, &waterToFert, &fertToSoil, &soilToSeed }; + + defer seedToSoil.deinit(); + defer soilToFert.deinit(); + defer fertToWater.deinit(); + defer waterToLight.deinit(); + defer lightToTemp.deinit(); + defer tempToHumid.deinit(); + defer humidToLocation.deinit(); + + defer locationToHumid.deinit(); + defer humidToTemp.deinit(); + defer tempToLight.deinit(); + defer lightToWater.deinit(); + defer waterToFert.deinit(); + defer fertToSoil.deinit(); + defer soilToSeed.deinit(); + + var index: usize = 2; + var stages: usize = 0; + + while (index < input.len) { + var line = input[index]; + + if (line[0] < '0' or line[0] > '9') { + stages += 1; + index += 1; + continue; + } + + var range = try parseRange(line, false); + var reverseRange = try parseRange(line, true); + + if (stages == 0) { + try seedToSoil.append(range); + try soilToSeed.append(reverseRange); + } else if (stages == 1) { + try soilToFert.append(range); + try fertToSoil.append(reverseRange); + } else if (stages == 2) { + try fertToWater.append(range); + try waterToFert.append(reverseRange); + } else if (stages == 3) { + try waterToLight.append(range); + try lightToWater.append(reverseRange); + } else if (stages == 4) { + try lightToTemp.append(range); + try tempToLight.append(reverseRange); + } else if (stages == 5) { + try tempToHumid.append(range); + try humidToTemp.append(reverseRange); + } else if (stages == 6) { + try humidToLocation.append(range); + try locationToHumid.append(reverseRange); + } + + index += 1; + } + + var lowest: usize = 999999999999; + var lowestSeed: usize = 0; + + for (seeds) |seed| { + var location = traverseMaps(maps, seed); + if (location < lowest) { + lowest = location; + lowestSeed = seed; + } + } + + print("Part 1: {} | Seed: {}\n", .{ lowest, lowestSeed }); + + var part2: usize = 1; + outerLoop: while (true) { + var seed = traverseMaps(reverseMaps, part2); + var i: usize = 0; + while (i <= seeds.len / 2) { + if (seeds[i] <= seed and seeds[i] + seeds[i + 1] > seed) { + break :outerLoop; + } + i += 2; + } + + if (part2 % 10_000_000 == 0) { + print("Counting: {}\n", .{part2}); + } + + part2 += 1; + } + print("Part 2: {}\n", .{part2}); +} diff --git a/AdventOfCode2023/src/main.zig b/AdventOfCode2023/src/main.zig index 54e5e31..aec1c5b 100644 --- a/AdventOfCode2023/src/main.zig +++ b/AdventOfCode2023/src/main.zig @@ -2,13 +2,14 @@ const std = @import("std"); // const day1 = @import("./day1/day1.zig"); // const day2 = @import("./day2/day2.zig"); // const day3 = @import("./day3/day3.zig"); -const day4 = @import("./day4/day4.zig"); +// const day4 = @import("./day4/day4.zig"); +const day5 = @import("./day5/day5.zig"); const utils = @import("utils.zig"); pub fn main() !void { const allocator = std.heap.page_allocator; - var input = try utils.getInput("./src/day4/input.txt", allocator); + var input = try utils.getInput("./src/day5/input.txt", allocator); defer allocator.free(input); - try day4.solve(input); + try day5.solve(input); }