FEAT: Day10
This commit is contained in:
300
AdventOfCode2023/src/day10/day10.zig
Normal file
300
AdventOfCode2023/src/day10/day10.zig
Normal file
@ -0,0 +1,300 @@
|
||||
const std = @import("std");
|
||||
const print = std.debug.print;
|
||||
|
||||
const VERTICAL = '|';
|
||||
const HORIZONTAL = '-';
|
||||
const NORTH_EAST = 'L';
|
||||
const NORTH_WEST = 'J';
|
||||
const SOUTH_EAST = 'F';
|
||||
const SOUTH_WEST = '7';
|
||||
const EMPTY = '.';
|
||||
const START = 'S';
|
||||
|
||||
const Direction = enum { up, down, right, left };
|
||||
|
||||
fn isRightPointing(c: u8) bool {
|
||||
return c == HORIZONTAL or c == NORTH_EAST or c == SOUTH_EAST;
|
||||
}
|
||||
fn isLeftPoiting(c: u8) bool {
|
||||
return c == HORIZONTAL or c == NORTH_WEST or c == SOUTH_WEST;
|
||||
}
|
||||
fn isUpPointing(c: u8) bool {
|
||||
return c == VERTICAL or c == NORTH_EAST or c == NORTH_WEST;
|
||||
}
|
||||
fn isDownPointing(c: u8) bool {
|
||||
return c == VERTICAL or c == SOUTH_WEST or c == SOUTH_EAST;
|
||||
}
|
||||
|
||||
const Grid = struct {
|
||||
grid: [][]u8,
|
||||
x: usize,
|
||||
y: usize,
|
||||
|
||||
lastDirection: Direction,
|
||||
|
||||
// ONLY CALL AT VERY BEGINNING
|
||||
pub fn findStart(self: Grid) u8 {
|
||||
var current = self.grid[self.y][self.x];
|
||||
|
||||
var up = self.grid[self.y - 1][self.x];
|
||||
var down = self.grid[self.y + 1][self.x];
|
||||
var left = self.grid[self.y][self.x - 1];
|
||||
var right = self.grid[self.y][self.x + 1];
|
||||
|
||||
if (up == VERTICAL and down == VERTICAL) {
|
||||
// |
|
||||
current = VERTICAL;
|
||||
} else if (left == HORIZONTAL and right == HORIZONTAL) {
|
||||
current = HORIZONTAL;
|
||||
} else if (isRightPointing(left) and isDownPointing(up)) {
|
||||
// NORTH_WEST == J
|
||||
current = NORTH_WEST;
|
||||
} else if (isLeftPoiting(right) and isDownPointing(up)) {
|
||||
// NORTH_EAST = L
|
||||
current = NORTH_EAST;
|
||||
} else if (isRightPointing(left) and isUpPointing(down)) {
|
||||
// SOUTH_WEST
|
||||
current = SOUTH_WEST;
|
||||
} else if (isLeftPoiting(right) and isUpPointing(down)) {
|
||||
// SOUTH_EAST
|
||||
current = SOUTH_EAST;
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
pub fn walk(_self: *Grid, map: *std.AutoHashMap(u128, usize)) !void {
|
||||
var self = _self.*;
|
||||
|
||||
var encoding: u128 = @as(u128, self.x) << 64 | @as(u128, self.y);
|
||||
try map.*.put(encoding, 1);
|
||||
|
||||
var current = self.grid[self.y][self.x];
|
||||
|
||||
if (current == START) {
|
||||
current = self.findStart();
|
||||
}
|
||||
|
||||
if (current == VERTICAL) {
|
||||
// up or down valid.
|
||||
if (self.lastDirection == Direction.up) {
|
||||
_self.*.y = self.y + 1;
|
||||
} else {
|
||||
_self.*.y = self.y - 1;
|
||||
}
|
||||
return;
|
||||
} else if (current == HORIZONTAL) {
|
||||
// left or right valid
|
||||
if (self.lastDirection == Direction.left) {
|
||||
_self.*.x = self.x + 1;
|
||||
} else {
|
||||
_self.*.x = self.x - 1;
|
||||
}
|
||||
return;
|
||||
} else if (current == NORTH_EAST) {
|
||||
// up or right valid
|
||||
if (self.lastDirection == Direction.up) {
|
||||
_self.*.x = self.x + 1;
|
||||
_self.*.lastDirection = Direction.left;
|
||||
} else {
|
||||
_self.*.y = self.y - 1;
|
||||
_self.*.lastDirection = Direction.down;
|
||||
}
|
||||
return;
|
||||
} else if (current == NORTH_WEST) {
|
||||
// up or left valid
|
||||
if (self.lastDirection == Direction.up) {
|
||||
_self.*.x = self.x - 1;
|
||||
_self.*.lastDirection = Direction.right;
|
||||
} else {
|
||||
_self.*.y = self.y - 1;
|
||||
_self.*.lastDirection = Direction.down;
|
||||
}
|
||||
return;
|
||||
} else if (current == SOUTH_EAST) {
|
||||
// down or right valid
|
||||
if (self.lastDirection == Direction.down) {
|
||||
_self.*.x = self.x + 1;
|
||||
_self.*.lastDirection = Direction.left;
|
||||
} else {
|
||||
_self.*.y = self.y + 1;
|
||||
_self.*.lastDirection = Direction.up;
|
||||
}
|
||||
return;
|
||||
} else if (current == SOUTH_WEST) {
|
||||
// down or left valid
|
||||
if (self.lastDirection == Direction.down) {
|
||||
_self.*.x = self.x - 1;
|
||||
_self.*.lastDirection = Direction.right;
|
||||
} else {
|
||||
_self.*.y = self.y + 1;
|
||||
_self.*.lastDirection = Direction.up;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fn initZeroes(line: *[]u8) void {
|
||||
var l = line.*;
|
||||
for (0..l.len) |i| {
|
||||
l[i] = EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
fn createGrid(allocator: std.mem.Allocator, input: [][]const u8) !(*Grid) {
|
||||
var gridRows = try allocator.alloc([]u8, input.len + 2);
|
||||
|
||||
var x: usize = 0;
|
||||
var y: usize = 0;
|
||||
|
||||
for (0..gridRows.len) |i| {
|
||||
gridRows[i] = try allocator.alloc(u8, input[0].len + 2);
|
||||
|
||||
gridRows[i][0] = EMPTY;
|
||||
gridRows[i][input[0].len + 1] = EMPTY;
|
||||
|
||||
if (i == 0 or i == gridRows.len - 1) {
|
||||
initZeroes(&gridRows[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
var index: usize = 1;
|
||||
for (input[i - 1], 1..) |c, k| {
|
||||
if (c == START) {
|
||||
y = i;
|
||||
x = k;
|
||||
}
|
||||
|
||||
gridRows[i][index] = c;
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
var grid = Grid{ .grid = gridRows, .x = x, .y = y, .lastDirection = Direction.left };
|
||||
return &grid;
|
||||
}
|
||||
|
||||
pub fn solve(input: [][]const u8) !void {
|
||||
var allocator = std.heap.page_allocator;
|
||||
var _grid = try createGrid(allocator, input);
|
||||
|
||||
var grid = _grid.*;
|
||||
|
||||
var map = std.AutoHashMap(u128, usize).init(allocator);
|
||||
defer map.deinit();
|
||||
|
||||
var start = grid.findStart();
|
||||
var firstGo = Direction.up;
|
||||
var secondGo = Direction.down;
|
||||
|
||||
grid.grid[grid.y][grid.x] = start;
|
||||
|
||||
if (start == VERTICAL) {
|
||||
// up or down valid.
|
||||
firstGo = Direction.up;
|
||||
secondGo = Direction.down;
|
||||
} else if (start == HORIZONTAL) {
|
||||
// horizonal;
|
||||
firstGo = Direction.left;
|
||||
secondGo = Direction.right;
|
||||
} else if (start == NORTH_EAST) {
|
||||
// up or right valid
|
||||
firstGo = Direction.up;
|
||||
secondGo = Direction.right;
|
||||
} else if (start == NORTH_WEST) {
|
||||
// up or left valid
|
||||
firstGo = Direction.up;
|
||||
secondGo = Direction.left;
|
||||
} else if (start == SOUTH_EAST) {
|
||||
// down or right valid
|
||||
firstGo = Direction.down;
|
||||
secondGo = Direction.right;
|
||||
} else if (start == SOUTH_WEST) {
|
||||
// down or left valid
|
||||
firstGo = Direction.down;
|
||||
secondGo = Direction.left;
|
||||
}
|
||||
|
||||
grid.lastDirection = firstGo;
|
||||
|
||||
var startX = grid.x;
|
||||
var startY = grid.y;
|
||||
var part1: usize = 1;
|
||||
|
||||
try grid.walk(&map);
|
||||
while (grid.x != startX or grid.y != startY) {
|
||||
try grid.walk(&map);
|
||||
part1 += 1;
|
||||
}
|
||||
|
||||
var encoding: u128 = @as(u128, grid.x) << 64 | @as(u128, grid.y);
|
||||
try map.put(encoding, 1);
|
||||
|
||||
var part2: usize = 0;
|
||||
|
||||
for (0..grid.grid.len) |i| {
|
||||
for (0..grid.grid[0].len) |j| {
|
||||
if (grid.grid[i][j] != EMPTY) {
|
||||
var e: u128 = @as(u128, j) << 64 | @as(u128, i);
|
||||
if (map.get(e)) |_| {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//F
|
||||
//||.
|
||||
|
||||
// Count number of various things
|
||||
// || = Outside loop, we want an odd number
|
||||
// LJ = Outside loop, we want north's to not pair up
|
||||
// F7 = outisde loop.
|
||||
|
||||
var verticalCounter: usize = 0;
|
||||
|
||||
var lastChar: u8 = EMPTY;
|
||||
|
||||
for (0..j) |k| {
|
||||
var e: u128 = @as(u128, k) << 64 | @as(u128, i);
|
||||
if (map.get(e)) |_| {
|
||||
// print("Checking: {},{}\n", .{ i, k });
|
||||
var a = grid.grid[i][k];
|
||||
if (a == VERTICAL) {
|
||||
// print("Incrementing vertical\n", .{});
|
||||
verticalCounter += 1;
|
||||
} else if (a == NORTH_EAST) {
|
||||
// L7
|
||||
// if (lastChar == SOUTH_WEST) {
|
||||
// print("1\n", .{});
|
||||
// verticalCounter += 1;
|
||||
// }
|
||||
} else if (a == NORTH_WEST) {
|
||||
// FJ
|
||||
if (lastChar == SOUTH_EAST) {
|
||||
verticalCounter += 1;
|
||||
}
|
||||
} else if (a == SOUTH_EAST) {
|
||||
// if (lastChar == NORTH_WEST) {
|
||||
// print("3\n", .{});
|
||||
// verticalCounter += 1;
|
||||
// }
|
||||
} else if (a == SOUTH_WEST) {
|
||||
if (lastChar == NORTH_EAST) {
|
||||
verticalCounter += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (grid.grid[i][k] != HORIZONTAL) {
|
||||
lastChar = grid.grid[i][k];
|
||||
}
|
||||
}
|
||||
|
||||
if (verticalCounter % 2 == 1) {
|
||||
// print("Adding: {},{} | With: {}\n", .{ i, j, verticalCounter });
|
||||
part2 += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print("Part 1: {}\n", .{part1 / 2});
|
||||
print("Part 2: {}\n", .{part2});
|
||||
}
|
66
AdventOfCode2023/src/day9/day9.zig
Normal file
66
AdventOfCode2023/src/day9/day9.zig
Normal file
@ -0,0 +1,66 @@
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const print = std.debug.print;
|
||||
|
||||
fn isAllZeroes(nums: []i128) bool {
|
||||
for (nums) |n| {
|
||||
if (n != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fn nextNum(allocator: std.mem.Allocator, nums: []i128) !i128 {
|
||||
if (isAllZeroes(nums)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var diff = try allocator.alloc(i128, nums.len - 1);
|
||||
for (0..nums.len - 1) |n| {
|
||||
var d = nums[n + 1] - nums[n];
|
||||
diff[n] = d;
|
||||
}
|
||||
|
||||
return nums[nums.len - 1] + try nextNum(allocator, diff);
|
||||
}
|
||||
|
||||
test "Next num finder" {
|
||||
var allocator = std.heap.page_allocator;
|
||||
var nums = [_]i128{ 0, 3, 6, 9, 12, 15 };
|
||||
try expect(try nextNum(allocator, nums[0..]) == 18);
|
||||
|
||||
var nums2 = [_]i128{ 1, 3, 6, 10, 15, 21 };
|
||||
try expect(try nextNum(allocator, nums2[0..]) == 28);
|
||||
|
||||
var nums3 = [_]i128{ 10, 13, 16, 21, 30, 45 };
|
||||
try expect(try nextNum(allocator, nums3[0..]) == 68);
|
||||
}
|
||||
|
||||
pub fn solve(input: [][]const u8) !void {
|
||||
var allocator = std.heap.page_allocator;
|
||||
var part1: i128 = 0;
|
||||
var part2: i128 = 0;
|
||||
|
||||
for (input) |line| {
|
||||
var list = std.ArrayList(i128).init(allocator);
|
||||
var tokenizer = std.mem.tokenizeSequence(u8, line, " ");
|
||||
while (tokenizer.next()) |n| {
|
||||
try list.append(try std.fmt.parseInt(i128, n, 10));
|
||||
}
|
||||
|
||||
var n1 = try nextNum(allocator, list.items);
|
||||
|
||||
std.mem.reverse(i128, list.items);
|
||||
|
||||
var n2 = try nextNum(allocator, list.items);
|
||||
|
||||
part1 += n1;
|
||||
part2 += n2;
|
||||
|
||||
list.deinit();
|
||||
}
|
||||
|
||||
print("Part 1: {}\n", .{part1});
|
||||
print("Part 2: {}\n", .{part2});
|
||||
}
|
@ -6,13 +6,14 @@ const std = @import("std");
|
||||
// const day5 = @import("./day5/day5.zig");
|
||||
// const day6 = @import("./day6/day6.zig");
|
||||
// const day7 = @import("./day7/day7.zig");
|
||||
const day8 = @import("./day8/day8.zig");
|
||||
// const day9 = @import("./day9/day9.zig");
|
||||
const day10 = @import("./day10/day10.zig");
|
||||
const utils = @import("utils.zig");
|
||||
|
||||
pub fn main() !void {
|
||||
const allocator = std.heap.page_allocator;
|
||||
var input = try utils.getInput("./src/day8/input.txt", allocator);
|
||||
var input = try utils.getInput("./src/day10/input.txt", allocator);
|
||||
defer allocator.free(input);
|
||||
|
||||
try day8.solve(input);
|
||||
try day10.solve(input);
|
||||
}
|
||||
|
Reference in New Issue
Block a user