This commit is contained in:
		
							
								
								
									
										170
									
								
								src/day10.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								src/day10.zig
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,170 @@
 | 
			
		||||
const std = @import("std");
 | 
			
		||||
const util = @import("util.zig");
 | 
			
		||||
const mem = std.mem;
 | 
			
		||||
const assert = std.debug.assert;
 | 
			
		||||
 | 
			
		||||
pub fn main() !void {
 | 
			
		||||
    const input = @embedFile("data/day10.txt");
 | 
			
		||||
    const sln = try solve(util.gpa, input);
 | 
			
		||||
    try printPipes(std.io.getStdOut(), input);
 | 
			
		||||
    std.debug.print("{d}\n", .{sln.a});
 | 
			
		||||
    std.debug.print("{d}\n", .{sln.b});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Solution = struct {
 | 
			
		||||
    a: usize,
 | 
			
		||||
    b: usize,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const Direction = enum(u2) {
 | 
			
		||||
    up,
 | 
			
		||||
    down,
 | 
			
		||||
    left,
 | 
			
		||||
    right,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
fn Walker(comptime T: type) type {
 | 
			
		||||
    return struct {
 | 
			
		||||
        r: T,
 | 
			
		||||
        c: T,
 | 
			
		||||
        facing: Direction,
 | 
			
		||||
 | 
			
		||||
        fn init(r: T, c: T) @This() {
 | 
			
		||||
            return .{ .r = r, .c = c, .facing = .up };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn walk(self: *@This(), grid: [][]u8) void {
 | 
			
		||||
            self.walkSpace(grid[self.r][self.c]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn walkSpace(self: *@This(), char: u8) void {
 | 
			
		||||
            switch (char) {
 | 
			
		||||
                'S' => {},
 | 
			
		||||
                '|' => assert(self.facing == .up or self.facing == .down),
 | 
			
		||||
                '-' => assert(self.facing == .left or self.facing == .right),
 | 
			
		||||
                'L' => switch (self.facing) {
 | 
			
		||||
                    .down => self.turn(.right),
 | 
			
		||||
                    .left => self.turn(.up),
 | 
			
		||||
                    else => unreachable,
 | 
			
		||||
                },
 | 
			
		||||
                'J' => switch (self.facing) {
 | 
			
		||||
                    .down => self.turn(.left),
 | 
			
		||||
                    .right => self.turn(.up),
 | 
			
		||||
                    else => unreachable,
 | 
			
		||||
                },
 | 
			
		||||
                '7' => switch (self.facing) {
 | 
			
		||||
                    .up => self.turn(.left),
 | 
			
		||||
                    .right => self.turn(.down),
 | 
			
		||||
                    else => unreachable,
 | 
			
		||||
                },
 | 
			
		||||
                'F' => switch (self.facing) {
 | 
			
		||||
                    .up => self.turn(.right),
 | 
			
		||||
                    .left => self.turn(.down),
 | 
			
		||||
                    else => unreachable,
 | 
			
		||||
                },
 | 
			
		||||
                else => unreachable,
 | 
			
		||||
            }
 | 
			
		||||
            self.fwd();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn move(self: *@This(), row: i32, col: i32) void {
 | 
			
		||||
            self.*.r += row;
 | 
			
		||||
            self.*.c += col;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn fwd(self: *@This()) void {
 | 
			
		||||
            switch (self.facing) {
 | 
			
		||||
                .up => self.move(-1, 0),
 | 
			
		||||
                .down => self.move(1, 0),
 | 
			
		||||
                .left => self.move(0, -1),
 | 
			
		||||
                .right => self.move(0, 1),
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn turn(self: *@This(), dir: Direction) void {
 | 
			
		||||
            self.*.facing = dir;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn solve(alloc: mem.Allocator, input: []const u8) !Solution {
 | 
			
		||||
    _ = alloc;
 | 
			
		||||
    var grid: [][]u8 = undefined; // try alloc.alloc(u8, mem.count(u8, input, &[_]u8{'\n'}));
 | 
			
		||||
 | 
			
		||||
    var s_found = false;
 | 
			
		||||
    var sr: u32 = 0;
 | 
			
		||||
    var sc: u32 = 0;
 | 
			
		||||
 | 
			
		||||
    var it = util.splitLines(input);
 | 
			
		||||
    var curr_row: u32 = 0;
 | 
			
		||||
    while (it.next()) |line| {
 | 
			
		||||
        if (line.len == 0) continue;
 | 
			
		||||
        // grid[curr_row] = line;
 | 
			
		||||
 | 
			
		||||
        if (!s_found) {
 | 
			
		||||
            if (mem.indexOfScalar(u8, line, 'S')) |col| {
 | 
			
		||||
                _ = col;
 | 
			
		||||
                sr = curr_row;
 | 
			
		||||
                // sc = col;
 | 
			
		||||
                s_found = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Find actual starting position.
 | 
			
		||||
    var walker = Walker(u32).init(sr, sc);
 | 
			
		||||
    if (mem.indexOfScalar(u8, "|7F", grid[sr - 1][sc])) |_| {
 | 
			
		||||
        walker.facing = .up;
 | 
			
		||||
    } else if (mem.indexOfScalar(u8, "|JL", grid[sr + 1][sc])) |_| {
 | 
			
		||||
        walker.facing = .down;
 | 
			
		||||
    } else if (mem.indexOfScalar(u8, "-LF", grid[sr][sc - 1])) |_| {
 | 
			
		||||
        walker.facing = .left;
 | 
			
		||||
    } else if (mem.indexOfScalar(u8, "-J7", grid[sr][sc + 1])) |_| {
 | 
			
		||||
        walker.facing = .right;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var steps: u32 = 1;
 | 
			
		||||
    while (true) {
 | 
			
		||||
        steps += 1;
 | 
			
		||||
        if (grid[walker.r][walker.c] == 'S') break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return .{ .a = steps / 2, .b = 0 };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn printPipes(writer: anytype, input: []const u8) !void {
 | 
			
		||||
    for (input) |char| {
 | 
			
		||||
        _ = switch (char) {
 | 
			
		||||
            '|' => try writer.write("│"),
 | 
			
		||||
            '-' => try writer.write("─"),
 | 
			
		||||
            'L' => try writer.write("└"),
 | 
			
		||||
            'J' => try writer.write("┘"),
 | 
			
		||||
            '7' => try writer.write("┐"),
 | 
			
		||||
            'F' => try writer.write("┌"),
 | 
			
		||||
            '.' => try writer.write(" "),
 | 
			
		||||
            'S' => try writer.write("o"),
 | 
			
		||||
            '\n' => try writer.write("\n"),
 | 
			
		||||
            else => unreachable,
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
test "silver" {
 | 
			
		||||
    const input =
 | 
			
		||||
        \\-L|F7
 | 
			
		||||
        \\7S-7|
 | 
			
		||||
        \\L|7||
 | 
			
		||||
        \\-L-J|
 | 
			
		||||
        \\L|-JF
 | 
			
		||||
    ;
 | 
			
		||||
    const sln = try solve(std.testing.allocator, input);
 | 
			
		||||
    try std.testing.expectEqual(@as(usize, 6), sln.a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
test "gold" {
 | 
			
		||||
    const input =
 | 
			
		||||
        \\
 | 
			
		||||
    ;
 | 
			
		||||
    const sln = try solve(std.testing.allocator, input);
 | 
			
		||||
    try std.testing.expectEqual(@as(usize, 0), sln.b);
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user