const std = @import("std");
const ArrayList = std.ArrayList;
pub fn solve_part1(allocator: std.mem.Allocator, file: []const u8) !void {
var inputs = try std.fs.cwd().openFile(file, .{});
var buffered_reader = std.io.bufferedReader(inputs.reader());
var in_stream = buffered_reader.reader();
var grid: [][100]u8 = try allocator.alloc([100]u8, 100);
@memset(grid, [_]u8{0} ** 100);
var buffer: [200]u8 = undefined;
var history = ArrayList([][100]u8).init(allocator);
var rows: u32 = 0;
var columns: u32 = 0;
while (try in_stream.readUntilDelimiterOrEof(&buffer, '\n')) |line| {
columns = @intCast(line.len);
@memcpy(grid[rows][0..columns], line);
rows += 1;
}
var total_cycles: u32 = 1000000000;
var cycle_length: u32 = 0;
var cycle_start: u32 = 0;
var d: u32 = 0;
_ = d;
tilt(.NORTH, grid, rows, columns);
var part1_result = calc(grid, rows);
tilt(.WEST, grid, rows, columns);
tilt(.SOUTH, grid, rows, columns);
tilt(.EAST, grid, rows, columns);
var grid_new: [][100]u8 = try allocator.alloc([100]u8, 100);
@memcpy(grid_new, grid);
try history.append(grid_new);
outer: for (1..total_cycles) |i| {
tilt(.NORTH, grid, rows, columns);
tilt(.WEST, grid, rows, columns);
tilt(.SOUTH, grid, rows, columns);
tilt(.EAST, grid, rows, columns);
grid_new = try allocator.alloc([100]u8, 100);
@memcpy(grid_new, grid);
try history.append(grid_new);
std.log.info("{d}", .{calc(history.items[i], rows)});
for (history.items, 0..) |grid_other, grid_i| {
if (grid_i + 1 == history.items.len) {
break;
}
if (equals(grid_other, grid, rows, columns)) {
cycle_length = @intCast(i - (grid_i));
cycle_start = @intCast(grid_i + 1);
break :outer;
}
}
}
std.log.info("Start: {d}", .{cycle_start});
std.log.info("Length: {d}", .{cycle_length});
if (total_cycles == 0 or cycle_start == 0 or cycle_length == 0) {
std.log.info("Failed to find cycle", .{});
std.os.exit(1);
}
var last_grid_i: usize = cycle_start + (total_cycles - cycle_start) % cycle_length;
var last_grid = history.items[last_grid_i - 1];
std.log.info("Part 1: {d}", .{part1_result});
var part2_result: u64 = calc(last_grid, rows);
std.log.info("Part 2: {d}", .{part2_result});
}
fn equals(grid_1: [][100]u8, grid_2: [][100]u8, rows: u32, columns: u32) bool {
for (0..rows) |r| {
if (!std.mem.eql(u8, grid_1[r][0..columns], grid_2[r][0..columns])) {
return false;
}
}
return true;
}
fn calc(grid: [][100]u8, rows: u32) u64 {
var result: u64 = 0;
for (0..grid.len) |i| {
for (0..grid[i].len) |j| {
if (grid[i][j] == 'O') {
result += rows - i;
}
}
}
return result;
}
const TilDirection = enum {
NORTH,
EAST,
SOUTH,
WEST,
};
const Direction = struct {
x: i32 = 0,
y: i32 = 0,
};
fn tilt(tilt_direction: TilDirection, grid: [][100]u8, rows: u32, columns: u32) void {
switch (tilt_direction) {
.NORTH => tilt_north(grid, rows, columns),
.SOUTH => tilt_south(grid, rows, columns),
.WEST => tilt_west(grid, rows, columns),
.EAST => tilt_east(grid, rows, columns),
}
}
fn tilt_south(grid: [][100]u8, rows: u32, columns: u32) void {
for (1..rows) |r| {
var row = rows - r - 1;
for (0..columns) |column| {
if (grid[row][column] == 'O') {
var t = row;
while (t < rows - 1) : (t += 1) {
if (grid[t + 1][column] == '.') {
grid[t + 1][column] = 'O';
grid[t][column] = '.';
} else {
break;
}
}
}
}
}
}
fn tilt_east(grid: [][100]u8, rows: u32, columns: u32) void {
for (1..columns) |c| {
var column = columns - c - 1;
for (0..rows) |row| {
if (grid[row][column] == 'O') {
var t = column;
while (t < rows - 1) : (t += 1) {
if (grid[row][t + 1] == '.') {
grid[row][t + 1] = 'O';
grid[row][t] = '.';
} else {
break;
}
}
}
}
}
}
fn tilt_north(grid: [][100]u8, rows: u32, columns: u32) void {
for (1..rows) |row| {
for (0..columns) |column| {
if (grid[row][column] == 'O') {
var t = row;
while (t > 0) : (t -= 1) {
if (grid[t - 1][column] == '.') {
grid[t - 1][column] = 'O';
grid[t][column] = '.';
} else {
break;
}
}
}
}
}
}
fn tilt_west(grid: [][100]u8, rows: u32, columns: u32) void {
for (1..columns) |column| {
for (0..rows) |row| {
if (grid[row][column] == 'O') {
var t = column;
while (t > 0) : (t -= 1) {
if (grid[row][t - 1] == '.') {
grid[row][t - 1] = 'O';
grid[row][t] = '.';
} else {
break;
}
}
}
}
}
}