diff --git a/src/Year_2015/P8.py b/src/Year_2015/P8.py new file mode 100644 index 0000000..662a241 --- /dev/null +++ b/src/Year_2015/P8.py @@ -0,0 +1,83 @@ +# --- Day 8: Matchsticks --- + +# Space on the sleigh is limited this year, and so Santa will be bringing his +# list as a digital copy. He needs to know how much space it will take up when +# stored. + +# It is common in many programming languages to provide a way to escape special +# characters in strings. For example, C, JavaScript, Perl, Python, and even PHP +# handle special characters in very similar ways. + +# However, it is important to realize the difference between the number of +# characters in the code representation of the string literal and the number of +# characters in the in-memory string itself. + +# For example: + +# "" is 2 characters of code (the two double quotes), but the string +# contains zero characters. +# "abc" is 5 characters of code, but 3 characters in the string data. +# "aaa\"aaa" is 10 characters of code, but the string itself contains six +# "a" characters and a single, escaped quote character, for a total of 7 characters in the string data. +# "\x27" is 6 characters of code, but the string itself contains just one +# - an apostrophe ('), escaped using hexadecimal notation. + +# Santa's list is a file that contains many double-quoted string literals, one +# on each line. The only escape sequences used are \\ (which represents a +# single backslash), \" (which represents a lone double-quote character), and +# \x plus two hexadecimal characters (which represents a single character with +# that ASCII code). + +# Disregarding the whitespace in the file, what is the number of characters of +# code for string literals minus the number of characters in memory for the +# values of the strings in total for the entire file? + +# For example, given the four strings above, the total number of characters of +# string code (2 + 5 + 10 + 6 = 23) minus the total number of characters in +# memory for string values (0 + 3 + 7 + 1 = 11) is 23 - 11 = 12. + +with open("files/P8.txt") as f: + lines = [line for line in f.read().strip().split()] + + +# TIL: eval() +def part_1() -> None: + res = sum(len(line) - len(eval(line)) for line in lines) + + print(f"There are {res} characters.") + + +# --- Part Two --- + +# Now, let's go the other way. In addition to finding the number of characters +# of code, you should now encode each code representation as a new string and +# find the number of characters of the new encoded representation, including +# the surrounding double quotes. + +# For example: + +# "" encodes to "\"\"", an increase from 2 characters to 6. +# "abc" encodes to "\"abc\"", an increase from 5 characters to 9. +# "aaa\"aaa" encodes to "\"aaa\\\"aaa\"", an increase from 10 characters to +# 16. +# "\x27" encodes to "\"\\x27\"", an increase from 6 characters to 11. + +# Your task is to find the total number of characters to represent the newly +# encoded strings minus the number of characters of code in each original +# string literal. For example, for the strings above, the total encoded length +# (6 + 9 + 16 + 11 = 42) minus the characters in the original code +# representation (23, just like in the first part of this puzzle) is +# 42 - 23 = 19. + + +def part_2() -> None: + # 2 for the "" + # just count numbers of \\ and new " + res = sum(2 + line.count("\\") + line.count('"') for line in lines) + + print(f"There are {res} characters.") + + +if __name__ == "__main__": + part_1() + part_2() diff --git a/src/Year_2015/files/P8.txt b/src/Year_2015/files/P8.txt new file mode 100644 index 0000000..94538e7 --- /dev/null +++ b/src/Year_2015/files/P8.txt @@ -0,0 +1,300 @@ +"qxfcsmh" +"ffsfyxbyuhqkpwatkjgudo" +"byc\x9dyxuafof\\\xa6uf\\axfozomj\\olh\x6a" +"jtqvz" +"uzezxa\"jgbmojtwyfbfguz" +"vqsremfk\x8fxiknektafj" +"wzntebpxnnt\"vqndz\"i\x47vvjqo\"" +"higvez\"k\"riewqk" +"dlkrbhbrlfrp\\damiauyucwhty" +"d\"" +"qlz" +"ku" +"yy\"\"uoao\"uripabop" +"saduyrntuswlnlkuppdro\\sicxosted" +"tj" +"zzphopswlwdhebwkxeurvizdv" +"xfoheirjoakrpofles\"nfu" +"q\xb7oh\"p\xce\"n" +"qeendp\"ercwgywdjeylxcv" +"dcmem" +"\"i\x13r\"l" +"ikso\xdcbvqnbrjduh\"uqudzki\xderwk" +"wfdsn" +"pwynglklryhtsqbno" +"hcoj\x63iccz\"v\"ttr" +"zf\x23\\hlj\\kkce\\d\\asy\"yyfestwcdxyfj" +"xs" +"m\"tvltapxdvtrxiy" +"bmud" +"k\"a" +"b\"oas" +"\"yexnjjupoqsxyqnquy\"uzfdvetqrc" +"vdw\xe3olxfgujaj" +"qomcxdnd\"\\cfoe\"" +"fpul" +"m\"avamefphkpv" +"vvdnb\\x\\uhnxfw\"dpubfkxfmeuhnxisd" +"hey\\" +"ldaeigghlfey" +"eure\"hoy\xa5iezjp\\tm" +"yygb\"twbj\\r\"\x10gmxuhmp\"" +"weirebp\x39mqonbtmfmd" +"ltuz\\hs\"e" +"ysvmpc" +"g\x8amjtt\"megl\"omsaihifwa" +"yimmm" +"iiyqfalh" +"cwknlaaf" +"q\x37feg\xc6s\"xx" +"uayrgeurgyp\\oi" +"xhug\"pt\"axugllbdiggzhvy" +"kdaarqmsjfx\xc3d" +"\"vkwla" +"d\"" +"tmroz\"bvfinxoe\\mum\"wmm" +"\"n\"bbswxne\\p\\yr\"qhwpdd" +"skzlkietklkqovjhvj\xfe" +"pbg\\pab\"bubqaf\"obzcwxwywbs\\dhtq" +"xxjidvqh\"lx\\wu\"ij" +"daef\x5fe\x5b\\kbeeb\x13qnydtboof" +"ogvazaqy\"j\x73" +"y" +"n\"tibetedldy\\gsamm\"nwu" +"wldkvgdtqulwkad" +"dpmxnj" +"twybw\"cdvf\"mjdajurokbce" +"ru\"\\lasij\"i" +"roc\\vra\\lhrm" +"pbkt\x60booz\"fjlkc" +"j\x4dytvjwrzt" +"\\uiwjkniumxcs" +"cbhm\"nexccior\"v\"j\"nazxilmfp\x47" +"qdxngevzrlgoq" +"\"lrzxftytpobsdfyrtdqpjbpuwmm\x9e" +"mdag\x0asnck\xc2ggj\"slb\"fjy" +"wyqkhjuazdtcgkcxvjkpnjdae" +"aixfk\xc0iom\x21vueob" +"dkiiakyjpkffqlluhaetires" +"ysspv\"lysgkvnmwbbsy" +"gy\"ryexcjjxdm\"xswssgtr" +"s" +"ddxv" +"qwt\"\x27puilb\"pslmbrsxhrz" +"qdg\xc9e\\qwtknlvkol\x54oqvmchn\\" +"lvo" +"b" +"fk\"aa\"\"yenwch\\\\on" +"srig\x63hpwaavs\\\x80qzk\"xa\"\xe6u\\wr" +"yxjxuj\"ghyhhxfj\"\xa6qvatre" +"yoktqxjxkzrklkoeroil" +"\"jfmik\"" +"smgseztzdwldikbqrh\"" +"jftahgctf\"hoqy" +"tcnhicr\"znpgckt\"ble" +"vqktnkodh\"lo\"a\\bkmdjqqnsqr" +"ztnirfzqq" +"s" +"xx" +"iqj\"y\\hqgzflwrdsusasekyrxbp\\ad" +"\\xzjhlaiynkioz\"\"bxepzimvgwt" +"s\x36rbw" +"mniieztwrisvdx" +"atyfxioy\x2b\\" +"irde\x85\x5cvbah\\jekw\"ia" +"bdmftlhkwrprmpat\"prfaocvp" +"w\\k" +"umbpausy" +"zfauhpsangy" +"p\"zqyw" +"wtztypyqvnnxzvlvipnq\"zu" +"deicgwq\\oqvajpbov\\or\"kgplwu" +"mbzlfgpi\\\\zqcidjpzqdzxityxa" +"lfkxvhma" +"\xf2yduqzqr\"\\fak\"p\"n" +"mpajacfuxotonpadvng" +"anb\\telzvcdu\\a\xf2flfq" +"lrs\"ebethwpmuuc\"\x86ygr" +"qmvdbhtumzc\"ci" +"meet" +"yopg\x0fdxdq\"h\\ugsu\xffmolxjv" +"uhy" +"fzgidrtzycsireghazscvmwcfmw\\t" +"cqohkhpgvpru" +"bihyigtnvmevx\"xx" +"xz" +"zofomwotzuxsjk\"q\"mc\"js\"dnmalhxd" +"\\ktnddux\\fqvt\"ibnjntjcbn" +"ia" +"htjadnefwetyp\xd5kbrwfycbyy" +"\"\\hkuxqddnao" +"meqqsz\x83luecpgaem" +"cvks\x87frvxo\"svqivqsdpgwhukmju" +"sgmxiai\\o\"riufxwjfigr\xdf" +"fgywdfecqufccpcdn" +"faghjoq\x28abxnpxj" +"zuppgzcfb\"dctvp\"elup\"zxkopx" +"xqs\x45xxdqcihbwghmzoa" +"anbnlp\\cgcvm\"hc" +"xf\"fgrngwzys" +"nrxsjduedcy\x24" +"\x71sxl\"gj\"sds\"ulcruguz\\t\\ssvjcwhi" +"jhj\"msch" +"qpovolktfwyiuyicbfeeju\x01" +"nkyxmb\"qyqultgt\"nmvzvvnxnb" +"ycsrkbstgzqb\"uv\\cisn" +"s" +"ueptjnn\"\"sh" +"lp\"z\"d\"mxtxiy" +"yzjtvockdnvbubqabjourf\"k\"uoxwle" +"\x82\"wqm\"" +"\xb5cwtuks\x5fpgh" +"wd" +"tbvf" +"ttbmzdgn" +"vfpiyfdejyrlbgcdtwzbnm" +"uc" +"otdcmhpjagqix" +"\\\xb1qso\"s" +"scowax" +"behpstjdh\xccqlgnqjyz\"eesn" +"r\xe1cbnjwzveoomkzlo\\kxlfouhm" +"jgrl" +"kzqs\\r" +"ctscb\x7fthwkdyko\"\x62pkf\"d\xe6knmhurg" +"tc\"kw\x3ftt" +"bxb\x5ccl" +"jyrmfbphsldwpq" +"jylpvysl\"\"juducjg" +"en\\m\"kxpq\"wpb\\\"" +"madouht\"bmdwvnyqvpnawiphgac\"" +"vuxpk\"ltucrw" +"aae\x60arr" +"ttitnne\"kilkrgssnr\xfdurzh" +"oalw" +"pc\"\"gktkdykzbdpkwigucqni\"nxiqx" +"dbrsaj" +"bgzsowyxcbrvhtvekhsh\"qgd" +"kudfemvk\"\"\"hkbrbil\"chkqoa" +"zjzgj\\ekbhyfzufy" +"\\acos\"fqekuxqzxbmkbnn\x1ejzwrm" +"elxahvudn\"txtmomotgw" +"\x2eoxmwdhelpr\"cgi\xf7pzvb" +"eapheklx" +"hfvma\"mietvc\"tszbbm\"czex" +"h\"iiockj\\\xc1et" +"d\"rmjjftm" +"qlvhdcbqtyrhlc\\" +"yy\"rsucjtulm\"coryri\"eqjlbmk" +"tv" +"r\"bfuht\\jjgujp\"" +"kukxvuauamtdosngdjlkauylttaokaj" +"srgost\"\"rbkcqtlccu\x65ohjptstrjkzy" +"yxwxl\\yjilwwxffrjjuazmzjs" +"dxlw\\fkstu\"hjrtiafhyuoh\"sewabne" +"\x88sj\"v" +"rfzprz\xec\"oxqclu\"krzefp\\q" +"cfmhdbjuhrcymgxpylllyvpni" +"ucrmjvmimmcq\x88\xd9\"lz" +"lujtt\"" +"gvbqoixn\"pmledpjmo\"flydnwkfxllf" +"dvxqlbshhmelsk\x8big\"l" +"mx\x54lma\x8bbguxejg" +"\x66jdati\xeceieo" +"\"iyyupixei\x54ff" +"xohzf\"rbxsoksxamiu" +"vlhthspeshzbppa\x4drhqnohjop\"\"mfjd" +"f\"tvxxla\"vurian\"\"idjq\x3aptm\xc3olep" +"gzqz" +"kbq\\wogye\\altvi\\hbvmodny" +"j\xd8" +"ofjozdhkblvndl" +"hbitoupimbawimxlxqze" +"ypeleimnme" +"xfwdrzsc\\oxqamawyizvi\\y" +"enoikppx\xa1ixe\"yo\"gumye" +"fb" +"vzf" +"zxidr" +"cu\x31beirsywtskq" +"lxpjbvqzztafwezd" +"\\jyxeuo\x18bv" +"b\"vawc\"p\\\\giern\"b" +"odizunx\"\"t\\yicdn\"x\"sdiz" +"\"\"tebrtsi" +"ctyzsxv\xa6pegfkwsi\"tgyltaakytccb" +"htxwbofchvmzbppycccliyik\xe5a" +"ggsslefamsklezqkrd" +"rcep\"fnimwvvdx\"l" +"zyrzlqmd\x12egvqs\\llqyie" +"\x07gsqyrr\\rcyhyspsvn" +"butg\"" +"gb" +"gywkoxf\"jsg\\wtopxvumirqxlwz" +"rj\"ir\"wldwveair\x2es\"dhjrdehbqnzl" +"ru\"elktnsbxufk\\ejufjfjlevt\\lrzd" +"\"widsvok" +"oy\"\x81nuesvw" +"ay" +"syticfac\x1cfjsivwlmy\"pumsqlqqzx" +"m" +"rjjkfh\x78cf\x2brgceg\"jmdyas\"\\xlv\xb6p" +"tmuvo\"\x3ffdqdovjmdmkgpstotojkv\"as" +"jd\\ojvynhxllfzzxvbn\"wrpphcvx" +"pz" +"\"twr" +"n\\hdzmxe\"mzjjeadlz" +"fb\"rprxuagvahjnri" +"rfmexmjjgh\\xrnmyvnatrvfruflaqjnd" +"obbbde\"co\"qr\"qpiwjgqahqm\\jjp\"" +"vpbq\"\"y\"czk\\b\x52ed\"lnzepobp" +"syzeajzfarplydipny\"y\"\xe8ad" +"mpyodwb" +"\x47rakphlqqptd" +"wa\"oj\"aiy" +"a" +"ropozx" +"q\x51nbtlwa" +"etukvgx\\jqxlkq" +"\"tp\"rah\"pg\"s\"bpdtes\\tkasdhqd" +"dn\"qqpkikadowssb\xcah\"dzpsf\\ect\"jdh" +"pxunovbbrrn\\vullyn\"bno\"\"\"myfxlp\"" +"qaixyazuryvkmoulhcqaotegfj\\mpzm" +"bvfrbicutzbjwn\\oml\"cf\"d\"ezcpv\"j" +"rmbrdtneudemigdhelmb" +"aq\\aurmbhy" +"wujqvzw" +"gf\"tssmvm\"gm\"hu\x9a\xb7yjawsa" +"hrhqqxow\xe2gsydtdspcfqy\"zw\\ou" +"ianwwf\\yko\\tdujhhqdi" +"xylz\"zpvpab" +"lwuopbeeegp" +"aoop\x49jhhcexdmdtun" +"\\\\mouqqcsgmz" +"tltuvwhveau\x43b\"ymxjlcgiymcynwt" +"gsugerumpyuhtjljbhrdyoj" +"lnjm\xb8wg\"ajh" +"zmspue\"nfttdon\\b\"eww" +"\"w\x67jwaq\x7ernmyvs\\rmdsuwydsd\"th" +"ogtgvtlmcvgllyv" +"z\"fqi\"rvddoehrciyl" +"yustxxtot\"muec\"xvfdbzunzvveq" +"mqslw" +"txqnyvzmibqgjs\xb6xy\x86nfalfyx" +"kzhehlmkholov" +"plpmywcnirrjutjguosh\\" +"pydbnqofv\"dn\\m" +"aegqof" +"eambmxt\\dxagoogl\\zapfwwlmk" +"afbmqitxxqhddlozuxcpjxgh" +"vgts" +"bfdpqtoxzzhmzcilehnflna" +"s\"idpz" +"\xcfhgly\"nlmztwybx\"ecezmsxaqw" +"aackfgndqcqiy" +"\x22unqdlsrvgzfaohoffgxzfpir\"s" +"abh\"ydv\"kbpdhrerl" +"bdzpg" +"ekwgkywtmzp" +"wtoodejqmrrgslhvnk\"pi\"ldnogpth" +"njro\x68qgbx\xe4af\"\\suan" diff --git a/src/Year_2016/P8.py b/src/Year_2016/P8.py new file mode 100644 index 0000000..c47b794 --- /dev/null +++ b/src/Year_2016/P8.py @@ -0,0 +1,133 @@ +# --- Day 8: Two-Factor Authentication --- + +# You come across a door implementing what you can only assume is an +# implementation of two-factor authentication after a long game of +# requirements telephone. + +# To get past the door, you first swipe a keycard (no problem; there was one on +# a nearby desk). Then, it displays a code on a little screen, and you type +# that code on a keypad. Then, presumably, the door unlocks. + +# Unfortunately, the screen has been smashed. After a few minutes, you've taken +# everything apart and figured out how it works. Now you just have to work out +# what the screen would have displayed. + +# The magnetic strip on the card you swiped encodes a series of instructions +# for the screen; these instructions are your puzzle input. The screen is 50 +# pixels wide and 6 pixels tall, all of which start off, and is capable of +# three somewhat peculiar operations: + +# rect AxB turns on all of the pixels in a rectangle at the top-left of the +# screen which is A wide and B tall. +# rotate row y=A by B shifts all of the pixels in row A (0 is the top row) +# right by B pixels. Pixels that would fall off the right end appear at the +# left end of the row. +# rotate column x=A by B shifts all of the pixels in column A (0 is the +# left column) down by B pixels. Pixels that would fall off the bottom appear +# at the top of the column. + +# For example, here is a simple sequence on a smaller screen: + +# rect 3x2 creates a small rectangle in the top-left corner: + +# ###.... +# ###.... +# ....... + +# rotate column x=1 by 1 rotates the second column down by one pixel: + +# #.#.... +# ###.... +# .#..... + +# rotate row y=0 by 4 rotates the top row right by four pixels: + +# ....#.# +# ###.... +# .#..... + +# rotate column x=1 by 1 again rotates the second column down by one pixel, +# causing the bottom pixel to wrap back to the top: + +# .#..#.# +# #.#.... +# .#..... + +# As you can see, this display technology is extremely powerful, and will soon +# dominate the tiny-code-displaying-screen market. That's what the +# advertisement on the back of the display tries to convince you, anyway. + +# There seems to be an intermediate check of the voltage used by the display: +# after you swipe your card, if the screen did work, how many pixels should be +# lit? + +import numpy as np +import numpy.typing as npt + +with open("files/P8.txt") as f: + instructions = [line for line in f.read().strip().split("\n")] + + +def rect(instruction: str, grid: npt.NDArray[int]) -> npt.NDArray[int]: + _, row = instruction.split("x") + _, col = _.split() + grid[: int(row), : int(col)] = 1 + + +def rotate_column( + instruction: str, grid: npt.NDArray[int] +) -> npt.NDArray[int]: + _, cols = instruction.split("=") + x, _, steps = cols.split() + new_col = np.roll(grid[:, int(x) : int(x) + 1], int(steps), axis=0) + grid[:, int(x) : int(x) + 1] = new_col + + +def rotate_row(instruction: str, grid: npt.NDArray[int]) -> npt.NDArray[int]: + _, rows = instruction.split("=") + y, _, steps = rows.split() + new_row = np.roll(grid[int(y) : int(y) + 1, :], int(steps), axis=1) + grid[int(y) : int(y) + 1, :] = new_row + + +# dimensions given by the problem +init_grid = np.zeros((6, 50), dtype=int) + + +def part_1() -> None: + + for instruction in instructions: + if instruction.startswith("rect"): + rect(instruction, init_grid) + elif instruction.startswith("rotate row"): + rotate_row(instruction, init_grid) + elif instruction.startswith("rotate column"): + rotate_column(instruction, init_grid) + + lit = np.sum(init_grid) + + print(f"There should be {lit} pixels lit") + + +# --- Part Two --- + +# You notice that the screen is only capable of displaying capital letters; in +# the font it uses, each letter is 5 pixels wide and 6 tall. + +# After you swipe your card, what code is the screen trying to display? + + +def display(grid: npt.NDArray[int]) -> None: + print( + "\n".join("".join("X" if one else " " for one in row) for row in grid) + ) + + +def part_2() -> None: + print("The code is the following:\n") + display(init_grid) + + +if __name__ == "__main__": + part_1() + part_2() diff --git a/src/Year_2016/files/P8.txt b/src/Year_2016/files/P8.txt new file mode 100644 index 0000000..5603dd8 --- /dev/null +++ b/src/Year_2016/files/P8.txt @@ -0,0 +1,173 @@ +rect 1x1 +rotate row y=0 by 20 +rect 1x1 +rotate row y=0 by 2 +rect 1x1 +rotate row y=0 by 3 +rect 2x1 +rotate row y=0 by 2 +rect 1x1 +rotate row y=0 by 3 +rect 2x1 +rotate row y=0 by 2 +rect 1x1 +rotate row y=0 by 4 +rect 2x1 +rotate row y=0 by 2 +rect 1x1 +rotate row y=0 by 2 +rect 1x1 +rotate row y=0 by 2 +rect 1x1 +rotate row y=0 by 3 +rect 2x1 +rotate row y=0 by 2 +rect 1x1 +rotate row y=0 by 5 +rect 1x1 +rotate row y=0 by 2 +rect 1x1 +rotate row y=0 by 6 +rect 5x1 +rotate row y=0 by 2 +rect 1x3 +rotate row y=2 by 8 +rotate row y=0 by 8 +rotate column x=0 by 1 +rect 7x1 +rotate row y=2 by 24 +rotate row y=0 by 20 +rotate column x=5 by 1 +rotate column x=4 by 2 +rotate column x=2 by 2 +rotate column x=0 by 1 +rect 7x1 +rotate column x=34 by 2 +rotate column x=22 by 1 +rotate column x=15 by 1 +rotate row y=2 by 18 +rotate row y=0 by 12 +rotate column x=8 by 2 +rotate column x=7 by 1 +rotate column x=5 by 2 +rotate column x=2 by 1 +rotate column x=0 by 1 +rect 9x1 +rotate row y=3 by 28 +rotate row y=1 by 28 +rotate row y=0 by 20 +rotate column x=18 by 1 +rotate column x=15 by 1 +rotate column x=14 by 1 +rotate column x=13 by 1 +rotate column x=12 by 2 +rotate column x=10 by 3 +rotate column x=8 by 1 +rotate column x=7 by 2 +rotate column x=6 by 1 +rotate column x=5 by 1 +rotate column x=3 by 1 +rotate column x=2 by 2 +rotate column x=0 by 1 +rect 19x1 +rotate column x=34 by 2 +rotate column x=24 by 1 +rotate column x=23 by 1 +rotate column x=14 by 1 +rotate column x=9 by 2 +rotate column x=4 by 2 +rotate row y=3 by 5 +rotate row y=2 by 3 +rotate row y=1 by 7 +rotate row y=0 by 5 +rotate column x=0 by 2 +rect 3x2 +rotate column x=16 by 2 +rotate row y=3 by 27 +rotate row y=2 by 5 +rotate row y=0 by 20 +rotate column x=8 by 2 +rotate column x=7 by 1 +rotate column x=5 by 1 +rotate column x=3 by 3 +rotate column x=2 by 1 +rotate column x=1 by 2 +rotate column x=0 by 1 +rect 9x1 +rotate row y=4 by 42 +rotate row y=3 by 40 +rotate row y=1 by 30 +rotate row y=0 by 40 +rotate column x=37 by 2 +rotate column x=36 by 3 +rotate column x=35 by 1 +rotate column x=33 by 1 +rotate column x=32 by 1 +rotate column x=31 by 3 +rotate column x=30 by 1 +rotate column x=28 by 1 +rotate column x=27 by 1 +rotate column x=25 by 1 +rotate column x=23 by 3 +rotate column x=22 by 1 +rotate column x=21 by 1 +rotate column x=20 by 1 +rotate column x=18 by 1 +rotate column x=17 by 1 +rotate column x=16 by 3 +rotate column x=15 by 1 +rotate column x=13 by 1 +rotate column x=12 by 1 +rotate column x=11 by 2 +rotate column x=10 by 1 +rotate column x=8 by 1 +rotate column x=7 by 2 +rotate column x=5 by 1 +rotate column x=3 by 3 +rotate column x=2 by 1 +rotate column x=1 by 1 +rotate column x=0 by 1 +rect 39x1 +rotate column x=44 by 2 +rotate column x=42 by 2 +rotate column x=35 by 5 +rotate column x=34 by 2 +rotate column x=32 by 2 +rotate column x=29 by 2 +rotate column x=25 by 5 +rotate column x=24 by 2 +rotate column x=19 by 2 +rotate column x=15 by 4 +rotate column x=14 by 2 +rotate column x=12 by 3 +rotate column x=9 by 2 +rotate column x=5 by 5 +rotate column x=4 by 2 +rotate row y=5 by 5 +rotate row y=4 by 38 +rotate row y=3 by 10 +rotate row y=2 by 46 +rotate row y=1 by 10 +rotate column x=48 by 4 +rotate column x=47 by 3 +rotate column x=46 by 3 +rotate column x=45 by 1 +rotate column x=43 by 1 +rotate column x=37 by 5 +rotate column x=36 by 5 +rotate column x=35 by 4 +rotate column x=33 by 1 +rotate column x=32 by 5 +rotate column x=31 by 5 +rotate column x=28 by 5 +rotate column x=27 by 5 +rotate column x=26 by 3 +rotate column x=25 by 4 +rotate column x=23 by 1 +rotate column x=17 by 5 +rotate column x=16 by 5 +rotate column x=13 by 1 +rotate column x=12 by 5 +rotate column x=11 by 5 +rotate column x=3 by 1 +rotate column x=0 by 1 diff --git a/src/Year_2017/P7.py b/src/Year_2017/P7.py index ed9b235..535de35 100644 --- a/src/Year_2017/P7.py +++ b/src/Year_2017/P7.py @@ -88,5 +88,78 @@ def part_1() -> None: print(f"The name of the bottom program is {root_program}") +# --- Part Two --- + +# The programs explain the situation: they can't get down. Rather, they could +# get down, if they weren't expending all of their energy trying to keep the +# tower balanced. Apparently, one program has the wrong weight, and until it's +# fixed, they're stuck here. + +# For any program holding a disc, each program standing on that disc forms a +# sub-tower. Each of those sub-towers are supposed to be the same weight, or +# the disc itself isn't balanced. The weight of a tower is the sum of the +# weights of the programs in that tower. + +# In the example above, this means that for ugml's disc to be balanced, gyxo, +# ebii, and jptl must all have the same weight, and they do: 61. + +# However, for tknk to be balanced, each of the programs standing on its disc +# and all programs above it must each match. This means that the following sums +# must all be the same: + +# ugml + (gyxo + ebii + jptl) = 68 + (61 + 61 + 61) = 251 +# padx + (pbga + havc + qoyq) = 45 + (66 + 66 + 66) = 243 +# fwft + (ktlj + cntj + xhth) = 72 + (57 + 57 + 57) = 243 + +# As you can see, tknk's disc is unbalanced: ugml's stack is heavier than the +# other two. Even though the nodes above ugml are balanced, ugml itself is too +# heavy: it needs to be 8 units lighter for its stack to weigh 243 and keep the +# towers balanced. If this change were made, its weight would be 60. + +# Given that exactly one program is the wrong weight, what would its weight +# need to be to balance the entire tower? + + +def child_values(node, node_map, node_values): + weights, unbalanced = [], [] + children = node_map[node] + for child in children: + if child in node_map.keys(): + child_weight, child_balance = child_values( + child, node_map, node_values + ) + value = sum(child_weight) + node_values[child] + unbalanced.append(child_balance) + else: + value = node_values[child] + weights.append(value) + if len(set(weights)) != 1: + unbalanced.append((node_map[node], weights)) + return weights, unbalanced + + +def part_2() -> None: + node_map, node_values = {}, {} + for line in towers: + if "->" in line: + lhs, rhs = line.split(" -> ") + parent, value = lhs.split() + node_values[parent] = int(value[1:-1]) + _childs = rhs.split(", ") + node_map[parent] = [child for child in _childs] + else: + child, value = line.split() + node_values[child] = int(value[1:-1]) + + _, unbalance = child_values("rqwgj", node_map, node_values) + + heavier_child_idx = unbalance[0][0][5][1].index(max(unbalance[0][0][5][1])) + heavier_child = unbalance[0][0][5][0][heavier_child_idx] + unbalanced_child = node_values[heavier_child] + + print(f"To balance the tower, the weight must be {unbalanced_child - 8}") + + if __name__ == "__main__": part_1() + part_2() diff --git a/src/Year_2021/P7.py b/src/Year_2021/P7.py new file mode 100644 index 0000000..6d3b186 --- /dev/null +++ b/src/Year_2021/P7.py @@ -0,0 +1,117 @@ +# --- Day 7: The Treachery of Whales --- + +# A giant whale has decided your submarine is its next meal, and it's much +# faster than you are. There's nowhere to run! + +# Suddenly, a swarm of crabs (each in its own tiny submarine - it's too deep +# for them otherwise) zooms in to rescue you! They seem to be preparing to +# blast a hole in the ocean floor; sensors indicate a massive underground cave +# system just beyond where they're aiming! + +# The crab submarines all need to be aligned before they'll have enough power +# to blast a large enough hole for your submarine to get through. However, it +# doesn't look like they'll be aligned before the whale catches you! Maybe you +# can help? + +# There's one major catch - crab submarines can only move horizontally. + +# You quickly make a list of the horizontal position of each crab (your puzzle +# input). Crab submarines have limited fuel, so you need to find a way to make +# all of their horizontal positions match while requiring them to spend as +# little fuel as possible. + +# For example, consider the following horizontal positions: + +# 16,1,2,0,4,2,7,1,2,14 + +# This means there's a crab with horizontal position 16, a crab with horizontal +# position 1, and so on. + +# Each change of 1 step in horizontal position of a single crab costs 1 fuel. +# You could choose any horizontal position to align them all on, but the one +# that costs the least fuel is horizontal position 2: + +# Move from 16 to 2: 14 fuel +# Move from 1 to 2: 1 fuel +# Move from 2 to 2: 0 fuel +# Move from 0 to 2: 2 fuel +# Move from 4 to 2: 2 fuel +# Move from 2 to 2: 0 fuel +# Move from 7 to 2: 5 fuel +# Move from 1 to 2: 1 fuel +# Move from 2 to 2: 0 fuel +# Move from 14 to 2: 12 fuel + +# This costs a total of 37 fuel. This is the cheapest possible outcome; more +# expensive outcomes include aligning at position 1 (41 fuel), position 3 (39 +# fuel), or position 10 (71 fuel). + +# Determine the horizontal position that the crabs can align to using the least +# fuel possible. How much fuel must they spend to align to that position? + +with open("files/P7.txt") as f: + positions = [int(num) for num in f.read().strip().split(",")] + + +def part_1() -> None: + fuel = [] + for pos in positions: + sum = 0 + for elem in positions: + sum += abs(elem - pos) + fuel.append(sum) + + print(f"It is needed {min(fuel)} units of fuel") + + +# --- Part Two --- + +# The crabs don't seem interested in your proposed solution. Perhaps you +# misunderstand crab engineering? + +# As it turns out, crab submarine engines don't burn fuel at a constant rate. +# Instead, each change of 1 step in horizontal position costs 1 more unit of +# fuel than the last: the first step costs 1, the second step costs 2, the +# third step costs 3, and so on. + +# As each crab moves, moving further becomes more expensive. This changes the +# best horizontal position to align them all on; in the example above, this +# becomes 5: + +# Move from 16 to 5: 66 fuel +# Move from 1 to 5: 10 fuel +# Move from 2 to 5: 6 fuel +# Move from 0 to 5: 15 fuel +# Move from 4 to 5: 1 fuel +# Move from 2 to 5: 6 fuel +# Move from 7 to 5: 3 fuel +# Move from 1 to 5: 10 fuel +# Move from 2 to 5: 6 fuel +# Move from 14 to 5: 45 fuel + +# This costs a total of 168 fuel. This is the new cheapest possible outcome; +# the old alignment position (2) now costs 206 fuel instead. + +# Determine the horizontal position that the crabs can align to using the least +# fuel possible so they can make you an escape route! How much fuel must they +# spend to align to that position? + +# TIL :D +def triangular_cost(steps: int) -> int: + return steps * (steps + 1) // 2 + + +def part_2() -> None: + fuel = [] + for pos in positions: + sum = 0 + for elem in positions: + sum += triangular_cost(abs(elem - pos)) + fuel.append(sum) + + print(f"It is needed {min(fuel)} units of fuel") + + +if __name__ == "__main__": + part_1() + part_2() diff --git a/src/Year_2021/files/P7.txt b/src/Year_2021/files/P7.txt new file mode 100644 index 0000000..152bc07 --- /dev/null +++ b/src/Year_2021/files/P7.txt @@ -0,0 +1 @@ +1101,1,29,67,1102,0,1,65,1008,65,35,66,1005,66,28,1,67,65,20,4,0,1001,65,1,65,1106,0,8,99,35,67,101,99,105,32,110,39,101,115,116,32,112,97,115,32,117,110,101,32,105,110,116,99,111,100,101,32,112,114,111,103,114,97,109,10,20,1091,861,228,628,186,980,996,710,541,354,1611,69,1331,91,1220,447,523,38,1286,244,643,1069,566,70,155,1710,1266,120,302,72,232,387,1086,278,1122,605,1559,98,111,1816,795,543,1217,304,356,129,839,704,49,523,370,74,13,232,179,101,664,892,266,622,197,404,147,882,435,504,48,766,684,1362,136,830,1393,1259,925,68,879,251,43,1339,61,98,403,51,1008,197,659,195,1823,233,121,731,82,141,580,18,427,774,13,685,496,752,63,132,39,237,18,167,51,299,22,19,1442,305,1283,253,159,731,302,76,115,185,136,447,821,307,207,30,1427,251,589,0,1096,1240,261,442,757,5,172,847,858,382,425,79,402,166,1058,186,35,21,324,183,1293,95,410,321,12,155,88,409,40,428,1180,199,1444,487,148,57,1187,15,100,983,77,0,1667,359,513,659,339,142,968,994,787,0,443,183,133,538,4,332,1459,204,1156,710,1654,20,36,407,890,1265,1090,743,36,78,1033,781,608,476,103,1401,24,4,875,414,799,305,1047,842,72,497,362,270,73,12,9,0,21,11,51,1357,455,505,483,552,199,1108,214,238,686,1496,116,154,1403,35,272,738,1024,50,50,934,564,19,395,324,447,794,1326,14,407,1694,452,439,455,442,86,1515,588,809,224,112,156,21,1405,610,187,23,370,112,397,995,777,75,1281,32,60,284,388,916,555,200,675,20,320,32,398,104,113,447,113,351,396,322,36,1674,1708,232,1004,514,95,859,382,116,277,239,343,3,433,11,55,699,513,1465,319,44,306,224,615,482,695,421,300,321,283,579,323,102,275,17,723,632,713,277,801,222,130,189,1549,49,784,690,136,444,1315,259,1334,472,711,1109,276,70,315,838,35,328,766,1100,460,4,178,630,571,5,106,429,368,547,1210,840,162,166,10,403,880,287,44,1001,316,402,1054,174,7,1194,105,58,268,667,86,588,166,547,238,1586,77,112,244,107,63,873,1152,16,407,198,26,587,20,1449,775,653,1369,732,262,566,222,10,102,22,573,233,297,1238,789,291,93,206,1274,177,58,841,672,37,16,262,201,241,938,133,774,978,631,511,0,263,498,799,51,330,11,206,325,173,676,15,457,364,46,373,34,1475,530,672,295,55,4,297,274,1519,15,688,555,96,160,185,583,646,41,378,1572,67,219,572,143,16,286,65,788,886,243,883,1012,109,90,742,464,1099,388,1855,731,62,6,415,66,232,542,98,1123,11,414,1262,4,440,8,691,130,164,773,992,423,115,1807,1618,153,168,1213,719,291,316,311,110,24,608,0,127,131,142,196,232,75,248,412,275,1295,239,86,967,133,422,415,894,280,807,345,446,250,979,231,713,201,1009,208,444,43,1400,434,8,221,141,235,909,1018,340,0,178,1144,353,662,491,294,6,440,446,824,1392,379,269,1427,911,671,231,424,102,718,86,54,130,206,514,137,1075,1573,248,472,602,249,974,8,372,59,2,940,165,1132,327,1424,63,6,97,140,1302,439,1237,59,324,733,397,477,426,278,274,1636,745,41,269,257,51,173,503,88,1223,754,228,584,72,632,645,323,156,7,337,192,375,583,613,370,172,528,1282,360,208,17,208,802,22,67,290,242,458,809,6,1388,49,14,327,911,121,475,101,617,284,91,1,35,421,293,1419,602,143,142,168,657,472,219,345,411,115,387,5,494,383,348,85,1070,154,42,63,586,953,563,12,1263,788,762,222,351,730,42,643,877,522,775,698,564,604,155,191,430,5,386,787,120,470,433,564,955,411,1090,210,1096,933,109,70,279,287,736,390,1075,30,194,30,1318,473,727,100,584,1227,89,432,120,393,1080,185,500,847,117,319,54,160,32,114,700,12,36,681,53,1063,113,82,1625,1426,53,658,80,253,36,16,810,560,602,177,275,147,335,1237,1447,176,55,366,721,471,501,217,67,899,914,168,981,1177,898,1,9,704,602,787,1280,305,57,786,1696,211,63,55,351,14,151,932,757,810,1748,169,1018,125,849,234,102,823,300,127,6,849,1163,229,726,397,656,135,466,137,1247,811,807,366,209,1703,24,1219,45,161,353,274,572,397,899,646,32,137,439,1048,2,391,8,214,736,518,409,414,567,1262,155,102,178,1247,526,10,94,759,781,18,14,1518,68,295,905,478,1581,89,429,937,438,915,1110,659,615,1128,8,125,89,289,1084,905,254,1227,184,883,983,110,1,24,748,1408,828,1187,63,264,481,214