1
0

Compare commits

..

10 Commits

Author SHA1 Message Date
ba0a624f85 Added day 16 2024-12-16 23:10:47 +01:00
4878bb4924 Added delimiter in table 2024-12-15 20:42:17 +01:00
cd5ae0e98c Typo in table 2024-12-15 20:41:19 +01:00
a902e6fc7f Added day 15 2024-12-15 20:39:38 +01:00
8c59c074f4 Added day 14 2024-12-15 12:57:26 +01:00
26a517c7a3 Added shitty day 13 2024-12-15 10:56:23 +01:00
3cd677bbaf Removed print 2024-12-13 23:24:57 +01:00
e0aa0ce26c Added day 11 and 12 2024-12-13 23:24:49 +01:00
b09d5fe966 Added day 10, proud of it, nice solution :) 2024-12-10 22:49:19 +01:00
832bef6497 Added day 9
Forgot to push yesterday :/
2024-12-10 17:58:08 +01:00
25 changed files with 4173 additions and 18 deletions

View File

@ -12,20 +12,36 @@ Can be run with `zig run -O ReleaseFast benchmark.zig`
| Day | Part | Mean (μs) | Min (μs) | Max (μs) |
|-----|------|-------------------|----------|----------|
| 1 | 1 | +23 ± 2.24 | +23 | +68 |
| 1 | 2 | +24 ± 4.24 | +23 | +86 |
| 2 | 1 | +36 ± 5.29 | +32 | +88 |
| 2 | 2 | +287 ± 42.28 | +245 | +550 |
| 3 | 1 | +24 ± 2.45 | +20 | +41 |
| 3 | 2 | +21 ± 3.74 | +17 | +42 |
| 4 | 1 | +213 ± 15.75 | +202 | +300 |
| 4 | 2 | +212 ± 13.78 | +202 | +340 |
| 5 | 1 | +160 ± 30.46 | +120 | +479 |
| 5 | 2 | +160 ± 27.29 | +118 | +366 |
| 6 | 1 | +31 ± 3.87 | +28 | +128 |
| 1 | 1 | +25 ± 6.93 | +23 | +67 |
| 1 | 2 | +25 ± 4.69 | +24 | +50 |
| 2 | 1 | +35 ± 3.00 | +33 | +45 |
| 2 | 2 | +266 ± 15.17 | +251 | +329 |
| 3 | 1 | +25 ± 2.45 | +24 | +40 |
| 3 | 2 | +18 ± 2.00 | +17 | +28 |
| 4 | 1 | +217 ± 4.47 | +211 | +232 |
| 4 | 2 | +218 ± 5.10 | +212 | +239 |
| 5 | 1 | +175 ± 50.21 | +131 | +353 |
| 5 | 2 | +141 ± 22.93 | +130 | +252 |
| 6 | 1 | +32 ± 1.73 | +31 | +42 |
| 6 | 2 | Too long ~60s | 0 | 0 |
| 7 | 1 | +191 ± 33.14 | +156 | +340 |
| 7 | 1 | +211 ± 16.19 | +189 | +288 |
| 7 | 2 | Too long ~0.2s | 0 | 0 |
| 8 | 1 | +527 ± 69.48 | +481 | +896 |
| 8 | 2 | +803 ± 92.79 | +736 | +1328 |
| Total | | +2712 ± 346.82 | +2403 | +5052 |
|-----|------|-------------------|----------|----------|
| 8 | 1 | +511 ± 13.93 | +497 | +581 |
| 8 | 2 | +844 ± 46.60 | +805 | +1095 |
| 9 | 1 | +1514 ± 122.07 | +1307 | +1811 |
| 9 | 2 | Too long ~0.6s | 0 | 0 |
| 10 | 1 | +37 ± 7.87 | +35 | +83 |
| 10 | 2 | +28 ± 5.57 | +27 | +62 |
| 11 | 1 | +2139 ± 291.76 | +1931 | +2989 |
| 11 | 2 | +5060 ± 159.47 | +4903 | +5580 |
| 12 | 1 | +44947 ± 1417.02 | +43224 | +49471 |
| 12 | 2 | +48279 ± 2536.03 | +45591 | +57175 |
| 13 | 1 | +1522 ± 119.51 | +1445 | +2178 |
| 13 | 2 | Too long ~6h | 0 | 0 |
| 14 | 1 | +137 ± 5.10 | +130 | +165 |
| 14 | 2 | Need input | 0 | 0 |
|-----|------|-------------------|----------|----------|
| 15 | 1 | +71 ± 41.96 | +42 | +182 |
| 15 | 2 | +200 ± 34.13 | +172 | +301 |
| Total| | +106677 ± 4935.90 | +101385 | +123638 |

View File

@ -16,8 +16,21 @@ const d71 = @import("day7/part1.zig");
const d72 = @import("day7/part2.zig");
const d81 = @import("day8/part1.zig");
const d82 = @import("day8/part2.zig");
const d91 = @import("day9/part1.zig");
const d92 = @import("day9/part2.zig");
const d101 = @import("day10/part1.zig");
const d102 = @import("day10/part2.zig");
const d111 = @import("day11/part1.zig");
const d112 = @import("day11/part2.zig");
const d121 = @import("day12/part1.zig");
const d122 = @import("day12/part2.zig");
const d131 = @import("day13/part1.zig");
const d141 = @import("day14/part1.zig");
const d151 = @import("day15/part1.zig");
const d152 = @import("day15/part2.zig");
const d161 = @import("day16/part1.zig");
const NUMBER_OF_RUN = 1000;
const NUMBER_OF_RUN = 50;
var total_mean: i64 = 0;
var total_min: i64 = 0;
@ -52,7 +65,31 @@ pub fn main() !void {
try benchmark(d81.main, 8, 1);
try benchmark(d82.main, 8, 2);
separator();
print("| Total | {d: >8} ± {d: <6.2} | {d:>8} | {d:>8} |\n", .{ total_mean, total_std_dev, total_min, total_max });
try benchmark(d91.main, 9, 1);
print("| 9 | 2 | Too long ~0.6s | 0 | 0 |\n", .{});
separator();
try benchmark(d101.main, 10, 1);
try benchmark(d102.main, 10, 2);
separator();
try benchmark(d111.main, 11, 1);
try benchmark(d112.main, 11, 2);
separator();
try benchmark(d121.main, 12, 1);
try benchmark(d122.main, 12, 2);
separator();
try benchmark(d131.main, 13, 1);
print("| 13 | 2 | Too long ~6h | 0 | 0 |\n", .{});
separator();
try benchmark(d141.main, 14, 1);
print("| 14 | 2 | Need input | 0 | 0 |\n", .{});
separator();
try benchmark(d151.main, 15, 1);
try benchmark(d152.main, 15, 2);
separator();
try benchmark(d161.main, 16, 1);
print("| 16 | 2 | Too long ~8s | 0 | 0 |\n", .{});
separator();
print("| Total | {d: >8} ± {d: <6.0} | {d:>8} | {d:>8} |\n", .{ total_mean, total_std_dev, total_min, total_max });
separator();
}
@ -66,7 +103,7 @@ pub fn benchmark(func: anytype, day: u8, part: u8) !void {
}
// Adjusted tabs for better alignment
print("| {d:<3} | {d:<4} | {d:>8} ± {d:<6.2} | {d:>8} | {d:>8} |\n", .{ day, part, mean(time_buff), std_dev(time_buff), min(time_buff), max(time_buff) });
print("| {d:<3} | {d:<4} | {d:>8} ± {d:<6.0} | {d:>8} | {d:>8} |\n", .{ day, part, mean(time_buff), std_dev(time_buff), min(time_buff), max(time_buff) });
total_mean += mean(time_buff);
total_min += min(time_buff);
total_max += max(time_buff);

60
day10/input Normal file
View File

@ -0,0 +1,60 @@
432109865210212123765432101234321098543289654320132112121058
045678774324301012892343023445456787650198763013241001034569
187678789465692321001056014896234986456787012894653212123678
296589921056789433217837895687145675323891233765784589238987
345437835434576544786921278761010014210710321212098676521067
032126546323465435695430789760121223121653450303145125430678
123010567810156543212345699859834321056544067654236012321589
543213498987657665401030787348765430187432198765987622345432
654100332394348972342321895201256589196343089543212331056741
789011241003238981089400776100343678015434567630105449879870
296721256210169895676510385011892349101325678921256756768987
129830787323456765410321294332761058210012310123890891057610
056745698234556786329454301245656567341110567894781232346521
145894510149645699438765892398305678956923498965654343765430
236586789838732388454326765567214307967845697874505652894321
105675676545321267565810674354303212875430786543216701678912
234321501656130054278989983289432120123421803403545810787600
321030432567032123123678100176563018987578912012932921298541
892349803498145031034563210327898101879647810123871092567432
785056712387236567687654389410787632768756303294562783458943
176120987656547858998545076585894583459843214785103698327874
015431234543218947657898145894983298708941025672234567016761
329122345692105438941763236783470165617652912341013053205430
478031001785676323430154100102565674320543805432332122124321
567649872434985610121894321211056589211230796901440345034234
456659763323810765456765894323987401108921687878981236565105
306778654310329876365498765012342322317834510967892387156076
219865011078478901278321001231451015436123423456785493087189
652104102569560110669125198340760896895034587655476334196892
765233243458721321701034567654878987764105694344301243234561
894310321029832459852567878723965430653298743213210358765410
132123478010741069743478989014436321541056543401821569898324
098034569123658978654321876101521087632347812114981678876543
107765678034567867569270965437698794545938903003470549987432
256872345621098654378187602348967003897821094012561232789501
345901436438767789210094511059854112766123285723034341076521
217894387589656231234543223456743245675054176894125652112430
306105498678543140567672100145101230984169065765898763203431
495218321067012056478981041234230121243078434965235678976521
584349452652100987329891230765345698732154567874143454989210
673458763643211011010010049874556781235463456963056763474321
567647601781012567892102156743765470346322161012369812565232
498678432692123476543103095652834387457210052623871001450143
304509543543001989698234589501921098768921106780982341019898
213219601982132670787825676501432349810123235691987432870767
894348732676544561236910787432321056769894344302346549961251
765210145690125650345210097899867892110765654219854678450340
890100126780034743094303126934786543023234565678765012321231
765987034621129802185412235025696541032167876789874349876012
876856541234988012276543384110567832249054965694101256778123
965987650945876543543215493201378980158345434783450126789894
457871056876067875456906780110234589267210321692569034670765
320432347780128965307878767820199674307890160541078765521254
011876548991234534218349856936788765216543254332112340432345
432965432781049621029256743245215656325321067210003451201056
547876501632898756540178652101304567101452198760116764342767
656983432542765987438769789012453898212968765641985895433898
898792323101874104329054210589562456703879454332076016924567
125601017652963265012123323676571329894312303549165327810430
034340178943012378901012334568980016765601212678234456901321

39
day10/part1.zig Normal file
View File

@ -0,0 +1,39 @@
const std = @import("std");
const print = std.debug.print;
const input = @embedFile("input");
const MAP_SIZE = 60;
pub fn main() !void {
var map: [MAP_SIZE + 2][MAP_SIZE + 2]u8 = undefined;
for (0..MAP_SIZE + 2) |x| for (0..MAP_SIZE + 2) |y| {
map[x][y] = 0;
};
for (input, 0..) |c, i| {
if (c == '\n') continue;
map[@divFloor(i, MAP_SIZE + 1) + 1][i % (MAP_SIZE + 1) + 1] = c - '0';
}
var total: usize = 0;
var founded = std.AutoHashMap([2]usize, void).init(std.heap.page_allocator);
defer founded.deinit();
for (1..MAP_SIZE + 1) |x| for (1..MAP_SIZE + 1) |y| if (map[x][y] == 0) {
founded.clearRetainingCapacity();
try step(map, x, y, &total, &founded);
};
try std.testing.expectEqual(744, total);
}
fn step(map: [MAP_SIZE + 2][MAP_SIZE + 2]u8, x: usize, y: usize, total: *usize, founded: *std.AutoHashMap([2]usize, void)) !void {
const height = map[x][y];
if (height == 9 and !founded.contains([2]usize{ x, y })) {
total.* += 1;
try founded.put([2]usize{ x, y }, {});
}
if (map[x - 1][y] == (height + 1)) try step(map, x - 1, y, total, founded); // Up
if (map[x + 1][y] == (height + 1)) try step(map, x + 1, y, total, founded); // Down
if (map[x][y - 1] == (height + 1)) try step(map, x, y - 1, total, founded); // Left
if (map[x][y + 1] == (height + 1)) try step(map, x, y + 1, total, founded); // Right
}

26
day10/part2.zig Normal file
View File

@ -0,0 +1,26 @@
const std = @import("std");
const input = @embedFile("input");
const MAP_SIZE = 60;
pub fn main() !void {
var map = [_][MAP_SIZE + 2]u8{[_]u8{0} ** (MAP_SIZE + 2)} ** (MAP_SIZE + 2);
for (input, 0..) |c, i| {
if (c == '\n') continue;
map[@divFloor(i, MAP_SIZE + 1) + 1][i % (MAP_SIZE + 1) + 1] = c - '0';
}
var total: usize = 0;
for (1..MAP_SIZE + 1) |x| for (1..MAP_SIZE + 1) |y| if (map[x][y] == 0) try step(map, x, y, &total);
try std.testing.expectEqual(1651, total);
}
fn step(map: [MAP_SIZE + 2][MAP_SIZE + 2]u8, x: usize, y: usize, total: *usize) !void {
const height = map[x][y];
if (height == 9) total.* += 1;
if (map[x - 1][y] == (height + 1)) try step(map, x - 1, y, total); // Up
if (map[x + 1][y] == (height + 1)) try step(map, x + 1, y, total); // Down
if (map[x][y - 1] == (height + 1)) try step(map, x, y - 1, total); // Left
if (map[x][y + 1] == (height + 1)) try step(map, x, y + 1, total); // Right
}

114
day11/part1.zig Normal file
View File

@ -0,0 +1,114 @@
const std = @import("std");
const print = std.debug.print;
const input = "890 0 1 935698 68001 3441397 7221 27";
const numberT = u64;
// Passed to a weird while loop instead of recurcive function because I run into limitation, too much recursion :/
const Stone = struct {
number: numberT,
next: ?*Stone = null,
fn step(self: *Stone, allocator: std.mem.Allocator) !void {
var current = self;
while (true) {
if (current.number == 0) {
current.number = 1;
if (current.next) |right_stone| {
current = right_stone;
} else {
break;
}
} else if (digitCount(current.number) % 2 == 0) {
const new_value = splitNumber(current.number);
const new_stone = try allocator.create(Stone);
new_stone.* = Stone{ .number = new_value[1], .next = current.next };
current.number = new_value[0];
current.next = new_stone;
if (new_stone.next) |right_stone| {
current = right_stone;
} else {
break;
}
} else {
current.number *= 2024;
if (current.next) |right_stone| {
current = right_stone;
} else {
break;
}
}
}
}
fn printStone(self: Stone) void {
print("{d} ", .{self.number});
if (self.right) |right_stone| {
right_stone.printStone();
} else {
print("\n", .{});
}
}
fn count(self: *Stone, total: *usize) void {
var current = self;
while (true) {
total.* += 1;
if (current.next) |right_stone| {
current = right_stone;
} else {
break;
}
}
}
};
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
var iter = std.mem.splitAny(u8, input, " ");
const first_stone = try allocator.create(Stone);
first_stone.* = Stone{ .number = try std.fmt.parseInt(numberT, iter.next().?, 10) };
var last_stone = first_stone;
while (iter.next()) |number| {
const new_stone = try allocator.create(Stone);
new_stone.* = Stone{ .number = try std.fmt.parseInt(numberT, number, 10) };
last_stone.next = new_stone;
last_stone = new_stone;
}
for (0..25) |_| try first_stone.step(allocator);
var total: usize = 0;
first_stone.count(&total);
try std.testing.expectEqual(194782, total);
}
fn digitCount(num: numberT) usize {
if (num == 0) return 1;
var n = num;
var count: usize = 0;
while (n != 0) : (n = @divFloor(n, 10)) {
count += 1;
}
return count;
}
fn splitNumber(num: numberT) [2]numberT {
const numDigits = digitCount(num);
const halfDigits = numDigits / 2;
var divisor: numberT = 1;
for (halfDigits) |_| {
divisor *= 10;
}
const left = @divFloor(num, divisor);
const right = num % divisor;
return [2]numberT{ left, right };
}

49
day11/part2.zig Normal file
View File

@ -0,0 +1,49 @@
const std = @import("std");
pub fn main() !void {
var map = std.AutoHashMap(usize, usize).init(std.heap.page_allocator);
defer map.deinit();
for ([_]usize{ 890, 0, 1, 935698, 68001, 3441397, 7221, 27 }) |n| try map.put(n, (map.get(n) orelse 0) + 1);
for (0..75) |_| try step(&map);
try std.testing.expectEqual(233007586663131, countStone(map));
}
fn step(map: *std.AutoHashMap(usize, usize)) !void {
var old_map = try map.clone();
defer old_map.deinit();
map.clearRetainingCapacity();
var iter = old_map.iterator();
while (iter.next()) |entry| {
if (entry.key_ptr.* == 0) {
try map.put(1, (map.get(1) orelse 0) + entry.value_ptr.*);
} else if (countDigit(entry.key_ptr.*) % 2 == 0) {
const splits = splitDigit(entry.key_ptr.*);
try map.put(splits[0], (map.get(splits[0]) orelse 0) + entry.value_ptr.*);
try map.put(splits[1], (map.get(splits[1]) orelse 0) + entry.value_ptr.*);
} else {
try map.put(entry.key_ptr.* * 2024, (map.get(entry.key_ptr.* * 2024) orelse 0) + entry.value_ptr.*);
}
}
}
fn countDigit(number: usize) usize {
var n: usize = number;
var count: usize = 0;
while (n != 0) : (count += 1) n = @divFloor(n, 10);
return count;
}
fn splitDigit(number: usize) [2]usize {
const divider = std.math.pow(usize, 10, (countDigit(number) / 2));
return [2]usize{ @divFloor(number, divider), number % divider };
}
fn countStone(map: std.AutoHashMap(usize, usize)) usize {
var total: usize = 0;
var iter = map.valueIterator();
while (iter.next()) |entry| total += entry.*;
return total;
}

140
day12/input Normal file
View File

@ -0,0 +1,140 @@
RRRRRRRRRRRRRRRRKKKKKKKKRRRRRRRRRRRRRRRRRRRROOPOOOOOOOOGOOONYYYYYYEDDDDDDDDDDDLLLLLLLLOOOOOOOOOOOOOOOXVVXHHHHHHHHHHLLLLLLLLLLLLLLJJJJJJJJJJC
RRRRRRRRRRRRRRRRKKKKKKKKKRRRRRRRRRRRRRRRRRRRROOOOOOOOOOOOOOYXYYYYKEDDDDDDDIIIDLLLLLLLLLLOOOOOOOOOOOOOXXXXHHHHHHHLLLLLLLLLLLLLLLLJJJJJJJJJJJC
RRRRRRRRRRRRRRKKKKKKKKKKRRRRRRRRRRRRRRRRRRRRROOOOOOOOOOOOOOYYYYYYKEDDDDDDDDDILLLLLLLLLLLOOOOOOOOOOOOOOXXXXXXXHHHHHLLLLLLLLLLLLLJJJJJJJJJJJJC
RRRRRRRRRRRRKKKKKKKKKKKKKRRRRRRRRRRRRRRRRRRRROOOOOOOOOOOOOOOOYYYYKDDDDDDDDDDIILLLLLLLLLLOOOOOOOOOOOOOOXXXXXXXHHHHHLLLLLLLLLLLLLLJJJJJJJJJJJC
RRRRRRRRRRRRKKKKKKKKKKKKKERREREERRRRRMMMRRRROOOOOOOOOOOOOOOOYYYYYKKDDDDDDDDDDDDLLLLLLLLOOOOOOOOOOOOOOOXXXXXXXHHHHLLLLLLLLLLLLLLJJJJJJJJJJAAA
RRRRRRRRRRRKKKKKKKKKKKKKKEEEEEBEERRRRRMRRRRROOOOOOOOOOOOOOQQQYYYKKKKDDDDDDDDDDDDLLLLLLOOOOOOOOOOOOOXXXXXXXXXXHLLLLLLLLLLLLLLLLLJLJJJJJJAAAAA
RRRRRRSRRRRKKJKKKKKKKKKKKKEEEEEEEERCRMMMMRROOOOOOOOOOOOOQQQQQYYYKKKKDDDDDDDDDDDDLLLLLLOOOOOOOOOOOOXXXXXXXXXXXXTTLLLLLLLLLLLLLLLLLLJJJJAAAAAA
RSRRRRSSRRRRRJKKLKKKKKHHKKEEEEEEEECCCWWCCRROOOOOOTOOTOOOQQQQQYQKKKKDDDDDDDDDRDDDDRLLLLLLOOOOOOOOOOXXXXXXXXXXXXXTLLLLLLLLLLLLLLLLLJJJAAAAAAAA
SSSSSSSRRRRRRRRKKKKKKKHHEEEEEEEEEECCCCCCCCROOOOOOTOTTOTQQQQQQYQQKKKEEEDDDDDDRRRRRRLRLLLLOOOOOOOOCCXXXXXXXXXXXXXXLLLLLWLLLPPLPLLLLJJAAAAAAAAA
SSSSSSSSSSRRRRKKKKKKOTHHHHEEEEEEECCCCCCCCCRROOOTTTTTTTTQQQQQQQQKKKEEEEEDEERRRRRRRRRRRRROOOOOOOOOCXXXXXXXXXXXXXXLLLLLLLLLLLPPPLLLLJJJAAAAAAAA
SASSSSSSSSRRRRKKKKKKTTTTTHEEEEOOCCCCCCCNNCRRRROTTTTTTTQQQQQQQQQKKKAEEEEEEERRRRRRRRRRRROOSOOOOOOOCCXXXXXXXXXXXXXXLLLLLLLQLLPPPLLQQAAAAAAAAAAA
SSSSSSSSSSSSRRKKKKKKKTTTTTODEEDOCCCCCCCCCRRRRRKKTTTTTTQQQQQQQQQKAAAELLEEEEERRRRRRRRRRRRSSSSOOOOCCXXDXXXXXXXXXXXXLLLLLLLQQPPHQLLQQAAAAAAAAAAA
SSSSSSSSSSSRRRKKKKKKTTTTTTODDDDOCWCCCCCTTTRRRRRRTTTTTTQQQQQQQQTKAAALLLLEEEERRRRRRRRRRRSSSSSSSSOCCCCDXXXXXXLLXXXLLLLLLLLLQQPHQQLQQAAAAAAAAAAA
SSSSSSSSSSUUZZZKKKKKKTTTTTDDDDDDWWCCCTTTTRRRRHRUUTTTTTWWQQQQQTTTTLLLLLLWLEERRRRRRRRRRRBSSSSSSSCCCCCDXSSXXLLLLLLLLLLLLLLQQQPQQQQQQQAAAAAAAAAA
SSSSSSSSSSZZZZZZZZKKKTTTTDDDDDDWWWRCCTTTRRRRUUUUUTTZTTWWWWWQQQQTHLLLLLLLLEERRRRRRRRRRRRKSSSSSSCCJCCDDDDXXXLLLLLLJJLLLLLQQQQQQQQQQQAAAAAAAAAA
SAQQSSSSSSQZZZZZZKKTTTTTTDDDDDRRRRRRRTTURURUUUUUUZZZTTWWWWWWQQQLLLLLLLLQLEERRRRRRRRRRRUSSSSSSSSJJJJDDDDXEXLLLLJJJJJEJJQQQQQQQQQQQQQAAAAAAAAA
QQQQQSQQQQQZZZZGGKTTTTTTTTTDRRRRRRRRUUUUUUUUUUUUUZZVWTWWWWWWLQQQLLLLLPPEEEERRRRRRRRRRRUUSSSSSWSJJJJRRRRQRXLLLLJJJJJJJJJQQQQQQYQQQQQQAAAABBAA
QQQQQQQQZZZZZZZGGGGGTTTTTTTTRNRRRRRRUUUUUUUUUUUUZZZVWTWWWWWWWWWWWLLLLLPPEEEEEEEEEEURUUUUSSSSSSJJJJJRRRRRRRRLLLJJJJJJJJBBBQQQYYYQQQAAAABBBAAA
QQQQQQQKKKKZZZZGGGGGTTTTTTTTTTTRRRRRRRURUUUUUUCUZZVVWWWWWWWWWWWWWLLLLLLLEEEEEEENNUUUUUUUUSSSSSSJJJRRRRRRWRCRLJJJJJJJJJJJJBBQQYQQQQQQAAAABAAA
QQQQQQQQQQQZZZZSSSSSSSSTTTTTTTTRRRRRRRRRRUUUUUCCVVVVVWWWWWWWWWWWLLLLLLLLEEEEEEENNUUUUUUUUSSISSJJJJJRRRRRRRRRRJJJJJJJJJJJJQQQYYYXXXQAAXXXXAAA
QQQQQQQQQQQZZZZSSSSSSSSTTTTTTTWWWWWRRRROOUUCCCCCVVVWWWWWWWWWLCLLLLLLLLLLLLEEEEENNUNUUUUUUUUSSLJJJJJJRRRRRRRRJJJJJJJJJJJJJQLQQYYXXXXXXXXXXAGA
QQQQQQQQQQQHLLLSSSSSSSSTTTTTTTWWWWWRRRROOOUCCCCCVVWWWWWWWWWWLLLOLGLLLLLLLLEEEEENNUNUUUUUUUUSJJJJJJJRRRRRRRRRRCCJJJJJJJYYYYQQQQYXXXXXXXXXXXGA
QQQQQQQQQQQQLLLSSSSSSSSSSTVSSSWWWWWRROROOUUCCCCCVVWWWWWWWLLLLOOOLLLLLLLLLLLEEEENNNNNUUWWUWUJJJJJJJJJRRRRRRRRRRJJJJJMMJYYYYQQQYYYXXXXXXXXXXXX
QQQQQQQQQQQQLLLSSSSSSSSSSVVSSSWWWWWRROOOOPCCCCCCNVWWWWWWWLLLLLOOOOOLLLLLLLEEEENNNNNNUUUWWWWWFJJJJJOOORRRRRRRRRJMMMJMMMYYYYYQYYYYXXXXXXXXXXXX
QQQQQQQQQKQLLLNSSSSSSSSSSVVSSSWWWWWRRRROPPCCCCCNNWWWWWWWWLLLLLOOOOOOLLLLLLEEEENNNNNNNUWWWWWFFJFJJJOOORRRRRRRRRJMMMMMMYYYYYYYYYYXXXXXXXXXXXXX
QQPQQQQQQQQLLLLSSSSSSSSSSRRSSSSDWWWRRRRPPPCCCNCNNNWWWWWWWLLLLLLOOOOOOOOLLEEEEEENNUUUNNWWWWWFFFFGGGOOORGRRIIMMMMMMMMMMMYYYYYYYYXXXXXXXXXXXXXF
QPPPPPQQQQQQLLLSSSSSSSSSSRRSSSSDWWWRRRRPPCCCCNNNNNNNWWWLLLLLLLLOOWWWOOOLLEEEEEIINUUUWWWWWWWFFFGGGGGGRRGGGIMMMMMMMMMMMMYYZZZZYYYYYXXXXXXXXXFF
QPPPPQQQQQQLLLLSSSSSSSSSSSSSSSSDWWWRRPPPPPCCCNNNNNFNWWWLLLLLLLLWWWWWWOOWLQEEIIIIIIQUWWWWWWFFFFGGLGGGGGGGIIIMMMMMMMMMMMMYYYYZYYYYYYYYXXXXFFFF
PPPPPQQQQQQQLLLLMMMMMSSSSSSSSSSDWWWRRPPPPPCCCCNNNNNNWWLLLLLLLLWWWWWWWWOWGIIPPIIIHIQWWWWWWWWFFFFGLGGGGGGGGGIMMTMMMMMMMMMMYNYYYYYYYYYYXXXXFFFF
PPPPPPQBQQOOMMMMMMMMMSSSSSSSSSSDWWWWWPPPPPPPCNNNNNNNWWTLLLLLLLWWWWWWWWWWWIIPPIIIIIQWWAWWAJAFFFFFGGGGGGGGGGIMMMMMMMMMZMMMMNNYYYYYYYYYXXXXLFFL
PPPPPPPBBBOOMMMMMMMMMMSSSVVDDDDDWWWWWCLPPPPPCNNNNNNNTTTLLLLLLLWWWWWWWWWWWIIIIIIIMQQWWWQAAAAAAFFGGGGGGGLLLGIIIMMMMMMNNNNNNNNYYYYYYYYXXXXXLLLL
PPPPPPPBBBOOOMMMMMMMMMMDDDDDDDDDWWWWWCPPPPPPCNNNNNNNTTTLLLLLLLWWWWWWTWWWWIIIIIIIQQQWWAAAAAAAAFFFFGGGGGLLLIIIMMMMMMMNNNNNNNNYYYYYYYYYXLLLLLLL
PPPQPPPBBBOOOOMMMMMFMVMDDDDDDDDDWWWWWCPPPPPPCNNNNNNNNTTTTTTLLTTTTTTTTOOIIIIIIIIIDDDDDLLLLAAAJFFFFGGGGGLLLLIIIIINMNNNNNNNNNNSYYYYYYYYXXLLLLLL
TTTQPPVBBBBBOOOMMMMMMVDDDDDDDDDDDDWWWCCPPPPPNNNNNNNNNNNTTTTTTTTTTTTTTOOOIIIIIIIIDDDDDLLLAAAKJJJJJKGGGGCLLIIIIIINMNNNNNNNNNNBYYYYYYYYXLLLLLLL
TTTTPPVBBBBBBBMMCMMMMMDDDDDDDDDDDDWWWCPPPPPNNNNNNNNTTTTTWWWTTTTTTTTTTTTIIIIIIIIOKDDDLLLLKKKJJJJJJJGGGGCLLLLIIINNNNNNNNNNNNBBBYYYYYYMMMLLMMML
TTTTPPVBBBBBBBMMCCMMMMDDDDDDWDDDDDWWWCCNNPNNNNNNNNNTTWWWWWTTTTTTTTATTTTTIIIIIIIKKDKLLLLLLKKJJJJJJJJGCGCCVVLIIINNNNNNNNNNNNBBYYYYYYMMMMLMMMML
TTTTTTBBBBBBBBBCCCCMCMDDDDDDWDDDDDWWWNNNNPNNNNNNNNNNTTWWWWWWTTTTTAAEEEZTIIIKKIKKKKKKKKKLLKKKJJJJJOJCCCCVVCDDNNNNNNNNNNNNNNBBYYYYYYMMMMMMMMMM
TTTTTTBBBBBBBBCCCCCMCBDDDDDDWDDDDDWWWCCNNNNNNNNNNNNNWWWWWWWWTTTTTTAAEEEEIIKKKKKKKKKKKKKKLKKKJJJJJCCCCCCCCCCDNBBBBBBBBBBBNNBBYYBYYMMMMMMMMMFF
TTTTTBBBBBBBBBCCCCCCCBDDDDDDWDDDDDWWWCNNNNNNNNNNNNNNWWWWWWWTTTTTTTEEEEEJEIKKKKKKKKKKKKKKKKJJJJJJJCCCCCCCCCCDDBBBBBBBBBBNNNBBBBBYAMMMMMMMMMFM
TTTTTTBBBBBBNNNCCCCCCBBBBBBBWDDDDDDDWIIINNNNNNNNAANLWWWWWWWTTTTTTTMEEEEEEKKKKKKKKKKKKKKKKKJJJJJJJCCCCCCCCCCCDBBBBBBBBBBNNNBBBBBBMMMMMMMMMMFM
HHTHHBBBBBBNNNCCCCCCCBBBBBBBWDDDDDDDWIIIIIIINNZZZZZZZZWKWWWTTTTWTTMEEEEEEKKKKKKKKKKKKKKKKKJJJJJJJCCCCCCCCCJCJBBBBBBBBBBNKNBBBBBBBMMMMMMMMMMM
GHHHHHBBBBNNNNNNCCCCCBBBBBBBWDDDDDDDWIIIIIINNAZZZZZZZZWKKWWWWWTWTTMEEEEEEKKKKKKKKKKKKKKKKKKKKJJJJCCCCCCCCJJJJBBBBBBBBBBDDNBBBBMMMMMMMMMMMMMV
HHHHSSSBBBNNNNNNCCCBBBBBBBBBBDDDDDDDWIIIIIANAAZZZZZZZZKKWWWWWWWWWTTEEEEEEKKEKKKKKKKKKKKKKKKKKKKKKKCCCCCCCCCJJBBBBBBBBBBDDLBBBBMMMMMMMMMMMMMM
HHHHSSSBBBNNNNNNCNNBBBBBBBBBBDDDDDDDIIIIIVAAAAZZZZZZZZKKKKWWWWWWWEEEEEEEEEEEEKKKKKKKKKKKKKKKKKKKKKBMBBCCDDDJJBBBBBBBBBBDDDBBBBBBMMMMMMMMMMMM
HHHSSSSNNBNNNNNNNNNBBBGGGGGBBDDDDDDDIIIZZZZZZZZZZZZZZZKKKKKKWWWWEVVEEEEEEEEEEKKKKKNNNKKKKKKKKKKBBBBBBBBBBBBBBBBBBBBBBBBDDYYYABBBBMMMMMMMMMMM
HHHSSSNNNNNNNNNNNNNBBBGGGGGBBBBBIIIIIIIZZZZZZZZZZZZZZKKKKKWKWWWWEEEEEEEEEEEEQQKKKKNNNNKKKKKKKKKBBBBBBBBBBBBBBBBBBBBBDDDDYYYYYBBBBMMMMMMMMGMG
HHHSSSNNNNNNNNNNQNBBBBGGGGGBBBBBIIIIIIVZZZZZZZZZZZZZZKKKKKWWWWWEEEEEEEEEEEEEEEKCCCNNNKKKKZZKKKKKBBBBBBBBBBBBBBBBBBBBDDDYYYYYYBBBBBMMMMMMMGGG
HHHSSSSNNNNNNNNNQQBVVBGGGGGBBBBYXIIIIIVZZZZZZZZZZZZZZKKKKKWWWWWWEEEEEEEEEEEECCCCCNNNNZZKKZZZZKKKBBBBBBBBBBBBBBBBBBBBGDDYYYYYYBBBBBBMMMMMGGGG
SSSSSSNNNNNNNNNNQQQBBBGGGGGGGGGYXIIIIIBZZZZZZZZZZZZZZKKKKKWWWWEEEEEEEEEEEEETCTCCCNNNNZVZZZZZZZBBBBBBBBBBBBBBBBBBBBBBGDQQYYYYYBBBBBMMMUMSSGGG
SSSUUUNFNNNZNNNQQQQBBBGGGGGGGGGGGXIIIIVZZZZZZZZZZZZZZKKKKWWWWWWWEEEEEEEEEWWTTTTNNNNNNZZZZZZZZZZBBBBBBBBBBBBBBBBBBBBBGGQQYYYYYYYBBBBSSUSSGGGG
SCCUUUYFFNNNQQQQQQQBQQGGGGGGGGGGGNNINNVZZZZZZZZZZZZZZXKFOWWWWWWTETEEEEEETTWTTTTWNNNNZZZZZZZZZZZZBBBBBBBBBBBBBBBBBBBBGGQYYYYYYYBBBSSSSSSSGGGG
SCCYUYYFFVVNQQQQQQQQQQQQQGGGGGGGGYNNNNVZZZZZZZZZZZZZZOOOOOOWWWTTTTTTTTETTTTTTTTTVTPPZZZZZZZZZZZZBBBBBBBBBBBBBBBBBBBBGGYYYYYYYYYYBSSSSSSSSSSS
CCYYYYYYYVVVVVQQQQQQQQGGGGGGGGGGGNNNNNVZZZZZZZZZZKKKKOOOOOOOTTTTTTTTTTTTTTTTTTTTTTHPZZZZZZZZZZZBBBBBBBBBBBBBBBBBBBBBTYYYYYYYYYYYYSTSSSSSSSSS
YYYYYYYYVVVVVVQQQQQQQHHHHGGGGGGGGNYNNNVZZZZZZZZVVVKKKOOOOOEEEETTTTTTTTTTTTTTTTTTHHHPPAZZZZZZUUTTTBBBBBBBBBBBBBBBBBBBYYYYYYYYYYYYYRTSSSSSSSSR
YYYYYYYYYYYVVVQVQQQQQHHHYGGGGGGGGYYNNNVVVVVVVVVVUUUUOOOOOOYYYTTTTTTTTTTTTTTTTTHHHHAPAAZZZZZPUUTBBBBBBBBBBDIBBBBBBIIIYYYYYYYYYOYRRRRRSSSSRSRR
YYYYYYYYYVYVVVVVVQQQQHHJYYYYYYGGGYNNNNNVLVVVVVVTOUOOOOOOOOYYYTTTTTSTTSTTTTTTTAAAAAAAAAZZHHHUUUBBBBBBBBBBDDDBBBBBBIIIYYYYYYYYYOYRRRRRSSSRRRRR
YYYYYYYYUVVVVVVVQQQQQHHYYYYYYYYYNNNNNNVVVVVVVWVOOOOOOOOOOOYYYZTTTTSSSSTTTTTTTAZAAAAAAAAAHHHUUUUUBUBUUBDLDDDBBBBBBIIIYYYYYYYYYOORRRRRSSSSRRRR
YYYYYYYYYVVVVVVQQQQQQPHYYYYWWYYYYNNNNNNNVNNVVWWWOOOOOOOOOYYYYZZOTTSSSSSSSSTTTAAAAAAAAAAAAHHVUUUUUUUUUUDDDDDIIIIIIIIIIYYYYYYYYYYROOQRRRRRRRRR
YYYYYYYYYYVVVVVQQQQQQPPYPYUUYYYYNNNNNNNNNNNNVWWWOOOOOOOOOOUYYOOOOSSSSSSSSSSAAAAAAAAAAAAAHHVVUUUUUUUUUUUDDEEIIIIIIIIIIYYYYYYYYXYROQQQRRRRRRRR
YYYYYYYYYYVZZVVZQQQQQPPPPUUUYRYYNNNNNNNNNNNNVWFFOOOOOOOODUUDYOOOOISSDDSSSSSAAAAAAAAAAAAVVVVUUUUUUUUUUKKKKEIIIIIIIIIIIIYIYYYYXXXXQQQRRRRRRRRR
YYYYYYYYYZIZZZZZZQQQQPPPPUYUURYYYYNNNNZNNNNNNFFFOOOOOONNDDDDDDOOOOSSSDSSSQSAAAAAAAAAZAAVVVVVVUUUUUUUUKKKKKKIIIIIIIIIIIIIIYYYXXXQQQQOROORRRRR
YYYYYYYYYZZZZZZZZQQQPPQUUPUUUUYUUYNNNNZNNNFFFFFFPOOOFONDDDDDDDDDDOSDDDDSSSSDDAAAAAAAZAAAVVVVUUUUUUUUUKKKKKVKIIIIIIIIIIIIIYMMMMMQQQQOOOOORRRR
YYYYYYYZZZZZZZZZQQZQQQQQUUUUUUUUUONNNNZAAAAFFFFFPOOFFONNNDDDDDDDDDDDDDDSSSSDDAAAJABAAAAVVVVVUUUUUUUUKKKKKKKKIIIIIIIIIIMIIFMMMMKQQQQOOORRRRRR
YYYYYJZZZZZZZZZZZZZQQQQQUUUUUUUUVOOONZZAAAAAFFFFFOGFFONNNDDDDDDDDDDDDDDDSSSDDAZAABBBBBAVVVVVUUUUUKKKKKKKKKKIIIIIIMMMMMMIMMMMMMKQOOOOOOOORRRR
GGZZZZZZZZZZZZZZZZHQQQQQHUUUUUUUVOOOZZZAAAAAFFFFFFFFFFNNNNNNDDDDDDDDDDDDDDDDDRZRBBBBBBVVVVVVYUUUUUUURRKKKKIIIIIIILMMMMMMMMMMMMMOOOOOOOOORRRR
GGZZZZZZZZZZZZZZZZHHQHQHHUUUUUUUVVOOOZZZAAAFLFFFFFFFFFFNNEEEEEEEEEEDDDDDDDDDDRRRRBBBBBBBVVVYYUUUUUUIIKKKKKKIIUMMMMMMMMMMMMMMMMMOOOOOOOOORRRR
GZZZZZZZZZZZZZZZZHHHQHHHHHUVVUUUVVZZZZZZAAFFFFFFFFFFFFNNNEEEEEEEEEEDDDDDDDDRRRRRRBBBBBBBVVYYYYYUUUUIIIKKKKUUUUUUMMMMMMMFFFFMMMMOOOOOOOOOOORR
GGZZZZZZZZZZZZZZZZHHHHHHHHVVVVUVVVZZZZZZZZMFFFFFFFFFFFNNNEEEEEEEEEEEEEEERRRRRRRRRBBBBFFBVVVYYYYYYUUUIJDDKKKUUUUUMMMMMMMFFFFMMMMOOOOOOOOORRRR
ZZZZZZZZZZZWWWWZZCHWHHHHHHHVVVVVVVZZZZZZZAMFFFFFFFFFFFNNNEEEEEEEEEEEEEEERRRRRRRRRFBFFFFFFVVFFYYYYUUJSJDDKUUUUUUUMMMMMMMFFFFMMMMOOOOOOOMMMRMR
QQZZZZZZZZZZZWWZZWWWHHHHHHHVVVVVVVZZZZZGZAFFFFFFFFFNFNNNNEEEEEEEEEEEEEEEDRRRRRRRRFFFFFFFFFFFFYYYYYJJJJUUEUUUUUUUUMMMMMMFFFFMMMMOOOOOOMMMMMMM
QQZZZYZZZWZWWWWWWWWHHHHHHHHVVVVVVVZZZZZAAAAFFFFFFNNNNNNNNEEEEEEEEEEEEEEEVVRRRRRRRFFFFFFFFFFFFFYYYYJJJUUUUUUUUUUUUUXMMMMFFFFMMMNOOOOOOOOMMMMM
QQQQZZZZZWWWWWWWWWWHHGKKHHHHVVVVVVZZZZZZAAAAFFFFNNNNNNNNNEEEEEEEEEEEEEEEVVRVRRRRRFFFFFFFFFFFFYYJJJJJZZZUUUUUUUUUUXXMMMMFFFFMMMOOOOOOOOOOMMMM
QQQQQQKKKKKWWWWWWWWHKKKKKHHVVTTVVVVZZZZAAAAAFFFFNNNNNNNNNNNKKKKKEEEEEEEEVVVVVRFRFFFFFFFFFFFFFYYJJJJJJUZUUUUUUUUUUXXXMMMFFFFMMMOOOOOOUOUOMMMM
QQQQQQQKKKKWWWWWWWWWUKKKKKHVITTVVVVZZZAAAAAAFFLLNNNNNNNNNNNKKHHKEEEEEEEEEVVVVRFFFFFFFFFFFFFFYYJJJJJJRUFFFFFFUUUIXXXXMMMFFFFMMMOOOOOOUUUOMMMM
QQQQQXXXKKWWWWWWWWWKKKKKKKKIITTTVVVVAAAAAAAAAAAAVNNNNNNGGGNNKHKKEEEEEEEEEVVVVFFFFFFFFFFFFFFJYJJJJJJJJUFFFFFFUUIIFXXXXMMMMMMMMMOOOOOOUUUUUMMM
QQQQQXXKKKWWWWWWWWOKKKKKKKKIITTTTTVVAAAAAAAAAAAAVNMNNNGGGGGNKHHHEEEEEEEEEEEEEVVFFFFFFFFFAAJJJJJJJJJJIUFFFFFFIIIIFXXXMMMMMMMMUUUUOOOUUUUUMMMM
QQQQXXXKKKKWWWWDWWWKKKKKKKKTITTTTTTVVAAAAAAAAAAAAMMMMGGGGGGGHHHHEEEEEEEEEEEEEVFFFFFFFFFFFAJJJJJJJJJJJKFFFFFFIIIIIXXXMMMMMMMMUUUUUOOUUUUUMMMP
QQQQXXXKKKKKKWDDWDDDKKKKKKTTTTTTTETVVAAAAAAAAAAAAMMMMMGGGGGGHHHHEEEEEEEEEEEEEVFFFFFFFFFFFAJJJJJJJJRRRKFFFFFFIIILIXXXXXMMMMMMMUUUUUUUUUUUMMPP
QQQQXXXXKKKKKDDDDDDDKKKKTTTTTTTTTTPTTTAAAAAAAAMMMMMMMMMMGGWMHHHHEEEEEEEEEEEEELFFFFFRFFFFFFJJJJJJJJJRFFFFFFFFIIIIIXXXXXXXMMMMUUUUUUUUUUUUUUPP
QQXXXXXXKXKKKDDDDDDDDDDTTTTTTTTTTTTTTTAAAAMMAAMMMMMMMMMMMMMMHHHHEEEEEEEEEEEEELFFFFFRFFFFJJJJJJJJRRRRFFFFFFFFIIIIIIXXXXXXXXMMUUUUUUUUUUUUUUUP
QQQXXXXXXXXXDDDDDDDDDTTTTTTTTTTTTTTTTTTMMMMMAMMMMMMMMTMMMMMHHHHHEEEEEEEEEEEEEBRBFOFRRRFJJJJJJJJJRRRRFFFFFFFFFFFIIXXXXXXXXXXMUUUUUUUUUUUUUUPP
QQXXXXXXXXXDDDDDDDDDDDTTTTTTTTTTTTTTTOEOOMMMMMMMMMTMMTTTTTMHHHHHEEEEEEEEHBBBBBBBBOORRRTTTTJJJJJJJRRRFFFFFFFFFFFXXXXXXXXXXXXMQUUUUUUUUUUUUPPP
QXXXXXXXIXXXDDDDDDDDDTTTTTTTTTRRTOOTOOEOOMMMMMMMMMTMTTTTTHHHHHHHEEEEEEEEBBBBBBBBBORRRTTTPTTJJJJJRRRRFFFFFFFFFFFXXXXXXXXXXXXUUUUUUUUUUTUUPPPP
XXXXXXIXIIXXDDDDDDTTTTTTTTTTRRRRTTOTOOOOOOMMMTMMTTTTTTTTTTHHHHYYEEEEEEEEEEEEBBBBBORRRTTTTTTJJJJJRRRRRFFFFFFFFXXXXXXXXXXXXXDLUUUUUUUUUUUPPPPP
KXXXXXIIIIIDDDDDDDDDTTTTTTTTRRRRRROOOOOOOMMMTTTTGTTTTTTTTTTHYYYYYYYYYEEEEEEEBBBOOOTTTTTTTTTJJJJJRRRRRFFFFFFFFRXPPXXXXXXXXPLLMMMUUUUUUHUPPPPP
KKKKKIIIIIIIIDDDDDDDDOTTTTTTRRRRRROOOOOOOMMMMTTTTTTTTTTTTTAYRRYYYYYYYEEEEEEEBBBOOTTTRRTTJJTJJJJJRRRRRFFFFFFFFXXXPXXXXXPPLLLMMMMUUUUUUUUPPPPP
KKKKKKIIIIIIIIDDDDDDDDTTTTTRRRRRRRRROOOOOMOMTTTTTTTTTTTTTTAYYYYYYYYYDEEEEEEEBSBOOTOOOOOJJJJJJJRRRRRRRFFFFFFFFXOOPPPPPPPPLLLMMMMUUUUUUUUUUUPP
KKKFFFFFIIIIDDDDDDDDDDTEEEERRRRRROOOOOOOOOOTTTTTTTTTTTTTTTAYYYYYYYYYBEEEEEEEBBOOOOOOOOJJJJBJJJRRRRRRRFFFFFFFFOOOOPPPPLLLLLMMMMMMWWUUUUUPPPPP
KKFFFFFFIIIIDDDDDDDDDDDDDEEOSRRRROOOOOROOOTTTTTTTTTTTTTTTTYYYYYYYYYYBEEEEEEEBBOOOOOOOOFJJZJJJRRRRRFRRFRFFFFFFOOOOOPPPLLLLLLLMMMMWUUUUUUPBPPP
KKFFFFFIIIIIDDMMDMDDDDDOOOOOSRRROOOOOOOOOOBTTTTTTTTTTTTTTTYYYYYYYYYYYBBBBBBBBOOOOOOOOOOZZZZZZZZZWWFFFFRFFFFFFOOOOOOOLLLLLLLLMWWWWWWUCULBBPBB
KKFFFFFUIIIIDMMMDMMDDDDDOOOORROROOOOOOOOOOBTTTTTTTTTTTTTTYYYQYYYYYYYYYBBBBBBBBOOOOOOOOKZZZZZJZZFFFFFFFFFFFFFFOOOOOBBLLLLLLLWMMMMWWWWCCCBBPBB
KFFKKFFUIMMMMMMMMMDDDDDNNOOORROOOOOOOOOOOOOTNTTOOOOTTTTOOYQQQYYYYYYYYYBVBOBBOOOOOOOOOKKZZZZJJZZFJFFFFFFFFUFFOOOOOBBBLLLLLLLWMMMMWWWCCCCBBPBB
KKKKKFUUUMMMMMMMDDDVDNNNNOOJXXXXXXOOOOOOOUUTTTTOOOOOTTOOOQQQQYYYYYYYYNBOOOOOOOOOOOKKKKKKZZZJJJZZJJFFFFFFFFFFFOOOOBOBBBLLLLDWWWMWWWWCCCCBBBBB
KKKKMFMMMMMMMMMMLLLNNNNNNNNXXXXXXDXOOOOOOOTTTOOOOOOOOOOOOQQYYYYYYYYYYYYYOOOOOOOOOOKKKKKZZZJJJJJSFFFFFFFFFFFFFOOOOOOBBBLLLLLWWWWWWWWCCCCBBBBB
KKKKMMMMMMMMMMMMMNNNNNNNNNNXXXXXXXXXOOOOOOOOOOOOOOOOOXOOOQQYYYYLIIYYYYYYOOOOOOOOOOFKKKKZZZJJJJSSSSBFFFFFFFFFFFSOOOBBBBBBLLWWWWWWWWCCCCBBBBBB
KKKKMMMMMMMMMMMHHNNNNNNNNNNNXXXXXXXXXXXOOOOJOOOBBOOOOOOOOOQQYYYLIPIYIVVVOOOOOOOOFFFFFZZZZZJJJJSSSFFFFFFFFFEWWWWWWOBBBBBBBAWWWWWWWWBBBBBBBBBB
KKKKKKMMMMMMMMMMMNNNNNNNNNNXXXXXXXXXVXXOOOOJJBBBBBOOOTOOOIQIIRRIIIIIIIVVOOOOOOOOOOFFZZZZZZZZJJSSFFFFFFFFFWWWWWWWWBBBBBBBBAAWWWWWWWWBBBBBBBBB
KKKKKMMMMMMMMMMMMNNNNNNNNNNXXXXXXXXVVVVOYYYBBBBBOOOOOOOOOIIIIIRIIIIIDDNNNNOOOOOOOOOFZZZZZZZZSSSSSFFFFFFFFWWWWWWWWBBBBBBBAAAWWAWWWWBBBBBBBBBB
KKKMMMMMMMMMMMMMTNNNNNTNNTNXXXXXSXXVVVVOYYYBBBBBBOOOOOOOOIIIIIIIIIIDDDDNNOOOOLOOOODFZZZZZZZZSSSSSSSFQFFFFWWWWWWWWBBBBBBBBAAAWAAAWWBBBBBBBBBB
KKKKKKMMMMMMMMDDNNNTNTTTTTTJXXSSSHVVVHVVYVYBBHBJBOOOOOOOOIIIIIIIIIDDDDNNDDOOOLXOOODZZZZZZZZZSSSSSSSQQFIFWWWWWWWBBBBBBBBBBAAAAAAAABBBBBBBBBBB
KKKKKKMMMMMMMMMLLNNTTTTTTLTJJXSSSHHHHHVVVVYYBBBBOOOOOOOOOOIIIIIIIIDDDDDDDDDDOXXXDDDDZQZZZZZZCCCOSSQQQFWWWWWWWWWWBBBBBBBBBBBAAAAAAABBBBBBBBXX
KKKKKMMMMMMMMMMMLNTTTTTTTTTJJXSSHHHHHHHYYVVYBBBBOOOOOOOUUUIIIIIIIIDDDDDDDDDDXDXXXDDDZZZZZZZZZZGGGGGGGGGGWWWWWWWWBBBBBBBBBBBBAAAAAATTTTBBXXXX
UUUKZZDDZMMMMMMMLLLTLTTTTTJJJJHHHHHMMHHYYYYYBVVBOOOOOOOUUUUUIIIIIIGGDDGGDDXXXXXXXXXDZDZXIZIIOOGGGGGGGGGGWWWWWWWWBBBBBBBBBBBBBAAATTTBBBBXZZXX
UUUZZZZZZMMMMMMLLLLTLTTTTTTTTTWHHHHMMMBYYYYBBBBBBBOOOOOUUUUIIIIIIIGGGGGDDXXXXXXXXXXDDDDIIIIIOOGGGGGGGGGGMMMWWWWWBBBBBBBBBBBBBAAATTTTXXXXXXXX
UUZZZZZZZLMMMMLLLLLLLLTTTTTTSSHHHTTZMMBBYBYBBBBBBUOOUUUUUUIIIIIIIIGGGGGGXXXXXXXXXXXXDDDDIDIIIIGGGGGGGGGGMMMWWMMMMBBBBBBBBBBBBBAATTTTKKXFXXXX
UUZZZZZZZLLMMMLLLLLLLLTTTTSSSSSSSZZZZBBBBBBBBBBBBUUUUUUUUUIIIIIIIGGGGGGXXXXXXXXXXXXXXMDDDDDIIIGGGGGGGGGGMMMWWMMMMMBBBBBBBBBBBBTTTTTTTTXXXXXX
ZZZZZZZZZLLLLMLLLLLLLLTTTTSSSSSSSSZZZZUBBBBBBJBBUUUUUUUUUUIIIIIIIGGGGGGXXXXXXXXXXXXKMMDDDDDDIIGGGGGGGGGGMMMWMMMMMMBBBBBBBBBBEEEETTTTTTXXXXXX
ZZZZZZZZLLLLLLLLLLLLLLTSSSSSSSSSSSSZZUUBBBBBBBBBBUUUUUUUUUIIIIIIIGGGGGGDXXXXXXXXXXXXMMMDDDDDDIGGGGGGGGGGMMMWMMMMBBBBBBBBBBBBETTTTTTTTSTHHHHH
ZZZZZZZZLLLLLLLLLLLLLLSSSSVVVVSSSSSZSSSSBBBBBBBBRRUUUUUUUUIIIIIIIGGGGGDDDXXXXXXXXXXMMMMMMMDDIIGGGGGGGGGGGGGMMMMQBBBBBBBBBBBTTTTTTTTTTTTTHHHH
ZZZZZZZZLLLLLLLLLLLLSSSSSSSVZZSSSSSSSSSSBBBBOOOORUUUUUUUUIIIIIIIGGGGGGDDDDXXXXXXXXXMMMMMMDDDIIGGGGGGGGGGGGGQMQQQBBBBBBBBBBCCTTTTTTTTTTTTHHHH
ZZZZZZZLLLLLLLLLLLLLSSSSSSSJZJSSIISSSSSXXBBOOOORRKRRRUUUUUUUUUGGGGGGGGGGDXXXXXXXXXXMMMMMDDDDDIIGGGGGGGGGGGGQQQQQQBBBBBBBCCCCTTTTTTTTTTTTHHHH
ZZZZZZLLLLLLLLLLLLLSSSSSSSSJJJJJJIIISYTYYYYYORRRRRRRRUZZZZZUGGGGGGGVXGXXXXXXXXXXNXMMMMMMMDDDDHIGGGGGGGGGGGGQQQQQQYBBBBBBBCCCCBTTTTTTTTTTHHHH
ZZZZZZLLLLLLLLLGGGSSSSSSSSSSSJJJJJIIIYYYYYYOORRRRRRRRUZZZZZZZZGGVGVVXXXXXXXXXXXXXMMMMMMMDDDDHHHGGGGGGGGGGGGQQQQQQQQQQZZBBBBBCBDTTTTTTTTTTHHH
ZFZZZZZLLLLLGGLGGGGGGSSSSSSSSJJJJJJIKYYYYYYRRRRRRRRRRZZZZZZZZVVVVVVVVXXXXXSSXXXBXMMMMMMMHDDHHHHGGGGGGGGGGGGQQQQQQQQQQQZZZBBBBBBEEEETTTTTTHHH
VFFZZZZZLLLGGGGGGGGGGSSSSSSSSSJJJJJYYYYYYYYYYRRRRRRWZZZZZZZNNQQIVIVVXXXXDXXXXXXBYMMMMMMMHHHHHHHGGGGGGGGGGGGGQQQQQQQQQQZZZBZBBBBEEEEKTKTTTKHK
VFFZZZZZLLLGGGGGGGGGYYSSUUUUPPJJJKJYYYYYYYYYYRRRRRRRRRZZZZCCNNQIIIVXXXXXXXXPPYYBYMMMMMMMHHHHHHHGGGGGGGGGGGGGQQQQQQQQQQQZZZZZBEEEEEKKKKKKKKKK
VVFFZZLLLLGGGGGGGGGGGGSSUUUUPPJGJKKYYYYYYYYYYRRRRRRRRRZZZZCCCQQIIIXXXXXXXXXPYYYYYMMMMMMMHHHHHHHGGGGGGGGGGGGGQQQQQQQQQQQZZZZBBEEEEEKKKKKKKKKK
VVFFZZLLLLLFGGGGGGGGGGGWUUUUPPKKKKKKYYYYYYYYRRRRRRRRRZZZZZCCQQQIIIIXXXXXXXXPYYYYYYYMMMMMMGGGGGGGGGGGHSPPKKQQQQQQQQDDPDQZZOOOOEOOOOKKKKKKKKKK
VVVZZZVLLGGGGGGGGGGGGGGWUUUUPPKKBKKKYYYYYYYYRRRRRRZZZZZZCCCCCIIIIIIIIIIIIIXYYYYYYYYYMMMMMGGGGGGGGGHHHHKKKKQQQQQQQDDDDDDZZZOOOEOOOOKKKKKKKKKK
VVVZZVVVLLUGGGGGGGGGGGWWWPPPPKKKKKKKYYYYYYYYRRRRRRRZZZCCCCCCCCIIIIIIIIIIIIIYYYYYYYYYYMMMMGGGGGGGGGHHHHKKKKQQQQQQQDDDDZZZZZZOOEOOODKKKKKKKKKK
VVVVVVVVVVUGGGGGGGGGGGHHHPPPPPPKKKKKYYYYYYYYRRZZRRZZZCCCCCCCDCIIIIIIIIIIIIIYIYYYYYYYMMMMMGGGGGGGGGOHHHHHHKKKQKQQQQDDDZZKZZOOOOOOOOKKKKKKKKKE
VVVVVVVUUUUGGGGGUGUUUUHHHPPPPPPKKKKKKKYYYYYZRRZZZZZZZZZZCCCCCCIIIIIIIIIIIIIIIYYYYYMMMMMMMJJJHHHHHOOUHQHKKKKKKKKQQQQQZZKKZVVVOOOOOOOMMKKKKKKE
VVRVVUVUUUUUUUUUUUUUUUHPPPPPPPPKKKPPKPYYYYYZZZZZZZZZZZZZCCCCCCCIIIIIIIIIIIIIIIIYYYYMMMMJJJJJHHHHHOOUHHKKKKKKKKKKQQKKKKKZZVVVOOOOOOOOOOOSKSSS
VRRUUUUUUUUUUUUUUUUUUUHHPPPPPPPKKPPPPPYYYYYZZZZZZZZZNZZCCCCCCCCCCIIIIIIIIIIIIIYYYYYYMMMJJVVJJHHHHHOUHKKKKKKKKKKKKKKKKYVVVVVVOOOOOOOOOOSSKSSS
VVRRRUXXUUUUUUUUUUUUUUHHPHPPPPPPPPPPPPYYYYYZZZZZZZZZNNZCCCCCCCCCCIICCIIIIIIIEIYYYYYYMYVVVVRVJJHOTOOHHKIKKKKYYYKKKKYKKVVVVVVVVOOOOOOOOASSSSSS
VVUUUUXXUUUUUUUUUUUUUUHHHHHPPPPPPPPPPPPZZZZZZZZZZZZNNNCCCCCCCCCCCCCCIIIIIIEEEEYYYYYYMMFVVVVVVOOOOOOPHKIKKKKYAYYYYYYEVVVVVVVVVOOOOOOOSSSSSSSS
VUUUUUUUUUUUUUUUUUSSUUHHHPPPPPPPPPPPPPZZZZZZZZZZZZZNNICCCCCCCCCCCJCIIIIIIIEEEYYYYYYMMYYVVVVVVWOOOOOOOIIIIKKYYYYYYYYVVVVVVVVVVOOOOOOWSSSSSSSS
UUUUUUUUUUUUUUUUUUUUUUHHHPPPPPPPPPPPPPMZZZZZZZZYYZZNNCCCCCCCCCCCCJIIIIIIIIEEEEYYYYYMMYYYYYYWWWOOOOOOOIIIIIIVYYYYYYYVVVVVVVVVVOEOOOUSSSSSSSSS
UUUUUUUUUUUUUUUUUUHHHHHHSXXPPPPPPPPPPPMZZZZZZZZYYYYYNNTTCCCCCCCCCJIIIIIIIEEEEEEYYYYYYYYYYLJWJWOOOOIIIIIIIIIYYYYYYYYDVVVVVVVVVOOOCUUUUSSSSSSS
UUUUUUUUUUUUUUUUUHHHHHHHSSXPPPPPPPPPPMMMZJYYZZZYYYYYNNNNCCCCCCCCCJJJIIIIIFFEEEEYYYYYYYYYYYJJJJJOOOOOIIIIIIYYYYYYYYDDVVVVVVVVVCCCCCCUSSSSSSSS
QQBBBUUUBVVUUUUUHHHHHHSSSSSPPPPPPPPPPMMMMYYYYYYYYYYJNNSDDDCCCCCJJJJJJJIIIFYEYYYYYYYYYYYYJJJJJJJOORRRIIIIYYYYYYYYYYVVVVVVVVVVCCCCCCCSSSSSSSSS
QQQBBUBBBBBBQQQHHHHHHSSSSSSLPPPPMMMMMMMMMYYYYYYYYYYYYYSSDDCRCCJJJJJJJJJJIFYYYYYYYYYYYYYJJVJJJJJOORJJIIIIIYYYYYYYYVVVVVVVVVVJCCCCCCSSSSSSSSSS
QQQBBBBBBBBBBBQHHHHHHHVSSLLLPPLMMMMMMMMMMYYYYYYYYYYYYPSSSDSRRBBJBJJJJJJWFFWYYYYYYYYYYYYJJJJJJJJJJJJIIIIYYYYYYYYYYIIIIVIIIVVCCCCCCCCCSCSQSSSS
BBBBBBBBBBBBBBBYHHHVHAVSLLLLLPLMMMMMMMMMMYYYYYYYYYYYPPSSSSSSSNBBBJJJJJWWFWWYYYYYYYYNNNCCCJJJJJJJJJJJIIIYYYYYYYYYYYIIIIIIIIVCCNCNCCCCSCCSSSSS
BBBBBBBBBBBBBBBVVVVVVVVVVVLLLLLLMMMMMMMMMYYYYYYYYYYYPSSSSSSSSBBBBJJJJJWWWWWYYYYYYYYNNNCCCJJJJJJJJJJJJIIYYYYYYYYYYYIIIIIIIIIIBNCCCCCCCCSSSSSC
BBBBBBBBBBBBBBVVVVVVVVVVLLLLLLLLLLMMMMMMMYYYYYYYYYYYYSSSSSSSBBBBBJJJWWWWWWWWWYYYYNNNNNCCJJJJJJJJJJJJJIIYYYYYYYYYYIIIIIIIIIIINNNNNCCCCCSCSCSC
BBBBBBBBBBBBBBVVVVVVVVVVVLLLLLLLLMMMMMMMMMYYYYYYYYYYYMSSSSSSBJJJJJJJJJWWWWWWWYYYYYNNNNJJJJJJJJJJJJJJJIIIYYYYYYYYYIIIIIIIIIIINNNNNCCCCCCCSCCC
BBBBBBBBBBBBBVVVVVVVVVVVLLLLLLLLLLMMMMMMMMYYYYYYYYYYYSSSSSSSBJJJJJJJJWWWWWWWWYYYXXNNNNNNJJJJJJJJJJJJUIYYYYYYMYYYYCIIIIIIIIIINNNNCCCCCCCCCCCC
BBBBBBBBBBBBBBVVVVVVVVVLLLLLLLLLLLMMMMMMMMMMYYYYYYYYYESSSSSJJJJJJJJJJWWWWWWWWWWXXXXNNNJJJJJJJJJJJJJJUIIYYYYYYYYYIIIIIIIIIIIINNNNCCCCCCCCCCCC
BBBBBBBBBBBBBBVVVVVVVVLLLLLLLLLLLLMMMMVMMMMMMFFFFFYYYEEEEESJJJJJJJJWWWWWWWWWWWWXXNNNNNNNNJJJJJJJJJJJJIIZZYYYYYYYYIIIIIIIIIICCCCCCCCCCCCCCCCC

160
day12/part1.zig Normal file
View File

@ -0,0 +1,160 @@
const std = @import("std");
const print = std.debug.print;
const input = @embedFile("input");
const MAP_SIZE = 140;
const Area = struct {
positions: *std.AutoHashMap([2]usize, void),
char: u8,
perimeter: usize = 0,
area: usize = 0,
fn init(allocator: std.mem.Allocator, char: u8) !Area {
const positions = try allocator.create(std.AutoHashMap([2]usize, void));
positions.* = std.AutoHashMap([2]usize, void).init(allocator);
return Area{
.positions = positions,
.char = char,
};
}
};
const Map = struct {
allocator: std.mem.Allocator,
map: [MAP_SIZE + 2][MAP_SIZE + 2]u8 = undefined,
areas: *std.ArrayList(Area),
area_search_x: usize = 0,
area_search_y: usize = 0,
fn init(allocator: std.mem.Allocator) !Map {
const areas = try allocator.create(std.ArrayList(Area));
areas.* = std.ArrayList(Area).init(allocator);
return Map{
.allocator = allocator,
.areas = areas,
};
}
fn printMap(self: Map) void {
for (0..MAP_SIZE + 2) |x| {
print("\n", .{});
for (0..MAP_SIZE + 2) |y| print("{c}", .{self.map[x][y]});
}
print("\n", .{});
}
fn printPos(self: Map, x: usize, y: usize) void {
for (0..MAP_SIZE + 2) |x2| {
print("\n", .{});
for (0..MAP_SIZE + 2) |y2| {
if (x == x2 and y == y2) {
print("{c}", .{self.map[x][y]});
} else {
print(".", .{});
}
}
}
print("\n", .{});
}
fn printAreas(self: Map) void {
for (self.areas.items) |area| {
print("Region {c} with Perimeter: {d}; and Area: {d}\n", .{ area.char, area.perimeter, area.area });
}
}
fn printAreasOneByOne(self: Map) !void {
for (self.areas.items) |area| {
clearScreen();
print("Region {c} with Perimeter: {d}; and Area: {d}\n", .{ area.char, area.perimeter, area.area });
for (0..MAP_SIZE + 2) |x| {
print("\n", .{});
for (0..MAP_SIZE + 2) |y| {
if (area.positions.contains([2]usize{ x, y })) {
print("{c}", .{self.map[x][y]});
} else {
print(".", .{});
}
}
}
print("\n", .{});
try waitForInput();
}
}
fn setInput(self: *Map) void {
for (input, 0..) |c, i| {
if (c == '\n') continue;
self.map[@divFloor(i, MAP_SIZE + 1) + 1][i % (MAP_SIZE + 1) + 1] = c;
}
}
fn set(self: *Map, char: u8) void {
for (0..MAP_SIZE + 2) |x| for (0..MAP_SIZE + 2) |y| {
self.map[x][y] = char;
};
}
fn posInArea(self: Map, x: usize, y: usize) bool {
for (self.areas.items) |area| {
if (area.positions.contains([2]usize{ x, y })) return true;
}
return false;
}
fn populateAreas(self: *Map) !void {
for (1..MAP_SIZE + 1) |x| for (1..MAP_SIZE + 1) |y| {
if (self.posInArea(x, y)) continue;
try self.areas.append(try Area.init(self.allocator, self.map[x][y]));
try self.lookAround(x, y);
};
}
fn lookAround(self: *Map, x: usize, y: usize) !void {
self.checkBorder(x, y);
self.areas.items[self.areas.items.len - 1].area += 1;
try self.areas.items[self.areas.items.len - 1].positions.put([2]usize{ x, y }, {});
if (self.map[x - 1][y] != '.' and self.map[x - 1][y] == self.map[x][y] and !self.areas.getLast().positions.contains([2]usize{ x - 1, y })) try self.lookAround(x - 1, y);
if (self.map[x + 1][y] != '.' and self.map[x + 1][y] == self.map[x][y] and !self.areas.getLast().positions.contains([2]usize{ x + 1, y })) try self.lookAround(x + 1, y);
if (self.map[x][y - 1] != '.' and self.map[x][y - 1] == self.map[x][y] and !self.areas.getLast().positions.contains([2]usize{ x, y - 1 })) try self.lookAround(x, y - 1);
if (self.map[x][y + 1] != '.' and self.map[x][y + 1] == self.map[x][y] and !self.areas.getLast().positions.contains([2]usize{ x, y + 1 })) try self.lookAround(x, y + 1);
}
fn checkBorder(self: *Map, x: usize, y: usize) void {
if (self.map[x + 1][y] != self.map[x][y]) self.areas.items[self.areas.items.len - 1].perimeter += 1; //Down
if (self.map[x - 1][y] != self.map[x][y]) self.areas.items[self.areas.items.len - 1].perimeter += 1; //Down
if (self.map[x][y - 1] != self.map[x][y]) self.areas.items[self.areas.items.len - 1].perimeter += 1; //Left
if (self.map[x][y + 1] != self.map[x][y]) self.areas.items[self.areas.items.len - 1].perimeter += 1; //Right
}
fn calculPrice(self: Map) usize {
var total: usize = 0;
for (self.areas.items) |area| {
total += area.perimeter * area.area;
}
return total;
}
};
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
var map = try Map.init(allocator);
map.set('.');
map.setInput();
try map.populateAreas();
try std.testing.expectEqual(1375476, map.calculPrice());
}
fn clearScreen() void {
print("\x1B[2J\x1B[H", .{});
}
fn waitForInput() !void {
var buf: [5]u8 = undefined;
const stdin = std.io.getStdIn().reader();
_ = try stdin.readUntilDelimiter(&buf, '\n');
}

225
day12/part2.zig Normal file
View File

@ -0,0 +1,225 @@
const std = @import("std");
const print = std.debug.print;
const input = @embedFile("input");
const MAP_SIZE = 140;
const Direction = enum { UP, DOWN, LEFT, RIGHT };
const Side = struct {
start: [2]usize,
end: [2]usize,
direction: Direction,
};
const Area = struct {
positions: *std.AutoHashMap([2]usize, void),
sides: *std.ArrayList(Side), // start and end point
char: u8,
area: usize = 0,
fn isInSide(self: Area, x: usize, y: usize, direction: Direction) bool {
for (self.sides.items) |side| {
if (direction != side.direction) continue;
if (side.start[0] == side.end[0] and side.start[0] == x and side.start[1] <= y and y <= side.end[1]) return true;
if (side.start[1] == side.end[1] and side.start[1] == y and side.start[0] <= x and x <= side.end[0]) return true;
}
return false;
}
fn init(allocator: std.mem.Allocator, char: u8) !Area {
const positions = try allocator.create(std.AutoHashMap([2]usize, void));
positions.* = std.AutoHashMap([2]usize, void).init(allocator);
const sides = try allocator.create(std.ArrayList(Side));
sides.* = std.ArrayList(Side).init(allocator);
return Area{
.positions = positions,
.sides = sides,
.char = char,
};
}
};
const Map = struct {
allocator: std.mem.Allocator,
map: [MAP_SIZE + 2][MAP_SIZE + 2]u8 = undefined,
areas: *std.ArrayList(Area),
area_search_x: usize = 0,
area_search_y: usize = 0,
fn init(allocator: std.mem.Allocator) !Map {
const areas = try allocator.create(std.ArrayList(Area));
areas.* = std.ArrayList(Area).init(allocator);
return Map{
.allocator = allocator,
.areas = areas,
};
}
fn setInput(self: *Map) void {
for (input, 0..) |c, i| {
if (c == '\n') continue;
self.map[@divFloor(i, MAP_SIZE + 1) + 1][i % (MAP_SIZE + 1) + 1] = c;
}
}
fn set(self: *Map, char: u8) void {
for (0..MAP_SIZE + 2) |x| for (0..MAP_SIZE + 2) |y| {
self.map[x][y] = char;
};
}
fn posInArea(self: Map, x: usize, y: usize) bool {
for (self.areas.items) |area| {
if (area.positions.contains([2]usize{ x, y })) return true;
}
return false;
}
fn populateAreas(self: *Map) !void {
for (1..MAP_SIZE + 1) |x| for (1..MAP_SIZE + 1) |y| {
if (self.posInArea(x, y)) continue;
try self.areas.append(try Area.init(self.allocator, self.map[x][y]));
try self.lookAround(x, y);
};
}
fn lookAround(self: *Map, x: usize, y: usize) !void {
try self.checkSide(x, y);
self.areas.items[self.areas.items.len - 1].area += 1;
try self.areas.items[self.areas.items.len - 1].positions.put([2]usize{ x, y }, {});
if (self.map[x - 1][y] != '.' and self.map[x - 1][y] == self.map[x][y] and !self.areas.getLast().positions.contains([2]usize{ x - 1, y })) try self.lookAround(x - 1, y);
if (self.map[x + 1][y] != '.' and self.map[x + 1][y] == self.map[x][y] and !self.areas.getLast().positions.contains([2]usize{ x + 1, y })) try self.lookAround(x + 1, y);
if (self.map[x][y - 1] != '.' and self.map[x][y - 1] == self.map[x][y] and !self.areas.getLast().positions.contains([2]usize{ x, y - 1 })) try self.lookAround(x, y - 1);
if (self.map[x][y + 1] != '.' and self.map[x][y + 1] == self.map[x][y] and !self.areas.getLast().positions.contains([2]usize{ x, y + 1 })) try self.lookAround(x, y + 1);
}
fn checkSide(self: *Map, x: usize, y: usize) !void {
if (self.map[x + 1][y] != self.map[x][y] and !self.areas.getLast().isInSide(x, y, .DOWN)) try self.addSide(x, y, .DOWN);
if (self.map[x - 1][y] != self.map[x][y] and !self.areas.getLast().isInSide(x, y, .UP)) try self.addSide(x, y, .UP);
if (self.map[x][y - 1] != self.map[x][y] and !self.areas.getLast().isInSide(x, y, .LEFT)) try self.addSide(x, y, .LEFT);
if (self.map[x][y + 1] != self.map[x][y] and !self.areas.getLast().isInSide(x, y, .RIGHT)) try self.addSide(x, y, .RIGHT);
}
fn addSide(self: *Map, x: usize, y: usize, direction: Direction) !void {
var start_x: usize = x;
var start_y: usize = y;
var end_x: usize = x;
var end_y: usize = y;
switch (direction) {
.UP => {
while (self.map[x][start_y - 1] == self.map[x][y] and self.map[x - 1][start_y - 1] != self.map[x][y]) start_y -= 1;
while (self.map[x][end_y + 1] == self.map[x][y] and self.map[x - 1][end_y + 1] != self.map[x][y]) end_y += 1;
},
.DOWN => {
while (self.map[x][start_y - 1] == self.map[x][y] and self.map[x + 1][start_y - 1] != self.map[x][y]) start_y -= 1;
while (self.map[x][end_y + 1] == self.map[x][y] and self.map[x + 1][end_y + 1] != self.map[x][y]) end_y += 1;
},
.LEFT => {
while (self.map[start_x - 1][y] == self.map[x][y] and self.map[start_x - 1][y - 1] != self.map[x][y]) start_x -= 1;
while (self.map[end_x + 1][y] == self.map[x][y] and self.map[end_x + 1][y - 1] != self.map[x][y]) end_x += 1;
},
.RIGHT => {
while (self.map[start_x - 1][y] == self.map[x][y] and self.map[start_x - 1][y + 1] != self.map[x][y]) start_x -= 1;
while (self.map[end_x + 1][y] == self.map[x][y] and self.map[end_x + 1][y + 1] != self.map[x][y]) end_x += 1;
},
}
try self.areas.items[self.areas.items.len - 1].sides.append(Side{
.start = [2]usize{ start_x, start_y },
.end = [2]usize{ end_x, end_y },
.direction = direction,
});
}
fn calculPrice(self: Map) usize {
var total: usize = 0;
for (self.areas.items) |area| {
total += area.sides.items.len * area.area;
}
return total;
}
fn printPos(self: Map, x: usize, y: usize) void {
for (0..MAP_SIZE + 2) |x2| {
print("\n", .{});
for (0..MAP_SIZE + 2) |y2| {
if (x == x2 and y == y2) {
print("{c}", .{self.map[x][y]});
} else {
print(".", .{});
}
}
}
print("\n", .{});
}
fn printAreasOneByOne(self: Map) !void {
for (self.areas.items) |area| {
clearScreen();
print("Region {c} with Side: {d}; and Area: {d}\n", .{ area.char, area.sides.items.len, area.area });
for (area.sides.items) |side| {
print("Side {any}\n", .{side});
}
for (0..MAP_SIZE + 2) |x| {
print("\n", .{});
for (0..MAP_SIZE + 2) |y| {
if (area.positions.contains([2]usize{ x, y })) {
print("{c}", .{self.map[x][y]});
} else {
print(".", .{});
}
}
}
print("\n", .{});
try waitForInput();
}
}
fn printAreasSideOneByOne(self: Map) !void {
for (self.areas.items) |area| {
for ([4]Direction{ .UP, .DOWN, .LEFT, .RIGHT }) |direction| {
clearScreen();
print("Region {c} with Side: {d}; and Area: {d}, Direction {any}\n", .{ area.char, area.sides.items.len, area.area, direction });
for (0..MAP_SIZE + 2) |x| {
print("\n", .{});
for (0..MAP_SIZE + 2) |y| {
if (area.isInSide(x, y, direction)) {
print("{c}", .{self.map[x][y]});
} else {
print(".", .{});
}
}
}
print("\n", .{});
try waitForInput();
}
}
}
};
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
var map = try Map.init(allocator);
map.set('.');
map.setInput();
try map.populateAreas();
//try map.printAreasSideOneByOne();
try std.testing.expectEqual(821372, map.calculPrice());
}
fn clearScreen() void {
print("\x1B[2J\x1B[H", .{});
}
fn waitForInput() !void {
var buf: [5]u8 = undefined;
const stdin = std.io.getStdIn().reader();
_ = try stdin.readUntilDelimiter(&buf, '\n');
}

1279
day13/input Normal file

File diff suppressed because it is too large Load Diff

89
day13/part1.zig Normal file
View File

@ -0,0 +1,89 @@
const std = @import("std");
const print = std.debug.print;
const input = @embedFile("input");
const vec2 = @Vector(2, usize);
// So I need to find out ax + by = c
// With x and y the number of time I click on a and b respectivly
// a and b as how much I advance per click
// And c as total
// And I have 2 equation, one for prize position x and one for y
// Which you can easely do, for float, not int =(
// So how do I approach this ?
// 1. Brute force: I can do all combinaison of x and y. For like 200 max click. 320 prize, 200 * 200 * 320 = 12_800_000
// 2. Pretty sure I can do something with a modulo, because the end pos can only be reach by few combinaison
const State = enum {
ReadButtonA,
ReadButtonB,
ReadPrize,
ReadJump,
};
pub fn main() !void {
var iter = std.mem.splitAny(u8, input, "\n");
var state = State.ReadButtonA;
var buttonA: vec2 = undefined;
var buttonB: vec2 = undefined;
var prize: vec2 = undefined;
var total: usize = 0;
while (iter.next()) |line| switch (state) {
.ReadButtonA => {
var iterLine = std.mem.splitAny(u8, line, " ");
_ = iterLine.next(); // Skip Button
_ = iterLine.next(); // Skip A
const buf = iterLine.next().?;
buttonA[0] = try std.fmt.parseInt(usize, buf[2 .. buf.len - 1], 10);
buttonA[1] = try std.fmt.parseInt(usize, iterLine.next().?[2..], 10);
state = .ReadButtonB;
},
.ReadButtonB => {
var iterLine = std.mem.splitAny(u8, line, " ");
_ = iterLine.next(); // Skip Button
_ = iterLine.next(); // Skip B
const buf = iterLine.next().?;
buttonB[0] = try std.fmt.parseInt(usize, buf[2 .. buf.len - 1], 10);
buttonB[1] = try std.fmt.parseInt(usize, iterLine.next().?[2..], 10);
state = .ReadPrize;
},
.ReadPrize => {
var iterLine = std.mem.splitAny(u8, line, " ");
_ = iterLine.next(); // Skip Price
const buf = iterLine.next().?;
prize[0] = try std.fmt.parseInt(usize, buf[2 .. buf.len - 1], 10);
prize[1] = try std.fmt.parseInt(usize, iterLine.next().?[2..], 10);
state = .ReadJump;
},
.ReadJump => {
state = .ReadButtonA;
const result = bruteforce(buttonA, buttonB, prize, vec2{ 0, 100 });
if (result.cost != 99999) total += result.cost;
},
};
try std.testing.expectEqual(33921, total);
}
const Result = struct {
clickA: usize = 0,
clickB: usize = 0,
cost: usize = 999999,
};
fn bruteforce(buttonA: vec2, buttonB: vec2, prize: vec2, range: vec2) Result {
var minA: usize = 99999;
var minB: usize = 99999;
var min_cost: usize = 99999;
for (range[0]..range[1]) |clickA| for (range[0]..range[1]) |clickB| {
const end_pos = buttonA * @as(vec2, @splat(clickA)) + buttonB * @as(vec2, @splat(clickB));
if (!@reduce(.And, end_pos == prize)) continue;
const cost = clickA * 3 + clickB;
if (cost < min_cost) {
minA = clickA;
minB = clickB;
min_cost = cost;
}
};
return Result{ .clickA = minA, .clickB = minB, .cost = min_cost };
}

135
day13/part2.zig Normal file
View File

@ -0,0 +1,135 @@
const std = @import("std");
const print = std.debug.print;
const input = @embedFile("input");
const Usize = std.atomic.Value(usize);
const vec2 = @Vector(2, usize);
// I am not proud of this solution, it take like 6h to run on 16 thread :/
// I am sure I can change the bruteForce function to use modulo to reduce the number of clickA
// But it was late, I was tired so I juste started this version and the next morning it was complete soooo
// I will no go futher, I am already 2 days behind :/
const State = enum {
ReadButtonA,
ReadButtonB,
ReadPrize,
ReadJump,
};
pub fn main() !void {
var iter = std.mem.splitAny(u8, input, "\n");
var state = State.ReadButtonA;
var buttonA: vec2 = undefined;
var buttonB: vec2 = undefined;
var prize: vec2 = undefined;
var total = Usize.init(0);
var finished = Usize.init(0);
var to_wait: usize = 0;
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
var thread_arena = std.heap.ThreadSafeAllocator{
.child_allocator = allocator,
};
var thread_pool: std.Thread.Pool = undefined;
thread_pool.init(std.Thread.Pool.Options{
.allocator = thread_arena.allocator(),
.n_jobs = 16,
}) catch @panic("=(");
while (iter.next()) |line| switch (state) {
.ReadButtonA => {
var iterLine = std.mem.splitAny(u8, line, " ");
_ = iterLine.next(); // Skip Button
_ = iterLine.next(); // Skip A
const buf = iterLine.next().?;
buttonA[0] = try std.fmt.parseInt(usize, buf[2 .. buf.len - 1], 10);
buttonA[1] = try std.fmt.parseInt(usize, iterLine.next().?[2..], 10);
state = .ReadButtonB;
},
.ReadButtonB => {
var iterLine = std.mem.splitAny(u8, line, " ");
_ = iterLine.next(); // Skip Button
_ = iterLine.next(); // Skip B
const buf = iterLine.next().?;
buttonB[0] = try std.fmt.parseInt(usize, buf[2 .. buf.len - 1], 10);
buttonB[1] = try std.fmt.parseInt(usize, iterLine.next().?[2..], 10);
state = .ReadPrize;
},
.ReadPrize => {
var iterLine = std.mem.splitAny(u8, line, " ");
_ = iterLine.next(); // Skip Price
const buf = iterLine.next().?;
prize[0] = try std.fmt.parseInt(usize, buf[2 .. buf.len - 1], 10) + 10000000000000;
prize[1] = try std.fmt.parseInt(usize, iterLine.next().?[2..], 10) + 10000000000000;
state = .ReadJump;
},
.ReadJump => {
state = .ReadButtonA;
try thread_pool.spawn(bruteforce, .{ buttonA, buttonB, prize, &total, &finished, to_wait });
to_wait += 1;
},
};
while (to_wait > finished.load(.monotonic)) {
std.time.sleep(1000000);
printProgressOverall(finished.load(.monotonic), to_wait);
}
print("Total: {d}\n", .{total.load(.monotonic)});
}
const Result = struct {
clickA: usize = 0,
clickB: usize = 0,
cost: usize = 999999,
};
fn bruteforce(buttonA: vec2, buttonB: vec2, prize: vec2, total: *Usize, finished: *Usize, id: usize) void {
var min_cost: usize = std.math.maxInt(usize);
const max_clickA = @min(@divFloor(prize[0], buttonA[0]), @divFloor(prize[1], buttonA[1])) + 10;
var clickA: usize = 0;
while (clickA <= max_clickA) : (clickA += 1) {
if (clickA % 1000000000 == 0) printProgress(clickA, max_clickA, id);
const remaining = prize - buttonA * @as(vec2, @splat(clickA));
if (@reduce(.Or, remaining < @as(vec2, @splat(0)))) continue;
const clickB = @divFloor(remaining, buttonB);
if (clickB[0] != clickB[1]) continue;
if (@reduce(.Or, remaining % buttonB != @as(vec2, @splat(0)))) continue;
const cost = clickA * 3 + clickB[0];
if (cost < min_cost) min_cost = cost;
}
if (min_cost != std.math.maxInt(usize)) {
_ = total.fetchAdd(min_cost, .monotonic);
}
_ = finished.fetchAdd(1, .monotonic);
}
fn printProgress(value: usize, max: usize, id: usize) void {
print("Thread {d}: {d}% | {d}/{d}\n", .{ id, @divFloor(value * 100, max), value, max });
}
fn printProgressOverall(finished: usize, total: usize) void {
std.debug.print("Overall: {d}/{d} ({d}%) \r", .{ finished, total, @divFloor(finished * 100, total) });
}
fn gcd(a: u64, b: u64) u64 {
if (b == 0) {
return a;
} else {
return gcd(b, a % b);
}
}
fn isPossible(a: u64, b: u64, c: u64) bool {
return c % gcd(a, b) == 0;
}

500
day14/input Normal file
View File

@ -0,0 +1,500 @@
p=52,66 v=37,34
p=0,87 v=41,-19
p=92,102 v=-26,86
p=7,12 v=-16,-17
p=85,34 v=81,38
p=80,28 v=88,-61
p=25,20 v=27,92
p=28,45 v=-80,66
p=72,86 v=47,-85
p=36,2 v=28,30
p=36,29 v=28,69
p=84,102 v=-26,86
p=52,73 v=68,-91
p=26,38 v=-68,-69
p=54,100 v=65,-70
p=99,77 v=-1,-42
p=50,59 v=-94,87
p=65,34 v=47,-96
p=87,100 v=-78,86
p=25,31 v=-62,7
p=78,8 v=67,-69
p=19,59 v=-28,9
p=85,61 v=-17,84
p=20,28 v=-25,13
p=25,21 v=-68,-50
p=34,30 v=9,32
p=91,15 v=-4,45
p=2,58 v=-60,56
p=52,89 v=-21,-79
p=59,11 v=-88,23
p=64,45 v=-91,72
p=42,102 v=-15,-92
p=64,56 v=99,-36
p=69,36 v=10,-15
p=22,74 v=-74,-13
p=74,32 v=-11,-15
p=49,37 v=-9,-48
p=31,55 v=70,-78
p=15,75 v=-65,-38
p=69,38 v=54,-69
p=32,36 v=93,68
p=36,96 v=67,23
p=57,96 v=-82,-67
p=6,88 v=48,30
p=13,67 v=76,87
p=32,34 v=-67,-87
p=87,41 v=-57,11
p=1,14 v=54,-99
p=88,51 v=34,50
p=73,80 v=38,56
p=19,95 v=88,27
p=80,71 v=-66,-82
p=79,30 v=84,54
p=24,22 v=91,-55
p=56,27 v=-27,1
p=69,80 v=4,46
p=50,78 v=-85,84
p=7,27 v=51,29
p=71,78 v=47,96
p=86,90 v=-23,58
p=31,37 v=6,19
p=47,31 v=-95,16
p=33,91 v=-89,80
p=36,64 v=-3,6
p=80,50 v=-38,25
p=54,84 v=28,21
p=77,26 v=58,81
p=43,43 v=68,56
p=60,95 v=-48,71
p=95,25 v=5,-57
p=80,95 v=-45,78
p=66,29 v=-20,82
p=99,76 v=-7,-91
p=81,31 v=-69,-88
p=76,57 v=-75,94
p=82,17 v=-66,-5
p=86,13 v=-13,21
p=12,94 v=-89,51
p=21,30 v=61,72
p=7,98 v=-35,-79
p=64,92 v=-41,27
p=16,54 v=-27,-53
p=69,56 v=-35,-67
p=51,84 v=-33,99
p=87,98 v=78,64
p=10,25 v=33,-75
p=57,12 v=13,42
p=9,98 v=-83,-23
p=97,66 v=32,-75
p=86,50 v=-29,22
p=43,0 v=18,21
p=90,23 v=29,-49
p=18,63 v=77,-51
p=61,58 v=-60,-44
p=69,94 v=-94,33
p=67,100 v=77,-8
p=12,50 v=30,47
p=57,96 v=-24,2
p=60,95 v=25,-51
p=9,4 v=3,-46
p=4,22 v=94,60
p=79,16 v=38,-93
p=62,57 v=78,-72
p=78,0 v=70,92
p=7,91 v=-93,-25
p=83,48 v=-57,34
p=73,35 v=-51,-90
p=5,32 v=94,-9
p=89,36 v=-23,44
p=36,33 v=-27,60
p=90,98 v=-66,2
p=81,9 v=93,58
p=27,101 v=92,36
p=72,39 v=96,-15
p=48,75 v=-77,-52
p=64,1 v=10,45
p=31,75 v=-31,-99
p=54,50 v=-92,-40
p=82,78 v=23,46
p=92,48 v=34,-65
p=91,54 v=20,-84
p=90,67 v=69,-88
p=72,35 v=-60,-40
p=18,76 v=55,-44
p=25,101 v=-92,-73
p=64,15 v=7,-77
p=42,42 v=-67,66
p=47,38 v=-95,44
p=54,46 v=-45,-19
p=25,0 v=37,-27
p=0,55 v=23,-62
p=41,66 v=43,-94
p=58,89 v=-61,11
p=41,90 v=-58,52
p=29,83 v=-37,2
p=50,45 v=16,6
p=59,6 v=65,-83
p=78,84 v=37,73
p=2,24 v=-58,-46
p=100,30 v=8,-96
p=13,55 v=64,65
p=84,83 v=78,-1
p=16,46 v=79,38
p=94,34 v=-1,75
p=36,82 v=-58,-85
p=4,52 v=25,-64
p=31,101 v=49,5
p=89,6 v=26,36
p=46,97 v=58,-64
p=65,5 v=74,55
p=24,37 v=-25,41
p=40,89 v=67,24
p=84,5 v=29,-48
p=26,94 v=81,98
p=51,8 v=-21,-84
p=10,82 v=-51,-32
p=56,89 v=50,-6
p=53,13 v=-58,68
p=47,36 v=-73,85
p=59,68 v=16,-60
p=1,83 v=54,-63
p=43,6 v=-67,-49
p=2,68 v=51,9
p=58,42 v=40,-75
p=10,71 v=-22,-26
p=17,79 v=-80,59
p=28,12 v=24,-11
p=1,100 v=26,84
p=58,99 v=16,67
p=54,8 v=-79,-92
p=69,26 v=81,-58
p=11,7 v=47,-41
p=87,15 v=-99,26
p=60,20 v=-40,-24
p=71,92 v=3,37
p=97,82 v=-41,40
p=54,12 v=-30,-27
p=32,17 v=61,82
p=54,95 v=-38,-16
p=42,26 v=-67,57
p=22,45 v=73,69
p=18,0 v=-22,-92
p=70,39 v=19,95
p=63,72 v=10,21
p=26,88 v=24,46
p=4,101 v=75,43
p=31,31 v=30,-12
p=71,10 v=43,-86
p=68,42 v=-2,94
p=90,76 v=-38,68
p=71,76 v=63,-13
p=35,76 v=-21,6
p=95,28 v=35,-77
p=22,7 v=-52,-8
p=23,56 v=-8,69
p=54,45 v=-76,-90
p=56,64 v=-91,-75
p=28,39 v=-41,77
p=42,51 v=-12,19
p=28,67 v=12,-44
p=86,52 v=75,-84
p=69,54 v=71,90
p=42,70 v=-52,-25
p=14,48 v=16,-96
p=1,65 v=-26,-72
p=80,34 v=-39,-6
p=78,15 v=41,-33
p=13,5 v=-7,64
p=28,80 v=-40,18
p=43,15 v=40,-8
p=98,68 v=-6,82
p=16,32 v=86,11
p=66,56 v=65,75
p=84,58 v=48,-33
p=65,22 v=-63,-84
p=93,52 v=-75,72
p=17,23 v=-68,-74
p=77,65 v=-8,-66
p=61,37 v=-42,69
p=86,8 v=66,-20
p=4,7 v=-44,70
p=15,82 v=9,-23
p=67,95 v=-95,57
p=5,24 v=69,4
p=58,96 v=99,46
p=38,21 v=50,56
p=60,76 v=-64,74
p=29,0 v=-55,-25
p=24,13 v=65,71
p=48,76 v=-67,37
p=19,39 v=-62,29
p=33,58 v=6,28
p=29,38 v=-98,-68
p=50,55 v=-55,65
p=5,77 v=91,71
p=99,38 v=-8,77
p=58,47 v=16,44
p=43,45 v=12,-31
p=21,102 v=45,-20
p=79,99 v=83,-46
p=52,56 v=83,16
p=56,27 v=74,-68
p=17,20 v=82,-77
p=62,8 v=13,95
p=58,24 v=-48,-2
p=86,68 v=-3,-37
p=2,24 v=63,-8
p=1,81 v=-41,-88
p=15,40 v=-25,66
p=77,97 v=-23,5
p=48,4 v=34,42
p=41,74 v=-3,-91
p=90,53 v=44,-76
p=50,42 v=-79,13
p=77,67 v=17,-53
p=69,3 v=-8,3
p=89,60 v=-8,19
p=15,93 v=54,-32
p=11,24 v=36,63
p=22,6 v=-52,79
p=11,101 v=-80,-79
p=79,87 v=-8,77
p=46,97 v=13,61
p=90,25 v=-45,7
p=46,95 v=13,-23
p=89,62 v=-72,-94
p=32,100 v=-49,58
p=58,30 v=68,-40
p=97,28 v=11,37
p=76,61 v=-88,-31
p=6,45 v=-7,38
p=79,34 v=-69,-90
p=96,76 v=57,-29
p=9,100 v=-7,55
p=59,23 v=50,43
p=19,7 v=33,-74
p=45,43 v=86,66
p=50,19 v=56,33
p=28,65 v=-9,-89
p=14,2 v=-74,-33
p=91,98 v=-50,99
p=93,80 v=94,-48
p=55,81 v=-7,-20
p=57,100 v=-30,-39
p=62,76 v=68,-38
p=15,20 v=-77,-90
p=37,33 v=89,60
p=18,101 v=-3,20
p=56,65 v=71,-60
p=26,26 v=-58,-99
p=33,75 v=-49,-91
p=10,71 v=-56,-34
p=25,83 v=39,-6
p=13,17 v=37,61
p=98,95 v=2,80
p=26,83 v=-49,-35
p=9,27 v=-72,46
p=27,73 v=-9,40
p=71,5 v=-94,-89
p=60,6 v=-21,30
p=10,68 v=-82,-31
p=87,45 v=-38,66
p=55,46 v=-68,-93
p=34,77 v=55,-63
p=5,51 v=38,31
p=3,65 v=94,-16
p=70,24 v=-48,10
p=89,78 v=-75,40
p=32,39 v=3,66
p=28,94 v=40,-36
p=91,38 v=-35,66
p=29,66 v=-94,-50
p=90,80 v=63,74
p=15,31 v=-95,78
p=50,19 v=7,-71
p=58,64 v=-5,68
p=16,64 v=65,-35
p=46,93 v=-59,-22
p=65,5 v=53,-33
p=10,83 v=84,47
p=23,12 v=49,-76
p=58,14 v=-36,-80
p=49,4 v=28,17
p=62,43 v=-39,56
p=61,11 v=-36,-52
p=60,72 v=71,87
p=44,56 v=-85,-76
p=37,88 v=-3,27
p=10,35 v=-90,-18
p=14,40 v=30,-34
p=22,95 v=27,95
p=32,92 v=-37,2
p=54,3 v=-54,-82
p=98,5 v=11,-24
p=39,76 v=37,90
p=69,15 v=47,45
p=56,40 v=-79,13
p=80,41 v=63,32
p=11,85 v=-7,74
p=24,45 v=46,-50
p=98,49 v=-38,-81
p=26,45 v=-26,-80
p=2,87 v=60,6
p=93,74 v=26,-16
p=24,70 v=-28,-85
p=59,21 v=-63,62
p=44,74 v=-7,14
p=75,94 v=47,-86
p=84,16 v=6,41
p=17,79 v=33,-44
p=5,72 v=18,58
p=96,11 v=8,17
p=34,48 v=62,14
p=17,36 v=-42,-64
p=87,55 v=93,65
p=84,1 v=75,52
p=30,74 v=-5,-33
p=34,22 v=-32,-91
p=85,94 v=-51,17
p=37,90 v=-9,55
p=9,85 v=-58,-37
p=58,30 v=-2,72
p=90,55 v=-53,-78
p=34,48 v=-8,-33
p=76,62 v=13,18
p=16,21 v=76,-99
p=42,71 v=46,68
p=95,9 v=-75,64
p=63,99 v=62,-39
p=73,97 v=68,92
p=79,17 v=-17,-39
p=16,54 v=27,90
p=48,34 v=9,-49
p=88,72 v=51,59
p=94,24 v=62,-43
p=93,37 v=22,24
p=90,80 v=-23,15
p=10,98 v=88,80
p=60,9 v=65,64
p=44,80 v=21,68
p=32,3 v=-95,83
p=83,13 v=78,1
p=20,49 v=70,-94
p=51,82 v=-30,71
p=31,12 v=61,86
p=67,51 v=4,3
p=19,25 v=67,76
p=96,6 v=-99,-11
p=35,13 v=-98,-42
p=89,13 v=-29,95
p=73,73 v=-60,87
p=50,4 v=77,98
p=5,86 v=61,49
p=14,56 v=-7,40
p=97,4 v=8,-64
p=19,67 v=-37,-47
p=61,23 v=-88,60
p=23,11 v=-59,11
p=11,16 v=33,-9
p=90,29 v=-12,75
p=81,62 v=-9,51
p=34,60 v=58,84
p=46,16 v=58,67
p=47,12 v=74,67
p=33,50 v=-31,87
p=76,32 v=-52,-66
p=56,39 v=-79,88
p=92,18 v=-75,63
p=9,17 v=36,70
p=70,42 v=-11,74
p=11,8 v=46,69
p=30,19 v=64,-5
p=78,42 v=-45,-46
p=98,64 v=-99,-66
p=83,31 v=14,-39
p=97,66 v=73,96
p=33,55 v=46,-38
p=67,59 v=59,3
p=19,34 v=82,-37
p=9,77 v=45,46
p=88,100 v=29,55
p=77,2 v=-54,-42
p=59,49 v=-79,-53
p=22,83 v=94,99
p=75,40 v=99,-15
p=44,33 v=-28,2
p=83,42 v=44,-65
p=61,13 v=-7,-8
p=39,25 v=-90,93
p=18,11 v=32,98
p=49,24 v=3,32
p=75,30 v=99,85
p=48,21 v=52,40
p=5,23 v=91,-52
p=40,41 v=92,-62
p=14,51 v=-34,-41
p=17,86 v=30,27
p=77,15 v=-11,-80
p=26,18 v=-77,73
p=26,42 v=26,-25
p=10,97 v=27,80
p=24,37 v=-40,-65
p=75,40 v=-81,-43
p=6,19 v=57,38
p=16,82 v=-74,-85
p=87,81 v=-32,15
p=36,91 v=53,-60
p=25,32 v=6,-71
p=11,69 v=-41,65
p=31,81 v=-22,33
p=7,51 v=-88,-93
p=75,18 v=84,-30
p=59,65 v=-33,-22
p=53,19 v=87,-14
p=53,98 v=-30,55
p=69,88 v=-27,-12
p=34,93 v=-37,52
p=16,17 v=11,65
p=65,53 v=-33,-28
p=81,45 v=-66,-5
p=97,92 v=18,-58
p=88,18 v=72,1
p=72,62 v=-34,64
p=79,70 v=29,26
p=64,66 v=7,75
p=48,65 v=-89,-68
p=47,18 v=-7,-64
p=50,89 v=-73,-64
p=13,91 v=33,29
p=63,6 v=-45,42
p=84,22 v=84,-71
p=68,100 v=53,5
p=89,66 v=-55,59
p=66,19 v=-17,95
p=49,16 v=61,-60
p=16,15 v=58,70
p=38,12 v=-37,47
p=98,44 v=81,-75
p=34,72 v=-3,28
p=36,54 v=16,31
p=48,63 v=55,6
p=14,68 v=33,90
p=18,67 v=-1,-53
p=10,35 v=58,59
p=13,67 v=57,-38
p=48,69 v=83,90
p=88,17 v=-75,26
p=69,72 v=-98,54
p=87,12 v=-48,16
p=99,2 v=14,64
p=71,97 v=47,39
p=69,64 v=14,-3
p=36,82 v=38,-93
p=24,77 v=21,-10
p=10,21 v=-34,-30
p=34,44 v=-98,47
p=38,9 v=-39,-74
p=76,21 v=44,60
p=66,75 v=-33,-66
p=26,31 v=9,-40

70
day14/part1.zig Normal file
View File

@ -0,0 +1,70 @@
const std = @import("std");
const print = std.debug.print;
const input = @embedFile("input");
const Int = i16;
const MAP_SIZE: [2]Int = .{ 101, 103 };
pub fn main() !void {
var tl_quadrant: usize = 0;
var tr_quadrant: usize = 0;
var bl_quadrant: usize = 0;
var br_quadrant: usize = 0;
const mapW = MAP_SIZE[0];
const mapH = MAP_SIZE[1];
var iter = std.mem.splitAny(u8, input, "\n");
while (iter.next()) |line| {
if (std.mem.eql(u8, line, "")) continue;
var iter_space = std.mem.splitAny(u8, line, " ");
const part1 = iter_space.next().?;
var iter_comma = std.mem.splitAny(u8, part1, ",");
const x = try std.fmt.parseInt(Int, iter_comma.next().?[2..], 10);
const y = try std.fmt.parseInt(Int, iter_comma.next().?, 10);
const part2 = iter_space.next().?;
iter_comma = std.mem.splitAny(u8, part2, ",");
const vX = try std.fmt.parseInt(Int, iter_comma.next().?[2..], 10);
const vY = try std.fmt.parseInt(Int, iter_comma.next().?, 10);
const end_pos = posFinal(x, y, vX, vY, mapW, mapH, 100);
switch (detectQuadrant(end_pos[0], end_pos[1], mapW, mapH)) {
.TopLeft => tl_quadrant += 1,
.TopRight => tr_quadrant += 1,
.BottomLeft => bl_quadrant += 1,
.BottomRight => br_quadrant += 1,
.None => {},
}
}
try std.testing.expectEqual(218965032, tl_quadrant * tr_quadrant * bl_quadrant * br_quadrant);
}
fn posFinal(x0: Int, y0: Int, vX: Int, vY: Int, mapW: Int, mapH: Int, dt: Int) [2]Int {
var t: Int = 0;
var x: Int = x0;
var y: Int = y0;
while (t < dt) : (t += 1) {
x = x + vX;
y = y + vY;
// Dected boundary
if (x >= mapW) x = x - mapW; //Move back to 0 + xt1 - mapW
if (x < 0) x = mapW + x;
if (y >= mapH) y = y - mapH;
if (y < 0) y = mapH + y;
}
return [2]Int{ x, y };
}
fn detectQuadrant(x: Int, y: Int, mapW: Int, mapH: Int) enum { TopLeft, TopRight, BottomLeft, BottomRight, None } {
if (x < @divFloor(mapW, 2)) {
if (y < @divFloor(mapH, 2)) return .TopLeft;
if (y > @divFloor(mapH, 2)) return .BottomLeft;
} else if (x > @divFloor(mapW, 2)) {
if (y < @divFloor(mapH, 2)) return .TopRight;
if (y > @divFloor(mapH, 2)) return .BottomRight;
}
return .None;
}

135
day14/part2.zig Normal file
View File

@ -0,0 +1,135 @@
const std = @import("std");
const print = std.debug.print;
const input = @embedFile("input");
const Int = i16;
const MAP_SIZE: [2]Int = .{ 101, 103 };
// I am pretty sure that I can detect the tree by using the distance of each drone from each drone
// Something like that, some kind of noise
// If they picture a tree, it mean they are close to each other right ? So it is less 'noisy' or less enthropy
const Drone = struct {
x: Int,
y: Int,
vX: Int,
vY: Int,
fn next(self: *Drone) void {
const mapW = MAP_SIZE[0];
const mapH = MAP_SIZE[1];
self.x += self.vX;
self.y += self.vY;
// Dected boundary
if (self.x >= mapW) self.x -= mapW; //Move back to 0 + xt1 - mapW
if (self.x < 0) self.x += mapW;
if (self.y >= mapH) self.y -= mapH;
if (self.y < 0) self.y += mapH;
}
fn detectQuadrant(self: Drone, mapW: Int, mapH: Int) enum { TopLeft, TopRight, BottomLeft, BottomRight, None } {
if (self.x < @divFloor(mapW, 2)) {
if (self.y < @divFloor(mapH, 2)) return .TopLeft;
if (self.y > @divFloor(mapH, 2)) return .BottomLeft;
} else if (self.x > @divFloor(mapW, 2)) {
if (self.y < @divFloor(mapH, 2)) return .TopRight;
if (self.y > @divFloor(mapH, 2)) return .BottomRight;
}
return .None;
}
};
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
const drones = try parseDrone(allocator);
var list = std.ArrayList(u8).init(allocator);
const writer = list.writer();
for (0..10000) |i| {
list.clearRetainingCapacity();
for (drones) |*drone| drone.next();
if (!detectIfDroneClose(drones, 40, 2)) continue;
clearScreen();
try printDrone(writer, drones);
print("{s}\nTime: {d}s", .{ list.items, i });
try waitForInput();
}
}
fn parseDrone(allocator: std.mem.Allocator) ![]Drone {
var list = std.ArrayList(Drone).init(allocator);
var iter = std.mem.splitAny(u8, input, "\n");
while (iter.next()) |line| {
if (std.mem.eql(u8, line, "")) continue;
var iter_space = std.mem.splitAny(u8, line, " ");
const part1 = iter_space.next().?;
var iter_comma = std.mem.splitAny(u8, part1, ",");
const x = try std.fmt.parseInt(Int, iter_comma.next().?[2..], 10);
const y = try std.fmt.parseInt(Int, iter_comma.next().?, 10);
const part2 = iter_space.next().?;
iter_comma = std.mem.splitAny(u8, part2, ",");
const vX = try std.fmt.parseInt(Int, iter_comma.next().?[2..], 10);
const vY = try std.fmt.parseInt(Int, iter_comma.next().?, 10);
try list.append(Drone{ .x = x, .y = y, .vX = vX, .vY = vY });
}
return try list.toOwnedSlice();
}
fn printDrone(writer: anytype, drones: []const Drone) !void {
var buf: [MAP_SIZE[0]][MAP_SIZE[1]]u8 = [_][MAP_SIZE[1]]u8{[_]u8{0} ** MAP_SIZE[1]} ** MAP_SIZE[0];
for (drones) |drone| {
const x = @as(usize, @intCast(drone.x));
const y = @as(usize, @intCast(drone.y));
buf[x][y] += 1;
}
for (buf) |line| {
for (line) |v| {
if (v == 0) {
try writer.writeByte(' ');
} else {
try writer.writeByte('0');
}
}
try writer.writeByte('\n');
}
}
// Detect if at least 10 drones have 10 other drones close it it
fn detectIfDroneClose(drones: []Drone, to_find: usize, distance_max: f64) bool {
var founded1: usize = 0;
for (drones) |drone1| {
var founded2: usize = 0;
for (drones) |drone2| {
if (distance(drone1, drone2) < distance_max) founded2 += 1;
}
if (founded2 > to_find) founded1 += 1;
}
return founded1 > to_find;
}
pub fn distance(drone1: Drone, drone2: Drone) f64 {
const dx = @as(f64, @floatFromInt(drone2.x - drone1.x));
const dy = @as(f64, @floatFromInt(drone1.y - drone1.y));
return std.math.sqrt(dx * dx + dy * dy);
}
fn clearScreen() void {
print("\x1B[2J\x1B[H", .{});
}
fn waitForInput() !void {
var buf: [5]u8 = undefined;
const stdin = std.io.getStdIn().reader();
_ = try stdin.readUntilDelimiter(&buf, '\n');
}

71
day15/input Normal file
View File

@ -0,0 +1,71 @@
##################################################
#..O.O..#..O.O.O.O.......##O..OOO.....O...O..#..O#
#.O.O.#.....O..O......O.O.OOO.......OO.O.....#...#
#OO........O.....OO......##OO.#OO.OO..O....OOO...#
#......O...O..O.#....O...O.....O..#.O.O.O...#O...#
#OOO.OO.OO...####O.#O...O..OO...O#.O..#.OO.O...O.#
#O#...OOOO......O#O#....#OO...O.....O.O.OOO.OOO..#
#O.O...O.#OO......#...........O...OO.O..O#.#OO...#
#O.....O.O.O.#...OO..O#....OO.O.O....#.........O.#
#.O.#O.O#...O#..O.O.#.O.OO..O..O...O.O...OO.O...O#
#..#..O.#.O..##......OO...........O.....O...#.#..#
#.OO#.........O...O.....OO.O...OO............O#.O#
##.O.OO.O...O.O..O..OO.#....O.#....O......OOO...O#
#..OO..O.O..O..O..O...O..O.....#OO.....O...#OOO.O#
#.......O.#O.OO..#......O..OO.......O..O.O....OO##
#.....O.........O...#.O..O..#OO.O...O.O.#....O...#
#.OO##O#..O.#..O......OO..OO.OO.....O..OO#O.O..O##
#.O....O...#O.O..O#....O#O...OO.....O....O.......#
#...OOO....#O.OO...#.OO#O...O#O..#..#.O..O....#..#
##....O.OO.O#..........O#.OOO.#....#...O#....OO..#
#.#OOO..OO..O.......#.OO.O..#O.#.OO....OO.O.....O#
#.O......#..O.#.O..........#O..O.OO...#O...O#....#
#.#....O.O....O.......O..OOO..OO...OO.#OOO.O.O.#.#
#.O.#.O.O....OOO...O...O#......OO##.O..OO.....O..#
#.OO.......#O.OO#..#....@O...O....OOO.O..OO......#
#O..#..#OO...O#OO.......OO..##..O.#.O.O..O.O..OO.#
#.#.O.OO.........OO#.O..O.O...OOO.O......O#...OO.#
#.OO...#..OO.##......O#.O.OO....O..O#.......O.OO##
#OO..O.O.O....O#.O..O......#...OO#.O..O.O..O..OOO#
#...OO....OOO.....O..O..O....OO......OOO.........#
#O...#.....O...O..OO..O.OO....O.O..O....O....O.O.#
#.....OOOO..#..#.O.OO.......O....OO#.O...O..O..O.#
##.OO...O.#O......#O.O#O#..O#..O.....O....OO..O.##
#..O..OOO...OO.OO.#O#.OOO......O...OO...O.O......#
#.OO.O..O.O.O#..O.#.O.OOO...O..OO.O##.O.#...#...O#
#........#...O##.....OO....O.O....OO#.O.O.O.#OO.O#
#.O..O.O.#...O.......#...#..O...O.#.........#..O##
#...........O.....O..OO.......#..#...O...#..O.##O#
#.OOO..O..OO....#..OOOO......O...##..#.......O...#
##..#O..OOO.#O...O..OO...O....OO..#..#.OO.O.OO...#
##O....#...OO#.O.O...O...O.O..O.......O.....O..#.#
#........#.O##...O#..O..O.#O........O#..OO#.O.O###
#....#.O............O..O...OO....OOO...OO...#....#
#.#O.....#...OO.OO.........#.#.OOO.OO.O...O#.O.#.#
##....#..OO...O...O..#O..O.O..O.O..O..O.OO.......#
#...........OO.O.O...O......O...O.OOO.....O..O...#
##O.O..O.O...O.....O.O.O.O.OO.#O.O.O..#.....#....#
##.O.......#O.#...O#O#O..O..#O..O....OO.O.O......#
#O...O.O.........O......O.......O......#..O.....##
##################################################
^>>^v><^>v>>^v^^^v<>>v><vvv<>v^>>v><<<>^<<v^>vvvv^v^>v^>>^<v><>vv^>^>^v<^v^v<<<<^<>v<<>vv<>^vv<^v><^^>^>^v>>^>^v>>>v<<^>^>^<^<><^vvv<<^vvv>v<v<<>v^><<v^<>v^v^^^>v^<^v<vv^v^>>^^<<>^><<<>>>^v^>vv><<>>v>vv<<>^v<>>v<v^<>><>>^<v<>^<^^<^v>v^<vvv^<v<v^>vv>>^^^>v><^<vv<>>><v>>>^v>><v^>vv<v>vvv<vv>>>^<v<^vv^<^<<v^^vv<^>^<<<v<v<^><v<<^^v^v<>>>^v^<<<vvvvv<<^><^v<>v>^v>>>><v>v^><^v^^<<><v^>^<v<>v><v^^^^<^v>^><>^^<^>^<<^<<^v>^v^^v><>v^^^<^^<>vv<v<<><>v^<vv>^vv><vvvvv<^v<vvvv^vv^v^>>vv>^<v>^^v<^v><^v^^v^^v>vvvv^v^^>^^v^^^v>v><>^<v<<^><v>^v^<vvvv>>v^v^v>v^<vv>>^>^>>^>><>^<v<<^v^<>^><^<vv>^^^vv>v>^^vv^>><^v<v<v><v<>>vv>>v<v<>vv<vvv^<><^>v<^^^<>^v<>>v>^>>^^v>vv>vv^><<^v<<^><<v<v^vv<<^v<^<>^>>^<<><^vv<v<<<v^v<<>^>v<<v<^v>>vv^^>v^><><><<vv<^><>v^vv><<v<vvv<>^<^^vv<<<>^^<>^vv>>vvv<<^<v>^^><<^><vvv^>^^>^<^^>v><<<<<vv^><>>vv<^<<^^v<>v<>v<<v>v^^v<>>><<^^>v>vv^^^<^<>^^><^>vvvv>vv^<v^<>^<<^^>^^^>^<^<v^<<v<><v^>v^>^>^>v<^<^><<<>><>>>^^<<>^v>^^>>v^v<^^<v>v^v<v>^vv^^^<>^v^^v<>v<>vv<^^<<>vv^>>^^^vv<^^^<><>^<<><>^v
<v<^v<<^vv^>^vv>^vvv<^<<>^>>^^>^v<^<>v^^<<^v<v><>>^<^<<v<^v<^^<<v<<^^^^><><v<^^^v>><<^<<>>><>^v>vv>>v^<>v^<^v>v^>>^v<v<v<>^<<^>>><><^<^v<<^>v^^^<><<>>><<^vv>>v^<vv<<>^^<<v>>v><>^<<>^^><<><>v>v^<^v^<^>vvv<>v>>>>>>^vvv>v^<^v<>v>v^><^vv<vv<v>>v<^>v>^>^<v^^^<<>^><v>^>><^<vvv>>v^v^>^<vv^<v^>>v<>>>v^>v<v<^^>^><^>><v^><^v^^<>vv>>^^^>v^<><^<><^^<v^v^<<<^<vv>v>^^>v<^<<v^>^>v<<<>^>><^v<vv>v^v^^^^<vv^><>v^>v>><<v<<>v<>v^>v><v^^^v^<v<^<>^v<v<v>v^v<^^v<v^>v<v^v^>><^>><v><>>^<><v^<<<v<><<^^><><<v><vvv<v><>>^>>>vv<^^^>^<<<<^^^v<vv^<>vv>>^^^^vv>v<^>><<v^^^v>vv^v><^v><v^<<<v<>^v>vv^^>v<v^<<>^>><<^v^^>^>>^^><<^<<>^>>v>v<^<v^^^v<^^>>^^^<>^>><<v><<v>vv<>>>^vv<<><v^>>>vvv^>vv><v<<>^^>^v<^^>v>v^<^>^<v<v<>>><vv<vv^<<>^v<v<^^<vv>vv^>v<<>^<>v<^>v^<vv<><<>^v<>>^^<^><vv>^^^<^v<<^>^^<<<vvv><^v<^^^v>>v>><v<><>><v>^<>>vvv<v>v^^<v<>>><>v>^>>><v<v<<>v^>>^>^v>^><^v>^<v>v<vv^><>v<v>^v>>^v><v<<^>v>^^<<^v<^<vv<>^<><vv^v<<v>>^v<<^>>^<^>^><v^><^>>v<v^<^v<^^v>^<v<^vvv<v^>vvv><^v<v<v<v^^>^<^>^^>v<^^^<^^>^v>><v^<<><>>v^^v^v^v
<<<>>>^>><><>^^>>^<<vv>vvvv<><^<^v^v<>>>><^<>v><^vv<^v>>v<<<^^>^<<><>^^><<^><<<<^^v^^>v<<vv>^>>^^^v>^<v><<^><<vv^<><^>^><vv>v^<<v<>v^>^<><<>>>v^>^>v<v><><<v<<>>^vv>>><<^^>vvv^<vv<v<<>><<^^v>>><v<<<^<^v>v^>v>>vv^^^v>>v^><<<>v><^<^v<<<^^<^v<<^^v<>^^<>^>^<v^^^^^^>v<<v>^vv<>v<>vv>v<>v<^^v><^<vv<^<>>^<v<>v^<>v><>v<^v>>v>^^><v<vvv^^<v>>v^><vv<<<>>^<v>v^vv>><^<<v>^^^>>>v><>>vv>^^<vv<vv><v^v>^v<>vvvv<>^v<>>^<><vv^><>>>^^^^>>vv^v^<>><^^><^^>><<<v<>^vvv^>vv><>v>v^<^v^<vv<><<<v<vv<v>^>v^>><<^>^>^vv>^<v>v^>v<<>>><<vv^<<v>v>^<<<<<<>>vv^^^<<v<<<^<<<v^v<^<v>>>vv>v<>>>^<>^>^v<>vv>>v<<^>v>^vv>vvv^<>><<vv<^^><<^>vvv><v^v><><<v^^vv>^<>>v^>^^>v>>>v>vv^><>>><<<<<>^>vv^<<^^<^>^<>^>v<v<<>v^v>>>^v^v>^v>^<<v>^vvv>>vv<>v><v><v^<>v^v^>v<><vv><^^vv^v<vvv>^<<^^>^>v^^>^^<>^>>>>v^<^>><>^v>v>v>><^vv^v^<^<v<<<v><v>vv<<<>>>>^v<<v^^<^^><>^^<^^v^v<>><><>><>v>>v^v^><^<^v^>>><vvv<>>><v><v^^v^><vvv>>^^>>>^><<<>v>^^v<v<<v<<><^<>^^vv^<^><v><^>^<>v><vv^^^v<<^<>^^>^^v<^v<vv<<<><v><v><v<<^^v<v>>^>^^<>^vvvvv^^^>><<^<><v>^>^<v>>>v
<^<^^<v^v>^>vv^v><>^>^>^^<vv<^><^v^><^v^><^><<<^^v>v>^>^><vv>^^^v^>^v^<v<<<<<>>v>>>vv><<<v>v<<><<v<v^>>^v<<v<<^vv<<^<^>><^^v>vvv>>v>><^vv>^<<<^>v<^<><^v>^<<v^<<v^>>v>>v<<^^v^^><^>v^v>^<<<<v^v^<>>v^>v^^v^<v^^<^>v<v>>v^v>>^^<>><vv^<>v<><^^>^^^^vvv>vvv>^><><^><<<>^v^<>v^>^^>>^vv>^<>>>>v<vv^vvv>><^^<<>^>^^>><<^<^>^^v<vv>^^>^v>v^>^^<<v>>>^<vv^vv^>v><>v><<vv^>>^vvv<<^v^<vvvv>^<^<^<^<vv<>>^<vv>v^>v^><<^^><^v<vv<>>^<v^<>^>v^<<<v^>>>>><<<vvv>v<^vvv>v><^^^<v^v^>v>^<>v^<>>^vvv<v^<v<^>^<v<v<>v<<>^<<>^^^^v<v<^v<v<<>^>^vv^>v>v>vv^>vvv>v^vv><^>vv^><^^v<^>v<>^>^<v<>^vv^^<<<<>^^^v^^^<>v<>^<>><v>>v>^>v^>^>^<v>^<^<>^<<<v<<^><^<v^>><>>v^^v>v<^^><><v<^<<^v>>^v^>^<<<vvvv>^><^><vv^v>^^^>v><>v>^>^v>^v^<^v>>v^v^><^^<^^<v^v^<v^>^^>v>><<v><vv^^><<^^><>v>><<<^<<>>v><>v^<<<vv>^<<<>vv<<v<>v<vv^v^>^>v^^>^vv^^><v<^><<>v^<v^>^v<v>v>>^vv<v<>v>>v^v^^^>>^vv^^><<<^<^v>v^v<<>^vvv<v<v^^vv<>v^><v><<^>^<^><>>>>>v<v<<<^vv<^^v^v>vv<^<>>>^>>>v^>^v^^^>^>^<>^^<v>>>><<><<vvv>vv><v^^<^v>>v<<>vv^^<<><vv<^>^v>v^v^vv^vv<><v<<<^<vvvvv>>
v^v<><v>v><><v>v^^^<^v>>^v>v^><v^v^><<>>>><><^>v<^^^>v>v><^^v<v^<><<<^v<><^<<^^>>^>^>><^>><<^^v^^>><>>v<v<vv<><<>>vv>vv^vvv<<>>vv<^^>><<vv<><v^<v^<>>^>^^v>^>>v<<<<>>>v<^^v>>v>^><>^<v<v><>v>>^>vv<^^v<<>v>>^<^^>><^<v>>v<>v>^^>v^v<^<^^<v>v^<^<v^^>^<<^^>>v^v^^v<vv<<v<^v<>^v^<^^<>^^>>^<^v><>v<v><^^^<vv<<^^v^<<^v^^v>^v^<<^vv>v>^v^v<^v<vv>v<^><>><^v><v<vv^<>v>>^^^>v>v^v^>v>><>><<<vv<v^<^v^>>>v<v>><v>v^>^<>>>>><v^<^v>^<^<^^>>><v^><v^^^<>v^^>v^vv<>^<<v>^>>^<^>^^>^^>>^<v>v>><<>^>^>^v>><^^<^><v^v<<^>>vv>v>>vv<v<>^><><<<><><<^<>>>v>^^v<<>v^>v><<vvv><>>v<<^<>><<>^><>^v<<^vv<^<^<>>vv<^v^>v><v><^v^v>^<><>^>>>v^><>>^<<^v<v^vv^><<v^>v^^><>v>><v^<<v><^>>vv^>^><^v>v^><>><>>>v>^^>^<v<vvv>vvv<><v<vv>>>>^^^><<>^<^^<^vv<>v>^>>>vv^>>>v>vv<<>^vvv^<><><>v<^<>>^<><><>v^vv>^v>vv^vv^^<^<^>>v<^<v<^<vv>^<>><v<^><<><<^v>>vv^>v<<vv>^<>^v>^>v<<<<>>^>>^^^^v<<^^><v^v^^vv<v<^^v^v^v<v^^>>^>v^>^^><^<^<^v>^^v>><>>^>>v>v^^^<^^>>>^<v<<<>^^v^v>>>>^^v^><>><v<^vv<><><v^>>v<<>>>>vv^>^^><><v<^>vvv>^>>v<<<>><^<^^^^^<^>^^^v<><^^^v<vv
<<^<^>>^^<<>v^^<<^<v^<v>^>^<vv>^<v<v<>><>^<><^<v<<^<v^<<<vv^vv<>>^^^<v<^v^>^vv<>^^<><^^>>v^v<><^>v^><^^^>v^>vv<vvvv<<^^>^v^>^>^^^v^<<v<vvv^^v>^^v>^^>^><><vv^^<v^<>v<vv^^^>>^^<<v>><<<v><<><^<<vv<^<^<v>^<^<v><<><v<<<>^^^^><^^v^<>v>v^<^v>^^vv><><vvvvv<>><v>^vv^^^v><<<<^<<<^<v^>^>>^v<<>vvvv>^>^v<<v^>>^>v^>v^^^<v^v<vv<<><v^^<^^^v<v<v<<v^vv<<<^^<>^vvvvv^<vvv><^<^^^^<<^>v<^vv><<<v^>vv<v^<<^^^v<v>^v>>v^>><><<v<<v^<^>><^<vv^v^<v>^v<<>v^<<>vv<>>>^<v>v^^<^>^v<>^>v^v>^<>vv^vvvv>v^<<>v<v>>><^^<<^^^<vvv>^v<^>^vvv^<>^v>><v<>v^<>^v^^^v<v^<<>vvv^^<v><vvv^^^^>>v^^<^>^><>^v^<v>v<^<v<<<><vv<v>v><^>>>^v<v<^<^^v^>^<v><^^>v><^v<<<<v^v<v^vv^>v>>^^<<v^<>^v>^>v<v^v><^v^v<v^^>vv<>^>>^v<^<><><>^>v^v<><>^v<^>^<v^<vv^^>>><v<>v<><<<^^>vv<><<^vvv<>^^^^>vv<<><>^^>v>^^^<vv>vvvv<<^^<v^<^>^>>><^>v<v^^><^^vv><v><<v<^<>v^^v<<vv^<>v<<<^<^><^v^^<^v><><<vv><v<v^<<>v>><<><>^><><<>>>^v^vv<vv^v><<^^<^^>^^^<v<<<^v<v^<<<<>v<vv^vv^>>>><>vv^>^<^<v<^v>>><^><<>v^v<>^v^>>v^v^^v^>vvv^<<v<^v<><>v^><v<v>>>^v<<>v<<>v>v>>^>><v>v^><vv<vv^<<v
><^>v><v<<<><^>v<^<^v><v^<v^>^<vv^^<^^<vv>vv<v><<v><^^^v<^v^<<<<v^<<^^vv^<^^^v<v^<><>>v><v<^><>><^>^><^v^^<^<<>><>>^v><>vvv^^v<vvv<>v^^>^v<<<><v^>^>>v>^<vv<<vv^^>v>^^<^>^>v><v^v>^<>>><^^v<>^^<>^v^v><>v<>v^>v<^>vv^v^>^<vv^<v^v>v<<v><^^<^^<<^^<^<<>>^<v^<>>>v^^<^^v><>><>>>><<^><>>^<v^v>><^<>v>>>^>><>>^^<v^^>^v<>>v^^v>vv^v>^<^^^<>^<v^^^<vvvvv<<<>vv<v<>v>v<^<^^<v<^^^<>^>>v>^<><v<<><<^>^^v<>v^<^vv<<<v>><><^>>^>v><>v>v>^v>^<v>>^^^<<<^>^^>>><^><^v^v<^>^^^v>v<>v<<<^<^<><>><>^^>>^<><v>^<^v<vvv^<><v>^<v>v>v<<>^v>v^><>><^v>vv>v^<><^^<v<v<vv<><^^v>^^^><<>v<^<<><^^><<>>v>^><v>^v<<^<vv<<^<vv^^^<vv>>v^v<^><>^<v^vv><><<^><^^><v^^v<^><>^v>><<^v^>v^^v^^><<vv^<>^<>v^>^^>>v>v^^vv>>><^>>^^<v><<^>^>>><>vvv^<^vv><^>^^<><<>v^^v<^vvv>^>>vv^^<>v^^>^^<vv<<v^>>^<<v<v<^v<<^<^>>^^v<>v^<v<<<v><^vv<^^><^v>^<<<vv>v<v>>vvv<><><vv>^v^v^v<^v><^<v^>><<vv><<vvv^vvv^<<v>^v>^^><^^vv^^<<>^v<>^^v<^<v^^v>v<>^>^<^^>>>v><>^<v<<v><>^^>><vv<^^^^^v^^v^^v^<^>vv><v<<<^^^<>v>^vv<>^<^v^>^^<>>^<><^<>><>^v<^>vvv^<^<<<<^v><vv<v<><^>><<<v^v>
<>vv>>><>>^>^<<><^>><>v^^<^>>v><v<v^>>><v>^<^<>^vvv<>^^v<v<^<<v>v^v^<><^v>>v^>v^v^v>><<v<>>v<>>^<><>v^<^^>v^>^v^>v><^>^^v>^v<>v^<>><><v>v>><<><v<v^^v^><<^>^<vv>v^<^v>v>^<<<v<^v<v^v^v^<<v^vv^^<<v^v>v<vv^>^^vvv^^^^v>^<^<vv>>>^^<^>^><v^>^^vv^^^vvv>v^v^v<^<^vvv<><<>>>>^<v^v<^v<>vv^<^<<^v>><^v<><^>^v^>^^>^>vvvv^^^>><^^<<^v>v<>^^^>v^v>^<vv<<<<>^>^>^>^^<<^vvv^<<<^><><^>><^>>^><^<v>^^<<<<>v>v><><<vv<^>^>v<v<>v>v>^^vv^>v>v>^>^>v>^^v<><vv^^v^^v>^^^<>^><^^v>v>^^>>^<<>vv>^vvv>^v^>v<vv^<<<v<<v^<v><v^v^^>v>^><vv<v^<v><<^<^<v^<>^^<v>^>>^^><>vv^><>v>>v>^^v<<v^<>>^v>>v^>v^>^>vv<>>>^<<v<><<<<^vv>v>><^<>^>vv>v<>^<><<><<v>^^vv^<<v<vv<^^>><<<>>^>>v>>>>>^<vvv^<<>vv<^<vv^^<^^v^<>^<>^^>^^>>v>v><<^<>^v<<<<v>^<^v^v>^^v>v<^>>>vv<>>v^^^^><>vv<v>><<v<<<>v^v^>vv<<v<^>v>vv<>^>^v>^<>>>>^^<><^^<<v<v^>^^>^vv^<v<v<>^vvv>v<^v^^v<>v<^>>vv^^^^^^>>vv<><vv>>v><><v>vvv>>^>^^vv^v^^^>^>^v^^^v<v>>^v<>^v^^^>^v^<v^><^vv<v^v<>vv><>vvv>><^v>v<v>^vv><v<<>v<v<^v<v>vv>^<<>v>><>^<v<><<>^<>>^^><<vvv^>v^^v><<<>v<<^v^^>^<vvvvv><^>v^^<<^>>v
v<>>^^<<>v>^vv<><>vvv><>>^v><v^>vv>>>>^<v<<v<v<vv<>><^<^v>vv<><<<<v^<^>v<^v<>v<^^>>^v><><^^<<^^<<><<vv^<>^^vv>v^<v<<v><^vv>>v>^<>>v>v^>><>v>v^>v^^>>^v<<v^<>><>^^<<v^>vv^<v^^v<v><^^^v^<^>^>v<<vvv<v^<^^v>>^><v^<<vv<><^<v^<><>^><^>>^v^vv^<<vv>v<>>^>^^^v^<>v^>v^^^>v<><><<^><v^<<<v^><>^<<><^v^<<v>^<>>^<^v<<v<>v^><v<v<^v^vvv<^^><<^<><vvv<^^v^>^v>^^<>>><v<<>^^<<<v><v<>^v>^^<v^><v<<<><<v<<vv>v><>>><^>v><<<^^v>>vvvv<<v>>^^^^^<^<^v^<v^v<<vv>>v^^>vv>^^v<vv>><>><^<>><v^>>^>^<vv^>v^>vvvvv<^^><>^^>^^v>>>vv>^<<v^v>>v^v^<v^<<^v<>^^^^<^v><<^vvv>^<v><v^><>><v<<>^^v>>>>><><>>>vv^<vvv><vv>v^<>^^v^>>v>>^^<<>v^<>v>^v>><v>^>v<<><<>^><vv^>v>>v>vv^v>vv<<v^>v<>^<v>>><v>^^^>vv>^>vv^><^v^v<vvv<<v>^<^vvv^<>v>^^^<^v^>^>>>v^<><>><vvv^<<<vvv>v^<<>v>^v<><v^vv<>^<><><^>^^^^v^v><<v<<vv^v<v<<<<v^v<v>^^^><vv^^<<<<>v><<<^^>>^^^^>^vv><<v>>>v^>^vv<vvv^<<<^><v^<>^^<>^<<<vv>v>^^>^vv<^<<^<<^<><<v^>^v<v>>>>v>><^<v><<<^>^<v<^>v<vvv>v^vv<v<^^>><v^v<v<vv^v^^><<^><v<>^<^v^><v^>v^v>>^vv^<<^v^<>v<^<^^v^<>^<>^><^>^^^^v<^v^^v><<vv^<<<<v
>>>>v<>>v^>^>>^<<v^<<<^<>v<^^<v>^^>^^<^<<v^<<^><>>>v<v>><^^>^<<<^<>^<v<^>>^>v><<^v<<<v^vvv<><><><<<>^<><^v<><v^<>^v<vvv^^<v<v^>v>>v<v^v>vvv<^v^^^^^v>v<^^^vvv<v>^>>>^vv^>><>^>^<>^^v<^v<v^v^><^^^^><^v^><<<>><<<<>^<^>v<<v<<<vv^^<<^>>v>^>><<<<^><^v<>^>^<>^>^<>^<<vv^>^<>vv>^v>>><^<^^v^>>^v>vv>v^^>^<<<<v><vv<<<^v<<vv<<^^<<>^vv><>v^><<v<v><^^><^><<<^^v<<vv><<><>v<<v>^>vv>^<^>^>><<<^><>vv^<>v>v^>^v<<^><<<v<^^^>^v<^^^>><<^v^^<v^^<^>v<v<<vvv<>^<^v<<^<<><>^<><>^^vv<>v<vv>^vv^<^v>v<<v><>^><^>v<<<<^>^>v<vv^>^^<^<>>^v>v>>v<>v>>^>>^<<^^<>><<vv>v^>v>vvv>^^<vv>vv<vv>><>>v>^>v<><^><<^v^>^><>vv<^<>^v>>vv<><^v>>^>v>v^>^^v<>>^^>^^^v<v><>vv^vv^^<<><>^>>v<vv>><^>>v>^<^<>^><v>^<>^v<>v<<<<v>^vvv^<^>v^vv<><<><v<>v<<v>><>v<>v>v<vv>^vv><^<^^v<><<><^^v<<>v<>v<>^><v^v>>v<><vvv^>><<vvv<>^<><^v>^v^v^><>v>vv<>>^^>vvv^vv<<^v<>^v^vv<v>v>>>><v><v^v>^^vv<<>v<^<vv<^>^<vv>^<^<v<>>v^^><^^>>>^v><<v><vv<<>^vv>vv^^^^v><^^v>>v<>vvv>^v>v^<v^>vv><><v<<vv^v>^^v<v>vv^^v^^<^^^vv<^^>>>vv<><<><><><v<<><>>v>^>>^<<>><v^>^<^^^>^><^vv><^<^
vv<>><<>vv^>v^^v>><^>^v^>v<<^<^>vv>^^v^><><v<^<><<^v>><>vv>v^<<><vv<<^vv<v^<^vv<^^<^>v^v^<><^>v><>^<<>^<v^><v>^^<^>>>>>>v><^^><v^^><<^v^v>v>>><^^v>>v>><<<><<v<vvv<^^<<>^^<vvv<^^^^^^<<><v<^>v>>>^>^^^<<<<<<v^<v>v>>v<^<v<^^vv<^^<<^<<><v<<<<v<<v^^^^^^v<^v<^^^>^^>^v>>vvv>v<>>v>v<^<v^<>>v<<><<<>^^<v^v>>^<v>>><v>^<vvv<v<v><>^v^^<>>>>v<vv<<>v>>>><^v<^^<v>>^v^<<vvv>vvvv>^v><v>><<v<<>^<^^^v>v<v><^<^<>v<vv<^>>^>><<>>>vvv^<>^v^<>^<<^<v^^<v<<<vv>vvv>v^<<><>^>v>v<v<<<>>v>>><v^>^v^v^v>>>^v^<v>^>^^><>vv<^v><><>v>^<^v>^>>^<<^>^^><<^v<^v^<>^v<^^>vv<<vvvv>v>v^<>^<<v><^<vv>>^<<>v^<v^<<v^^^v<^<<^<>>vv<<^><^>v<>>>>>>><v<^^>>><vv<v<>v^>><^><^>v^>^><<vv>>>^><vv<<v>><v<<<><>v>^><vv^>>^^v<<v>vv^><^v^><>^v^^v>^^<>>^vvv<<v<>v><>vv>^^>>v>^>v<^^<vv<>>v<v<vv^^<>>v>v<>^v<^vv>^vv^vvv<^v><>><vv><<^<v<>>>>>>vv<>^v<<<^<<vv><^<<<^^<v^<>^^<v^<v>>^<^<<>>>^^v<^>^v>^<^vvv>>v<^<vv<^>^^^>><>^<>v^><>>^^v^<v<v>^>><v^^>^>v<v>v<><><v>><<v^<vv>vv<^>^v^^v<v^>v^><<>^v>^^<^v^><v<><<><<v>v^>^vvv>v<><<>^^<>^<><>^<>v^><v^><><><>>^<vv^><v>
^v^><<>vvv^v>><>vvvv<<vv^v^v>><>v<<^v>^v^<^^><><>^>>^^v^v>v<^<>vvv^v^>v^v^><>^<><<><v^<^>^>vv>v>><>v<><><v^>^>><<^<^<<<^<>^><v^^v^<^<v>^<>^>^^>^^>^><<><>^<v>^>><v><<^<><v^v><v<>>v^>v^^>vv^v^>v^><vvv<^<v><^><>>v>>>v<>^>v^v^^^v<<v>><v>>^^v<vv^^^^v><<<^v>^>>>^v^>vv>^^>vv<^^^v<<<><<v^>>>v^<v>>v>vv><><<v><>^<v<<v<>v^vv^><>>><vvv><<>><^<<<>v><v^>^<v<<vvv><^<>^><vvv<<<vv^^<v<<>v<<<^>>^^v><vv>v><^<><<^^^<>^^^>v^v>v><^<<^v<>v^>^>>^^^<^<>v<^^v<^>^^^>^<^v>v>^^<v<^^v<<^vv>v<v^<v<>>v^v^<^>>>><<^<>vv<v<<v^>>>^v><^^>>v>^v<v>^>v^>>^^vv>v^v<<^^^^v<^^><>^vv>>^<^<>v<^^^<^v<^<><<^v>v^<>^v<>^<>v>><vv<^<^^v>>><>^^^v<^>>>^v<v>>v<>>><vv>^<^><v<v^>^<^<><<^v>><<<^>^vv^^v>^vv<>v<<<^<>vvv<<<<^<>>vv>v^<<v^^><<>vv<vv>^^^^<v^<^>><<^^v<vv<v>>v^v^vv<><vv^^>^^<v^v>vv^^v><<<>>^^<^<v^^>v><^>v<><v><^>v><<^>>>>>^>v^^v><^v>^>v^>^>^^>^^v<^>^^>^<<^v^^vvv><<>vv^>^^vv>^vv^v>><>><vv><<><>>vvv^^vv<<><v<^^^<<^vvv>^vv>^v<>^^^vv><^v>v^<v<v>vvvv>>^^^<v<<^>^<>^<^><<>v^v^v^<v^><vvvvvv^<>><<<>vv<<v^^v>v<v<^^<<^^><^^<<<<v><<^<>>v<>><vv<<
<>v^^<>>>>v^^>vv>v>v^^^^^vv<v^^v<<>><>^v<>^v>vv^><>v>><><^<^>>^^v^<<^><^>>>>>>>v><vv^^v^>^<>>^vv><vv>v^v>^^<>>><v^<<^<>vvv^><><^<<<^<>^>>>>v^^^>^^^<<>^<v<>v<><^v^^v<><>>^v^>^><<^v^^>v>>>v^>^>><^<^v><^<^^<^>v^^<^v^<^^^><>><^^<<>><^v^v>vvv>vv^<<^vv><<><>vv<>v>^>vv<>v<^^<<vv<^<>v^vvvv><v>^<>^v<^vv<v^v<^^>v^^<<vvv<^v>v><^>>^>^^<>vv<><^<^<^vvv<v^>^<>^<>v>vvv>v<<v><<<<>vv^v<>>^^v>^^v>v<>v>^v>>><<><<^v^^>^^v^^v^v<v>^<v>><v<^>^<>>v^^><v<>v>>^>^<><v><><v^<<^v^v^^^^<v^<vv>>vv<<<><^vv^<^^v>v^^>v<>><><><<>><^<<<^>v<^^^>^^v>vv<^>><><v>>^v><^<>v^>>^^<>^vv>>^^^^v<>><^<><>v>^v<<>^<v<^v^v^>vv>>>>>^>>>vvv<<<<^<<^<>><vv<v<<vv<v>>^<v<<<<^><<>v>v>v>^<<^^^<>^vv<>^v>vv>>>vv^^v<<>vvv^>^<<v>^v>>vvv>><>vvv>>^^v<^^v>^v>vv>>><vvv><vv>>v<<^v^<<<>^^>vv^><^v<>vv<<^<v^^v>^<<v<^>>><^^<v<^v^v^^^<<><^v<>^<<<v>^v><<<^v<vv<v^<v^^vv^<><<<>>^<><>^^v<>v^><><^^>vv^v>v>^v>^<>>vvv^>^vv^><><^^v<<^vv>^^><v>^<v^<v<<vv>^><^<v<<^vvv<><>^>^<^vv<^>vv>vv>^><<<>v<<^vv<>vv<^>>v<>vv^<v>^v<v<>>^<^^v^vv<><>>v>><vv>><v^<><>v^>v^><^^v<>v<^v^>
v>><^v>>vvv^<>^v<^<^v^v>>^^vv<<v<v>>v<^><<<v>^<<<<<^v<vv^v<v>v<v^>>><^>^^^vvvv><<vvv^><v>><>><v<>>^v<vv^><v><^^<>^>v<^<>^vvv^v^^<<^vv<<v^vv<>^vvv^<v<>><vv>v><>^><v<>^<vv<v>vvv^^>v<v<><vv>>v^^><<>^>^^>^>^^v<<v<>>>>^>>>v><v^<<<<^^>v<^^^>^^vv<><vvv><^<<>>>^<<vv^<<vv^v^<^^vv>v<^^<>^><<>^<>^>>><>v<>vv>^><>^<^>>^^>vv^v>>v>^^v><><^^v^^^^v>>>><>>vv^^v<^v>v^>^<v<<>v><vv>>v<<>^<<<>^<v>vvvv>v^<v<<<^^vvv>^>v<<>^^<<>v<v^v<>vv<^><vv<>^<v^><v><v^^^v>^vv<v>^^v<^^>v<><vvv<><<<>^vv>>v>^<v><^vv^>v^>>v>v^^<<v<>>v<>v^><<<^v<v><v><^v^><>^^>v^<v^<>v<^>^<<^^><><v<vv>v<>v<<^v><<><><^^^<v^^<v^<^vv^<v>v><<^<vvv><>^<<^^v^^><>><><>><^<><vv<>>^<v>v><^>^vv<<^vv>>><>v^>^vv>^vvv<^^>v>^v^^^^<v^<v><^^^v<v><<>^^><<<<v<>v><<>^>^vv^<^>^<<<<<vv<<^<vv<<<v>^<<>^>^v>^>>vvv^>vv^<^v<>>v^^<v<^v^^v^v^v<<>><v>^>><vv^^<^>>><><^>^v^^<^>><<<>^^>v<><^<>^^v^>^v<v>v<<<^<><v<<>v<<<v^<<<<^^>^><vvvv<^^>>^v^^v^<^>><<><><v<>^^v^vvv<<<v<v^^>^>^v>>>><<vv^v<v^>>><v>v><>vv^<><>><^v>^>^v>v<^<>>^vv<vv>vv^^^<<^v^<><>v^vvv^>^>^^>^>^^><<^^vvv<<vv>^<><
^vv><>^<v^v>vv^v>>vv<<<v^v<><>^v<<v>^>><><^>vvv<^v>>>vv><<^^<v<^<><^vv^^^^><>><v<>>>>vvv^>>vvv<^<<>><>v>^vvvv>v^vv>v^<>v^^>>v<>v<<^vv^^<v>^>^^<^v<<^v^vvv>^<<v>v<<^<><><v^>v>^<^<<^>>>^^^<v^^<v>>>>v>>v^<^^><>><^^<^v^>^>>v^<v>^><<^<^<<^v<vv<<>>^v>^^<^^>vvv>v<>v<>v<<>^<^<<><<>v>^^>v<^vv^<^<>>vvv>><<vv>>vv>vvv^^^^>>>^^>^^>^><<vv><>>^<^^^<v<^^^>vvvv^>^>><^^>><vv>v^<>v^<v><vv^v>^<^>^>^^v>^v<<vv<><v<<v^^^^<><v<>^>>^><^<^>vvv>><^><^<<v^<>^v^^^<>^^<^v>>>v<v>v<<<^>>>^>^^^^^<<v>^v>vv^^>><vv>v<^^v^><^^<^><v^vvvvvv<^v<>^v^v>>v^^^>v<vv>>>>>>>>^>><<<<><<<v<<><^v>^><^^<<vv^>v<v^v<<<^>^vv>><>v<><>^v>v<^<<<<<^>vv^>vv^v>^v<^v^^>v>^>>v>>v^v^v>>v<v^<<^><<>vvvv<><><v^>>^<v><<vvv<><><v>>^v<<v^<>^^v>><^v>v<<><>^v^^v<^<<>>>^^>^<>^v>^v^><>v>v<^>>vv^<><<vv>^v<^vv<^^v<>^^vvv^v<<<v^v<^<^^<v>^vv>v^>^>v><>v>>^>>^v>>v^v<^^^v>>v^<>>v>><>vv<v>v<^<>v^>^><><v>v<>>>>><vvv<<<>><vvvv^^<v<>>^^>v^v^>^^<v^>><v>v^^><v>v>^^>^^v<^<^<<^<^vv^>v<v^<^^v><v<^><^^^v<vv>^v<^^<>><v^^v<v^<<^>^>^<<>^<^><>v<vv^v^^>^v<^^^>^<><<>^^<>>>v<<v^>>>
>v^^^>v<>^v<v>>^^^<v<>><>vv^<v>^<><<vvv>>>^<>^vv^<<<^>v^^<>><v>vvv>>vv^vv<^^><^^<<^v^^><<^^><v>v^>><<>^vv>^<><<^^<<vvvv<^vv^^<^v><v^^v<v^^v><<<^^<><<<^<^v><>>>v><<><v<^<><^vv<v<<<>v>>^<v^>>^^<<>^<>v^>><>>^^^vv^v<>^>^v<^<^>v^<v>><<<v<^^v<^^^<>><v^>>><^><^<v><^v^>><v^>>>^><<>>^<^^>v<<>v^^v^<<<>^<>><>^vv^^<^^>v<><<^>><^v<>><>v^v><>^<^>^<<v>>v^^<v<v^<<<><<<^<<^^v<>v<^<v<v>^>>>v<v<^>^<<<>><^^^>>vvvvv^><<<^^v>^>>^^><<>>><<v>>v^<><><v>>v>>>v>>>vvv>vv<^<>^><><v<v<><v^<<^<^^v<^<^v><>><>v>v>v^<>><v><<vv^v^^^<<>vvv^^v^v^v^<<^<>^v^^<vv^v<>^>^>^>>v><<^<>^^<^<>v^>v<>><>v>^<v^^><>>^<<v^<><>^><<<<<<^^^>><^^>^^v<<<v>^<<<>v^^^v^^^^vv><>><v<^^>>>v^<^<<>^^>v^^<v>>v^^v<<^><<^vv<>v>>vv^<v>><v^v^<<vvv^<><<^<^^><><v>^<^^<v<vv<^^^^>^<>v^^vv<^<vv^<>^^<v^^<^>^><^>^v>v^<>>^^>><vvv<>v<v^^>v<vv><v>^><vv<^>>>^>^<>v^^v>^>>><>vv>v^vv<<^<<v<^<<v>><><><v<<^^^vv>>>v^v^<>^>><>>>vv>><^vvv<v^><>v>>v<<>^vvv>>^vvv^v>>>>^v><^^^>^^><^v^v^<v<^<v<^^>vv><v<^v>v<^^vvvv>><vvv^<^v^<v<><><vv>>v>^<><v<<^vvvv>>>v^>>v<<>^^<<><^^^<><v^v^v
<><>vv>v>vv<<>>v>><^<<^>^>><>^>v<^^^^^<^>>>>v>^><^^>v<<<^^v>>><>>^v<v><>v^^>^^vv^v<>^v<^^>v<^<<>^><>v<<>^^<v>v<><^<vv<v^v<vv<<^v<v<<<><>>^^>v<<>>v^>><>><>^vv<<v^vv><><<<v<v><v<<^>>^<>vv^<v^<<><<>>^>>v>>>v><>^>v><v<v>><>^<<^<^^<vvv>v<<^>^v>>>>^>>^>>v<^<vvv><>><vvv<>^^^^^>v>>>>>><<<<v<<<>><>><>>vv<><>v<><<^^<vvv>^<^<^^^>><vv^>>^v<>v^^v^^^<vvv><<<<<v<v<>^<>>vv^><^<^^^^<>v<<vv<>vv>><<^vv>>>>^vv^>><v>v^><v>v<^>v>v^v>><^<>v>>v<>vv^<<vv>>>^vv^>v^<>^^v^<>v<v^<<>><v^>^^v<^>>>>>v>>><>^><^v<>>v>>v<><><<>^v^<<^^v>>vv>v>^<>^vv>^^>^v^<>>vv^^^<>^<^^<<<^vv><<v<^v>v>>>^v>><>^^>>v<^><<>^<^^>^><v<v^>>v>><v<v<>^<vv<<<<vv>v>vv>>><>^^v>^^>v<vv<>v<v^>^vv^>^<>><><vv^<^^v><v^^<<v^^v^>><>>v<>v^<<^v<>>^v<<vvvv>v^>^>v><<<v>^>^>v><v^><<^>>>^^>v>>>^<<><v<^>^>>^v>v><v>^>^>vv>^>>^^>v><>vvv<>v^^<^^^>^<><^>>>vv<<><v>v<>v<<^>^^>v^^<v<<<>vv<>>vv^>v>><vv>>vvv^>vv<<<^>^^v>^^<v<>v>>^v>>^v>^v>>^>^<^v<^>><vv^<>>>^<v^<vv><vv<<>>v^><v^<<v<>^>^vv^<v<^>>><<<^^>>vv><v><><><^>v>vvv^><<<<<>v^^<^v<^>^>^^^^v<<^^^v^v<<^><^^<^>^v>><>>v^
>><v<^^^<>>^>^v<>>>^v>>><><vv>><^^^^^>><v>v><^^^<<v><vvv>vv<><^v<<^>v<^<><v<>v^<v^<^><^v>^><<<^v><><^<<>vvvv>^v^>><><<>v>^^>^vvv^^^<<v^>^^^<<v^^>^v^^vv<>vv^v<><v<>^v<><v^>^^<^><^>v<><^v<<><^vv<<<<^^^>>>^^^^<v^^^v^>^v<^v>v>v^><^>v<<>>^><><>^<^v>><<v<<<^^>>v><<v^^><vvvvvv<v^<>><>^>>>v^>v<vvv^<^^>^>^v<v>v>>^>v<^v>^>^<v^^<>^><<<<<>vv<^v<^v<^<^><>v^<<<<v>v>><^<v^v<v^>^><v>><<<>v^><<^>v^<>^<v<<v<<<>^<<>vv<>^^v>>v>^^v^><><vv^<v<>>^>><^^>>>>^<^>>>><vvv>^vv<>vv^<v><^<>^>^^>^<<^><<>>>^>>v^>v>^^^>^vv><>><vvv>v>>v>^<v^v>^><<<v^>^>vv<>v^^^>^^v>>vv<>>^v>v>^^<<vv><v<^>vvv^><<v><<v^>>^^^^>vv^<<><<>vvv<<v^^v^v<<v>^>>^v^<^>v>^<>>>v>v^^v<<v><>><<><^vvvv<<>^v>><^><v^vv>>>>^>><v<>>><<^^>v^^><>v>vv^>>>>>><vvv<^>>vv<>^<<v>^<<>v>>v^v^>^^>^>vv^v^>^><v>>v<^>^v^>^<^<v<<^vv<^><vv<^<<>v<<vv^>^v^>>v^v^<<<>^<^>>^<<v>>^>vv>v^^>v>>>>><^^<><>v<^^<v<v<v<v>>^<^<<>^vv<vv^>^v^>v^<<v<^v>^>vv>^<v^^^^<^<v^^<v<^<v^>v<^><>><vvvvv^><v<>v>>^>>v>>v>^<vv>v><>>^>>^<<vv^^><^v<<>^<v^^v>^^v>v><<v>^v<v^<>^>v^^>v>>^<^^>vv>v<>^v<vvvvv<^^v
<>>^vvv^<^^v^v<<v<v><><>^^>v<<v<<<v<<^<^^>vv^^<^>v><v^^^v>vv<>>>vv^^<><<v<>^v^>vvv><>v^vvv>>^<>>vv^v>><vv<^^<><>>v>v^<><v><^<><^v>v>v><^>^^^v^<^<v<><><vvvv<<>v><^^<><^v^<^>v>v>vv<vv<<><^<^><<v^v^v<v<><<^^vvv>><<vv^<>^<v^>v^^>^>v>vvv<<><^>^^^>v<^vvv>v<^^>v^^^>>>><vvv^<<<<^<v>><><^<v<>v>v^^^^<v><v<>v<v<^^v<<^><^v<v<v^vv>^>v^^v^^>>><^vvv>>>^^^>>v<^<v<>^v<vv<^^<<v<v><<v^^v<^<>>^v^>^<><v<<v<>vv^^^v<v<<<v<><>>v>v><<<>>^>v<v^^v>vvvv><><>><^^v>vvv^v>^v>^^^^<v<^^>v<>>vv>><vv^v<^>^<^v>^v>vv<><^>><^<^^^^<^>^>vv<v<vvvvvvv<^<><^<<<vv<^<>^vv>^^<^><>>v^<vv<<<><><v^^>>^^^v<<<^>^v^<vv>v>^v^<vv^^v<v>>v^<<^>^><><<^^^<^^>>^^>vv<v^v^vvv>>v<v^v<<>v<vv><v^v<<>>vv^^^>^^v^>^<><>^v^<><vv<^v>>v^v^^>^vv>vv^^><v>vvv<v><<>v<v^vv^v^><v<^v<v<^>^<>v<v^v>v<v^<v<^^<>^>>v<<>><>>>v^<><<<<<^<v<<>><><v><<<<^<^^<^>>^^><<^v><^>^vv><>v<v>v<><v^<>v<vvv^^<<<>^^v><>>v<v><<^v<>><v^v>><<<v><v<vv^^^vv>>^^<<><<^>v^<v^^^>v><v<>>>^vv<^^>^<>^v<v>>v^<>^v<>^^<<>v<>^^><v^<^^^<<^>>v<><v^<>>v<v^v<>v>^>>^v<^^v<<^><^v>^>v<v<<v^^v>^<>^^v<v>v><<
^<<v><>><<^vv^^<<<>v<^<><^><<^><^<<<^<>^^<>><v^v^vvv^v<^<>>^v<<^>>v<>v>v<^v^v^v>^<^v<^^>>v^<v>^<>^<<<>><<^^><>>v>^v^>><^v>^<<vv^v<<v^<<>^^>^<<><<^v>>^v^v>^<<^<v>v^v>>v^>^>v>^v^v<v<^^>>v><^>^^>^^^v<vv>^>^^v<^^>^><>><<>v^vvv><<><^<vv^<>v><v^<^<>>v<<>>v>>^><v>v>^^^<^^><^>>>^v^^^<>><>>>v^vvv^v<vv^^vv^<v^<<<^^>^v>v<v^v<>><^>>v<<^>^>>v^<<^>>><vv><^<><^>>^>>^vv^<>v<^^>v>>><<>><<^<^v>^>^>^v^>>><^><<><^<<><<<>v^^^^vv<>vv<<^>>^<vv<v<^v>^><v>>><^vvv>^<v><>^v^^<vvvv>>v^^v<>^^>^<>><><v<^^vv<^<<<><^^<^^^^<vv<v><^^<>><>>^<vvv>><^^>^^><^<><v^<><>>^<v<^^<vvv<>^^<<^<^^^>><^^>v<v><>^^^^>^^^><v>><v^>v>^^>^v<><<^<>vv<>^^><^vv<v<>><>>>^<<<v>>><>v>^<>^<>^<v^<<v^^v<<<<v^<<>>^>v>>v>>>>^<v^vv<<v>^><^^^^^><<^>^^<<<<v>v<^vvv<<v><v>><vv>>vv<^^<^^vvv^^^^v<<<^<^>v^vv<<^>vv>^<v><>^>vv^>v>v<>^<<>^^v>^^v>>>^<v><v<vvv<vv<<vvv^^<<<<^^v>vv>>^><v^^>>>><>>^v^^<><v^>^v^^v<><^>^>><^<<^>>>vv<v<^>v>vv^><v<>v>>^^>^>vv>vv<<^><^vv^>v<<>^^<<><>^v>vv^v^><<^<<<v^>^^<>>v>^^<><^<^<>^<v>>v><>>><>>v><v>>v>^v<<>v^<>^vvv<vv><><<<^<<^<>v^><

137
day15/part1.zig Normal file
View File

@ -0,0 +1,137 @@
const std = @import("std");
const print = std.debug.print;
const input = @embedFile("input");
const MAP_SIZE = 50;
const Cell = enum { Empty, Box, Wall, Robot };
const Direction = enum { Top, Bot, Left, Right };
const Position = struct { x: usize, y: usize };
pub fn main() !void {
var map: [MAP_SIZE][MAP_SIZE]Cell = undefined;
var robot_position: Position = undefined;
for (input[0 .. MAP_SIZE * (MAP_SIZE + 1)], 0..) |c, i| {
if (c == '\n') continue;
map[@divFloor(i, MAP_SIZE + 1)][i % (MAP_SIZE + 1)] = switch (c) {
'.' => .Empty,
'#' => .Wall,
'O' => .Box,
'@' => .Robot,
else => unreachable,
};
if (c == '@') robot_position = Position{ .x = @divFloor(i, MAP_SIZE + 1), .y = i % (MAP_SIZE + 1) };
}
for (input[MAP_SIZE * (MAP_SIZE + 1) ..]) |c| switch (c) {
'>' => next(&map, &robot_position, .Right),
'<' => next(&map, &robot_position, .Left),
'^' => next(&map, &robot_position, .Top),
'v' => next(&map, &robot_position, .Bot),
else => {},
};
try std.testing.expectEqual(1487337, calculateSumPosition(map));
}
// The copy paste suck but if I want to use -1 to do dx dy, I need to use something else than usize and it fuck up the indexing
fn next(map: *[MAP_SIZE][MAP_SIZE]Cell, robot_position: *Position, direction: Direction) void {
const x = robot_position.x;
const y = robot_position.y;
switch (direction) {
.Top => switch (map[x - 1][y]) {
.Empty => {
map[x][y] = .Empty;
map[x - 1][y] = .Robot;
robot_position.*.x -= 1;
},
.Wall => {},
.Box => if (detectFirstEmpty(map.*, robot_position.*, direction)) |first_empty| {
map[first_empty.x][first_empty.y] = .Box;
map[x][y] = .Empty;
map[x - 1][y] = .Robot;
robot_position.*.x -= 1;
},
else => unreachable,
},
.Bot => switch (map[x + 1][y]) {
.Empty => {
map[x][y] = .Empty;
map[x + 1][y] = .Robot;
robot_position.*.x += 1;
},
.Wall => {},
.Box => if (detectFirstEmpty(map.*, robot_position.*, direction)) |first_empty| {
map[first_empty.x][first_empty.y] = .Box;
map[x][y] = .Empty;
map[x + 1][y] = .Robot;
robot_position.*.x += 1;
},
else => unreachable,
},
.Left => switch (map[x][y - 1]) {
.Empty => {
map[x][y] = .Empty;
map[x][y - 1] = .Robot;
robot_position.*.y -= 1;
},
.Wall => {},
.Box => if (detectFirstEmpty(map.*, robot_position.*, direction)) |first_empty| {
map[first_empty.x][first_empty.y] = .Box;
map[x][y] = .Empty;
map[x][y - 1] = .Robot;
robot_position.*.y -= 1;
},
else => unreachable,
},
.Right => switch (map[x][y + 1]) {
.Empty => {
map[x][y] = .Empty;
map[x][y + 1] = .Robot;
robot_position.*.y += 1;
},
.Wall => {},
.Box => if (detectFirstEmpty(map.*, robot_position.*, direction)) |first_empty| {
map[first_empty.x][first_empty.y] = .Box;
map[x][y] = .Empty;
map[x][y + 1] = .Robot;
robot_position.*.y += 1;
},
else => unreachable,
},
}
}
fn detectFirstEmpty(map: [MAP_SIZE][MAP_SIZE]Cell, start: Position, direction: Direction) ?Position {
var x = start.x;
var y = start.y;
if (direction == .Top) x -= 1;
if (direction == .Bot) x += 1;
if (direction == .Left) y -= 1;
if (direction == .Right) y += 1;
while (x != 0 and x != MAP_SIZE - 1 and y != 0 and y != MAP_SIZE - 1) : ({
if (direction == .Top) x -= 1;
if (direction == .Bot) x += 1;
if (direction == .Left) y -= 1;
if (direction == .Right) y += 1;
}) {
switch (map[x][y]) {
.Empty => return Position{ .x = x, .y = y },
.Box => continue,
.Wall => return null,
.Robot => unreachable,
}
}
return null;
}
fn calculateSumPosition(map: [MAP_SIZE][MAP_SIZE]Cell) usize {
var total: usize = 0;
for (map, 0..) |row, x| for (row, 0..) |cell, y| switch (cell) {
.Box => total += x * 100 + y,
else => {},
};
return total;
}

192
day15/part2.zig Normal file
View File

@ -0,0 +1,192 @@
const std = @import("std");
const print = std.debug.print;
const input = @embedFile("input");
const MAPW = 50 * 2;
const MAPH = 50;
const Cell = enum { Empty, BoxL, BoxR, Wall, Robot };
const Direction = enum { Top, Bot, Left, Right };
const Position = struct { x: usize, y: usize };
pub fn main() !void {
var map: [MAPH][MAPW]Cell = undefined;
var robot_position: Position = undefined;
for (input[0 .. MAPH * (MAPH + 1)], 0..) |c, i| {
if (c == '\n') continue;
const x = @divFloor(i, MAPH + 1);
const y = (i % (MAPH + 1)) * 2;
map[x][y] = switch (c) {
'.' => .Empty,
'#' => .Wall,
'O' => .BoxL,
'@' => .Robot,
else => unreachable,
};
map[x][y + 1] = switch (c) {
'.', '@' => .Empty,
'#' => .Wall,
'O' => .BoxR,
else => unreachable,
};
if (c == '@') robot_position = Position{ .x = x, .y = y };
}
for (input[MAPH * (MAPH + 1) ..]) |c| switch (c) {
'>' => next(&map, &robot_position, .Right),
'<' => next(&map, &robot_position, .Left),
'^' => next(&map, &robot_position, .Top),
'v' => next(&map, &robot_position, .Bot),
else => continue,
};
try std.testing.expectEqual(1521952, calculateSumPosition(map));
}
// The copy paste suck but if I want to use -1 to do dx dy, I need to use something else than usize and it fuck up the indexing
fn next(map: *[MAPH][MAPW]Cell, robot_position: *Position, direction: Direction) void {
const x = robot_position.x;
const y = robot_position.y;
switch (direction) {
.Left => switch (map[x][y - 1]) {
.Empty => {
map[x][y] = .Empty;
map[x][y - 1] = .Robot;
robot_position.*.y -= 1;
},
.Wall => {},
.BoxR, .BoxL => if (moveLeftRight(map, robot_position.*, direction)) {
map[x][y - 1] = .Robot;
map[x][y] = .Empty;
robot_position.*.y -= 1;
},
else => unreachable,
},
.Right => switch (map[x][y + 1]) {
.Empty => {
map[x][y] = .Empty;
map[x][y + 1] = .Robot;
robot_position.*.y += 1;
},
.Wall => {},
.BoxR, .BoxL => if (moveLeftRight(map, robot_position.*, direction)) {
map[x][y + 1] = .Robot;
map[x][y] = .Empty;
robot_position.*.y += 1;
},
else => unreachable,
},
.Top => switch (map[x - 1][y]) {
.Empty => {
map[x][y] = .Empty;
map[x - 1][y] = .Robot;
robot_position.*.x -= 1;
},
.Wall => {},
.BoxL, .BoxR => if (moveTopBot(map, robot_position.*, direction)) {
map[x - 1][y] = .Robot;
map[x][y] = .Empty;
robot_position.*.x -= 1;
},
else => unreachable,
},
.Bot => switch (map[x + 1][y]) {
.Empty => {
map[x][y] = .Empty;
map[x + 1][y] = .Robot;
robot_position.*.x += 1;
},
.Wall => {},
.BoxL, .BoxR => if (moveTopBot(map, robot_position.*, direction)) {
map[x + 1][y] = .Robot;
map[x][y] = .Empty;
robot_position.*.x += 1;
},
else => unreachable,
},
}
}
fn moveLeftRight(map: *[MAPH][MAPW]Cell, start: Position, direction: Direction) bool {
if (direction == .Top or direction == .Bot) @panic("Nope");
var y = start.y;
var is_right = direction == .Right;
if (direction == .Left) y -= 1;
if (direction == .Right) y += 1;
while (y != 0 and y != MAPW - 1) : ({
if (direction == .Left) y -= 1;
if (direction == .Right) y += 1;
}) {
switch (map[start.x][y]) {
.Empty => {
while (y != start.y) : ({
if (direction == .Left) y += 1;
if (direction == .Right) y -= 1;
is_right = !is_right;
}) {
map.*[start.x][y] = if (is_right) .BoxR else .BoxL;
}
return true;
},
.BoxR, .BoxL => continue,
.Wall => return false,
.Robot => unreachable,
}
}
return false;
}
fn canMoveTopBot(map: [MAPH][MAPW]Cell, start: Position, direction: Direction) bool {
if (direction == .Right or direction == .Left) @panic("Nope");
var x = start.x;
if (direction == .Top) x -= 1;
if (direction == .Bot) x += 1;
switch (map[x][start.y]) {
.Empty => return true,
.BoxR => return canMoveTopBot(map, Position{ .x = x, .y = start.y }, direction) and canMoveTopBot(map, Position{ .x = x, .y = start.y - 1 }, direction),
.BoxL => return canMoveTopBot(map, Position{ .x = x, .y = start.y }, direction) and canMoveTopBot(map, Position{ .x = x, .y = start.y + 1 }, direction),
.Wall => return false,
.Robot => unreachable,
}
}
fn moveTopBot(map: *[MAPH][MAPW]Cell, start: Position, direction: Direction) bool {
if (direction == .Right or direction == .Left) @panic("Nope");
if (!canMoveTopBot(map.*, start, direction)) return false;
const x = if (direction == .Top) start.x - 1 else start.x + 1;
switch (map[x][start.y]) {
.Empty => return true,
.BoxR => if (moveTopBot(map, Position{ .x = x, .y = start.y }, direction) and moveTopBot(map, Position{ .x = x, .y = start.y - 1 }, direction)) {
map.*[if (direction == .Top) x - 1 else x + 1][start.y] = .BoxR;
map.*[if (direction == .Top) x - 1 else x + 1][start.y - 1] = .BoxL;
map.*[x][start.y] = .Empty;
map.*[x][start.y - 1] = .Empty;
return true;
} else return false,
.BoxL => if (moveTopBot(map, Position{ .x = x, .y = start.y }, direction) and moveTopBot(map, Position{ .x = x, .y = start.y + 1 }, direction)) {
map.*[if (direction == .Top) x - 1 else x + 1][start.y] = .BoxL;
map.*[if (direction == .Top) x - 1 else x + 1][start.y + 1] = .BoxR;
map.*[x][start.y] = .Empty;
map.*[x][start.y + 1] = .Empty;
return true;
} else return false,
.Wall => return false,
.Robot => unreachable,
}
}
fn calculateSumPosition(map: [MAPH][MAPW]Cell) usize {
var total: usize = 0;
for (map, 0..) |row, x| for (row, 0..) |cell, y| switch (cell) {
.BoxL => total += x * 100 + y,
else => {},
};
return total;
}

141
day16/input Normal file
View File

@ -0,0 +1,141 @@
#############################################################################################################################################
#.#.....#.........#.#.............#.....#.........#.........#.........#.....#.........#...........#.....#.....#.....#.........#............E#
#.#.#.#.#####.###.#.#.#####.#.###.#####.#.#.#####.###.#.#.#.###.#####.###.#.#.#.#####.#####.#####.#.#.#.###.###.###.#.#######.#######.#####.#
#...#.#.....#...#.#...#.#...#.#.......#...#...#.#...#.#.#.#...#...#.#.....#.................#.#...#.#.#.#...#...#.#...#...#...#...#...#.....#
#.###.#####.###.#.#.###.#.#.#.#####.#.#.#####.#.###.###.#.###.###.#.#######.#######.###.#.###.#.#####.#.#.###.#.#.#####.###.###.#.#.###.#####
#.#...#.......#.#.#.#...#.#.#...#.............#...#.#...#...#.....#.#.............#.......................#...#.#.......#...#...#...#.#...#.#
###.#########.#.#.#.#.#.#.#.###.###.###.#######.###.#.###.#########.#.###########.#.#.#####.#.#.#.###.#####.###.#.###.###.###.#######.#.#.#.#
#...#.....#.#.#.#.#...#.#.#...#.#.....#...........#...#...............#...#.......#.#.#.....#.#.#.#...#.....#...#.#.#.....#...#.............#
#.###.###.#.#.#.#.###.###.#.#.#.#.#.#.#.###.#.###.#.#########.#########.#.#.###.#####.#.#.#####.#.#.###.#######.#.#.#######.#.#.#.#.#######.#
#.#...#...#.#.#.#.#...#...#.....#...#.....#.................#.....#.....#.#...#.......#.#.#.....#.#.#...#.......#...#.......#.#.#.#.........#
#.#.###.###.#.#.#.#####.#.#.#.#.###.###.#.#.#.#.#.#.#.#.#.#.#######.#####.###.#.#.#####.###.#####.#.#.###.#########.#.#####.###.#.###########
#...#.#.#...#...#.#.....#.#...................#.#...#.#.#.#.........#.....#...#.#...#...#...#.....#.#.#...........#.#.#...#.#...#...#...#...#
#.###.#.#.#######.#.#######.###.#.#.###.#.###.#.###.#.#.#.#######.###.#####.#######.#.###.#######.#.#.#.#######.###.#.###.#.#.#####.#.#.#.#.#
#...#.#.#.#.....#.#.......#...#...#.....#.#.......................#...#.....#.......#.........#...#.#.#...#...#.#...#.....#...#...#...#...#.#
###.#.#.#.#.###.#.#######.#.#.#.###.#####.#.#.###.#.#.#.#.#.###.###.###.#####.#######.#######.#.#.###.###.#.#.#.#.#######.#####.#.#####.###.#
#...#.#.#.....#.#...........#.#...#.....#.#...#...#.#.#.#.#.#.#.....#.#...#...#.#...#...#...#...#.#...#.#.#.#...#...#.....#.....#...#...#...#
#.###.#.###.###.#.#.#####.###.#.#.#####.###.###.###.#.#.#.#.#.#.#.###.###.#.###.#.#.###.#.#.#####.#.###.#.#.#######.#####.#.#####.#.###.#.###
#...#.#...#.#...#.......#.#...#.#.......#...#...#.....#...#.#...#.#.....#.#...#...#.....#.#...#...#.#.#...#.#.......#...#...#.......#...#...#
###.#.###.#.#.###.###.#.###.###.#########.###.#######.#####.#.#.#.###.###.###.###########.###.#.###.#.#.###.#.#######.#.#####.#.#.#.#.#.###.#
#.#...#.#.#.#.#...#...#.....#.#...........#...#.........#...#...#...#.........#...........#.#.#.#...#...#.#.......#...#...#...#.#.....#.#.#.#
#.#.#.#.#.#.#.#.###.#########.###########.#.###.#########.###.###.#.#.#########.###########.#.###.###.###.#######.#.#####.#.#.###.#####.#.#.#
#.........#.#.....#.#...#...........#...#.#.#.....#...#...#.#.#...#.#.#.#...#...#...#.......#.#...#...........#.....#.#...#.#.......#.....#.#
#.#.#####.#########.#.###.###.#######.#.###.#.#####.#.#.###.#.#.###.#.#.#.#.#.###.#.#######.#.#.#######.#.#.#.#######.#.###.#####.#.#.#####.#
#.........#.........#.......#.#.......#.....#...#...#...#...#.#...#.#...#.#...#...#.........#.#.#.....#.#...#.#...#.....#.....#...#.#.#...#.#
#.#.#.#.#.#.#######.#.#######.#.###########.###.#.#######.###.###.#.#####.#######.###########.#.#.###.#.#.###.#.#.#.#####.###.#.#.#.#.#.#.#.#
#.#...#.#.#...#.........#.....#.........#.....#.#.#.#...#...#.#...#.....#.....#...#.........#.#...#...#.#.#.#.#.#.#.#.......#.#.....#.#.#...#
#.#.#.#.#####.#.#######.#.#############.#######.#.#.#.#.#.#.#.#.#######.#####.#.###.#######.#.#####.#####.#.#.#.#.#.#########.#.#.#####.###.#
#.............#.#.....#...#.....#...#.#.#...#...#.#.#.#...#.#.#...#...#.....#.#.....#.#...#.#...#...#.......#...#.#.#.....#...#...#.....#...#
###.#.#.#.#####.#.###.###.#.#.#.#.#.#.#.#.#.#.###.#.#.#####.#.###.#.#.#.#####.#.#####.#.#.#.###.#.###.###########.#.#.###.#.#.###.#.#####.###
#...#.#...#.#...#...#...#...#.#...#...#.#.#.....#.#.#...#.#...#...#.#.#.#.....#...#...#.#.....#.#...#...#...#.....#...#.#...#...#...#...#...#
#.#.#.#####.#.#####.###.#.#.#.###.#####.#.#######.#.###.#.#.#####.#.#.#.#.#.#####.#.###.#######.#.#.#.###.#.#.#########.#.#####.#.###.#.###.#
#...#.....#.......#.#...#...#...#.#...#.#.#...#...#...#...#.....#.#.#...#.#.....#.#.....#.......#.#...#...#...#...#...............#...#...#.#
###.#.###.#######.#.#.#####.###.###.#.#.#.###.#.###.#####.#.###.###.#.#.#.#.#####.###.#.#.#############.#######.###.#.#.#########.#.###.###.#
#...#.#.........#.#.#...#.#.#...#...#...#.#...#...#...#...#.#.#.#...#...#.#...#.......#.......#.....#...#.#.....#.....#.#...........#.#.....#
#.#.#.#########.###.###.#.#.#.#.#.#####.#.#.#.###.###.#.###.#.#.#.###.###.#.#.#.#############.#.#.#.#.###.#.#.###.###.###.#######.###.#######
#...#.....#.......#...#.#...#.#.#...#...#...#...#...#.#.#...#.#.#.#...#...#.#...#.........#.......#...#.....#.......#...#.....#...#.........#
###.#####.#######.###.#.#####.#.###.###########.###.#.#.#.#.#.#.#.#.###.###.#####.#######.#.###########.###############.#####.#.#.#######.#.#
#...#...#.#.....#.....#.#.....#...#.........#.....#.#...#.#.#.....#.#.#...#.....#.#.#.....#.......#.............#...........#...#.......#.#.#
#.###.#.#.#.#.#.#######.#.#############.#####.#####.#.#####.#######.#.###.#####.#.#.#.#####.#####.#######.#######.#########.###.###.###.###.#
#.#...#.#...#...#...#...#.#.............#.....#.....#.....#.......#.#...#.#...#.#.#...#...#.#...#.......#.#.....#.#...#...#.#.........#...#.#
#.###.#.#####.#####.#.#.#.#.#############.#####.#####.###.###.#.###.###.#.###.#.#.#.#.#.#.#.#.#.#.#.###.###.###.#.#.#.#.#.#.#######.#####.#.#
#.#...#.....#.....#.#.....#.........#.....#...#.........#.....#.....#...#...#.#.#.......#.....#.#.....#.#...#...#...#.#.#.......#...#.....#.#
#.#.#######.#.###.#.#.###########.#.#.#####.#.#########.###.###.#####.#.###.#.#.###.#########.#.#######.#.###.###.###.#########.#.#.#.#####.#
#...#.......#...#.#...#...#.....#...#.#.....#.........#...#...........#...#.#.....#.#.....#...#...#.....#.#.#.#.....#.....#.....#...#...#...#
#####.#######.###.#####.#.#.###.###.#.#.#.#########.#.###.#.#####.#.#####.#.#######.#.###.#######.#.#####.#.#.#####.#####.#.#######.###.#.#.#
#...#.#.....#.#...#.....#...#.......#.#.#.........#...#...#.#.....#...#...#.......#.#.#.#...#.....#.#.....#.#...#.#.#...#.#...#.......#.#.#.#
#.#.#.#.###.#.#.###.#####.#########.#.###########.#####.###.#.#######.###########.#.#.#.###.#.###.#.###.###.###.#.#.###.#.###.#.#.#####.###.#
#.#.#.#.#.....#...#...#...#...#.....#.....#.....#.....#.#...#.#.....#...#.........#...#.....#.#.#.#...#...#.#...#.#.....#.#.......#.....#...#
#.#.#.#.#####.###.###.#####.#.#####.#####.#.###.#####.#.###.###.###.#.#.#.#######.#####.#####.#.#.###.#.#.#.#.###.#####.#.#####.###.#####.#.#
#.............#.....#.#.....#.....#.#.....#.........#.#...#.....#.#.#.#.#...#...#.#.....#.....#...#.#.#...#.#.#.#.......#...#...#...#.....#.#
#.#####.###.#.#.#.###.#.#########.###.#######.#.###.#.###.#######.#.###.###.#.###.#.#####.#######.#.#.#.#.#.#.#.#.#########.#.###.###.#####.#
#.....#...#.#...#.#...#.......#.#.............#.....#...#...#.......#...#.#.#...#.#.......#.....#...#.#.#.#...........#.....#...#.#...#.....#
#####.#####.#.###.#.#########.#.###.#####.#.###.#####.#####.#####.###.#.#.#.#.#.#.#######.#.###.#####.###.#.###.#######.#####.###.#.###.#####
#...#.......#.....#.....#.....#...........#.#...#...#.....#.#...#...#.#...#.#.#...#.......#.#.#.#.....#...#...#...#.....#...#.#...#.#.#.#...#
#.###########.#######.#.#.#########.###.###.#.###.#.#.###.#.#.#.###.#.###.#.#####.#.#######.#.#.#.#####.#.###.#####.#######.#.#.###.#.#.#.#.#
#.#...........#...#...#.#.........#.#.#.....#.#...#.#.#.#.#.#.#...#...#.#.#.....#.#.........#.#.#.#.#.....#.#.......#.......#.#...........#.#
#.#.#########.#.#.#.###.#########.#.#.#######.#.###.#.#.#.#.#.###.#####.#.#####.#####.#.#####.#.#.#.#.###.#.#####.#######.###.#######.#.###.#
#.#.#.......#...#...#.......#...#...#.......#.....#...#.#.....#...#.#...#...#.#.#.....#.#.....#...#.#.#...#.#.....#.....#.#...#.....#.#...#.#
#.#.#.###.###.#.###########.###.#####.#####.#####.#.###.#.#####.###.#.#.###.#.#.#.#####.#.###.#####.#.#.###.#.#####.###.#.#.###.###.#.###.#.#
#.#.#.#...#...#.#.....#...#...........#...#.#...#.#.....#.....#.#...#.#.....#.#.#.....#.#...#...........#.....#.#...#.......#...#.......#...#
#.#.#.#.###.#.###.###.###.#.###.#######.#.#.#.#.#.#####.###.###.#.###.#######.#.#####.#.###.###########.#.#####.#.###.###.#.#.#.###########.#
#...#.#.#.#.#.#...#.#.#...#...#.#...#...#.#.#.#.#.....#...#.#...#...#.........#.......#.#.#.#.....#...#.#.#.....#.....#...#.#.#.#.........#.#
#.#.#.#.#.#.###.###.#.#.###.#.#.#.#.#.#####.#.#######.#.###.#.###.#.#######.###########.#.#.#####.#.#.#.#.#.#.###.#.###.#.#.#.#.#.#######.#.#
#.....#...#.....#...#.#.....#...#.#.......#...#...#...#.#...#...#.#.#...............#...#.#.....#.#.#...#...#.#...#...#.#...#.#.#.#.....#...#
###.###.#.#######.###.#.#######.#.#.###.#.###.#.#.#.#####.#.###.###.#.#######.#####.#.###.#####.#.#.###.#######.#####.###.###.#.#.###.#.#.###
#.......#.#...#...#...#.......#...#...#.#.....#.#.#.......#...#.#...#.#.....#.#...#.#.#.......#.#.#.#...#...........#...#.....#.#...#.#.....#
###.###.#.#.#.#.#.#.#######.###.#####.#####.###.#.###.#####.###.#.###.###.#.#.#.###.#.#.#####.#.#.#.#####.#############.###########.#.###.#.#
#.........#.#.#...#.......#.#...#...#.....#...#.#...#.#...#.#...#.........#.#.#.......#.....#.....#.#.....#...#.........#.....#...#.#.#.....#
#.#.#.#.#.#.#.#.#########.#.#.###.#.#####.#####.###.#.#.#.###.###.###########.###############.###.#.#.#####.###.#######.#.###.#.#.#.###.#.#.#
#.#...#...#.#.#...#.......#...#...#.....#.#.....#.#...#.#.#...#.#.....#.....#.....#.....#.......#.#.....#.#...#...#.#...#...#...#.#.#...#...#
#.#.###.###.#.###.#.#.#.#.#.#.#######.###.#.#####.###.#.#.#.#.#.#.###.#.###.#.###.#.###.#.#####.#######.#.#.#.###.#.#.###.#.#####.#.#.###.###
#...#...#...#...#...#.#.#.#.#.#...#...#...#...#...#.#...#...#.......#.#.#.#.#.......#...#.#...#.....#...#...#...#.#...#.#.#...#...#.#.......#
###.#.#.#.#####.#.#.#.#.#.###.#.#.#.#.#.#####.#.#.#.#.###.#####.###.#.###.#.#.#######.###.###.#####.###.#####.###.###.#.#.#.#.#.###.#.###.#.#
#...#.#...#.....#...#.#.#.#.........#.#.#.......#...#...#.#...#...#.....#...#.#.....#...#...#.....#...#.....#...#...#...#.#.#.#...#.#.....#.#
#.#.#.#.###.#########.#.#.#.#########.#.#.#############.###.#.#####.###.#.#.###.###.#.#.#.#.#####.###.#####.###.###.#.#.#.#.#.###.#.#####.#.#
#.......#...#.........#.#...........#.#...#...#.......#.#...#.....#.#...#.....#...#.#.#.#...#.....#.#.#...#...#...#.#...#...#.#.#...........#
#.#.###.#.###.#######.#.#####.#####.###.###.#.#.#####.#.#.#######.#.#.#######.###.#.#.#.#.###.###.#.#.###.###.#.#.#.#########.#.#####.###.#.#
#.#.#...#...#.........#.....#.#...#...#.....#.#.#...#.#...#...#...#.#.#.....#.....#.#.#...#...#.....#.#...#...#.#.#...#.....#.......#.#.....#
#.#.#.#.###.#####.#.###.###.#.#.#.###.###.#####.#.#.#.#.###.#.#.###.#.###.#########.#.#######.#####.#.#.###.###.#####.#.###.#######.#.###.###
#.#...#...#...#...#...#.#.....#...#...........#.#.#.#.#.....#.#...#.#...#.#.........#.#.......#...#.#.#...#.#...#.....#.#.....#...#.#.......#
#.#.###.#####.#.#####.#.#######.#.#########.#.#.#.###.###.#######.#.###.#.#.#########.#.###.#.#.#.###.#.#.#.#.#.#.#####.#.#####.#.#.#.###.#.#
#.....#.....#.#...#...#...#...#.#.....#.......#.#.....#.......#.........#.#.......#...#...#.#.#.#.....#.#...#.#.#.#.....#.......#.#.#.#...#.#
###.#.###.###.###.#.#####.#.#.#.#####.#####.#.#.###.###.#####.#.###.#####.#.###.#.###.###.#.###.#.#####.#####.#.#.#.###########.#.#.#.###.#.#
#...#.....#...#...#.#...#...#.......#.....#.#.....#...#...#.#...#.#.......#...#.#...#.#...#...#.#.#...#.#.....#.#.........#...#.#.#.#.....#.#
#.#########.###.###.#.###################.#.###.#.###.#.#.#.#####.#######.###.#.###.#.#######.#.###.#.#.#######.###########.#.###.#.#.###.#.#
#.....#...#.#...#...#...........#.........#...#.#.#...#.#.#...#...#.....#.#.#...#.#...........#.....#.#...#...#.....#.......#.....#.#.......#
#####.#.#.#.###.#.#######.#####.#.###########.###.#.###.#.#.#.#.#.#.###.#.#.#####.#.#########.#####.#.###.#.#.#.###.#.#########.###.#.###.#.#
#.......#.#.....#...#...#.#.....#.........#.......#.#...#.#.#.#.#.#...#.#.#...#...#...#.......#...#.#.#.....#...#.....#.......#.#...#.#...#.#
#.#.###.#.#########.#.#.###.###.#########.#########.###.#.#.###.#.###.#.#.#.#.###.###.#########.#.###.#.#############.#######.#.#.###.#.#.###
#.#.#...#.........#...#...#.....#.......#.........#...#.#.#.....#...#.#.#...#.....#.#.....#...#.#.....#.#.#...........#...#...#.#.#.....#...#
#.#.#.#.#.#.#############.#.#.###.#####.#######.#.###.###.#######.###.#.#########.#.#####.#.#.#.#######.#.#.#######.###.#.#.###.#.###.###.#.#
#.#...#...#.#...#.......#...#...#.....#...............#...#.......#...#.....#.....#.....#...#.#.#.....#...#.......#...#.#...#...#.......#.#.#
#.#####.###.#.#.#.#.#.#########.#.###.###########.#####.###.#####.#.#####.#.#.#########.#####.#.#.###.#.#######.#.#.#.#.#.###.#######.#.#.#.#
#...#.#...#.#.#.....#.......#...#...#.#.........#...#.....#...#...#...#...#.#...#...............#.#.#.#.#.....#.#.#.#...#.#...#.......#.....#
#.#.#.#.#.#.#.#####.#####.###.#####.#.#.#.#########.#####.#.#.#######.#.###.###.#.#.#######.#####.#.#.#.#.###.###.#.###.#.#.###.###.#.###.#.#
#.#.#.#.#.#.#.#...#...#...#...#.....#.....#...#...#.......#.#.#.......#.#...#...#.#...#.......#...#.#...#...#.....#.#.#.#...#.............#.#
#.#.#.#.#.#.#.#.#.#####.###.###.#####.###.#.#.#.#.###########.#.###.###.#.###.###.#.#.#########.###.#######.#.#####.#.#.#.###.#.###.#.###.#.#
#.#.#...#...#.#.#.......#.....#.....#...#...#.#.#.....#.......#.#.......#...#...#.#.#.....#.....#...#.......#.......#...#.#.............#.#.#
#.#.###.#####.#.#######.#.#.#######.###.#.###.#.###.###.###.###.#.###.#########.#.#.#####.#.#####.#.#.#.#####.###.#.#.###.###.#####.#####.#.#
#.#.....#.....#.#.#.....#.#.........#.#.#...#...#...#.....#.#...#.#...#.........#...#...#.#.#...#.#.#.....#.#...#...#...#...#...#.......#.#.#
#.#####.#.#####.#.#.#####.#.#########.#.#.###.###.###.#.###.#.###.#.#.#.#########.###.#.#.#.#.#.###.#.###.#.###.#.###.#.###.#####.#.###.#.#.#
#.#.#...#.....#.#.........#.#.....#...#.#.......#.....#.....#...#.#...#.#...#...#.#...#...#...#.....#...#.#...#.#.#.....#...#.....#.......#.#
#.#.#.#.#####.#.#.###.#####.#.###.#.#.#.#.#####.#######.#######.#.#####.#.###.#.#.#.#####.#########.#.#.#.#.###.#.#######.###.#####.#######.#
#...#.....#...#.#.#.#...#...#...#.#.#.#.#.....#...#...#...#.....#.....#.#.....#...#.#.............#.#.#...#...#.#...#.....#.....#.#.#.#.....#
###.###.#.#.###.#.#.###.#.###.###.#.#.#.#######.#.#.#.###.#.#######.#.#.###.#######.#.#########.###.#.#######.#.###.#.#####.###.#.#.#.#.#####
#.#.#.....#...#.#.....#.#.#...#...#.#.#.........#.#.#...#...#.....#.#.....#.......#.#...#.....#...#.#.......#.....#.#.....#.....#...#.#.....#
#.#.#.#.#.###.#.###.###.#.#.###.###.#.###########.#.#.#####.#.###.#######.#######.#.###.#.###.#.#.#.#######.#####.#.#####.#.#####.#.#.#####.#
#.#.#.#...#...#.#...#...#.....#...#.#...#.......#.#...#.....#.#.#.....#.#.#.....#.#...#.#...#.#.#.#.......#.....#.#.............#.#.......#.#
#.#.#.#.#.#.###.#.###.#######.#.#.#.###.#.###.###.###.#.#.#.#.#.#####.#.#.###.#.#.###.#.###.#.#.#.#######.#####.#############.###.#.###.###.#
#.#.#...#.#...#...#.#.#...#...#.#...#.....#.#.....#...#.#.#.....#...#.#.#...#.#...#.#.#.....#.#.#...#.....#...#...#.....#.....#.....#...#...#
#.#.###.#.###.#.#.#.#.#.#.#.#######.#.#####.#.###.#.#.#.#.###.###.#.#.#.###.#.#####.#.#######.###.#.#.#####.#.###.#.###.#.###.#.###.#####.###
#.#...#.#...#.#.#...#.#.#.#.#.....#.#.......#...#.#.#.#.#.....#...#...#...#.#...#...#...#...#...#.#.#.#.....#.#.#.#...#.#.#.#.#.#.......#...#
#.###.#.#####.#.###.#.###.#.#.###.#.#.#.#####.#.#.#.#.#.#######.#######.###.###.###.###.#.#.###.###.#.#.#####.#.#.###.#.#.#.#.#.#.#.###.###.#
#.#...#.#.....#.#...#...#.#...#.#.#...#.#.....#.#.#.#.#.#.#...#...#...#.....#.......#.#...#...#.....#...#...#.........#.#...#...#.#...#.....#
#.#.###.#.#####.#####.#.#.#####.#.#######.#####.#.#.#.#.#.#.#.###.###.#.#######.###.#.#######.###.#.#######.###.#######.#.#.#####.#.#.#######
#.#...#.#.#...#.......#.#...#...#...........#.#.#...#.#.#...#...#...#.#.#.....#...#.#.......#.#.......#.....#...#.#.......#.....#.#.#.......#
#.###.#.#.#.#######.###.#.#.#.#.#.#########.#.#.#####.#.#####.#.###.#.#.###.#.###.#.###.###.#.#######.###.###.###.#.#.###.#.###.#.#.#######.#
#.....#...#.......#...#.#.#...#...#.....#.#...#.#...#.#.....#.#.#...#.#...#.#...#.....#.#...#.....#.......#...#.#...#...#.#.....#.#.....#...#
#.#########.###.#.#.#.#.#.#####.#.#.###.#.###.#.#.#.#.#####.#.###.###.###.#.#.#.#####.###.#####.#.#######.#.###.#.###.#.#.#####.#.#####.#.#.#
#.#.......#...#.#.#.......#.....#.#.#.#.#.....#...#.#.....#.#...#...#.......#.#.#...#.....#...#.#...#.....#...#.#.....#.#.....#.#.#.......#.#
#.#.#####.###.#.#.#.#########.#.#.#.#.#.###########.#######.###.###.#########.#.#.#.#######.#.#####.#.#.#.###.#.#.#####.#####.###.#######.###
#.#.#...#...#.#.#.#.....#...#.#...#.#...#...........#.......#.............#...#...#.#...#...#...#...#.......#.#...#.....#...#...#.......#...#
#.#.#.#.###.###.#.#.###.#.#.#####.#.###.#.#.#########.#######.###.#######.###.#####.#.#.#.#####.#.###########.#.###.###.#.#.###.#######.###.#
#.#.#.#...#...#.#.#.#...#.#.....#.#...#...#...........#.......#.....#...#...#.....#...#...........#.....#...#.#...#.#...#.#...#.......#.....#
#.#.#####.###.#.#.#.#.#.#.#####.#.###.#######.#.#######.#####.#.#####.#.###.#.###.###.#.#########.#.###.#.#.#.###.#.#.###.###.#######.#####.#
#...............#.#.#.#.#...........#.#...#.........#.#.#.....#.#.....#.....#...#...............#.#...#.#.#.#...#...#...#.#.......#.#.......#
#####.#.#.#.#####.###.#######.#####.#.#.#.#.###.###.#.#.#.#.#.#.#.#.###################.#######.#.#.#.#.#.#.###.###.#.#.#.#.#####.#.#########
#.....#.#.#.........#.......#.#.......#.#.#.....#...#...#.#.#.#.#.#.......#.........#...#.#...#.......#...#...#.....#...#.#.#...#.#.........#
#.#.###.###.###.###.#.#.###.#.#.#####.#.#.#######.###.###.#.#.#.#.#.#####.#.#######.#.###.#.#.#####.#######.#########.#####.###.#.#########.#
#.#...#.....#.....#.#...#...#.#...#.....#.......#.#...#...#...#.#.#.....#.#...#.....#...#...#.....#.........................#...#...........#
#.###.#.###########.#.###.###.###.#.#.###.###.###.#####.#######.#.#.#.###.#.###.#.#####.#.###.###.#.#.###.#.#.#.#.###.#######.#############.#
#...#.#.#...#.......#...#...#...#.#...#.#.#...#...#.....#...........#.#...#.#...#.#.....#.#...#...#.#...#.#...#.#.#.....#.............#...#.#
###.#.#.#.#.#.#######.#.#######.#####.#.#.#.###.###.#.#.#.#####.###.#.#.###.#.###.#.#######.#####.#.###.#.#####.###.#.#.#.#########.###.#.#.#
#.#.#.#.#.#...#.......#.#.....#.....#.#.#.#.#.#.#...#.#.#...#...#...#.#.#...#.#.#.#.#.....#.......................#...#...#.......#...#.#...#
#.#.#.###.#####.#######.#.#.#######.#.#.#.#.#.#.#.###.#.###.#.#.#.#.#.#.#.###.#.#.#.#.###.#.###.#.#.#.#.#.###.###.###.#####.#########.#.#####
#...#...#.....#...#...#...#.....#.#.#.#.#.#...#...#.#...#.#.#...#.#.#.#...#...#...#...#.#.#...#...#.#...#.#.#...#.#...#...........#...#.#...#
#.#####.#####.###.#.#.#######.#.#.#.#.#.#.#.#######.#.###.#.###.#.#.#.#####.#.#.#.#####.#.#######.#.#.###.#.#.###.#.###.#########.#.###.#.###
#.#...........#...#.#.....#...#...#.......................#.......#.#.#.....#...#.#.....#...#.....#.#.....#.#.#...#...#.....#...#.#...#.#...#
#.###.#.###.#######.#####.#.#####.#.#.#.###.#.###.#.#.###.#########.#.#.#####.#.###.#.#####.#.#####.#.#.###.#.#.#####.#######.#.#.###.#.###.#
#S....#.............#.......#.....#.........#.....#...............#...#.......#.....#.........#.........#.....#...............#.....#.......#
#############################################################################################################################################

175
day16/part1.zig Normal file
View File

@ -0,0 +1,175 @@
const std = @import("std");
const print = std.debug.print;
const input = @embedFile("input");
const MAP_SIZE = 141;
// So so so, how do I do that ?
// I am thinking bruteforce but stop early if the score is already > min
// Otherwise I can do it from the rnf, I dont need to do from start to end. I can do from end to start
// I cant really brute force it either though. As their is an infinite number of path since I can go around for ever
// So start from the start and making a random next step is a bit stupide it seem
// Specially because I think the next part will be a freaking giant map of something like that
// So first of all, rotation is 1000 cost lol. So Basically I need to find the lower number of turn until the end.
// If there is 2 identical, I check how many case it is. And maybe they are the same. You can do left right and right left, same price.
// But what matter is the number of turn
// Ok so what I can do it for each intersection, I do do all possible turn. But I need to do the step one by one
// I cant use recursion. Because I stop at the first found solution
// Damn that a good solution tho I think, as it will always take the minimum amount of calculation for 100% sure it's the minimum.
// Because Iam sure I can find a pathfinding algo somewhere that find the best at 95% but using 1% of the time.
//
// Anyway, so how do I do that ?
// I think I have a list of position + direction and a step function
// At each step, I go at the end of strait line and append to the next list if I find a possible route
// Like that it count like one turn and the next step it fo strait line
// When I found something the touch the exit I STILL FINISH THE CURRENT LIST as another one can finish at the same time in less cost
//
// If I need to turn 2 time, that mean I am in a cue de sac. So I can just forget it and don't add it to the next list
const Direction = enum { Top, Bottom, Left, Right };
const Cell = struct {
is: enum { Wall, Empty, End },
visited_by: struct {
top: bool = false,
bottom: bool = false,
left: bool = false,
right: bool = false,
} = .{},
fn visit(self: *Cell, direction: Direction) void {
if (direction == .Top) self.visited_by.top = true;
if (direction == .Left) self.visited_by.left = true;
if (direction == .Right) self.visited_by.right = true;
if (direction == .Bottom) self.visited_by.bottom = true;
}
fn visited(self: *Cell, direction: Direction) bool {
return switch (direction) {
.Top => self.visited_by.top,
.Bottom => self.visited_by.bottom,
.Right => self.visited_by.right,
.Left => self.visited_by.left,
};
}
};
const Position = struct {
x: usize,
y: usize,
};
const Path = struct {
position: Position,
direction: Direction,
number_of_turn_done: usize, // I could just save the cost total, I dont really need those 2 value
number_of_tile_walked: usize,
};
const Map = struct {
map: [MAP_SIZE][MAP_SIZE]Cell,
paths: *std.ArrayList(Path),
minimum: ?usize = null,
fn init(allocator: std.mem.Allocator) !Map {
const list = try allocator.create(std.ArrayList(Path));
list.* = std.ArrayList(Path).init(allocator);
var map: [MAP_SIZE][MAP_SIZE]Cell = undefined;
for (input[0 .. MAP_SIZE * (MAP_SIZE + 1)], 0..) |c, i| {
if (c == '\n') continue;
map[@divFloor(i, MAP_SIZE + 1)][i % (MAP_SIZE + 1)] = switch (c) {
'.', 'S' => Cell{ .is = .Empty },
'#' => Cell{ .is = .Wall },
'E' => Cell{ .is = .End },
else => unreachable,
};
if (c == 'S') try list.append(Path{
.direction = .Right,
.position = Position{ .x = @divFloor(i, MAP_SIZE + 1), .y = i % (MAP_SIZE + 1) - 1 },
.number_of_turn_done = 0,
.number_of_tile_walked = 0,
});
}
return Map{ .paths = list, .map = map };
}
// Each step is a turn of a path. So if a path need to turn to continue, it add itself to self.paths to be continue in the next step
// If it can continue walking it just continue walking as it cost nothing
fn solve(self: *Map, allocator: std.mem.Allocator) !?usize {
var minimum: ?usize = null;
while (minimum == null and self.paths.items.len != 0) {
const paths = try allocator.alloc(Path, self.paths.items.len);
defer allocator.free(paths);
for (self.paths.items, 0..) |path, i| paths[i] = path;
self.paths.clearRetainingCapacity();
for (paths) |*path| blk: while (true) {
var x: usize = path.position.x;
if (path.direction == .Top) x -= 1 else if (path.direction == .Bottom) x += 1;
var y: usize = path.position.y;
if (path.direction == .Left) y -= 1 else if (path.direction == .Right) y += 1;
if (self.map[x][y].is == .Wall) break :blk;
if (self.map[x][y].is == .End) {
if (minimum == null or path.number_of_turn_done * 1000 + path.number_of_tile_walked < minimum.?) {
minimum = path.number_of_turn_done * 1000 + path.number_of_tile_walked;
}
break :blk;
}
if (self.map[x][y].visited(path.direction)) break :blk;
self.map[x][y].visit(path.direction);
path.number_of_tile_walked += 1;
path.position.x = x;
path.position.y = y;
try self.checkSurroundingAndCreatePath(path.*);
};
}
return minimum;
}
fn checkSurroundingAndCreatePath(self: *Map, path: Path) !void {
const x = path.position.x;
const y = path.position.y;
switch (path.direction) {
.Right, .Left => {
if (self.map[x - 1][y].is == .Empty and !self.map[x - 1][y].visited(path.direction)) try self.paths.append(Path{
.position = path.position,
.direction = .Top,
.number_of_tile_walked = path.number_of_tile_walked,
.number_of_turn_done = path.number_of_turn_done + 1,
});
if (self.map[x + 1][y].is == .Empty and !self.map[x + 1][y].visited(path.direction)) try self.paths.append(Path{
.position = path.position,
.direction = .Bottom,
.number_of_tile_walked = path.number_of_tile_walked,
.number_of_turn_done = path.number_of_turn_done + 1,
});
}, //
.Top, .Bottom => {
if (self.map[x][y - 1].is == .Empty and !self.map[x][y - 1].visited(path.direction)) try self.paths.append(Path{
.position = path.position,
.direction = .Left,
.number_of_tile_walked = path.number_of_tile_walked,
.number_of_turn_done = path.number_of_turn_done + 1,
});
if (self.map[x][y + 1].is == .Empty and !self.map[x][y + 1].visited(path.direction)) try self.paths.append(Path{
.position = path.position,
.direction = .Right,
.number_of_tile_walked = path.number_of_tile_walked,
.number_of_turn_done = path.number_of_turn_done + 1,
});
},
}
}
};
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
var map = try Map.init(allocator);
const minimum = try map.solve(allocator);
try std.testing.expectEqual(127520, minimum.?);
}

197
day16/part2.zig Normal file
View File

@ -0,0 +1,197 @@
const std = @import("std");
const print = std.debug.print;
const input = @embedFile("input");
const MAP_SIZE = 141;
const Direction = enum { Top, Bottom, Left, Right };
const Cell = struct {
is: enum { Wall, Empty, End },
visited_by: struct {
top: bool = false,
bottom: bool = false,
left: bool = false,
right: bool = false,
} = .{},
just_visited_by: struct {
top: bool = false,
bottom: bool = false,
left: bool = false,
right: bool = false,
} = .{},
fn visit(self: *Cell, direction: Direction) void {
if (direction == .Top) self.just_visited_by.top = true;
if (direction == .Left) self.just_visited_by.left = true;
if (direction == .Right) self.just_visited_by.right = true;
if (direction == .Bottom) self.just_visited_by.bottom = true;
}
fn update(self: *Cell) void {
if (self.just_visited_by.top) {
self.just_visited_by.top = false;
self.visited_by.top = true;
}
if (self.just_visited_by.bottom) {
self.just_visited_by.bottom = false;
self.visited_by.bottom = true;
}
if (self.just_visited_by.right) {
self.just_visited_by.right = false;
self.visited_by.right = true;
}
if (self.just_visited_by.left) {
self.just_visited_by.left = false;
self.visited_by.left = true;
}
}
fn visited(self: *Cell, direction: Direction) bool {
return switch (direction) {
.Top => self.visited_by.top,
.Bottom => self.visited_by.bottom,
.Right => self.visited_by.right,
.Left => self.visited_by.left,
};
}
};
const Position = struct {
x: usize,
y: usize,
};
const Path = struct {
position: Position,
direction: Direction,
number_of_turn_done: usize, // I could just save the cost total, I dont really need those 2 value
number_of_tile_walked: usize,
visited: [10000]Position = undefined,
visited_len: usize = 0,
};
const Map = struct {
map: [MAP_SIZE][MAP_SIZE]Cell,
paths: *std.ArrayList(Path),
minimum: ?usize = null,
fn init(allocator: std.mem.Allocator) !Map {
const list = try allocator.create(std.ArrayList(Path));
list.* = std.ArrayList(Path).init(allocator);
var map: [MAP_SIZE][MAP_SIZE]Cell = undefined;
for (input[0 .. MAP_SIZE * (MAP_SIZE + 1)], 0..) |c, i| {
if (c == '\n') continue;
map[@divFloor(i, MAP_SIZE + 1)][i % (MAP_SIZE + 1)] = switch (c) {
'.', 'S' => Cell{ .is = .Empty },
'#' => Cell{ .is = .Wall },
'E' => Cell{ .is = .End },
else => unreachable,
};
if (c == 'S') try list.append(Path{
.direction = .Right,
.position = Position{ .x = @divFloor(i, MAP_SIZE + 1), .y = i % (MAP_SIZE + 1) - 1 },
.number_of_turn_done = 0,
.number_of_tile_walked = 0,
});
}
return Map{ .paths = list, .map = map };
}
// Each step is a turn of a path. So if a path need to turn to continue, it add itself to self.paths to be continue in the next step
// If it can continue walking it just continue walking as it cost nothing
fn solve(self: *Map, allocator: std.mem.Allocator) !usize {
var minimum: ?usize = null;
var visited = std.AutoHashMap(Position, void).init(allocator);
while (minimum == null and self.paths.items.len != 0) {
const paths = try allocator.alloc(Path, self.paths.items.len);
defer allocator.free(paths);
for (self.paths.items, 0..) |path, i| paths[i] = path;
self.paths.clearRetainingCapacity();
for (0..MAP_SIZE) |x| for (0..MAP_SIZE) |y| self.map[x][y].update();
for (paths) |*path| blk: while (true) {
var x: usize = path.position.x;
if (path.direction == .Top) x -= 1 else if (path.direction == .Bottom) x += 1;
var y: usize = path.position.y;
if (path.direction == .Left) y -= 1 else if (path.direction == .Right) y += 1;
if (self.map[x][y].is == .Wall) break :blk;
path.visited_len += 1;
if (self.map[x][y].visited(path.direction)) break :blk;
self.map[x][y].visit(path.direction);
path.visited[path.visited_len] = Position{ .x = x, .y = y };
path.number_of_tile_walked += 1;
if (self.map[x][y].is == .End) {
if (minimum == null or path.number_of_turn_done * 1000 + path.number_of_tile_walked < minimum.?) {
minimum = path.number_of_turn_done * 1000 + path.number_of_tile_walked;
}
if (path.number_of_turn_done * 1000 + path.number_of_tile_walked == minimum.?) {
for (path.visited[0..path.visited_len]) |pos| try visited.put(pos, {});
}
break :blk;
}
path.position.x = x;
path.position.y = y;
try self.checkSurroundingAndCreatePath(path.*);
};
}
return visited.count();
}
fn checkSurroundingAndCreatePath(self: *Map, path: Path) !void {
const x = path.position.x;
const y = path.position.y;
switch (path.direction) {
.Right, .Left => {
if (self.map[x - 1][y].is == .Empty and !self.map[x - 1][y].visited(path.direction)) try self.paths.append(Path{
.position = path.position,
.direction = .Top,
.number_of_tile_walked = path.number_of_tile_walked,
.number_of_turn_done = path.number_of_turn_done + 1,
.visited = path.visited,
.visited_len = path.visited_len,
});
if (self.map[x + 1][y].is == .Empty and !self.map[x + 1][y].visited(path.direction)) try self.paths.append(Path{
.position = path.position,
.direction = .Bottom,
.number_of_tile_walked = path.number_of_tile_walked,
.number_of_turn_done = path.number_of_turn_done + 1,
.visited = path.visited,
.visited_len = path.visited_len,
});
}, //
.Top, .Bottom => {
if (self.map[x][y - 1].is == .Empty and !self.map[x][y - 1].visited(path.direction)) try self.paths.append(Path{
.position = path.position,
.direction = .Left,
.number_of_tile_walked = path.number_of_tile_walked,
.number_of_turn_done = path.number_of_turn_done + 1,
.visited = path.visited,
.visited_len = path.visited_len,
});
if (self.map[x][y + 1].is == .Empty and !self.map[x][y + 1].visited(path.direction)) try self.paths.append(Path{
.position = path.position,
.direction = .Right,
.number_of_tile_walked = path.number_of_tile_walked,
.number_of_turn_done = path.number_of_turn_done + 1,
.visited = path.visited,
.visited_len = path.visited_len,
});
},
}
}
};
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
var map = try Map.init(allocator);
const total = try map.solve(allocator);
try std.testing.expectEqual(565, total);
}

1
day9/input Normal file

File diff suppressed because one or more lines are too long

81
day9/part1.zig Normal file
View File

@ -0,0 +1,81 @@
const std = @import("std");
const print = std.debug.print;
const file = @embedFile("input");
// Take first free space and last file and swap
const Block = struct {
id: ?usize,
type_: enum { file, empty },
};
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer {
const deinit_status = gpa.deinit();
if (deinit_status == .leak) @panic("TEST FAIL");
}
const allocator = gpa.allocator();
var total_file_block: usize = 0;
var total_free_block: usize = 0;
var list = std.ArrayList(Block).init(allocator);
for (file[0 .. file.len - 1], 0..) |c, i| {
const number = c - '0';
if (i % 2 == 0) {
total_file_block += number;
for (0..number) |_| try list.append(Block{ .id = @divFloor(i, 2), .type_ = .file });
} else {
total_free_block += number;
for (0..number) |_| try list.append(Block{ .id = null, .type_ = .empty });
}
}
sort(list.items, total_file_block);
try std.testing.expectEqual(6401092019345, checksum(list.items, total_file_block));
}
fn checksum(list: []Block, total_file_block: usize) usize {
var total: usize = 0;
for (list[0..total_file_block], 0..) |block, i| total += block.id.? * i;
return total;
}
fn sort(list: []Block, total_file_block: usize) void {
var left_index: usize = 0;
var right_index: usize = list.len - 1;
var block_buff: Block = undefined;
// I dont want a while loop where I check the list everytime, I need to know the number of swap that I need to do and use a for loop
// Like that I dont need to check if the list is sorted, it will be at the end of the for loop
// To know how many to move I need to know the number of file block and free block. This I can do it when I parse the first time.
// Then I can parse the list one time and for each type not at the right position, it's a swap, then divide by 2
for (0..total_swap_needed(list, total_file_block)) |_| {
left_index = next_empty_block(list, left_index).?;
right_index = next_file_block(list, right_index).?;
block_buff = list[left_index];
list[left_index] = list[right_index];
list[right_index] = block_buff;
}
}
fn next_empty_block(list: []Block, index: usize) ?usize {
for (index..list.len) |i| if (list[i].type_ == .empty) return i;
return null;
}
fn next_file_block(list: []Block, index: usize) ?usize {
for (0..index) |i| if (list[index - i].type_ == .file) return (index - i);
return null;
}
fn total_swap_needed(list: []Block, total_file_block: usize) usize {
var total: usize = 0;
for (list, 0..) |block, i| {
if ((block.type_ == .file and i > total_file_block) or (block.type_ == .empty and i < total_file_block)) total += 1;
}
return @divFloor(total, 2);
}

86
day9/part2.zig Normal file
View File

@ -0,0 +1,86 @@
const std = @import("std");
const print = std.debug.print;
const file = @embedFile("input");
//const file = "2333133121414131402\n";
// I think I just need to change both next function
// The e;pty block now take a size argument
// And the file take the current file index
const Block = struct {
id: ?usize,
type_: enum { file, empty },
};
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
const max_file_index = @divFloor(file.len - 1, 2);
// 1. create the list
var list = std.ArrayList(Block).init(allocator);
defer list.deinit();
for (file[0 .. file.len - 1], 0..) |c, i| {
if (i % 2 == 0) {
for (0..c - '0') |_| try list.append(Block{ .id = @divFloor(i, 2), .type_ = .file });
} else {
for (0..c - '0') |_| try list.append(Block{ .id = null, .type_ = .empty });
}
}
sort(list.items, max_file_index);
try std.testing.expectEqual(6431472344710, checksum(list.items));
}
fn checksum(list: []Block) usize {
var total: usize = 0;
for (list, 0..) |block, i| total += if (block.id) |id| id * i else 0;
return total;
}
fn sort(list: []Block, max_file_index: usize) void {
for (0..max_file_index) |i| {
const result = file_size_index(list, max_file_index - i) orelse continue;
const index = empty_space(list, result[0]) orelse continue;
if (index > result[1]) continue;
swap_memory(list, result[1], index, result[0]);
}
}
fn empty_space(list: []Block, size: usize) ?usize {
var mesuring: bool = false;
var len: usize = 0;
for (list, 0..) |block, i| {
if (mesuring and len == size) return (i - len);
if (block.type_ == .empty and !mesuring) {
mesuring = true;
len = 1;
} else if (block.type_ == .file and mesuring) {
mesuring = false;
len = 0;
} else if (block.type_ == .empty and mesuring) len += 1;
}
return null;
}
fn file_size_index(list: []Block, file_index: usize) ?[2]usize {
var mesuring: bool = false;
var len: usize = 0;
for (list, 0..) |block, i| {
if (!mesuring and block.id == file_index) {
mesuring = true;
len = 1;
} else if (mesuring and (block.type_ != .empty and block.type_ == .file and block.id.? == file_index)) {
len += 1;
} else if (mesuring and (block.type_ == .empty or (block.type_ == .file and block.id.? != file_index))) return [2]usize{ len, i - len };
}
return [2]usize{ len, list.len - len };
}
fn swap_memory(list: []Block, from: usize, to: usize, len: usize) void {
var buf: [9]Block = undefined;
for (to..to + len, 0..len) |i, j| buf[j] = list[i];
for (to..to + len, from..from + len) |i, j| list[i] = list[j];
for (from..from + len, 0..len) |i, j| list[i] = buf[j];
}