Skip to content

Instantly share code, notes, and snippets.

@ndbn

ndbn/14.zig Secret

Created December 15, 2023 18:34
Show Gist options
  • Save ndbn/154c3045013172eac25ee54eb8ed840a to your computer and use it in GitHub Desktop.
Save ndbn/154c3045013172eac25ee54eb8ed840a to your computer and use it in GitHub Desktop.
AoC 2024 Day 14
const std = @import("std");
const print = std.debug.print;
// const input_file_name = "inputs/14_test2.txt";
const input_file_name = "inputs/14_test.txt";
// const input_file_name = "inputs/14.txt";
const input_data = blk: {
@setEvalBranchQuota(300_000);
var result: []const []const u8 = &.{};
const input_file = @embedFile(input_file_name);
var token = std.mem.splitSequence(u8, input_file, "\r\n");
while (token.next()) |val| {
result = result ++ [1][]const u8{val};
}
break :blk result;
};
const rows = input_data.len;
const cols = input_data[0].len;
pub fn countLoadNorth(data: []const []const u8) usize {
var result: usize = 0;
for (0..cols) |col| {
var skip: usize = 0;
for (0..rows) |row| {
const c = data[row][col];
if (c == '.') skip += 1;
if (c == '#') skip = 0;
if (c == 'O') {
const new_row_num = rows - row + skip;
result += new_row_num;
}
}
}
return result;
}
pub fn countLoad(data: []const []const u8) usize {
var result: usize = 0;
for (0..cols) |col| {
for (0..rows) |row| {
const c = data[row][col];
if (c == 'O') {
const new_row_num = rows - row;
result += new_row_num;
}
}
}
return result;
}
pub fn cycleRocks(data: []const []u8) void {
// N
for (0..cols) |col| {
var skip: usize = 0;
for (0..rows) |row| {
const c = data[row][col];
if (c == '.') skip += 1;
if (c == '#') skip = 0;
if (c == 'O') {
const new_row_num = row - skip;
std.mem.swap(u8, &data[row][col], &data[new_row_num][col]);
}
}
}
// W
for (0..rows) |row| {
var skip: usize = 0;
for (0..cols) |col| {
const c = data[row][col];
if (c == '.') skip += 1;
if (c == '#') skip = 0;
if (c == 'O') {
const new_col_num = col - skip;
std.mem.swap(u8, &data[row][col], &data[row][new_col_num]);
}
}
}
// S
for (0..cols) |col| {
var skip: usize = 0;
for (0..rows) |srow| {
const row = rows - srow - 1;
const c = data[row][col];
if (c == '.') skip += 1;
if (c == '#') skip = 0;
if (c == 'O') {
const new_row_num = row + skip;
std.mem.swap(u8, &data[row][col], &data[new_row_num][col]);
}
}
}
// E
for (0..rows) |row| {
var skip: usize = 0;
for (0..cols) |ecol| {
const col = cols - ecol - 1;
const c = data[row][col];
if (c == '.') skip += 1;
if (c == '#') skip = 0;
if (c == 'O') {
const new_col_num = col + skip;
std.mem.swap(u8, &data[row][col], &data[row][new_col_num]);
}
}
}
}
fn part1() !usize {
var result: usize = 0;
result = 0;
result = countLoadNorth(input_data);
return result;
}
fn part2() !usize {
var result: usize = 0;
result = 0;
// Cycles
var data: [rows][]u8 = undefined;
for (0..rows) |r| data[r] = @constCast(input_data[r][0..]);
const CACHE_CAP = 250;
var cache = try std.BoundedArray(usize, CACHE_CAP).init(0);
for (0..cache.capacity()) |i| {
_ = i;
cycleRocks(&data);
const r = countLoad(&data);
try cache.append(r);
}
const cache_slice = cache.constSlice();
var max_cycle_len: usize = 0;
var cycle_start: usize = 0;
var last_pos: usize = 0;
loop: for (0..cache_slice.len - 1) |s| {
for (s + 1..cache_slice.len) |ss| {
const search_str = cache_slice[s..ss];
// print("SERCH s={d} ss={d} {any}\n", .{ s, ss, search_str });
if (std.mem.indexOfPos(usize, cache_slice[ss..], 0, search_str)) |pos| {
const cycle_len = ss - s;
if (cycle_len > max_cycle_len) {
max_cycle_len = cycle_len;
cycle_start = s;
last_pos = ss + pos;
// Almost hardcoded !!!!
if (max_cycle_len > 20 and std.mem.startsWith(usize, cache_slice[ss + search_str.len ..], search_str)) {
break :loop;
}
}
} else break;
}
}
const cycle = cache_slice[cycle_start .. cycle_start + max_cycle_len];
print("CYCLE cycle_start={d} max_cycle_len={d} last_pos={d}\n {any}\n", .{
cycle_start,
max_cycle_len,
last_pos,
cycle,
});
var cycles: usize = 1_000_000_000;
cycles = cycles - cycle_start;
const cycle_index = cycles % cycle.len - 1;
result = cycle[cycle_index];
return result;
}
pub fn main() !void {
var timer = try std.time.Timer.start();
const part1_result = try part1();
print("part 1 {d} {d}ms\n", .{ part1_result, timer.lap() / std.time.ns_per_ms });
const part2_result = try part2();
print("part 2 {d} {d}ms\n", .{ part2_result, timer.lap() / std.time.ns_per_ms });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment