2024 Day 22 Part 2
This commit is contained in:
parent
e6a34fa600
commit
4bf490dfa3
1 changed files with 78 additions and 6 deletions
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue