a few days

This commit is contained in:
2023-12-25 01:06:07 +00:00
parent f399c692b2
commit 254588ad6f
4 changed files with 386 additions and 4 deletions

View File

@ -5,7 +5,7 @@ const ROCK = '#';
const START = 'S';
const GARDEN = '.';
const STEPS = 1;
const PART2_STEPS = 6;
const PART2_STEPS = 50;
fn printGrid(grid: [][]u8) void {
for (grid) |row| {
@ -154,6 +154,7 @@ pub fn solve(input: [][]const u8) !void {
var eastCoordY = y(east) % input.len;
if (grid[northCoordY][northCoordX] != ROCK) {
print("{} - {},{}\n", .{ north, northCoordX, northCoordY });
try newCurrentSteps.put(north, true);
}
if (grid[southCoordY][southCoordX] != ROCK) {

View File

@ -0,0 +1,268 @@
const std = @import("std");
const print = std.debug.print;
const expect = std.testing.expect;
const WALL = '#';
pub fn Queue(comptime Child: type) type {
return struct {
const This = @This();
const Node = struct {
data: Child,
next: ?*Node,
};
gpa: std.mem.Allocator,
start: ?*Node,
end: ?*Node,
pub fn init(gpa: std.mem.Allocator) This {
return This{
.gpa = gpa,
.start = null,
.end = null,
};
}
pub fn enqueue(this: *This, value: Child) !void {
const node = try this.gpa.create(Node);
node.* = .{ .data = value, .next = null };
if (this.end) |end| end.next = node //
else this.start = node;
this.end = node;
}
pub fn dequeue(this: *This) ?Child {
const start = this.start orelse return null;
defer this.gpa.destroy(start);
if (start.next) |next|
this.start = next
else {
this.start = null;
this.end = null;
}
return start.data;
}
};
}
test "Hash maps as refs" {
var allocator = std.heap.page_allocator;
var q = Queue(*std.AutoHashMap(u128, bool)).init(allocator);
var m = std.AutoHashMap(u128, bool).init(allocator);
try m.put(0, true);
try m.put(1, true);
try expect(m.count() == 2);
try q.enqueue(&m);
var mPointer: *std.AutoHashMap(u128, bool) = q.dequeue().?;
try expect(mPointer.*.count() == 2);
}
fn coord(myX: usize, myY: usize) u128 {
return @as(u128, myX) << 64 | @as(u128, myY);
}
fn x(c: u128) usize {
return @truncate(c >> 64);
}
fn y(c: u128) usize {
return @truncate(c);
}
fn linear_search(arr: []u128, search: u128) bool {
for (arr) |i| {
if (i == search) {
return true;
}
}
return false;
}
fn short_copy(longerArr: []u128, shorterArr: []u128) void {
for (0..shorterArr.len) |i| {
longerArr[i] = shorterArr[i];
}
}
fn isStep(s: u8, want: u8) bool {
if (s == '.') {
return true;
}
return want == s;
}
// const Edge = struct {
// weight: usize,
// node: *Node,
// };
//
// const Node = struct {
// edges: []?Edge,
// };
fn bfs(grid: [][]const u8, goal: u128, explored: *std.AutoHashMap(u128, bool), root: u128, allocator: std.mem.Allocator, part2: bool) !usize {
var q = Queue(u128).init(allocator);
var qLength = Queue(usize).init(allocator);
var qPaths = Queue([]u128).init(allocator);
try explored.*.put(root, true);
try q.enqueue(root);
try qLength.enqueue(0);
var myPaths = try allocator.alloc(u128, 2);
var keyIter = explored.keyIterator();
var index: usize = 0;
while (keyIter.next()) |key| {
myPaths[index] = key.*;
index += 1;
}
try qPaths.enqueue(myPaths);
var part1: usize = 0;
while (q.dequeue()) |c| {
var child: u128 = c;
var size: usize = qLength.dequeue().?;
var paths: []u128 = qPaths.dequeue().?;
if (child == goal) {
// don't return, because we need all routes.
print("Size: {}\n", .{size + 1});
part1 = size + 1;
continue;
}
var up = child - 1;
var upX = x(up);
var upY = y(up);
var down = child + 1;
var downX = x(down);
var downY = y(down);
var right = child + (@as(u128, 1) << 64);
var rightX = x(right);
var rightY = y(right);
var left = child - (@as(u128, 1) << 64);
var leftX = x(left);
var leftY = y(left);
var lastStep = paths[paths.len - 1];
var lastStepX = x(lastStep);
var lastStepY = y(lastStep);
var l = grid[lastStepY][lastStepX];
if (part2) {
l = '.';
}
if (!linear_search(paths, up) and grid[upY][upX] != WALL and isStep(l, '^')) {
var pathsCopy = try allocator.alloc(u128, paths.len + 1);
short_copy(pathsCopy, paths);
pathsCopy[pathsCopy.len - 1] = up;
try q.enqueue(up);
try qLength.enqueue(size + 1);
try qPaths.enqueue(pathsCopy);
}
if (!linear_search(paths, down) and grid[downY][downX] != WALL and isStep(l, 'v')) {
var pathsCopy = try allocator.alloc(u128, paths.len + 1);
short_copy(pathsCopy, paths);
pathsCopy[pathsCopy.len - 1] = down;
try q.enqueue(down);
try qLength.enqueue(size + 1);
try qPaths.enqueue(pathsCopy);
}
if (!linear_search(paths, right) and grid[rightY][rightX] != WALL and isStep(l, '>')) {
var pathsCopy = try allocator.alloc(u128, paths.len + 1);
short_copy(pathsCopy, paths);
pathsCopy[pathsCopy.len - 1] = right;
try q.enqueue(right);
try qLength.enqueue(size + 1);
try qPaths.enqueue(pathsCopy);
}
if (!linear_search(paths, left) and grid[leftY][leftX] != WALL and isStep(l, '<')) {
var pathsCopy = try allocator.alloc(u128, paths.len + 1);
short_copy(pathsCopy, paths);
pathsCopy[pathsCopy.len - 1] = left;
try q.enqueue(left);
try qLength.enqueue(size + 1);
try qPaths.enqueue(pathsCopy);
}
allocator.free(paths);
}
return part1;
}
fn dps(grid: [][]const u8, root: u128, goal: u128, explored: []u128, size: usize, allocator: std.mem.Allocator) !usize {
if (root == goal) {
print("Size: {}\n", .{size});
return size;
}
var up = root - 1;
var down = root + 1;
var right = root + (@as(u128, 1) << 64);
var left = root - (@as(u128, 1) << 64);
var neighbours = [_]u128{ up, down, right, left };
var highest: usize = 0;
for (neighbours) |n| {
var nx = x(n);
var ny = y(n);
if (!linear_search(explored, n) and grid[ny][nx] != WALL) {
var copyExplored = try allocator.alloc(u128, explored.len + 1);
short_copy(copyExplored, explored);
copyExplored[copyExplored.len - 1] = n;
var h = try dps(grid, n, goal, copyExplored, size + 1, allocator);
if (h > highest) {
highest = h;
}
allocator.free(copyExplored);
}
}
return highest;
}
pub fn solve(input: [][]const u8) !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
var allocator = gpa.allocator();
var explored = std.AutoHashMap(u128, bool).init(allocator);
var start = coord(1, 0);
try explored.put(start, true);
var fakeStart = coord(1, 1);
var goal = coord(input[0].len - 2, input.len - 1);
_ = goal;
// var part1 = try bfs(input, goal, &explored, fakeStart, allocator, false);
// print("Part 1: {}\n", .{part1});
// var part2 = try bfs(input, goal, &explored, fakeStart, allocator, true);
// print("Part 2: {}\n", .{part2});
var exp = try allocator.alloc(u128, 1);
exp[0] = start;
// var exampleLastInter = coord(19, 20);
var exampleLastInter = coord(133, 137);
var part2 = try dps(input, fakeStart, exampleLastInter, exp, 0, allocator);
print("Part 2: {}\n", .{part2 + 21});
}

View File

@ -0,0 +1,111 @@
const std = @import("std");
const print = std.debug.print;
const expect = std.testing.expect;
const Line = struct {
x: i128,
y: i128,
z: i128,
dx: i128,
dy: i128,
dz: i128,
pub fn isNegative(self: Line) bool {
if (self.dx < 0 and self.dy < 0) {
return false;
}
return self.dx < 0 or self.dy < 0;
}
pub fn time(self: Line, point: f128) f128 {
var fx: f128 = @floatFromInt(self.x);
var fdx: f128 = @floatFromInt(self.dx);
return (point - fx) / fdx;
}
};
// const LOWER = 7;
// const HIGHER = 27;
const LOWER = 200000000000000;
const HIGHER = 400000000000000;
const Solution = struct {
x: f128,
y: f128,
z: f128,
};
test "Floating points" {
var a: i128 = 5.123;
var b: i128 = 5.123;
try expect(a - b == 0);
}
fn asFloat(a: i128) f128 {
return @as(f128, @floatFromInt(a));
}
fn linear_algebra_2d(line1: Line, line2: Line) ?Solution {
var m1: f128 = asFloat(line1.dy) / asFloat(line1.dx);
var A: f128 = asFloat(line1.y) - m1 * asFloat(line1.x);
var m2: f128 = asFloat(line2.dy) / asFloat(line2.dx);
var B: f128 = asFloat(line2.y) - m2 * asFloat(line2.x);
if (m1 == m2) {
return null;
}
var deltaM = m2 - m1;
var x = A / deltaM - B / deltaM;
var y = (A * m2) / deltaM - (B * m1) / deltaM;
return Solution{ .x = x, .y = y, .z = 0 };
}
pub fn solve(input: [][]const u8) !void {
var allocator = std.heap.page_allocator;
var lines = try allocator.alloc(Line, input.len);
for (input, 0..) |line, i| {
var tokenizer = std.mem.tokenizeAny(u8, line, " ,@");
var x = try std.fmt.parseInt(i128, tokenizer.next().?, 10);
var y = try std.fmt.parseInt(i128, tokenizer.next().?, 10);
var z = try std.fmt.parseInt(i128, tokenizer.next().?, 10);
var dx = try std.fmt.parseInt(i128, tokenizer.next().?, 10);
var dy = try std.fmt.parseInt(i128, tokenizer.next().?, 10);
var dz = try std.fmt.parseInt(i128, tokenizer.next().?, 10);
var l = Line{ .x = x, .y = y, .z = z, .dx = dx, .dy = dy, .dz = dz };
lines[i] = l;
}
var part1: usize = 0;
for (0..lines.len) |i| {
for (i + 1..lines.len) |j| {
var line1 = lines[i];
var line2 = lines[j];
var sol = linear_algebra_2d(line1, line2);
if (sol) |s| {
if (s.x > LOWER and s.y > LOWER and s.x < HIGHER and s.y < HIGHER) {
if (line1.time(s.x) < 0 or line2.time(s.x) < 0) {
continue;
}
part1 += 1;
}
continue;
}
}
}
print("Part 1: {}\n", .{part1});
}

View File

@ -14,13 +14,15 @@ const std = @import("std");
// const day16 = @import("./day16/day16.zig");
// const day18 = @import("./day18/day18.zig");
// const day19 = @import("./day19/day19.zig");
const day21 = @import("./day21/day21.zig");
// const day21 = @import("./day21/day21.zig");
// const day23 = @import("./day23/day23.zig");
const day24 = @import("./day24/day24.zig");
const utils = @import("utils.zig");
pub fn main() !void {
const allocator = std.heap.page_allocator;
var input = try utils.getInput("./src/day21/input.txt", allocator);
var input = try utils.getInput("./src/day24/input.txt", allocator);
defer allocator.free(input);
try day21.solve(input);
try day24.solve(input);
}