diff --git a/day14/build.zig b/day14/build.zig new file mode 100644 index 0000000..6195db4 --- /dev/null +++ b/day14/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) void { + // Standard target options allows the person running `zig build` to choose + // what target to build for. Here we do not override the defaults, which + // means any target is allowed, and the default is native. Other options + // for restricting supported target set are available. + const target = b.standardTargetOptions(.{}); + + // Standard release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day14", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day14/input b/day14/input new file mode 100644 index 0000000..98121d1 --- /dev/null +++ b/day14/input @@ -0,0 +1,584 @@ +mask = 1X11X010X000X0X101X00100011X10100111 +mem[40278] = 36774405 +mem[51306] = 55175378 +mem[31036] = 805355 +mem[8433] = 48148 +mem[58481] = 45466 +mask = 1000101X11001XXX00X01110X1X000XX0100 +mem[42362] = 2765432 +mem[20493] = 213778 +mem[52954] = 756325 +mask = 10010000X00X1010000101X0010X001X1X10 +mem[34108] = 155448 +mem[19047] = 166539692 +mask = 1X0000111X0X10100X10X1110010X0100000 +mem[44380] = 108787272 +mem[50688] = 178803 +mem[13224] = 18328 +mem[47270] = 41220136 +mem[1679] = 5379693 +mem[25086] = 5316 +mask = 100010X011001X1000X1000XXX0000X010X0 +mem[8433] = 12191 +mem[45074] = 466358 +mem[57607] = 88673989 +mem[1764] = 3258736 +mask = X0011010110010010000X00100100X1001X0 +mem[42636] = 8106931 +mem[26732] = 819582135 +mem[61324] = 115576 +mem[46608] = 259438 +mem[62850] = 325 +mask = 11XX001111001X1001110X1XXX1110001X0X +mem[52922] = 2111 +mem[39872] = 2919426 +mem[49237] = 13351029 +mem[25369] = 403711 +mem[25714] = 525 +mem[11361] = 930295699 +mask = 100010001100X110X0111000X000X00X0000 +mem[55023] = 398985 +mem[1543] = 794 +mem[47160] = 65745 +mask = 1000001011X010XX00001001010X11101X01 +mem[3993] = 6186451 +mem[15936] = 678 +mem[12520] = 889 +mask = 110010XX10X0101X01X011X1010X00001100 +mem[21281] = 1112 +mem[1813] = 834 +mem[23778] = 88 +mem[877] = 4305190 +mem[41759] = 688804 +mem[31991] = 4165476 +mask = 1000X0101X001010000X10X00X00X01X00X1 +mem[62604] = 118285948 +mem[25086] = 804036 +mem[52954] = 414491 +mem[61838] = 14920 +mem[12372] = 14382 +mask = XXX1X00010001000X00X101X001000X01111 +mem[38767] = 23779 +mem[15107] = 3739 +mem[19591] = 35246 +mem[64406] = 27640 +mem[47997] = 1470326 +mask = 1011101011X0X1X100X0X11110010100X011 +mem[57638] = 42095143 +mem[18633] = 7407282 +mem[23584] = 1861 +mem[9800] = 35320 +mem[25647] = 17074 +mask = X0XX10X0100X1010X000X00011X100001101 +mem[19475] = 11720838 +mem[22303] = 3396 +mem[31371] = 963 +mem[27119] = 913 +mem[48910] = 28628571 +mem[48457] = 3430746 +mask = 1000101X1XX011010000010001000011XX00 +mem[42746] = 439123 +mem[26673] = 186688 +mem[9335] = 104841 +mem[47814] = 814 +mem[31051] = 23 +mem[26161] = 192849624 +mask = 110000X1X100101X011X001X0011XX011001 +mem[10584] = 8361 +mem[21594] = 83379 +mem[47043] = 458757662 +mem[1767] = 3878 +mem[37986] = 5338251 +mem[59740] = 779934 +mem[22725] = 495512 +mask = 10110X10100010X1011010X00010X11101X1 +mem[32885] = 15961 +mem[49329] = 11659 +mem[49589] = 883656 +mem[58578] = 3299 +mem[13410] = 16573 +mem[57567] = 56589 +mem[17446] = 2435 +mask = 100100001XX01110X00010000X100101X0X0 +mem[46571] = 57904 +mem[64234] = 1904852 +mem[17836] = 917 +mem[3697] = 79951109 +mem[17934] = 311 +mem[62943] = 105198 +mem[43632] = 127650 +mask = 110X001X00001X100X001X011100X01X0X01 +mem[32984] = 5679479 +mem[2985] = 52007072 +mask = 1000X01011001100XX0000X1110X00010101 +mem[52709] = 46005248 +mem[64106] = 148 +mem[10607] = 177262862 +mem[1672] = 768 +mem[55771] = 114128471 +mem[102] = 407505 +mask = X0X01010X1X011000X0000000X1001101X10 +mem[24357] = 37895788 +mem[4818] = 12679 +mem[1895] = 677 +mem[19538] = 1012377512 +mem[51317] = 290 +mem[26273] = 3433 +mask = 100X0X10X101100X1X10X111111001001X00 +mem[30547] = 1084 +mem[55023] = 38977 +mem[62922] = 235723 +mem[26793] = 2101257 +mem[3343] = 846 +mem[23767] = 749476 +mask = 10001XXX11X01101X0101X11101X1110X010 +mem[61302] = 2841122 +mem[54867] = 8646 +mem[50226] = 130817 +mem[48234] = 29376 +mem[39560] = 605311 +mask = 110010101X001X1X000000000X0001110X10 +mem[44651] = 1982752 +mem[46095] = 7221 +mem[22548] = 1154372 +mask = 11X100X0XX101010X00011101110X1010X01 +mem[28851] = 10138786 +mem[40188] = 9003080 +mem[46594] = 260547019 +mem[13047] = 644 +mem[61575] = 318501037 +mem[17933] = 130721 +mask = 10X000111X01X010XX1X0XX11001010001X0 +mem[17836] = 11610 +mem[60798] = 17334088 +mem[18040] = 8111502 +mem[5507] = 3549486 +mask = 100010101X001XXX00X0X10001X10111X01X +mem[1101] = 1830700 +mem[12750] = 44919 +mem[61081] = 1145728 +mem[221] = 98190 +mem[5230] = 1674762 +mask = 10110101X0X0100001X01101X1111X011011 +mem[63476] = 774 +mem[38765] = 6583 +mem[53101] = 425799 +mem[2689] = 76519 +mask = 1X0X0X001XX010100000X1X0X1000X010100 +mem[63306] = 25107559 +mem[29367] = 7911 +mem[33854] = 333886 +mem[34129] = 1601023 +mem[19106] = 105039 +mem[20340] = 33500 +mask = 1XX11X10100XX00X0X001010011010010111 +mem[17552] = 318 +mem[52954] = 755503843 +mem[45796] = 251387 +mask = 110010X01000101001000101X100001X010X +mem[19611] = 4546530 +mem[94] = 16405 +mem[37449] = 16299407 +mem[63044] = 1717 +mem[60882] = 53035 +mask = 1X111010100010X10X00X110XX0010010XX1 +mem[46825] = 38742 +mem[1559] = 2601 +mem[17127] = 10125964 +mem[45796] = 17645381 +mem[57067] = 650 +mem[12750] = 7052753 +mem[51876] = 223481 +mask = X00X1010110010010X000X000110X0X0X00X +mem[20021] = 98402475 +mem[62492] = 59443811 +mask = 100X101X100X1010000100010X000010X011 +mem[11361] = 790603 +mem[32392] = 1461971 +mem[16860] = 55486 +mem[48278] = 118088 +mem[6887] = 436990 +mem[44042] = 244740 +mask = 1000X01XX100X10000XX1X0011001XX01110 +mem[20112] = 2750699 +mem[12269] = 52907343 +mem[42636] = 6065 +mem[17001] = 169286 +mask = 10X1101X1X001X010X00011X0X0111001X11 +mem[37947] = 96 +mem[63306] = 7396 +mem[5465] = 1081 +mem[14662] = 1011 +mem[65279] = 131 +mask = 110100111100XX1X0111011110101000000X +mem[37780] = 7990 +mem[31512] = 40679485 +mem[14491] = 737737 +mem[30998] = 124949091 +mask = X1011X001000101XX0001X0X00111101001X +mem[33157] = 12243 +mem[56747] = 419147 +mem[11586] = 6256 +mem[64708] = 76550 +mem[37957] = 243778 +mem[5091] = 2456 +mask = 11X110X0X0001011X0000X0000100101X0X1 +mem[25324] = 2093940 +mem[36379] = 2777325 +mem[54213] = 228702576 +mem[32976] = 5846431 +mem[29430] = 119936 +mask = 1101010000101000X0001111100XXX111X11 +mem[31402] = 7431602 +mem[2073] = 7956 +mem[36885] = 3966 +mem[32392] = 37896 +mem[6832] = 173996362 +mem[53853] = 16478619 +mem[65160] = 667963 +mask = 100XX10X100X101X0X00000011X00X110X00 +mem[62304] = 3584301 +mem[57317] = 963348 +mem[16414] = 7872061 +mem[34763] = 1271472 +mask = 10XX001011000100000010X0100X01100111 +mem[48910] = 527784663 +mem[6555] = 360 +mem[52875] = 2675 +mem[18803] = 524 +mem[42703] = 3789970 +mask = 1X0100101X00X00X011100X1X11100X0101X +mem[45317] = 6806741 +mem[48723] = 23187771 +mem[34283] = 291852 +mem[29981] = 115905 +mem[63917] = 245041 +mask = 10010X0011001X10000000001X1001X10XX0 +mem[24836] = 124320580 +mem[13017] = 387784 +mem[49496] = 6149582 +mem[40990] = 3612867 +mem[42530] = 414515530 +mask = 11010XX01100X001XX1100X00001XX001011 +mem[49876] = 340001 +mem[12520] = 447064754 +mem[31346] = 2199326 +mem[38744] = 3174513 +mask = 100X101XX100100100101X000X00011111X0 +mem[58504] = 161861 +mem[51785] = 352 +mem[5035] = 14642386 +mask = 10XX0011100X101010110001110X11001X0X +mem[55328] = 912776 +mem[54729] = 404668417 +mem[1081] = 1230593 +mem[43126] = 275450 +mem[9568] = 6977 +mem[38414] = 258888 +mem[17523] = 628 +mask = 11011X10110010001110110X0XX1XX001101 +mem[14522] = 3706 +mem[23442] = 84315 +mem[60757] = 7650 +mem[64106] = 4820 +mem[12365] = 24537836 +mem[46911] = 2142190 +mem[60482] = 14617749 +mask = 11X1001111001X10X11100X000X010100110 +mem[30003] = 4640103 +mem[46235] = 8912631 +mem[28941] = 239 +mem[3232] = 2552211 +mem[14072] = 24479 +mem[45848] = 97107 +mem[27490] = 7267061 +mask = X00XXX1111X01101X0101110001XXX101110 +mem[50700] = 61091 +mem[2006] = 46171 +mem[54190] = 13801104 +mem[437] = 700 +mem[25806] = 370455 +mask = 1X00X0X0X00010100X00X00X010XX1100101 +mem[23418] = 3953103 +mem[4151] = 16351752 +mem[33858] = 2781804 +mem[40347] = 48747047 +mem[24323] = 185098 +mem[13410] = 3244984 +mem[22024] = 2046007 +mask = 101110XXX1001X01X100X1XX000111111111 +mem[42442] = 6862901 +mem[37947] = 133 +mem[52715] = 90558 +mask = 1X0XX0X0100010X0000X010X010X0001010X +mem[41622] = 3864588 +mem[37947] = 2574041 +mem[36379] = 282 +mem[7539] = 1884 +mem[43885] = 252462770 +mask = 1X0000XX110XX0X0X01101X0100X11101010 +mem[31739] = 122014445 +mem[12525] = 35483 +mem[49565] = 120526 +mask = 10000X00111X1010X0X00X0001X001X111X0 +mem[50] = 184186855 +mem[26970] = 28009237 +mem[43747] = 57180 +mask = XX01X010110X1XX101X11011X00101000011 +mem[34649] = 23812 +mem[19379] = 739289 +mem[9427] = 290837028 +mask = 1000001101X0X1000011111XX000101X11XX +mem[53212] = 976414185 +mem[54319] = 309721 +mem[61044] = 26059565 +mem[58543] = 112 +mem[47508] = 485916879 +mem[58912] = 603 +mask = 11X100000000100X000011101X001X0X0011 +mem[12536] = 1079539 +mem[60933] = 890 +mem[38277] = 24422421 +mem[31503] = 275497096 +mask = 10111010111011110X001111X0X01XX0X011 +mem[36315] = 732755 +mem[12521] = 5283380 +mem[14593] = 11354059 +mask = 110X10001000100X00001100X10000001XX0 +mem[178] = 10049489 +mem[58352] = 1284 +mem[55836] = 13364 +mem[8955] = 148648 +mask = 1001001X110010X01111001X0001010X1101 +mem[51286] = 424 +mem[24896] = 685 +mem[35764] = 984973816 +mem[1767] = 21227 +mem[58224] = 509700911 +mem[54139] = 681 +mask = 10X0101001001100X010X11001110X1X1101 +mem[4197] = 3959433 +mem[28314] = 4080074 +mem[64406] = 2275763 +mask = 10111011110011010XX0X111X00X1111111X +mem[53633] = 24715 +mem[12901] = 288197152 +mem[61838] = 365048 +mem[9985] = 113625770 +mask = 1000101011X0110X00000XX001XX0X1XX011 +mem[18728] = 2722863 +mem[62115] = 373062209 +mem[24406] = 14575043 +mem[1135] = 1658799 +mem[36109] = 27585 +mem[43154] = 932674865 +mask = 1X00001X1100101000XX01110001X01010X0 +mem[38443] = 2595746 +mem[45834] = 8200415 +mem[32618] = 2473 +mem[45317] = 204863 +mem[36385] = 1258950 +mem[1559] = 178687 +mem[7129] = 274257 +mask = 1X01X010110X1000111X11X00X1101011X01 +mem[64351] = 89231 +mem[23767] = 2060338 +mem[8182] = 3870 +mem[55067] = 3498 +mem[27490] = 113212315 +mask = 10000010110010100001XX01000X1XX00000 +mem[22484] = 465878 +mem[199] = 492230203 +mem[40351] = 41069 +mem[40347] = 28883121 +mem[54190] = 132583179 +mem[45157] = 1230 +mem[3262] = 763080 +mask = 1001010110011011X0X0100011X00X00X011 +mem[9068] = 1859901 +mem[65291] = 1860 +mem[4025] = 21940594 +mask = 11010X00X0X01X000000111010X0X1111X01 +mem[33551] = 154606 +mem[11586] = 6143673 +mem[55294] = 602657 +mem[25418] = 1846 +mem[31307] = 32063880 +mem[20048] = 1695818 +mask = 1X111X10110010110100110X110110X00000 +mem[24896] = 9413794 +mem[37579] = 13947393 +mem[62604] = 5335 +mem[9937] = 13537 +mem[14199] = 601827 +mask = 111110101X00X0110X000110X000101000X0 +mem[48234] = 1067197062 +mem[43126] = 1849938 +mem[26161] = 32826701 +mem[42432] = 2056 +mask = 10001X10110011000X100001X1100X000000 +mem[35283] = 15811124 +mem[6943] = 592604 +mem[25032] = 189694567 +mem[36455] = 163580 +mem[23535] = 61178 +mem[28952] = 363311 +mask = 1XX0000000001X10000X100001001X10X1X1 +mem[14987] = 1027 +mem[59069] = 14400510 +mem[27100] = 13017 +mem[70] = 22529 +mem[9653] = 120954062 +mask = 1X001X1010001010X001X0101000X1100001 +mem[36385] = 7634 +mem[51785] = 373478 +mem[62871] = 1219093 +mem[48687] = 720 +mem[46211] = 184017955 +mem[44651] = 4180012 +mask = 1X111X1X1100110100X0X11X011100010101 +mem[30714] = 86493051 +mem[9781] = 6458038 +mem[44042] = 196093756 +mem[54852] = 49986 +mask = 1X0X001XX10010X0XX11001100X1000100X1 +mem[59055] = 8554849 +mem[30511] = 238 +mem[59740] = 291 +mem[46825] = 4021 +mem[57257] = 47883555 +mask = 1001XX0X100X10000000X101XX0101X1X011 +mem[57317] = 3753201 +mem[36109] = 89435982 +mem[2071] = 92612 +mem[51306] = 3807708 +mem[60626] = 16185176 +mem[6288] = 52787155 +mem[51876] = 5014 +mask = 10X10X0X10X0100X0X00010X100111010000 +mem[47779] = 2632 +mem[44258] = 3287861 +mem[55067] = 554823 +mem[5507] = 16374932 +mask = X00000X01X0X101001XX00011010X010X110 +mem[15082] = 734057 +mem[20325] = 9406 +mem[43154] = 681 +mem[14046] = 2718549 +mem[36608] = 18836 +mask = 10001XX1110XX10X00X01100001011001010 +mem[64106] = 948524 +mem[63156] = 717606237 +mem[21756] = 8193201 +mem[61081] = 12060571 +mem[26182] = 1980 +mask = 100XX0X011001X0X00100101010100X100X0 +mem[40347] = 7113 +mem[20846] = 1812874 +mem[52954] = 31235865 +mem[15176] = 73255675 +mem[33551] = 45182604 +mask = 1000101X1000100000001001X10001010X1X +mem[53536] = 78486 +mem[14207] = 25081 +mem[6943] = 406911928 +mem[20627] = 33813239 +mem[52083] = 5810 +mem[51593] = 2963 +mask = 100XX01010X0100100XX1X0X011001111110 +mem[50540] = 521342322 +mem[25666] = 517512832 +mem[19475] = 60787116 +mask = 100X1010XX0011X000100010X0X1X0111X11 +mem[44296] = 11404 +mem[19921] = 12860 +mask = 10011000XX0X100000X1X10X001X00X10X10 +mem[15030] = 28046260 +mem[36124] = 53286373 +mem[18115] = 57486 +mem[14821] = 6413 +mem[46807] = 4097123 +mem[5230] = 758650 +mem[47154] = 2777 +mask = 1001X0101X0010000X11011X01001XX11101 +mem[61830] = 63370 +mem[31503] = 16024 +mem[12525] = 246729437 +mem[33593] = 115066 +mem[46594] = 59939695 +mem[178] = 6489337 +mask = 110XX000100010000000100110110XX0XX01 +mem[61044] = 1681 +mem[48145] = 78509 +mem[14662] = 317884442 +mask = 10010011110XX01000111011011X1011X111 +mem[63129] = 26 +mem[3729] = 72549 +mem[60816] = 33039 +mem[5097] = 620696594 +mem[24325] = 1480 +mem[52500] = 507 +mem[9653] = 77992342 +mask = 10X11010XX00X00100X0011X100X110X0011 +mem[50406] = 75245910 +mem[65160] = 121691 +mem[10605] = 5972898 +mem[31113] = 122549 +mask = 10X0111111101101001X1XXX1X0011101010 +mem[32648] = 13078 +mem[16040] = 42554293 +mem[49180] = 14823 +mem[12178] = 18873 +mem[45060] = 58303 +mem[49248] = 59412 +mask = 1000X010110X101001100X0010100100011X +mem[14950] = 106014 +mem[41759] = 6142194 +mem[53704] = 2925 +mask = 1000001011001010000X10010000X110X10X +mem[38572] = 30247028 +mem[23767] = 23066 +mem[32618] = 542388 +mem[10770] = 411 +mem[16831] = 40856 +mem[13505] = 2142 +mem[28786] = 140994490 +mask = 1100X0X000001XX00100X0010110X0X01X01 +mem[17768] = 45460151 +mem[4197] = 705 +mem[2953] = 12201 +mask = 1000000011XX10X00X0010X1011X111X0111 +mem[18985] = 29719899 +mem[45172] = 258207909 +mem[49882] = 85394924 +mem[21653] = 603 +mem[31300] = 37290319 +mem[5035] = 5768 +mem[6427] = 15769266 +mask = 10010011110010X0111101X000000101X0X1 +mem[47082] = 157766 +mem[13410] = 3842391 +mem[58172] = 2576 +mask = 10X000001000101000011101X0X000XX1001 +mem[3121] = 198929928 +mem[59740] = 16383 +mem[12269] = 37852 +mem[18190] = 1240 +mask = 10000XX001000100XX0X100X1010110110X0 +mem[9713] = 1435 +mem[50404] = 1789 +mem[28429] = 3239 +mem[178] = 2804 +mask = 1000010010X11011X0X01X0111010011X0X0 +mem[44077] = 202823 +mem[30483] = 3929 +mem[25920] = 10040 +mem[221] = 135771 +mask = 10X0X01111001100000000000100X0001X1X +mem[9427] = 152879 +mem[38057] = 11090 +mem[58564] = 32957206 +mask = 110X0010110X1X100010101X00100X001010 +mem[30968] = 2095418 +mem[3121] = 139148 +mem[53666] = 26824 diff --git a/day14/src/main.zig b/day14/src/main.zig new file mode 100644 index 0000000..5a24b72 --- /dev/null +++ b/day14/src/main.zig @@ -0,0 +1,296 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + var gpa = &arena.allocator; + + var map = std.hash_map.AutoHashMap(u64, u64).init(gpa); + defer map.deinit(); + + var f = try std.fs.cwd().openFile("input", .{}); + var contents = try f.readToEndAlloc(gpa, std.math.maxInt(u32)); + + // Part one + var and_mask : u64 = std.math.maxInt(u64); + var or_mask : u64 = 0; + + var it = std.mem.tokenize(contents, "\n"); + while (it.next()) |line| { + std.log.debug("{}", .{line}); + if (std.mem.eql(u8, line[0..4], "mask")) { + // Set mask + var mask_iter = std.mem.tokenize(line, "="); + _ = mask_iter.next(); // skip the first one + if (mask_iter.next()) |v| { + set_masks(std.mem.trim(u8, v, " "), &and_mask, &or_mask); + } + } + else { + var memory_location: u64 = 0; + var memory_value: u64 = 0; + var mem_iter = std.mem.tokenize(line, "=["); + std.log.warn("{}", .{mem_iter.next()}); // skip 'mem[' + if (mem_iter.next()) |location_line| { + std.log.debug("parsing '{}'", .{location_line}); + memory_location = try std.fmt.parseUnsigned(u64, std.mem.trim(u8, location_line, " ]"), 10); + } + if (mem_iter.next()) |value_line| { + memory_value = try std.fmt.parseUnsigned(u64, std.mem.trim(u8, value_line, " "), 10); + } + try write_memory(&map, memory_location, memory_value, and_mask, or_mask); + } + } + + var map_it = map.iterator(); + var sum : u64 = 0; + while (map_it.next()) |entry| { + sum += entry.value; + } + std.log.info("Part 1: Sum of non-zero memory locations: {}", .{sum}); + + // Part 2 + map.deinit(); + map = std.hash_map.AutoHashMap(u64, u64).init(gpa); + gpa.free(contents); + try f.seekTo(0); + contents = try f.readToEndAlloc(gpa, std.math.maxInt(u32)); + it = std.mem.tokenize(contents, "\n"); + var address_mask : [36]u8 = undefined; + while (it.next()) |line| { + std.log.debug("{}", .{line}); + if (std.mem.eql(u8, line[0..4], "mask")) { + // Set mask + var mask_iter = std.mem.tokenize(line, "="); + _ = mask_iter.next(); // skip the first one + if (mask_iter.next()) |v| { + std.mem.copy(u8, &address_mask, std.mem.trim(u8, v, " ")); + } + } + else { + var memory_location: u64 = 0; + var memory_value: u64 = 0; + var mem_iter = std.mem.tokenize(line, "=["); + _ = mem_iter.next(); // skip 'mem[' + if (mem_iter.next()) |location_line| { + std.log.debug("parsing '{}'", .{location_line}); + memory_location = try std.fmt.parseUnsigned(u64, std.mem.trim(u8, location_line, " ]"), 10); + } + if (mem_iter.next()) |value_line| { + memory_value = try std.fmt.parseUnsigned(u64, std.mem.trim(u8, value_line, " "), 10); + } + try write_memory_address_masked(&map, memory_location, memory_value, address_mask[0..]); + } + } + map_it = map.iterator(); + sum = 0; + while (map_it.next()) |entry| { + sum += entry.value; + } + std.log.info("Part 2: Sum of non-zero memory locations: {}", .{sum}); +} + +fn write_memory_address_masked(map: *std.hash_map.AutoHashMap(u64, u64), location: u64, value: u64, + mask: []const u8) !void { + // Fuse the value into the character mask + var i : u6 = 0; + var new_mask : [36]u8 = undefined; + std.mem.copy(u8, &new_mask, mask); + while (i < 36) : (i += 1) { + if (new_mask[i] == 'X') { + continue; + } + else if (new_mask[i] == '1') { + continue; + } + else if (new_mask[i] == '0') { + // mask to isolate bit at position 35 - i + // kth() counts from LSB to MSB, we are going in string order from + // MSB to LSB + new_mask[i] = switch(kth_bit(location, 35-i)) { + 0 => '0', + 1 => '1', + else => { + unreachable; + }, + }; + //std.log.warn("Index {}: {c} -> {c}", .{i, new_mask[i], mask[i]}); + } + } + std.log.warn("\nValue: {b:36} ({})\nPre-fuse: {}\nPst-fuse: {}", .{location, location, mask, new_mask}); + var addresses = try generate_address_list(map.allocator, new_mask[0..]); + defer addresses.deinit(); + + for (addresses.items) |address| { + std.log.warn("Wrote {} to address {}", .{value, address}); + try map.put(address, value); + } +} + +// Caller is responsible for freeing this +// This function takes the "fused mask", where the only thing left to resolve +// if the 'X' bits. +fn generate_address_list(allocator: *std.mem.Allocator, mask: []const u8) !std.ArrayList(u64) { + var masks = std.ArrayList(u64).init(allocator); + var i : u64 = 0; + // Store the offsets of the locations of the X character + var x_locations = std.ArrayList(usize).init(allocator); + defer x_locations.deinit(); + for (mask) |c, k| { + if (c == 'X') { + try x_locations.append(k); + } + } + var n_variants = std.math.pow(u64, 2, x_locations.items.len); + //std.log.warn("{} Xs in mask '{}', {} variants", .{x_locations.items.len, mask, n_variants}); + while (i < n_variants) : (i += 1) { + var m = try allocator.alloc(u8, mask.len); + std.mem.copy(u8, m, mask); + var bit_index : u6 = 0; + while (bit_index < x_locations.items.len) : (bit_index += 1) { + // At 0, all Xs become zero, + // At 1, last X becomes one, otherwise Xs are zero + // ... + m[x_locations.items[bit_index]] = switch(kth_bit(i, bit_index)) { + 0 => '0', + 1 => '1', + else => { + unreachable; + }, + }; + } + var value = try std.fmt.parseUnsigned(u64, m, 2); + //std.log.warn("\nFrom: {:64}\nGot: {b:64}", .{m, value}); + try masks.append(value); + allocator.free(m); + } + return masks; +} + +// @see https://www.geeksforgeeks.org/find-value-k-th-bit-binary-representation/ +fn kth_bit(value: u64, k: u6) u64 { + //std.debug.warn("\nKey: {}, V: {}\nOrig: {b:64}\n", .{k, value, value}); + var one: u64 = 1; + var shifted: u64 = 0; + var overflowed = @shlWithOverflow(u64, one, k, &shifted); + if (overflowed) { + std.log.warn("OVERFLOWED", .{}); + } + //std.debug.warn("Shft: {b:64}\n", .{shifted}); + //std.debug.warn("Andd: {b:64}\n", .{value & shifted}); + //std.debug.warn("Rslt: {b:64}\n", .{(value & shifted) >> k}); + return (value & shifted) >> k; +} + +fn write_memory(map: *std.hash_map.AutoHashMap(u64, u64), location: u64, value: u64, and_mask: u64, or_mask: u64) !void { + // Mask + var new_value = value; + new_value &= and_mask; + new_value |= or_mask; + try map.put(location, new_value); + std.log.debug("Wrote '{}' to '{}' (pre-masked: '{}')", + .{new_value, location, value}); + //std.log.warn("\npre_mask: {b:64}\nand_mask: {b:64}\nor_mask :{b:64}\npst_mask: {b:64}", + // .{value, and_mask, or_mask, new_value}); +} + +//const maskWidth : u64 = 36; +fn set_masks(line: []const u8, and_mask: *u64, or_mask: *u64) void { + and_mask.* = std.math.maxInt(u64); + or_mask.* = 0; + + var one: u64 = 1; + for (line) |c, k| { + var offset = @intCast(u6, line.len - k - 1); + switch(c) { + '1' => { + // Only need to tweak the or_mask + or_mask.* |= (one << offset); + }, + '0' => { + and_mask.* &= ~(one << offset); + }, + 'X' => { + continue; + }, + else => unreachable, + } + } + std.log.debug("and mask:{b:64}", .{and_mask}); + std.log.debug("or mask:{b:64}", .{or_mask}); +} + +test "mask_setting" { + var and_mask : u64 = 0; + var or_mask : u64 = 0; + var l = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X"; + set_masks(l, &and_mask, &or_mask); +} + +test "memory_writing" { + var and_mask : u64 = 0; + var or_mask : u64 = 0; + var l = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X"; + set_masks(l, &and_mask, &or_mask); + + var map = std.hash_map.AutoHashMap(u64, u64).init(std.testing.allocator); + defer map.deinit(); + + try write_memory(&map, 8, 11, and_mask, or_mask); + try write_memory(&map, 7, 101, and_mask, or_mask); + try write_memory(&map, 8, 0, and_mask, or_mask); + + if (map.get(8)) |v| { + std.testing.expectEqual(v, 64); + } + else { + unreachable; + } + + if (map.get(7)) |v| { + std.testing.expectEqual(v, 101); + } + else { + unreachable; + } +} + +test "kth_bit" { + var value : u64 = 13; + // 0000 1101 + var expected = [_]u64 { + // goes from LSB to MSB + 1, 0, 1, 1, + 0, 0, 0, 0, + }; + for (expected) |v, k| { + var key : u6 = @intCast(u6, k); + std.testing.expectEqual(kth_bit(value, key), expected[k]); + } +} + +test "generate_address_list" { + var mask = "000000000000000000000000000000X1101X"; + var addresses = try generate_address_list(std.testing.allocator, mask[0..]); + defer addresses.deinit(); + + //std.log.warn("\n26: {b:64}\n27: {b:64}\n58: {b:64}\n59: {b:64}\n", .{26, 27, 58, 59}); + std.testing.expectEqual(addresses.items.len, 4); + std.testing.expectEqual(addresses.items[0], 26); + std.testing.expectEqual(addresses.items[1], 58); + std.testing.expectEqual(addresses.items[2], 27); + std.testing.expectEqual(addresses.items[3], 59); +} + +test "part2" { + var map = std.hash_map.AutoHashMap(u64, u64).init(std.testing.allocator); + defer map.deinit(); + try write_memory_address_masked(&map, 42, 100, "000000000000000000000000000000X1001X"); + try write_memory_address_masked(&map, 26, 1, "00000000000000000000000000000000X0XX"); + var map_it = map.iterator(); + var sum : u64 = 0; + while (map_it.next()) |entry| { + sum += entry.value; + } + std.testing.expectEqual(sum, 208); +}