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; }