const std = @import("std"); const Str = []const u8; const INPUT = "cqjxjnds"; pub fn first(allocator: std.mem.Allocator) !Str { var input: [INPUT.len]u8 = undefined; for (INPUT) |ch, idx| { input[idx] = ch; } return std.fmt.allocPrint(allocator, "{s}", .{nextPw(&input)}); } pub fn second(allocator: std.mem.Allocator) !Str { var input: [INPUT.len]u8 = undefined; for (INPUT) |ch, idx| { input[idx] = ch; } _ = nextPw(&input); // move the pw forward movePw(&input); return std.fmt.allocPrint(allocator, "{s}", .{nextPw(&input)}); } test "day11a" { const res = try first(std.testing.allocator); defer std.testing.allocator.free(res); try std.testing.expectEqualStrings("cqjxxyzz", res); } test "day11b" { const res = try second(std.testing.allocator); defer std.testing.allocator.free(res); try std.testing.expectEqualStrings("cqkaabcc", res); } fn nextPw(in: []u8) Str { // change the first disallowed char in advance for (in) |*ch, idx| { switch (ch.*) { 'i', 'o', 'l' => { ch.* = ch.* + 1; idx += 1; while (idx < in.len) : (idx += 1) { in[idx] = 'a'; } break; }, else => {}, } } while (true) { if (checkPw(in)) return in; movePw(in); } unreachable; } test "nextPw" { var input: [8]u8 = .{ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' }; try std.testing.expectEqualStrings("abcdffaa", nextPw(&input)); input = .{ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n' }; try std.testing.expectEqualStrings("ghjaabcc", nextPw(&input)); } fn movePw(in: []u8) void { var idx: usize = 8; while (idx > 0) : (idx -= 1) { if (in[idx - 1] == 'z') { in[idx - 1] = 'a'; } else { in[idx - 1] = in[idx - 1] + 1; break; } } } fn checkPw(in: Str) bool { if (in.len < 3) return false; var straight: bool = false; var st_start: u8 = in[0]; var doubles: usize = 0; var db_prev: u8 = in[0]; var overlap: bool = false; var idx: usize = 1; while (idx < in.len) : (idx += 1) { switch (in[idx]) { 'i', 'o', 'l' => return false, else => { // check straight if (!straight and idx != in.len - 1) { if (in[idx] - 1 == st_start and in[idx + 1] - 2 == st_start) { straight = true; } else { st_start = in[idx]; } } // check doubles if (doubles < 2 and !overlap) { // std.debug.print("{}: {c} {c}\n", .{ idx, db_prev, in[idx] }); if (in[idx] == db_prev) { doubles += 1; overlap = true; } } else { overlap = false; } db_prev = in[idx]; }, } } // std.debug.print("{s}: {} {}\n", .{ in, straight, doubles }); return straight and (doubles > 1); } test "checkPw" { try std.testing.expectEqual(false, checkPw("hijklmmn")); try std.testing.expectEqual(false, checkPw("abbceffg")); try std.testing.expectEqual(false, checkPw("abbcegjk")); try std.testing.expectEqual(false, checkPw("abcdefgh")); try std.testing.expectEqual(true, checkPw("abcdffaa")); try std.testing.expectEqual(false, checkPw("ghijklmn")); try std.testing.expectEqual(true, checkPw("ghjaabcc")); }