135 lines
3.7 KiB
Zig
135 lines
3.7 KiB
Zig
|
const std = @import("std");
|
||
|
|
||
|
pub fn main() !void {
|
||
|
var allocator = std.heap.GeneralPurposeAllocator(.{}){};
|
||
|
var gpa = &allocator.allocator;
|
||
|
|
||
|
var f = std.fs.File { .handle = try std.os.open("input", std.os.O_RDONLY, 0) };
|
||
|
var buffer : [1024]u8 = undefined;
|
||
|
|
||
|
var byte_buffer = std.ArrayList(u8).init(&allocator.allocator);
|
||
|
defer byte_buffer.deinit();
|
||
|
|
||
|
var map = std.ArrayList([]u8).init(&allocator.allocator);
|
||
|
defer map.deinit();
|
||
|
|
||
|
const stdout = std.io.getStdOut().writer();
|
||
|
|
||
|
var read = try f.read(&buffer);
|
||
|
std.log.info("Read {} bytes", .{read});
|
||
|
while (read != 0) {
|
||
|
var last_pos : usize = 0;
|
||
|
for (buffer) | v, k | {
|
||
|
// We're through the read part of the buffer
|
||
|
if (k >= read) {
|
||
|
break;
|
||
|
}
|
||
|
if (v == '\n') {
|
||
|
try map.append(try std.mem.Allocator.dupe(gpa, u8, byte_buffer.items));
|
||
|
last_pos = k + 1;
|
||
|
// Reset buffer
|
||
|
byte_buffer.deinit();
|
||
|
byte_buffer = std.ArrayList(u8).init(&allocator.allocator);
|
||
|
continue;
|
||
|
}
|
||
|
try byte_buffer.append(v);
|
||
|
}
|
||
|
read = try f.read(&buffer);
|
||
|
std.log.info("Read {} bytes", .{read});
|
||
|
}
|
||
|
|
||
|
std.log.debug("Map has {} items", .{map.items.len});
|
||
|
//for (map.items) | v, k | {
|
||
|
// try stdout.print("{s}\n", .{v});
|
||
|
//}
|
||
|
var results : std.meta.Vector(5, u32) = [_]u32 {
|
||
|
sled(map, 1, 1),
|
||
|
sled(map, 3, 1),
|
||
|
sled(map, 5, 1),
|
||
|
sled(map, 7, 1),
|
||
|
sled(map, 1, 2),
|
||
|
};
|
||
|
std.log.info("Hit {} trees on slope 1,1", .{results[0]});
|
||
|
std.log.info("Hit {} trees on slope 3,1", .{results[1]});
|
||
|
std.log.info("Hit {} trees on slope 5,1", .{results[2]});
|
||
|
std.log.info("Hit {} trees on slope 7,1", .{results[3]});
|
||
|
std.log.info("Hit {} trees on slope 1,2", .{results[4]});
|
||
|
std.log.info("Multiple of each slop hits: {}", .{@reduce(.Mul, results)});
|
||
|
}
|
||
|
|
||
|
fn sled(map: std.ArrayList([]u8), right: usize, down: usize) u32 {
|
||
|
var map_height : usize = map.items.len;
|
||
|
var map_width : usize = map.items[0].len;
|
||
|
var x : usize = 0;
|
||
|
var y : usize = 0;
|
||
|
var n_trees : u32 = 0;
|
||
|
while (y < map_height) {
|
||
|
var char : u8 = map.items[y][x];
|
||
|
std.log.debug("{},{} : {}", .{x, y, char});
|
||
|
if (char == '#') {
|
||
|
n_trees += 1;
|
||
|
}
|
||
|
y += down;
|
||
|
x += right;
|
||
|
x %= map_width; // loop around
|
||
|
}
|
||
|
return n_trees;
|
||
|
}
|
||
|
|
||
|
fn parse_policy(line: []u8) Policy {
|
||
|
var min : u32 = 0;
|
||
|
var max : u32 = 0;
|
||
|
var char : u8 = 0;
|
||
|
var pass : []u8 = undefined;
|
||
|
|
||
|
var start : usize = 0;
|
||
|
var got_min = false;
|
||
|
var got_max = false;
|
||
|
for (line) | v, k | {
|
||
|
if (v == '-') {
|
||
|
min = atoi(line[start..k]);
|
||
|
start = k + 1;
|
||
|
got_min = true;
|
||
|
}
|
||
|
if (v == ' ' and !got_max) {
|
||
|
max = atoi(line[start..k]);
|
||
|
start = k + 1;
|
||
|
got_max = true;
|
||
|
}
|
||
|
if (v == ':') {
|
||
|
char = line[start..k][0];
|
||
|
start = k + 2;
|
||
|
}
|
||
|
if (k == line.len-1) {
|
||
|
pass = line[start..];
|
||
|
}
|
||
|
}
|
||
|
return Policy {
|
||
|
.min = min,
|
||
|
.max = max,
|
||
|
.value = char,
|
||
|
.password = pass,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
fn part2() void {
|
||
|
}
|
||
|
|
||
|
fn part1() void {
|
||
|
}
|
||
|
|
||
|
fn atoi(a: []u8) u32 {
|
||
|
var i : u32 = 0;
|
||
|
for(a) |v, k| {
|
||
|
if (! std.ascii.isDigit(v)) {
|
||
|
std.log.warn("Byte {x} is not a digit", .{v});
|
||
|
continue;
|
||
|
}
|
||
|
// 48 is '0' in ascii
|
||
|
std.debug.assert(v >= 48 and v < 58);
|
||
|
i += @as(u32, (v - 48) * std.math.pow(u32, 10, @intCast(u32, a.len - k - 1)));
|
||
|
}
|
||
|
//std.log.debug("{x} --> {}", .{a, i});
|
||
|
return i;
|
||
|
}
|