diff --git a/benchmark.zig b/benchmark.zig index 10c2f55..8429892 100644 --- a/benchmark.zig +++ b/benchmark.zig @@ -20,8 +20,12 @@ 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 NUMBER_OF_RUN = 1000; +const NUMBER_OF_RUN = 50; var total_mean: i64 = 0; var total_min: i64 = 0; @@ -62,6 +66,12 @@ pub fn main() !void { 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(); print("| Total | {d: >8} ± {d: <6.2} | {d:>8} | {d:>8} |\n", .{ total_mean, total_std_dev, total_min, total_max }); separator(); } diff --git a/day11/part1.zig b/day11/part1.zig new file mode 100644 index 0000000..cfb2a48 --- /dev/null +++ b/day11/part1.zig @@ -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 }; +} diff --git a/day11/part2.zig b/day11/part2.zig new file mode 100644 index 0000000..d286777 --- /dev/null +++ b/day11/part2.zig @@ -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; +} diff --git a/day12/input b/day12/input new file mode 100644 index 0000000..3a2ca2e --- /dev/null +++ b/day12/input @@ -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 diff --git a/day12/part1.zig b/day12/part1.zig new file mode 100644 index 0000000..e8a0904 --- /dev/null +++ b/day12/part1.zig @@ -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'); +} diff --git a/day12/part2.zig b/day12/part2.zig new file mode 100644 index 0000000..caf9ba7 --- /dev/null +++ b/day12/part2.zig @@ -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'); +}