12: part1+2
This commit is contained in:
parent
df3ee0e171
commit
fd0c840fdb
4 changed files with 330 additions and 0 deletions
24
12/input
Normal file
24
12/input
Normal file
|
@ -0,0 +1,24 @@
|
|||
hl-WP
|
||||
vl-fo
|
||||
vl-WW
|
||||
WP-start
|
||||
vl-QW
|
||||
fo-wy
|
||||
WW-dz
|
||||
dz-hl
|
||||
fo-end
|
||||
VH-fo
|
||||
ps-vl
|
||||
FN-dz
|
||||
WP-ps
|
||||
ps-start
|
||||
WW-hl
|
||||
end-QW
|
||||
start-vl
|
||||
WP-fo
|
||||
end-FN
|
||||
hl-QW
|
||||
WP-dz
|
||||
QW-fo
|
||||
QW-dz
|
||||
ps-dz
|
130
12/part1.zig
Normal file
130
12/part1.zig
Normal file
|
@ -0,0 +1,130 @@
|
|||
const std = @import("std");
|
||||
const print = std.debug.print;
|
||||
|
||||
const Node = []const u8;
|
||||
const Route = std.ArrayList(Node);
|
||||
const Edge = struct {
|
||||
left: Node,
|
||||
right: Node
|
||||
};
|
||||
|
||||
fn contains(list: []Node, x: Node) bool {
|
||||
for (list) |node| {
|
||||
if (std.mem.eql(u8, node, x)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn getOther(edge: Edge, node: Node) ?Node {
|
||||
if (std.mem.eql(u8, edge.left, node)) {
|
||||
return edge.right;
|
||||
}
|
||||
if (std.mem.eql(u8, edge.right, node)) {
|
||||
return edge.left;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
fn isSmol(node: Node) bool {
|
||||
for (node) |rune| {
|
||||
if (!std.ascii.isLower(rune)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
var alloc = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer std.debug.assert(!alloc.deinit());
|
||||
var gpa = &alloc.allocator;
|
||||
|
||||
const stdin = std.io.getStdIn().reader();
|
||||
|
||||
var res: u32 = 0;
|
||||
|
||||
var edges = std.ArrayList(Edge).init(gpa);
|
||||
defer edges.deinit();
|
||||
|
||||
var input = try stdin.readAllAlloc(gpa, 4096);
|
||||
defer gpa.free(input);
|
||||
|
||||
var lines = std.mem.split(input, "\n");
|
||||
while (lines.next()) |line| {
|
||||
var it = std.mem.split(line, "-");
|
||||
var left = it.next() orelse unreachable;
|
||||
var right = it.next() orelse unreachable;
|
||||
|
||||
try edges.append(Edge{
|
||||
.left = left,
|
||||
.right = right,
|
||||
});
|
||||
}
|
||||
|
||||
var routes = std.ArrayList(Route).init(gpa);
|
||||
defer {
|
||||
for (routes.items) |route| {
|
||||
route.deinit();
|
||||
}
|
||||
routes.deinit();
|
||||
}
|
||||
{
|
||||
var route = Route.init(gpa);
|
||||
try route.append("start");
|
||||
try routes.append(route);
|
||||
}
|
||||
|
||||
// var x: u8 = 0;
|
||||
|
||||
while (true) {
|
||||
var cont = false;
|
||||
|
||||
var newRoutes = std.ArrayList(Route).init(gpa);
|
||||
defer newRoutes.deinit();
|
||||
|
||||
var stale = std.ArrayList(usize).init(gpa);
|
||||
defer stale.deinit();
|
||||
|
||||
// print("Routes ({}):\n", .{routes.items.len});
|
||||
// for (routes.items) |route| {
|
||||
// print("{s}\n", .{route.items});
|
||||
// }
|
||||
|
||||
for (routes.items) |route, i| {
|
||||
const last = route.items[route.items.len - 1];
|
||||
if (std.mem.eql(u8, last, "end")) {
|
||||
continue;
|
||||
}
|
||||
cont = true;
|
||||
try stale.append(i);
|
||||
|
||||
for (edges.items) |edge| {
|
||||
if (getOther(edge, last)) |other| {
|
||||
// print("> {s}\n", .{other});
|
||||
if (isSmol(other) and contains(route.items, other)) {
|
||||
continue;
|
||||
} else {
|
||||
var newRoute = Route.init(gpa);
|
||||
try newRoute.appendSlice(route.items);
|
||||
try newRoute.append(other);
|
||||
// print("new route: {s}\n", .{newRoute.items});
|
||||
try newRoutes.append(newRoute);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var i: usize = 0;
|
||||
while (i < stale.items.len) : (i += 1) {
|
||||
var route = routes.orderedRemove(stale.items[stale.items.len-1-i]);
|
||||
route.deinit();
|
||||
}
|
||||
|
||||
try routes.appendSlice(newRoutes.items);
|
||||
|
||||
if (!cont) break;
|
||||
}
|
||||
|
||||
std.debug.print("{}\n", .{routes.items.len});
|
||||
}
|
169
12/part2.zig
Normal file
169
12/part2.zig
Normal file
|
@ -0,0 +1,169 @@
|
|||
const std = @import("std");
|
||||
const print = std.debug.print;
|
||||
|
||||
const Node = u16;
|
||||
const Route = []Node;
|
||||
const Edge = struct {
|
||||
left: Node,
|
||||
right: Node
|
||||
};
|
||||
|
||||
const START_NODE = 0x0000;
|
||||
const END_NODE = 0xffff;
|
||||
|
||||
fn parseNode(input: []const u8) Node {
|
||||
if (std.mem.eql(u8, input, "start")) return START_NODE;
|
||||
if (std.mem.eql(u8, input, "end")) return END_NODE;
|
||||
if (input.len == 1) return @intCast(u16, input[0]) << 8 | 0x20;
|
||||
return @intCast(u16, input[0]) << 8 | input[1];
|
||||
}
|
||||
|
||||
fn isThereASmolDuplicate(list: []Node) bool {
|
||||
for (list) |node| {
|
||||
if (isSmol(node) and count(list, node) > 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn count(list: []Node, x: Node) u32 {
|
||||
var res: u32 = 0;
|
||||
for (list) |node| {
|
||||
if (node == x) {
|
||||
res += 1;
|
||||
if (res == 2) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
fn isForbiddenSmol(list: []Node, x: Node) bool {
|
||||
if (isThereASmolDuplicate(list)) {
|
||||
for (list) |node| {
|
||||
if (node == x) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else if (x == START_NODE) {
|
||||
return true;
|
||||
} else {
|
||||
return count(list, x) > 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn getOther(edge: Edge, node: Node) ?Node {
|
||||
if (edge.left == node) {
|
||||
return edge.right;
|
||||
}
|
||||
if (edge.right == node) {
|
||||
return edge.left;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
fn isSmol(node: Node) bool {
|
||||
return (node & 0x2020) == 0x2020 or node == START_NODE or node == END_NODE;
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
var alloc = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer std.debug.assert(!alloc.deinit());
|
||||
var gpa = &alloc.allocator;
|
||||
|
||||
const stdin = std.io.getStdIn().reader();
|
||||
|
||||
var res: u32 = 0;
|
||||
|
||||
var edges = std.ArrayList(Edge).init(gpa);
|
||||
defer edges.deinit();
|
||||
|
||||
var input = try stdin.readAllAlloc(gpa, 4096);
|
||||
defer gpa.free(input);
|
||||
|
||||
var lines = std.mem.split(input, "\n");
|
||||
while (lines.next()) |line| {
|
||||
var it = std.mem.split(line, "-");
|
||||
var left = it.next() orelse unreachable;
|
||||
var right = it.next() orelse unreachable;
|
||||
var leftInt = parseNode(left);
|
||||
var rightInt = parseNode(right);
|
||||
|
||||
try edges.append(Edge{
|
||||
.left = leftInt,
|
||||
.right = rightInt,
|
||||
});
|
||||
}
|
||||
|
||||
var routes = std.ArrayList(Route).init(gpa);
|
||||
defer {
|
||||
for (routes.items) |route| {
|
||||
gpa.free(route);
|
||||
}
|
||||
routes.deinit();
|
||||
}
|
||||
{
|
||||
var route = try gpa.alloc(Node, 1);
|
||||
route[0] = START_NODE;
|
||||
try routes.append(route);
|
||||
}
|
||||
|
||||
var x: u8 = 0;
|
||||
|
||||
while (x < 1000) : (x += 1) {
|
||||
var cont = false;
|
||||
|
||||
var newRoutes = std.ArrayList(Route).init(gpa);
|
||||
defer newRoutes.deinit();
|
||||
|
||||
var stale = std.ArrayList(usize).init(gpa);
|
||||
defer stale.deinit();
|
||||
|
||||
// print("Routes ({}):\n", .{routes.items.len});
|
||||
// for (routes.items) |route| {
|
||||
// print("{any}\n", .{route.items});
|
||||
// }
|
||||
|
||||
for (routes.items) |route, i| {
|
||||
const last = route[route.len - 1];
|
||||
if (last == END_NODE) {
|
||||
continue;
|
||||
}
|
||||
cont = true;
|
||||
try stale.append(i);
|
||||
|
||||
for (edges.items) |edge| {
|
||||
if (getOther(edge, last)) |other| {
|
||||
// print("> {s}\n", .{other});
|
||||
if (isSmol(other) and isForbiddenSmol(route, other)) {
|
||||
continue;
|
||||
} else {
|
||||
var newRoute = try gpa.alloc(Node, route.len+1);
|
||||
std.mem.copy(Node, newRoute, route);
|
||||
newRoute[route.len] = other;
|
||||
// print("new route: {s}\n", .{newRoute.items});
|
||||
try newRoutes.append(newRoute);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// print("Removed routes: {}\n", .{stale.items.len});
|
||||
// print("Added routes: {}\n", .{newRoutes.items.len});
|
||||
|
||||
var i: usize = 0;
|
||||
while (i < stale.items.len) : (i += 1) {
|
||||
var route = routes.swapRemove(stale.items[stale.items.len-1-i]);
|
||||
gpa.free(route);
|
||||
}
|
||||
|
||||
try routes.appendSlice(newRoutes.items);
|
||||
|
||||
if (!cont) break;
|
||||
}
|
||||
|
||||
std.debug.print("{}\n", .{routes.items.len});
|
||||
}
|
7
12/testinput
Normal file
7
12/testinput
Normal file
|
@ -0,0 +1,7 @@
|
|||
start-A
|
||||
start-b
|
||||
A-c
|
||||
A-b
|
||||
b-d
|
||||
A-end
|
||||
b-end
|
Loading…
Reference in a new issue