2022-13 in zig
This commit is contained in:
parent
2debf9a00d
commit
d9d870306c
4 changed files with 840 additions and 0 deletions
213
2022/13-distress-signal/second.zig
Normal file
213
2022/13-distress-signal/second.zig
Normal file
|
@ -0,0 +1,213 @@
|
|||
const std = @import("std");
|
||||
|
||||
const example = @embedFile("example");
|
||||
const input = @embedFile("input");
|
||||
|
||||
var allocator: std.mem.Allocator = undefined;
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
defer arena.deinit();
|
||||
allocator = arena.allocator();
|
||||
|
||||
try std.testing.expectEqual(try solve(example), 140);
|
||||
const result = try solve(input);
|
||||
try std.io.getStdOut().writer().print("{}\n", .{result});
|
||||
}
|
||||
|
||||
const ListErrors = error{
|
||||
OutOfMemory,
|
||||
};
|
||||
|
||||
const List = struct {
|
||||
data: std.ArrayList(Elt),
|
||||
fn addOne(l: *List) !*Elt {
|
||||
return try l.data.addOne();
|
||||
}
|
||||
fn init(reader: anytype) !*List {
|
||||
var l = try allocator.create(List);
|
||||
l.data = std.ArrayList(Elt).init(allocator);
|
||||
while (true) {
|
||||
const c = reader.readByte() catch break;
|
||||
switch (c) {
|
||||
'[' => {
|
||||
var e = try l.data.addOne();
|
||||
e.* = Elt{ .list = try List.init(reader) };
|
||||
},
|
||||
']' => {
|
||||
return l;
|
||||
},
|
||||
',' => { // comma after a list ending, ignore
|
||||
},
|
||||
else => { // a digit
|
||||
var e = try l.data.addOne();
|
||||
e.* = Elt{ .int = c - '0' };
|
||||
while (true) {
|
||||
const d = reader.readByte() catch unreachable;
|
||||
if (d == ']') {
|
||||
return l;
|
||||
} else if (d == ',') {
|
||||
break;
|
||||
}
|
||||
e.int = e.int * 10 + d;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
||||
fn initEmpty() !*List {
|
||||
var l = try allocator.create(List);
|
||||
l.data = std.ArrayList(Elt).init(allocator);
|
||||
return l;
|
||||
}
|
||||
fn initSingleton(n: u8) !*List {
|
||||
var l = try allocator.create(List);
|
||||
l.data = std.ArrayList(Elt).init(allocator);
|
||||
var e = try l.data.addOne();
|
||||
e.* = Elt{ .int = n };
|
||||
return l;
|
||||
}
|
||||
fn isLowerThan(l: *List, o: *List) ListErrors!?bool {
|
||||
var i: usize = 0;
|
||||
while (true) : (i += 1) {
|
||||
if (o.len() <= i) {
|
||||
if (l.len() <= i) {
|
||||
return null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (l.len() <= i) {
|
||||
return true;
|
||||
}
|
||||
const t = try l.data.items[i].isLowerThan(&(o.data.items[i]));
|
||||
if (t != null) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
inline fn len(l: *List) usize {
|
||||
return l.data.items.len;
|
||||
}
|
||||
fn print(l: *List) void {
|
||||
for (l.data.items) |e| {
|
||||
switch (e) {
|
||||
Elt.int => |i| std.debug.print("{d} ", .{i}),
|
||||
Elt.list => |o| {
|
||||
std.debug.print("[", .{});
|
||||
o.print();
|
||||
std.debug.print("]", .{});
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const EltType = enum {
|
||||
int,
|
||||
list,
|
||||
};
|
||||
|
||||
const Elt = union(EltType) {
|
||||
int: u8,
|
||||
list: *List,
|
||||
fn isLowerThan(e: *Elt, f: *Elt) !?bool {
|
||||
switch (e.*) {
|
||||
Elt.int => |i| switch (f.*) {
|
||||
Elt.int => |j| {
|
||||
if (i == j) {
|
||||
return null;
|
||||
}
|
||||
return i < j;
|
||||
},
|
||||
Elt.list => |o| {
|
||||
var l = try List.initSingleton(i);
|
||||
return l.isLowerThan(o);
|
||||
},
|
||||
},
|
||||
Elt.list => |l| switch (f.*) {
|
||||
Elt.int => |j| {
|
||||
var ll = Elt{ .list = try List.initSingleton(j) };
|
||||
return e.isLowerThan(&ll);
|
||||
},
|
||||
Elt.list => |o| {
|
||||
return l.isLowerThan(o);
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fn lesserThan(context: void, a: *Elt, b: *Elt) bool {
|
||||
_ = context;
|
||||
var tt = a.isLowerThan(b) catch unreachable;
|
||||
if (tt) |t| {
|
||||
if (t) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn solve(puzzle: []const u8) !u64 {
|
||||
var it = std.mem.tokenize(u8, puzzle, "\n");
|
||||
var list = std.ArrayList(*Elt).init(allocator);
|
||||
var divider2Line = std.io.fixedBufferStream("[[2]]");
|
||||
var div2 = try list.addOne();
|
||||
div2.* = try allocator.create(Elt);
|
||||
div2.*.* = Elt{ .list = try List.init(divider2Line.reader()) };
|
||||
var divider6Line = std.io.fixedBufferStream("[[6]]");
|
||||
var div6 = try list.addOne();
|
||||
div6.* = try allocator.create(Elt);
|
||||
div6.*.* = Elt{ .list = try List.init(divider6Line.reader()) };
|
||||
// process input
|
||||
while (it.next()) |line| {
|
||||
var bs = std.io.fixedBufferStream(line);
|
||||
var elt = try list.addOne();
|
||||
elt.* = try allocator.create(Elt);
|
||||
elt.*.* = Elt{ .list = try List.init(bs.reader()) };
|
||||
}
|
||||
// sort the list
|
||||
std.sort.sort(*Elt, list.items, {}, lesserThan);
|
||||
//for (list.items) |l| {
|
||||
// l.list.print();
|
||||
// std.debug.print("\n", .{});
|
||||
//}
|
||||
// compute output
|
||||
var ret: usize = 1;
|
||||
for (list.items) |l, i| {
|
||||
switch (l.*) {
|
||||
Elt.int => {},
|
||||
Elt.list => |ll| {
|
||||
if (ll.len() != 1) {
|
||||
continue;
|
||||
}
|
||||
switch (ll.data.items[0]) {
|
||||
Elt.int => {},
|
||||
Elt.list => |lll| {
|
||||
if (lll.len() != 1) {
|
||||
continue;
|
||||
}
|
||||
switch (lll.data.items[0]) {
|
||||
Elt.int => {},
|
||||
Elt.list => |llll| {
|
||||
if (llll.len() != 1) {
|
||||
continue;
|
||||
}
|
||||
switch (llll.data.items[0]) {
|
||||
Elt.int => |n| {
|
||||
if (n == 2 or n == 6) {
|
||||
ret *= (i + 1);
|
||||
}
|
||||
},
|
||||
Elt.list => {},
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue