Solution to 10-1
This commit is contained in:
parent
4fdbce7204
commit
d8fcb209ab
55
inputs/10/real.txt
Normal file
55
inputs/10/real.txt
Normal file
@ -0,0 +1,55 @@
|
||||
0123450128945212434498107654876212322345432110787870123
|
||||
1214563287654302345347278923945003411276741025696983254
|
||||
2307874390901201436256361010232156500985891234899874765
|
||||
3458965481896543457101454322121267898764210348760565856
|
||||
4547889332787612898654456541010128709654321409651487943
|
||||
9656971245610502348742363456723489214545670512342396512
|
||||
8746560330541461059231072019894876523039987651229603401
|
||||
0130450101232878762108981923785955432128896560318712101
|
||||
1221321432543969456676870831276843201017698431105657892
|
||||
4349898540158950387985106740189652122012587120234598761
|
||||
0456797643267341293234203651076561043403436011231034650
|
||||
1245687653212210982178312312345878654312345190345125141
|
||||
4334567064307807891089425405658969763233438987656776032
|
||||
5321018165616906702376596534787439890120107678949889120
|
||||
6910789278965215610345687321096521763011234589030672101
|
||||
7821898347654334321256786543212310652101347654121543432
|
||||
6734787658901223456105897610105432543276978903443430563
|
||||
2105676987911010897834978923076501034789877412352321694
|
||||
3456989876854323708929870134589632385676966543261430785
|
||||
4367810105763432612210165245678745690123457898170567014
|
||||
3210121234176501523878954354776544787430342347089698923
|
||||
2345665893080787438965410167889432156561231456798789654
|
||||
1058756702191898341014321054974321047892120321887018763
|
||||
0569845212012567634323015123125410430121011010986323454
|
||||
6578954307623498765487654304034543221030345654345432125
|
||||
5434356788545349854599001216787652107845210787216701034
|
||||
0125643699237898703678104325894567856956789891209834345
|
||||
7876212765103203612363215454383898945787698900340125876
|
||||
0980101894454114503054356965212432430694543215489876965
|
||||
1098234583467023212125407870106541021583210676098920145
|
||||
2347899602898908763256910187017865652678701587187813236
|
||||
3256678711743219854567823298894976569549652490296704367
|
||||
0100345620651278343289654350765987478230743321345410198
|
||||
9251201234230341230178760541034300300121890120034326789
|
||||
8349212945145650789078921632133211212010581631128965632
|
||||
7658767876054787632107634780124504321123498745489874541
|
||||
6107323945763096549616543995435665210898589654788103450
|
||||
5236014539892124328723012876343786789867670123694012367
|
||||
4345867622101015610654322301212891270184561054543231018
|
||||
2109988913412126789961001454309750301293432163210102309
|
||||
3458776804569234697872156545678543432789430673456943212
|
||||
4567566543678985586543267836787612545676521982987856103
|
||||
0103457012987876487434586927898707654568701201276547894
|
||||
1212388967876567393325698810989898965439632320567030985
|
||||
0327890658905058212016784543298781012344543011498121076
|
||||
9456541243014149801134569650185632307655676322399876125
|
||||
8767632332123232100123678745670546998764985431087565436
|
||||
3498234501104343034598988764321457884643891056016501098
|
||||
2567107698612352125667639058901210745012342347121432167
|
||||
1989278786783961012787540147654323654321435218930345236
|
||||
0876989695894878109896039236569456788760324306543210145
|
||||
0105874504185769854385128545478998699354413457850105256
|
||||
1234763213096854763014537654360187543263509766969876567
|
||||
2303452342187943212323456963201236984102678876878103498
|
||||
3212301056789810103410567870102345676101278987989012567
|
8
inputs/10/test.txt
Normal file
8
inputs/10/test.txt
Normal file
@ -0,0 +1,8 @@
|
||||
89010123
|
||||
78121874
|
||||
87430965
|
||||
96549874
|
||||
45678903
|
||||
32019012
|
||||
01329801
|
||||
10456732
|
29
scratch.zig
29
scratch.zig
@ -3,24 +3,29 @@ const print = std.debug.print;
|
||||
|
||||
const expect = @import("std").testing.expect;
|
||||
|
||||
test "Len of an iterator is not the same as size" {
|
||||
test ".toOwnedSlice does not seem to make deinit unnecessary" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
var map = std.AutoHashMap(u8, u8).init(allocator);
|
||||
try map.put('a', 'b');
|
||||
try map.put('c', 'd');
|
||||
try map.put('e', 'f');
|
||||
var listOfLists = std.ArrayList([]u32).init(allocator);
|
||||
try listOfLists.append(try buildAList(0, allocator));
|
||||
try listOfLists.append(try buildAList(1, allocator));
|
||||
|
||||
var keyIterator = map.keyIterator();
|
||||
const length = keyIterator.len;
|
||||
var counted_length: usize = 0;
|
||||
while (keyIterator.next()) |_| {
|
||||
counted_length += 1;
|
||||
const outer_slice = try listOfLists.toOwnedSlice();
|
||||
print("{any}\n", .{outer_slice});
|
||||
for (outer_slice) |inner_slice| {
|
||||
allocator.free(inner_slice);
|
||||
}
|
||||
print("DEBUG - length is {} and counted_length is {}\n", .{ length, counted_length });
|
||||
try expect(length == counted_length);
|
||||
allocator.free(outer_slice);
|
||||
}
|
||||
|
||||
fn buildAList(val: u32, allocator: std.mem.Allocator) ![]u32 {
|
||||
var list = std.ArrayList(u32).init(allocator);
|
||||
|
||||
try list.append(val);
|
||||
|
||||
return list.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
|
@ -184,11 +184,11 @@ fn hasSpaceToMove(disk: std.ArrayList(?u32), pointer: usize, file_size: usize) b
|
||||
|
||||
const expect = std.testing.expect;
|
||||
|
||||
// test "part_one" {
|
||||
// const part_one_response = try part_one(true);
|
||||
// print("DEBUG - part_one_response is {}\n", .{part_one_response});
|
||||
// try expect(part_one_response == 1928);
|
||||
// }
|
||||
test "part_one" {
|
||||
const part_one_response = try part_one(true);
|
||||
print("DEBUG - part_one_response is {}\n", .{part_one_response});
|
||||
try expect(part_one_response == 1928);
|
||||
}
|
||||
|
||||
test "part_two" {
|
||||
const part_two_response = try part_two(true);
|
||||
|
140
solutions/10.zig
Normal file
140
solutions/10.zig
Normal file
@ -0,0 +1,140 @@
|
||||
const std = @import("std");
|
||||
const print = std.debug.print;
|
||||
const util = @import("util.zig");
|
||||
|
||||
pub fn main() !void {
|
||||
const response = try part_one(false);
|
||||
print("{}\n", .{response});
|
||||
}
|
||||
|
||||
const Location = struct {
|
||||
x: usize,
|
||||
y: usize,
|
||||
// The amount of casting in this is astonishing. Surely there must be a better way to do this?
|
||||
fn newLocation(start: Location, x_move: i32, y_move: i32, width: usize, height: usize) ?Location {
|
||||
const start_x_as_i32: i32 = @intCast(start.x);
|
||||
const new_x = start_x_as_i32 + x_move;
|
||||
const start_y_as_i32: i32 = @intCast(start.y);
|
||||
const new_y = start_y_as_i32 + y_move;
|
||||
|
||||
if (new_x < 0 or new_x >= width or new_y < 0 or new_y >= height) {
|
||||
return null;
|
||||
}
|
||||
return Location{ .x = @intCast(new_x), .y = @intCast(new_y) };
|
||||
}
|
||||
};
|
||||
|
||||
fn part_one(is_test_case: bool) anyerror!u64 {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const input_file = try util.getInputFile("10", is_test_case);
|
||||
const data = try util.readAllInputWithAllocator(input_file, allocator);
|
||||
defer allocator.free(data);
|
||||
|
||||
const grid = try buildGrid(data, allocator);
|
||||
defer allocator.free(grid);
|
||||
print("{any}\n", .{grid});
|
||||
|
||||
// If we wanted, we could find trailheads during the `buildGrid` iteration, but given the small data sizes I'd much
|
||||
// rather keep small focused functions at the cost of some constant-factor performance.
|
||||
var total: u32 = 0;
|
||||
var i: usize = 0;
|
||||
while (i < grid.len) : (i += 1) {
|
||||
var j: usize = 0;
|
||||
while (j < grid[0].len) : (j += 1) {
|
||||
if (grid[i][j] == 0) {
|
||||
var so_far = std.AutoHashMap(Location, bool).init(allocator);
|
||||
const err = getReachablePeaks(grid, Location{ .x = j, .y = i }, 0, &so_far, allocator);
|
||||
if (err != null) {
|
||||
return err.?;
|
||||
}
|
||||
const score = so_far.count();
|
||||
print("DEBUG - for the trailhead at {}/{}, found a trailscore of {}\n", .{ j, i, score });
|
||||
total += score;
|
||||
so_far.deinit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wow I do _not_ like memory management
|
||||
for (grid) |line| {
|
||||
allocator.free(line);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
fn buildGrid(data: []const u8, alloc: std.mem.Allocator) ![][]u32 {
|
||||
var lines = std.ArrayList([]u32).init(alloc);
|
||||
defer lines.deinit();
|
||||
|
||||
var current_line = std.ArrayList(u32).init(alloc);
|
||||
defer current_line.deinit();
|
||||
|
||||
for (data) |c| {
|
||||
if (c == '\n') {
|
||||
const slice = try current_line.toOwnedSlice();
|
||||
try lines.append(slice);
|
||||
} else {
|
||||
try current_line.append(c - 48);
|
||||
}
|
||||
}
|
||||
return try lines.toOwnedSlice();
|
||||
}
|
||||
|
||||
fn buildNeighbours(grid: [][]u32, location: Location, alloc: std.mem.Allocator) ![]Location {
|
||||
var neighbours = std.ArrayList(Location).init(alloc);
|
||||
defer neighbours.deinit();
|
||||
|
||||
const up = Location.newLocation(location, 0, -1, grid[0].len, grid.len);
|
||||
if (up != null) {
|
||||
try neighbours.append(up.?);
|
||||
}
|
||||
|
||||
const right = Location.newLocation(location, 1, 0, grid[0].len, grid.len);
|
||||
if (right != null) {
|
||||
try neighbours.append(right.?);
|
||||
}
|
||||
|
||||
const down = Location.newLocation(location, 0, 1, grid[0].len, grid.len);
|
||||
if (down != null) {
|
||||
try neighbours.append(down.?);
|
||||
}
|
||||
|
||||
const left = Location.newLocation(location, -1, 0, grid[0].len, grid.len);
|
||||
if (left != null) {
|
||||
try neighbours.append(left.?);
|
||||
}
|
||||
|
||||
return neighbours.toOwnedSlice();
|
||||
}
|
||||
|
||||
fn getReachablePeaks(grid: [][]u32, start: Location, start_value: u32, so_far: *std.AutoHashMap(Location, bool), alloc: std.mem.Allocator) ?anyerror {
|
||||
if (start_value == 9) {
|
||||
try so_far.put(start, true);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check up, down, left, right - if they have the right next value, iterate from there
|
||||
const neighbours = try buildNeighbours(grid, start, alloc);
|
||||
for (neighbours) |neighbour| {
|
||||
if (grid[neighbour.y][neighbour.x] == start_value + 1) {
|
||||
const err = getReachablePeaks(grid, neighbour, start_value + 1, so_far, alloc);
|
||||
if (err != null) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
alloc.free(neighbours);
|
||||
return null;
|
||||
}
|
||||
|
||||
const expect = std.testing.expect;
|
||||
|
||||
test "part_one" {
|
||||
const part_one_response = try part_one(true);
|
||||
print("DEBUG - part_one_response is {}\n", .{part_one_response});
|
||||
try expect(part_one_response == 36);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user