NBWIQLPZIFZRXGCDMIFXQAAWWVQEOJDP6KIALLI2NJE4YSNCCNOAC
RS2AMNWLJ4SD24J3LSOCWW7XG3LHJ4KI2HYYDEA33JZ6YJNBAXOAC
TN7NPXNSXBULTXOU444VTHLR36NJJO32ZFVJJVYUHSQN7BPFEGPAC
GFSYZK3OMZY6WFJUQF6BKAXYV33PXSYS7BLICM4GZUUOP74IP3IAC
4TF5FCXVZAF23QJQ7H3I7QGCVUK33O6V37YUXVFEL64FPC5HRG6QC
ISKIMCRTCM4ZY34QENDO4AN7ZAKRRBPFLA5MYHXH2K6Q2WKJDZNQC
CD3QNDB3NQYMOMGANUU5B2XOX2LMII57DQ53Q2HJC5DSM4GCJB3AC
I2F5R3WUAQR4YWAZPUJ6FVZYMFLOEO7I2BQFW4JFKTDHPR5ERBYQC
UEINQUTKBUQEGQXJ3MFEBPRKNWI6ATMANFCHTMOOYRX5Y24FKYQQC
4FDJNKVA3K4JLSUPNALFOVXU3OLTNSOWEPUTS2RQGKM5YXWM74YAC
NNEOPQV6SNXJVL3UOUR45I4PLDL5IV72FE4GAQPJSHHRXGFL6QTAC
DEBJKGU2F4MD5O3DMLE3XPKOGJOAG2KZHMQX7DP52RAP4HBKGFSQC
_ = @import("day01.zig");
_ = @import("day02.zig");
_ = @import("day03.zig");
_ = @import("day04.zig");
_ = @import("day05.zig");
_ = @import("day01a.zig");
_ = @import("day01b.zig");
_ = @import("day02a.zig");
_ = @import("day02b.zig");
_ = @import("day03a.zig");
_ = @import("day03b.zig");
_ = @import("day04a.zig");
_ = @import("day04b.zig");
_ = @import("day05a.zig");
_ = @import("day05b.zig");
_ = @import("day06a.zig");
_ = @import("day06b.zig");
_ = @import("day07a.zig");
_ = @import("day07b.zig");
const std = @import("std");
const path = "../data/day07/input.txt";
const crabs = 1000;
const CrabType = u11;
const P2 = struct {
crs: [crabs]CrabType = undefined,
sum: usize,
};
fn parseInput() anyerror!P2 {
const in = @embedFile(path);
const input = std.mem.trimRight(u8, in, "\r\n");
var crbs = std.mem.tokenize(u8, input, ",");
var ret = P2{ .sum = 0 };
var idx: usize = 0;
while (crbs.next()) |crab| : (idx += 1) {
const crab_pos = try std.fmt.parseUnsigned(CrabType, crab, 10);
ret.crs[idx] = crab_pos;
ret.sum += crab_pos;
}
ret.sum = @floatToInt(usize, std.math.floor(@intToFloat(f32, ret.sum) / crabs));
return ret;
}
fn second() anyerror!usize {
const crbs = try parseInput();
var fuel: usize = 0;
for (crbs.crs) |c| {
var diff: usize = undefined;
if (c > crbs.sum) {
diff = c - crbs.sum;
} else {
diff = crbs.sum - c;
}
fuel += (diff * (diff + 1)) / 2;
}
return fuel;
}
pub fn main() anyerror!void {
var timer = try std.time.Timer.start();
_ = try second();
const s = timer.lap() / 1000;
std.debug.print("Day 7 \tsecond: {d}µs\n", .{s});
}
test "day07b" {
try std.testing.expectEqual(@as(usize, 95851339), try second());
}
}
const P2 = struct {
crs: [crabs]CrabType = undefined,
sum: usize,
};
fn parseInput2() anyerror!P2 {
const in = @embedFile(path);
const input = std.mem.trimRight(u8, in, "\r\n");
var crbs = std.mem.tokenize(u8, input, ",");
var ret = P2{ .sum = 0 };
var idx: usize = 0;
while (crbs.next()) |crab| : (idx += 1) {
const crab_pos = try std.fmt.parseUnsigned(CrabType, crab, 10);
ret.crs[idx] = crab_pos;
ret.sum += crab_pos;
}
ret.sum = @floatToInt(usize, std.math.floor(@intToFloat(f32, ret.sum) / crabs));
return ret;
const std = @import("std");
const path = "../data/day06/input.txt";
const ages = 9;
const AgeType = u4;
fn parseInput() anyerror![ages]usize {
const in = @embedFile(path);
const input = std.mem.trimRight(u8, in, "\r\n");
var ltrs = std.mem.tokenize(u8, input, ",");
var ret = [_]usize{0} ** ages;
while (ltrs.next()) |lantern_age| {
const age = try std.fmt.parseUnsigned(AgeType, lantern_age, 10);
ret[age] += 1;
}
return ret;
}
fn sum(ageArray: [ages]usize) usize {
var s: usize = 0;
for (ageArray) |value| {
s += value;
}
return s;
}
fn countFish(days: u9) anyerror![ages]usize {
var age = try parseInput();
var i: @TypeOf(days) = 0;
while (i < days) : (i += 1) {
const new = age[0];
age[0] = age[1];
age[1] = age[2];
age[2] = age[3];
age[3] = age[4];
age[4] = age[5];
age[5] = age[6];
age[6] = age[7] + new;
age[7] = age[8];
age[8] = new;
}
return age;
}
fn second() anyerror!usize {
return sum(try countFish(256));
}
pub fn main() anyerror!void {
var timer = try std.time.Timer.start();
_ = try second();
const s = timer.lap() / 1000;
std.debug.print("Day 6 \tsecond: {d}µs\n", .{s});
}
test "day06b" {
try std.testing.expectEqual(@as(usize, 1590327954513), try second());
}
const std = @import("std");
const path = "../data/day05/input.txt";
const RetType = u16;
const grid_size = 1000;
const max_grid_value = u2;
const Vents = [grid_size][grid_size]max_grid_value;
const CoordType = i20;
const Coord = struct { x: CoordType, y: CoordType };
fn countVents(directions: []const Coord, nodiag: bool) anyerror!RetType {
const input = @embedFile(path);
var lines = std.mem.split(u8, input, "\n");
var vts: Vents = [_][grid_size]max_grid_value{[_]max_grid_value{0} ** grid_size} ** grid_size;
var counter: RetType = 0;
while (lines.next()) |line| {
if (line.len == 0) continue;
var crop_line = std.mem.tokenize(u8, line, " -> ");
// parse coordinates
var l: [2]Coord = undefined;
var idx: usize = 0;
while (crop_line.next()) |cl| : (idx += 1) {
var coords = std.mem.tokenize(u8, cl, ",");
l[idx].x = try std.fmt.parseUnsigned(CoordType, coords.next().?, 10);
l[idx].y = try std.fmt.parseUnsigned(CoordType, coords.next().?, 10);
}
// check if diagonal lines count or not
if (nodiag and !((l[0].x == l[1].x) or (l[0].y == l[1].y))) continue;
// setup lines
const dir = try getDirection(l, directions);
while ((l[0].x != l[1].x + dir.x) or (l[0].y != l[1].y + dir.y)) : ({
l[0].x += dir.x;
l[0].y += dir.y;
}) {
var v = vts[@intCast(usize, l[0].x)][@intCast(usize, l[0].y)];
if (v == 1) {
counter += 1;
}
v +|= 1;
vts[@intCast(usize, l[0].x)][@intCast(usize, l[0].y)] = v;
}
}
return counter;
}
fn getDirection(c: [2]Coord, directions: []const Coord) !Coord {
var min = try manhattan(c[0], c[1]);
for (directions) |d| {
if ((try manhattan(Coord{ .x = c[0].x + d.x, .y = c[0].y + d.y }, c[1])) < min) {
return d;
}
}
unreachable;
}
fn manhattan(f: Coord, s: Coord) !CoordType {
const xdiff = try std.math.absInt(f.x - s.x);
const ydiff = try std.math.absInt(f.y - s.y);
return xdiff + ydiff;
}
fn second() anyerror!RetType {
const directions = [_]Coord{
// Diagonal manhattan distance can decrease by 2, so these must be
// tried first otherwise getDirection() will not return proper direction.
.{ .x = -1, .y = -1 },
.{ .x = -1, .y = 1 },
.{ .x = 1, .y = -1 },
.{ .x = 1, .y = 1 },
.{ .x = -1, .y = 0 },
.{ .x = 1, .y = 0 },
.{ .x = 0, .y = -1 },
.{ .x = 0, .y = 1 },
};
return try countVents(directions[0..], false);
}
pub fn main() anyerror!void {
var timer = try std.time.Timer.start();
_ = try second();
const s = timer.lap() / 1000;
std.debug.print("Day 5 \tsecond: {d}µs\n", .{s});
}
test "day05b" {
try std.testing.expectEqual(@as(RetType, 21577), try second());
}
}
fn second() anyerror!RetType {
const directions = [_]Coord{
// Diagonal manhattan distance can decrease by 2, so these must be
// tried first otherwise getDirection() will not return proper direction.
.{ .x = -1, .y = -1 },
.{ .x = -1, .y = 1 },
.{ .x = 1, .y = -1 },
.{ .x = 1, .y = 1 },
.{ .x = -1, .y = 0 },
.{ .x = 1, .y = 0 },
.{ .x = 0, .y = -1 },
.{ .x = 0, .y = 1 },
};
return try countVents(directions[0..], false);
const std = @import("std");
const path = "../data/day04/input.txt";
const retSize = u16;
const grid_size = 5;
const grid_item_size = u7;
const Board = struct {
items: [grid_size][grid_size]grid_item_size,
row: [grid_size]u5 = [_]u5{0} ** grid_size,
col: [grid_size]u5 = [_]u5{0} ** grid_size,
pub fn value(self: @This()) retSize {
var ret: retSize = 0;
for (self.items) |row, rowID| {
for (row) |item, col| {
if (self.row[rowID] & (@as(u5, 1) <<| col) == 0) {
ret += item;
}
}
}
return ret;
}
};
const Bingo = struct {
numbers: std.ArrayList(grid_item_size),
boards: std.ArrayList(Board),
};
fn parseInput(allocator: std.mem.Allocator) anyerror!Bingo {
const input = @embedFile(path);
var lines = std.mem.split(u8, input, "\n");
var ret = Bingo{
.numbers = std.ArrayList(grid_item_size).init(allocator),
.boards = std.ArrayList(Board).init(allocator),
};
var gridRow: u3 = 0;
var gridCol: u3 = 0;
var g = Board{ .items = undefined };
var idx: usize = 0;
while (lines.next()) |line| : (idx += 1) {
// read in numbers
if (idx == 0) {
var nums = std.mem.tokenize(u8, line, ",");
while (nums.next()) |num| {
try ret.numbers.append(try std.fmt.parseUnsigned(grid_item_size, num, 10));
}
continue;
}
// read in Grids
var items = std.mem.tokenize(u8, line, " ");
while (items.next()) |item| {
const value = try std.fmt.parseUnsigned(grid_item_size, item, 10);
g.items[gridRow][gridCol] = value;
gridCol += 1;
}
gridCol = 0;
if (line.len != 0) gridRow += 1;
// append grid
if (gridRow == 5) {
try ret.boards.append(g);
gridRow = 0;
gridCol = 0;
// create new grid
g = Board{ .items = undefined };
}
}
return ret;
}
fn second() anyerror!retSize {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
var bg = try parseInput(allocator);
defer { // cleanup code
bg.boards.deinit();
bg.numbers.deinit();
}
var to_remove = std.ArrayList(usize).init(allocator);
defer to_remove.deinit();
for (bg.numbers.items) |num| {
boards_loop: for (bg.boards.items) |_, idx| {
var grid = &bg.boards.items[idx];
for (grid.items) |row, i| {
for (row) |item, j| {
if (item == num) {
// increase row, col counter
grid.row[i] += @as(u5, 1) <<| j;
grid.col[j] += @as(u5, 1) <<| i;
// check if row or grid equals to 11111, return when true
if ((grid.row[i] == 0b11111) or (grid.col[j] == 0b11111)) {
if (bg.boards.items.len == 1) {
return num * grid.value();
} else {
try to_remove.append(idx);
}
}
// break out to grid loop
continue :boards_loop;
}
}
}
}
std.sort.sort(usize, to_remove.items, {}, comptime std.sort.desc(usize));
for (to_remove.items) |idx| {
_ = bg.boards.swapRemove(idx);
}
try to_remove.resize(0);
}
unreachable;
}
pub fn main() anyerror!void {
var timer = try std.time.Timer.start();
_ = try second();
const s = timer.lap() / 1000;
std.debug.print("Day 4 \tsecond: {d}µs\n", .{s});
}
test "day04b" {
try std.testing.expectEqual(@as(retSize, 1284), try second());
}
}
// break out to grid loop
continue :boards_loop;
}
}
}
}
}
unreachable;
}
fn second() anyerror!retSize {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
var bg = try parseInput(allocator);
defer { // cleanup code
bg.boards.deinit();
bg.numbers.deinit();
}
var to_remove = std.ArrayList(usize).init(allocator);
defer to_remove.deinit();
for (bg.numbers.items) |num| {
boards_loop: for (bg.boards.items) |_, idx| {
var grid = &bg.boards.items[idx];
for (grid.items) |row, i| {
for (row) |item, j| {
if (item == num) {
// increase row, col counter
grid.row[i] += @as(u5, 1) <<| j;
grid.col[j] += @as(u5, 1) <<| i;
// check if row or grid equals to 11111, return when true
if ((grid.row[i] == 0b11111) or (grid.col[j] == 0b11111)) {
if (bg.boards.items.len == 1) {
return num * grid.value();
} else {
try to_remove.append(idx);
}
const std = @import("std");
const path = "../data/day03/input.txt";
const retSize = u24;
const lineSize = getLineSize();
fn second() anyerror!retSize {
const input = @embedFile(path);
var lines = std.mem.tokenize(u8, input, "\n");
var buffer: [1000 * lineSize * 100]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&buffer);
const allocator = fba.allocator();
var lines_array = std.ArrayList(retSize).init(allocator);
defer lines_array.deinit();
var lines_array2 = std.ArrayList(retSize).init(allocator);
defer lines_array2.deinit();
while (lines.next()) |line| {
try lines_array.append(try std.fmt.parseUnsigned(retSize, line, 2));
try lines_array2.append(try std.fmt.parseUnsigned(retSize, line, 2));
}
const ox = try getOxigenRating(allocator, &lines_array);
const co = try getCO2Rating(allocator, &lines_array2);
return ox * co;
}
fn getOxigenRating(allocator: std.mem.Allocator, oxigen: *std.ArrayList(retSize)) anyerror!retSize {
var to_remove = std.ArrayList(usize).init(allocator);
defer to_remove.deinit();
var idx: usize = lineSize;
while (oxigen.items.len > 1) : (idx -= 1) {
var ones: retSize = 0;
var zeros: retSize = 0;
// count ones and zeros
for (oxigen.items) |line| {
if ((line & (@as(retSize, 1) <<| idx - 1)) != 0) {
ones += 1;
} else {
zeros += 1;
}
}
// std.debug.print("{d} {d} {d}", .{ones, zeros, idx-1});
for (oxigen.items) |line, i| {
if (ones >= zeros) {
if ((line & (@as(retSize, 1) <<| idx - 1)) == 0) {
try to_remove.append(i);
}
} else {
if ((line & (@as(retSize, 1) <<| idx - 1)) != 0) {
try to_remove.append(i);
}
}
}
std.sort.sort(usize, to_remove.items, {}, comptime std.sort.desc(usize));
for (to_remove.items) |i| {
_ = oxigen.swapRemove(i);
}
try to_remove.resize(0);
// std.debug.print("{d}\n", .{oxigen.items.len});
}
return oxigen.items[0];
}
fn getCO2Rating(allocator: std.mem.Allocator, co2: *std.ArrayList(retSize)) anyerror!retSize {
var to_remove = std.ArrayList(usize).init(allocator);
defer to_remove.deinit();
var idx: usize = lineSize;
while (co2.items.len > 1) : (idx -= 1) {
var ones: retSize = 0;
var zeros: retSize = 0;
// count ones and zeros
for (co2.items) |line| {
if ((line & (@as(retSize, 1) <<| idx - 1)) != 0) {
ones += 1;
} else {
zeros += 1;
}
}
// std.debug.print("{d} {d} {d}", .{ones, zeros, idx-1});
for (co2.items) |line, i| {
if (zeros <= ones) {
if ((line & (@as(retSize, 1) <<| idx - 1)) != 0) {
try to_remove.append(i);
}
} else {
if ((line & (@as(retSize, 1) <<| idx - 1)) == 0) {
try to_remove.append(i);
}
}
}
std.sort.sort(usize, to_remove.items, {}, comptime std.sort.desc(usize));
for (to_remove.items) |i| {
_ = co2.swapRemove(i);
}
try to_remove.resize(0);
// std.debug.print("{d}\n", .{co2.items.len});
}
return co2.items[0];
}
fn getLineSize() usize {
const input = @embedFile(path);
var ret: usize = 0;
for (input) |bit, idx| {
if (bit == '\n') {
ret = idx;
break;
}
}
return ret;
}
pub fn main() anyerror!void {
var timer = try std.time.Timer.start();
_ = try second();
const s = timer.lap() / 1000;
std.debug.print("Day 3 \tsecond: {d}µs\n", .{s});
}
test "day03b" {
try std.testing.expectEqual(@as(retSize, 4105235), try second());
}
fn second() anyerror!retSize {
const input = @embedFile(path);
var lines = std.mem.tokenize(u8, input, "\n");
var buffer: [1000 * lineSize * 100]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&buffer);
const allocator = fba.allocator();
var lines_array = std.ArrayList(retSize).init(allocator);
defer lines_array.deinit();
var lines_array2 = std.ArrayList(retSize).init(allocator);
defer lines_array2.deinit();
while (lines.next()) |line| {
try lines_array.append(try std.fmt.parseUnsigned(retSize, line, 2));
try lines_array2.append(try std.fmt.parseUnsigned(retSize, line, 2));
}
const ox = try getOxigenRating(allocator, &lines_array);
const co = try getCO2Rating(allocator, &lines_array2);
return ox * co;
}
fn getOxigenRating(allocator: std.mem.Allocator, oxigen: *std.ArrayList(retSize)) anyerror!retSize {
var to_remove = std.ArrayList(usize).init(allocator);
defer to_remove.deinit();
var idx: usize = lineSize;
while (oxigen.items.len > 1) : (idx -= 1) {
var ones: retSize = 0;
var zeros: retSize = 0;
// count ones and zeros
for (oxigen.items) |line| {
if ((line & (@as(retSize, 1) <<| idx - 1)) != 0) {
ones += 1;
} else {
zeros += 1;
}
}
// std.debug.print("{d} {d} {d}", .{ones, zeros, idx-1});
for (oxigen.items) |line, i| {
if (ones >= zeros) {
if ((line & (@as(retSize, 1) <<| idx - 1)) == 0) {
try to_remove.append(i);
}
} else {
if ((line & (@as(retSize, 1) <<| idx - 1)) != 0) {
try to_remove.append(i);
}
}
}
std.sort.sort(usize, to_remove.items, {}, comptime std.sort.desc(usize));
for (to_remove.items) |i| {
_ = oxigen.swapRemove(i);
}
try to_remove.resize(0);
// std.debug.print("{d}\n", .{oxigen.items.len});
}
return oxigen.items[0];
}
fn getCO2Rating(allocator: std.mem.Allocator, co2: *std.ArrayList(retSize)) anyerror!retSize {
var to_remove = std.ArrayList(usize).init(allocator);
defer to_remove.deinit();
var idx: usize = lineSize;
while (co2.items.len > 1) : (idx -= 1) {
var ones: retSize = 0;
var zeros: retSize = 0;
// count ones and zeros
for (co2.items) |line| {
if ((line & (@as(retSize, 1) <<| idx - 1)) != 0) {
ones += 1;
} else {
zeros += 1;
}
}
// std.debug.print("{d} {d} {d}", .{ones, zeros, idx-1});
for (co2.items) |line, i| {
if (zeros <= ones) {
if ((line & (@as(retSize, 1) <<| idx - 1)) != 0) {
try to_remove.append(i);
}
} else {
if ((line & (@as(retSize, 1) <<| idx - 1)) == 0) {
try to_remove.append(i);
}
}
}
std.sort.sort(usize, to_remove.items, {}, comptime std.sort.desc(usize));
for (to_remove.items) |i| {
_ = co2.swapRemove(i);
}
try to_remove.resize(0);
// std.debug.print("{d}\n", .{co2.items.len});
}
return co2.items[0];
}
const std = @import("std");
const path = "../data/day02/input.txt";
const intType = u32;
fn second() anyerror!intType {
const input = @embedFile(path);
var commands = std.mem.tokenize(u8, input, "\n");
const Postition = struct {
forward: intType = 0,
depth: intType = 0,
aim: intType = 0,
};
var pos: Postition = .{};
while (commands.next()) |c| {
// example: commands = forward 8
var comm_parts = std.mem.tokenize(u8, c, " ");
const direction = comm_parts.next().?;
const value = try std.fmt.parseUnsigned(intType, comm_parts.next().?, 10);
if (std.mem.eql(u8, direction, "forward")) {
pos.forward += value;
pos.depth += value * pos.aim;
}
if (std.mem.eql(u8, direction, "down")) {
pos.aim += value;
}
if (std.mem.eql(u8, direction, "up")) {
pos.aim -= value;
}
}
return pos.forward * pos.depth;
}
pub fn main() anyerror!void {
var timer = try std.time.Timer.start();
_ = try second();
const s = timer.lap() / 1000;
std.debug.print("Day 2 \tsecond: {d}µs\n", .{s});
}
test "day02b" {
try std.testing.expectEqual(@as(u32, 2120734350), try second());
}
var pos: Postition = .{};
while (commands.next()) |c| {
// example: commands = forward 8
var comm_parts = std.mem.tokenize(u8, c, " ");
const direction = comm_parts.next().?;
const value = try std.fmt.parseUnsigned(intType, comm_parts.next().?, 10);
if (std.mem.eql(u8, direction, "forward")) {
pos.forward += value;
pos.depth += value * pos.aim;
}
if (std.mem.eql(u8, direction, "down")) {
pos.aim += value;
}
if (std.mem.eql(u8, direction, "up")) {
pos.aim -= value;
}
}
return pos.forward * pos.depth;
}
const std = @import("std");
const lineLength = 4; // maximum line length (digits)
const decimalSize = u13; // every num in input is < 2^13
const maxItems = 2000; // number of items in input file
const path = "../data/day01/input.txt";
fn second() anyerror!decimalSize {
const values = try parseValues();
var inc: decimalSize = 0;
for (values) |_, idx| {
if (idx >= 3) {
// as idx-2 and idx-1 are in a and b too, this can be simplified
// const a = @intCast(u15, values[idx - 3]) + values[idx - 2] + values[idx - 1];
// const b = @intCast(u15, values[idx - 2]) + values[idx - 1] + values[idx];
const a = values[idx - 3];
const b = values[idx];
if (a < b) {
inc += 1;
}
}
}
return inc;
}
fn parseValues() anyerror![maxItems]decimalSize {
const file = @embedFile(path);
var lines = std.mem.tokenize(u8, file, "\n");
var values: [maxItems]decimalSize = undefined;
var i: decimalSize = 0;
while (lines.next()) |v| : (i += 1) {
values[i] = try std.fmt.parseUnsigned(decimalSize, v, 10);
}
return values;
}
pub fn main() anyerror!void {
var timer = try std.time.Timer.start();
_ = try second();
const s = timer.read() / 1000;
std.debug.print("Day 1 \tsecond: {d}μs\n", .{s});
}
test "day01b" {
try std.testing.expectEqual(@as(decimalSize, 1429), try second());
}
var inc: decimalSize = 0;
for (values) |_, idx| {
if (idx >= 3) {
// as idx-2 and idx-1 are in a and b too, this can be simplified
// const a = @intCast(u15, values[idx - 3]) + values[idx - 2] + values[idx - 1];
// const b = @intCast(u15, values[idx - 2]) + values[idx - 1] + values[idx];
const a = values[idx - 3];
const b = values[idx];
if (a < b) {
inc += 1;
}
}
}
return inc;
}