Watch
1
0
Fork
You've already forked advent-of-code
0

2024 Day 22 Part 2

This commit is contained in:
Jeremy Kaplan 2024-12-25 00:58:21 -08:00
commit 4bf490dfa3

View file

@ -27,24 +27,96 @@ pub fn main() !void {
var bw = std.io.bufferedWriter(std.io.getStdOut().writer()); var bw = std.io.bufferedWriter(std.io.getStdOut().writer());
const stdout = bw.writer(); const stdout = bw.writer();
try stdout.print("{}\n", .{part1(seeds.items)}); try stdout.print("{}\n{}\n", try solve(allocator, seeds.items));
try bw.flush(); try bw.flush();
} }
fn part1(seeds: []u64) u64 { fn solve(allocator: Allocator, seeds: []u64) !struct { u64, u64 } {
var totals = Map([4]i64, u64).init(allocator);
defer totals.deinit();
var sum: u64 = 0; var sum: u64 = 0;
for (seeds) |seed| { for (seeds) |seed| {
sum += simulate(seed, 2000); var profit = Map([4]i64, u64).init(allocator);
defer profit.deinit();
sum += try populate(seed, 2000, &profit);
var it = profit.iterator();
while (it.next()) |entry| {
const changes, const bananas = .{ entry.key_ptr.*, entry.value_ptr.* };
const total = try totals.getOrPutValue(changes, 0);
total.value_ptr.* += bananas;
}
} }
return sum;
var best: u64 = 0;
var it = totals.valueIterator();
while (it.next()) |p| {
best = @max(best, p.*);
}
return .{ sum, best };
} }
fn simulate(seed: u64, steps: usize) u64 { fn populate(seed: u64, steps: usize, profit: *Map([4]i64, u64)) !u64 {
var n: u64 = seed; var n: u64 = seed;
for (0..steps) |_| { var prices = [_]u64{0} ** 4;
// Pre-fill the first few updates, since those don't have enough changes yet.
for (0..3) |i| {
const price = n % 10;
prices[i] = price;
n = ((n * 64) ^ n) % 16777216; n = ((n * 64) ^ n) % 16777216;
n = ((n / 32) ^ n) % 16777216; n = ((n / 32) ^ n) % 16777216;
n = ((n * 2048) ^ n) % 16777216; n = ((n * 2048) ^ n) % 16777216;
} }
var changes = [_]i64{0} ** 4;
for (1..4) |i| {
const next: i64 = @intCast(prices[i]);
const prev: i64 = @intCast(prices[i - 1]);
changes[i] = next - prev;
}
// This is the first time we have a usable change sequence.
_ = try profit.getOrPutValue(changes, prices[3]);
for (3..steps) |_| {
n = ((n * 64) ^ n) % 16777216;
n = ((n / 32) ^ n) % 16777216;
n = ((n * 2048) ^ n) % 16777216;
const price = n % 10;
std.mem.copyForwards(u64, &prices, prices[1..]);
prices[3] = price;
std.mem.copyForwards(i64, &changes, changes[1..]);
{
const a: i64 = @intCast(prices[3]);
const b: i64 = @intCast(prices[2]);
changes[3] = a - b;
}
_ = try profit.getOrPutValue(changes, prices[3]);
}
// Everything but the update, because we *can* still sell here.
{
const price = n % 10;
std.mem.copyForwards(u64, &prices, prices[1..]);
prices[3] = price;
std.mem.copyForwards(i64, &changes, changes[1..]);
{
const a: i64 = @intCast(prices[3]);
const b: i64 = @intCast(prices[2]);
changes[3] = a - b;
}
_ = try profit.getOrPutValue(changes, prices[3]);
}
return n; return n;
} }