diff --git a/www/statics/aoc/2020/21_challenge.txt b/www/statics/aoc/2020/21_challenge.txt new file mode 100644 index 0000000..dff1523 --- /dev/null +++ b/www/statics/aoc/2020/21_challenge.txt @@ -0,0 +1,34 @@ +You reach the train's last stop and the closest you can get to your vacation island without getting wet. There aren't even any boats here, but nothing can stop you now: you build a raft. You just need a few days' worth of food for your journey. + +You don't speak the local language, so you can't read any ingredients lists. However, sometimes, allergens are listed in a language you do understand. You should be able to use this information to determine which ingredient contains which allergen and work out which foods are safe to take with you on your trip. + +You start by compiling a list of foods (your puzzle input), one food per line. Each line includes that food's ingredients list followed by some or all of the allergens the food contains. + +Each allergen is found in exactly one ingredient. Each ingredient contains zero or one allergen. Allergens aren't always marked; when they're listed (as in (contains nuts, shellfish) after an ingredients list), the ingredient that contains each listed allergen will be somewhere in the corresponding ingredients list. However, even if an allergen isn't listed, the ingredient that contains that allergen could still be present: maybe they forgot to label it, or maybe it was labeled in a language you don't know. + +For example, consider the following list of foods: + +mxmxvkd kfcds sqjhc nhms (contains dairy, fish) +trh fvjkl sbzzf mxmxvkd (contains dairy) +sqjhc fvjkl (contains soy) +sqjhc mxmxvkd sbzzf (contains fish) + +The first food in the list has four ingredients (written in a language you don't understand): mxmxvkd, kfcds, sqjhc, and nhms. While the food might contain other allergens, a few allergens the food definitely contains are listed afterward: dairy and fish. + +The first step is to determine which ingredients can't possibly contain any of the allergens in any food in your list. In the above example, none of the ingredients kfcds, nhms, sbzzf, or trh can contain an allergen. Counting the number of times any of these ingredients appear in any ingredients list produces 5: they all appear once each except sbzzf, which appears twice. + +Determine which ingredients cannot possibly contain any of the allergens in your list. How many times do any of those ingredients appear? + +--- Part Two --- + +Now that you've isolated the inert ingredients, you should have enough information to figure out which ingredient contains which allergen. + +In the above example: + + mxmxvkd contains dairy. + sqjhc contains fish. + fvjkl contains soy. + +Arrange the ingredients alphabetically by their allergen and separate them by commas to produce your canonical dangerous ingredient list. (There should not be any spaces in your canonical dangerous ingredient list.) In the above example, this would be mxmxvkd,sqjhc,fvjkl. + +Time to stock your raft with supplies. What is your canonical dangerous ingredient list? diff --git a/www/statics/aoc/2020/21_input.txt b/www/statics/aoc/2020/21_input.txt new file mode 100644 index 0000000..0895b73 --- /dev/null +++ b/www/statics/aoc/2020/21_input.txt @@ -0,0 +1,35 @@ +jfvltdz txzv szzbr fcbsv klzdr xclff jqqbnzz flzmlbf crfxz jxrlzm xcfpc tvk kdbx zlhlq gfpnx ccvsl zfl skllln lxqbsc frgnkt mrnd smjhxg cmqjlb jxdbh tsbffm mtjlb czbhh gbbxhp snsnj lmvx pbztj glvv jkzxn nnfps hnvrfvm fddx nhhgb hdt jg hrnzq tmgfr vjcbtd nklc fmbqgs hcg gpgrb qrgvj znqbr pfdkkzp vmrf mbqpfm pccmj bph hmngm fcbvh vtqhqs zsjlp rdbdd gtjmd bskstb krxj rglbcpq svqz jczm frssvh nmxdsnc hjbs xkpm tsvfrt txr flmm tjrm jccqsxs bncfz vlpq ngl dvfqqz hqxdv xzrdx qdnh hbqhvk spbxz pnxzqgp kjcdgh ttmcq dlvdt (contains peanuts) +bjqt frgnkt ctbmdg hbqhvk skllln spbxz frssvh rdbdd gpgrb nndr dvfqqz jlnrn tsvfrt jccqsxs jkzxn znqbr vlpq hcg gtjmd lmvx zck jnd vghkr fmfnh rlsqd vjcbtd kbszttf mdsg pfdkkzp stnb tjlz bqc gfpnx mfvxhv pdss tzglth mtpfk cnhbh thprs kvcc hnvrfvm klzdr xcfpc kdxvzqm (contains peanuts) +pngs tjlz nmxdsnc qdnh pccmj mkz rdbdd mbqpfm ngl znqbr tzglth tlbj klzdr pgrc fddx mxmvt srxrn gtjmd vdgsz dxzzp zfsmv svcmg mzjvq txr jkzxn smjhxg dptl flmm xlcgr srpqk kdbx bctn hnvrfvm qkvrf kvcc qzqdq krdmn vlpq tmjltg kdxvzqm hdt thprs pfdkkzp nklc cmqjlb jrrgck gpgrb mdnchc gzngn qrgvj pznt pdss zjh crfxz krxj xcfpc svrvv ctbmdg spbxz (contains shellfish) +xcfpc zfl cnhbh mdx tjlz pnxzqgp drzm glljh xsndjl hrnzq pdss zck kjcdgh pgrc bph gtjmd xmcsr ctgnz kbszttf gpgrb spbxz vtqhqs snsnj brjd znqbr mbqpfm crfxz blbfl rjds gdsk kdxvzqm mdnnfp mrnd mzjvq flzmlbf pznt pggzp txr vxx bncfz lzfmghs krxj pfdkkzp rtjxbbd (contains dairy, shellfish, fish) +mdx glcfml jqkxx jccqsxs kvcc nndr kbszttf mfvxhv rjds tjrm spbxz gtjmd vtqhqs fmbqgs dxzzp snptbf hrnzq rtjxbbd tmgfr sckhr hsdnz xkpm txzv fgrmrqhp gxbs gfpnx mdnnfp kbtkrcf drzm tbptvzf dtqplpj vxx cmtq zsjlp gpgrb glvv qrgvj tmjltg hnvrfvm pbztj czbhh tvk cnhbh krdmn flzmlbf lblbm mrnd znqbr kdbx xcfpc nhhgb mdsg zck txr stnb hdt hjbs pfdkkzp skks klh zfl (contains dairy) +skllln tvk srxrn snptbf cnhbh gbbxhp jczm spbxz pznt kbtkrcf fmbqgs tjlz frssvh pmhxl znqbr mtpfk fcbvh rdbdd xpmmdc vjcbtd cmqjlb jqqbnzz nnfps lblbm kdxvzqm qzqdq bjqt txzv qrgvj tmjltg mxfrnq hbqhvk gtjmd jlnrn kvcc hsdnz dfllfp mfvxhv mfcrq tgclx xlcgr glvv czbhh tsbffm hmnt xcfpc mkz cmtq gpgrb (contains soy) +gtjmd zbj vdgsz stnb tsbffm tjlz pdss jqqbnzz nklc srxrn klh glljh ctbmdg dptl jczm pfdkkzp jfvltdz nhhgb glvv jccqsxs hsdnz bskstb brjd ctgnz rjds tjrm qrgvj zck spbxz zfl xbp mfcrq svrvv zsjlp bqc pbztj xsndjl bctn lblbm fmfnh kdxvzqm cdntx hjbs gnkr rtjxbbd hdt hcg vjcbtd hmnt skqbbj frgnkt znqbr klzdr tmjltg nndr hsdqb tgclx txzv hnnz mdx pngs jg snptbf czbhh cnhbh jrrgck jlnrn gpgrb mfvxhv mdnnfp sckhr pccmj gfpnx dxzzp tbptvzf (contains peanuts, soy, dairy) +nkshjm pgmqs znqbr cdntx hsdnz kdxvzqm pmhxl tjlz nndr lzczv mtjlb jqkxx bjrbknjm pbztj nmpp mkz tbptvzf krxj bctn ctgnz qlzxbc hbqhvk mbqpfm dvfqqz gtjmd mfvxhv gdsk snptbf cmqjlb gpgrb jfvltdz vlpq zjh pggzp xkpm xpmmdc tgclx bqc spbxz kjcdgh lflzqr glvv stnb tjrm txzv qzqdq hjbs ccvsl jxdbh xcfpc bncfz flmm blbfl zbj rglbcpq srpqk tsvfrt fcbsv rtjxbbd bph tsbffm smjhxg tmjltg (contains shellfish) +snsnj tmjltg lxqbsc czbhh txzv svqz krdmn tjlz jg bnrf nmxdsnc ndhx zck zjh skks rdbdd bnnt srpqk svrvv spbxz pdss cmqjlb vmrf crfxz gpgrb jdvtlsv sgh mkz pznt tgclx kdxvzqm jfvltdz ccvsl jlnrn gdsk pfdkkzp flzmlbf xcfpc jqkxx dptl hrnzq vghkr tmgfr glvv mfvxhv gtjmd fgrmrqhp mdnnfp klh glljh kdbx lzczv klzdr (contains nuts, fish) +znqbr tsvfrt bjrbknjm kbtkrcf hsxp xsndjl jqkxx mrnd tjlz klzdr krxj gnzr nhhgb hqxdv mggk hsdqb zfl svqz hmngm ctbmdg tbptvzf bctn mdx gfpnx bskstb blbfl thprs sckhr lzfmghs rdbdd gbbxhp rglbcpq lmvx jkzxn lblbm bncfz ctgnz tjrm tlbj sndrzm tsbffm hdt spbxz jfvltdz gpgrb hrkf txzv ccvsl mtpfk vlpq pgmqs ttmcq pfdkkzp ndhx mdsg skllln xcfpc bph bdj (contains nuts, shellfish) +vdgsz srpqk jccqsxs txzv gtjmd xzrdx jdvtlsv hcg hjbs tsbffm vlpq bctn fmbqgs krdmn crfxz gpgrb zjh skllln bjqt kdxvzqm mdnchc zfl svrvv zlhlq tzglth ccvsl frgnkt xpmmdc rtjxbbd dptl dlvdt kdbx xclff gbbxhp lxqbsc vmrf lmvx smjhxg skqbbj nndr jnd rlsqd xmcsr pfdkkzp hmnt jfvltdz gnzr znqbr ctbmdg svcmg flzmlbf tjlz tbptvzf bncfz vxx tmjltg xcfpc qlzxbc klh jg xbp mrnd pgrc qkvrf qdnh qzqdq vghkr zfsmv fddx dkzz fcbsv mggk (contains shellfish, soy, eggs) +krxj kbszttf hnvrfvm mkz fjsgm nkshjm tjlz mfvxhv pccmj gnzr txzv flmm czbhh bnrf jccqsxs cnhbh gtjmd klh jg skllln hdt jrrgck nndr vtqhqs hrnzq dtqplpj blbfl glljh snptbf fddx spbxz pnxzqgp bjqt gnkr svqz dptl bncfz lhqxr pfdkkzp zsjlp srpqk dlvdt xcfpc dvfqqz zfl lmvx mzjvq thprs pngs sgh tmjltg tbptvzf vxx nmpp jdvtlsv hrkf rlsqd xzrdx mrnd skqbbj xclff szzbr srxrn vlpq nmxdsnc qkvrf hcg mfcrq fcbvh kbtkrcf mxmvt hjbs jfvltdz gpgrb (contains soy, shellfish) +bnrf jrrgck xcfpc kdxvzqm lmvx xzrdx pfdkkzp crfxz gtjmd krxj qkvrf kdbx jdvtlsv mdnchc mbqpfm jfvltdz txzv vghkr jqkxx jxrlzm klzdr bnnt xpmmdc tsvfrt fcbvh xbp tlbj rglbcpq hdt vdgsz spbxz dxzzp hsdnz jg fgrmrqhp tmjltg jxdbh gjt mggk svrvv zbj mxmvt bncfz hsdqb qdnh hbqhvk kbszttf jkzxn dvfqqz tsbffm mrnd jnd hsxp zck tjlz gpgrb (contains nuts, soy, dairy) +lmvx qzqdq mtpfk dkzz zck frssvh pbztj qlzxbc pccmj sckhr zfl dptl fddx mrnd gdsk mdnnfp hnvrfvm jfvltdz mtjlb lblbm spbxz hsdqb zbj krdmn lzfmghs pfdkkzp gzngn flmm hrnzq jqkxx znqbr jrrgck jkzxn svcs xcfpc mdsg fjsgm frgnkt rdbdd klh cmqjlb hrkf mxmvt hdt tzglth glcfml hbqhvk mkz bncfz pdss gtjmd jczm nrdv tjrm svrvv flzmlbf txzv pmhxl tjlz dvfqqz (contains peanuts, soy, nuts) +mfvxhv pfdkkzp nrdv xcfpc znqbr zck gjt snsnj lmvx nhhgb fgrmrqhp bdj bnrf hrnzq lhqxr kdbx spbxz zfl glvv gpgrb vmrf hnvrfvm pccmj bqc fjsgm jnd xpmmdc hmnt bjqt mrnd jczm fcbvh tjlz hjbs frssvh gnkr pgmqs lxqbsc skqbbj hrkf frgnkt tbptvzf rglbcpq xbp sckhr txzv vjcbtd jqqbnzz mkz (contains peanuts) +jczm gpgrb dfllfp tzglth txzv fmfnh jccqsxs zfl spbxz nhhgb cdntx txr kdxvzqm smjhxg fgrmrqhp qkvrf skqbbj kbszttf rjds snptbf cmqjlb szzbr glvv sckhr mbqpfm mxmvt gnzr pmhxl jqqbnzz bnrf frssvh bncfz znqbr dvfqqz mxfrnq hcg ttmcq kbtkrcf czbhh mdnchc hnnz xcfpc gbbxhp stnb pfdkkzp nrdv gtjmd zsjlp qzqdq flzmlbf vdgsz krdmn bjqt zjh kjcdgh sgh lblbm pdss hsdnz vxx skks mggk ctgnz xzrdx jqkxx klzdr fddx lflzqr svcmg xmcsr (contains nuts, shellfish) +hsxp tjlz crfxz xcfpc pggzp spbxz skqbbj jkzxn tzglth svrvv mtjlb gtjmd hmnt jccqsxs vlpq tmjltg zfl gpgrb lxqbsc znqbr pfdkkzp mdnchc dlvdt gbbxhp hdt sgh rjds skks mkz hmngm vxx mzjvq cnhbh pgmqs lzfmghs qkvrf tsvfrt czbhh qrgvj hrnzq lflzqr dvfqqz xclff jxdbh pdss fcbvh (contains wheat, shellfish, eggs) +jccqsxs rglbcpq pmhxl znqbr vdgsz jqkxx pngs txzv mdsg tvk cmtq dfllfp lhqxr fddx skllln dvfqqz crfxz lzczv brjd tlbj gfpnx gtjmd gxbs gnkr xmcsr dlvdt hsdnz bdj nklc zjh lzfmghs jqqbnzz pznt lflzqr bnrf cdntx tmjltg xcfpc lxqbsc tjlz mfcrq rlsqd kdbx vjcbtd dxzzp spbxz mkz pccmj hbqhvk nndr pfdkkzp fcbsv klzdr hdt svqz svrvv pbztj (contains shellfish) +skks tzglth lmvx bph txr gpgrb klzdr txzv jnd svcmg xclff zsjlp jrrgck spbxz kjcdgh mdnchc kbtkrcf bqc bctn kbszttf dxzzp gtjmd mtjlb pfdkkzp hnvrfvm smjhxg gnkr pggzp vjcbtd lzfmghs vtqhqs tjlz fgrmrqhp svrvv fcbvh ttmcq skllln fjsgm xpmmdc xcfpc nkshjm crfxz lzczv zfl rtjxbbd hsxp cmtq snptbf skqbbj cdntx (contains nuts, peanuts, soy) +xcfpc hrkf txr gxbs snptbf kbtkrcf jxrlzm mggk nmpp txzv vghkr mfcrq sckhr nrdv lflzqr xlcgr pfdkkzp hmnt fcbvh mkz glcfml znqbr cmtq spbxz crfxz gtjmd mdsg xzrdx skks stnb nkshjm zsjlp dptl fmbqgs kjcdgh jfvltdz blbfl vtqhqs lzfmghs hjbs hdt lxqbsc klzdr tjlz vxx pngs lmvx zck gdsk hsxp pccmj jrrgck fmfnh jqkxx fjsgm ccvsl jczm tlbj qkvrf smjhxg gjt jqqbnzz svqz rjds vlpq pmhxl qlzxbc pggzp lhqxr (contains wheat) +bdj bph smjhxg pggzp svrvv dvfqqz pnxzqgp rglbcpq skks dlvdt pccmj tjlz hsdqb zbj qkvrf pmhxl fmfnh cmtq txzv ctbmdg vghkr cmqjlb gtjmd vjcbtd xpmmdc gzngn hrkf blbfl srxrn ctgnz rlsqd dxzzp fcbsv vxx zfsmv lblbm lmvx pgmqs tzglth bncfz mdx vtqhqs drzm jg jnd pfdkkzp xcfpc zfl zjh jfvltdz skllln spbxz znqbr mtpfk dfllfp mxmvt zck svcmg kbtkrcf xsndjl gjt kdbx klh nnfps (contains peanuts, wheat) +jrrgck jfvltdz bjqt nndr znqbr xclff lzfmghs lxqbsc xbp dlvdt txzv tjrm ttmcq gtjmd rdbdd skqbbj dtqplpj kdbx mfcrq pggzp nhhgb tgclx pznt gnkr vghkr xcfpc klzdr krxj lzczv klh czbhh vtqhqs skllln rjds gbbxhp hsdnz bnnt qkvrf glvv bnrf tsbffm lblbm zlhlq dvfqqz bph jkzxn dkzz cnhbh tmgfr hsxp crfxz lhqxr ndhx ngl glcfml pfdkkzp mbqpfm ctgnz bdj spbxz brjd fcbvh gpgrb nklc smjhxg (contains dairy, peanuts, fish) +ttmcq gbbxhp vxx cmtq fmbqgs nklc svqz znqbr hsxp hnvrfvm mtpfk pccmj pdss jczm mrnd zbj gtjmd klzdr thprs czbhh fddx blbfl tlbj fmfnh jdvtlsv txr rdbdd xcfpc glljh snsnj tjlz jqkxx tgclx gpgrb gnzr skllln nrdv qkvrf sgh kbtkrcf hdt pfdkkzp kdxvzqm bnnt jnd jg hqxdv spbxz flmm szzbr sckhr (contains nuts, dairy) +svqz txzv gpgrb fcbvh gnzr tjlz drzm vmrf qkvrf dlvdt hsdqb hmnt spbxz tjrm mggk hnnz sckhr bjrbknjm jfvltdz xcfpc gtjmd zjh tvk srxrn mfcrq vjcbtd fcbsv xkpm gjt hbqhvk krdmn mdnchc zlhlq ndhx pfdkkzp mdnnfp xzrdx jxdbh gnkr zck pznt bncfz nmxdsnc hrnzq skqbbj mdx kdxvzqm snptbf hsdnz mdsg dxzzp rdbdd (contains shellfish, eggs, peanuts) +dptl rlsqd tjlz mdsg pfdkkzp tzglth mxfrnq gzngn tmjltg mggk hmngm mdnchc nkshjm hnnz zlhlq cmtq vxx hnvrfvm sgh frssvh pdss mdnnfp xcfpc kbtkrcf qzqdq mrnd xbp nndr znqbr szzbr ctgnz spbxz ndhx svqz pbztj bdj smjhxg kbszttf gpgrb jkzxn hqxdv dtqplpj kdxvzqm crfxz cdntx mbqpfm hsxp dxzzp nnfps pgrc cnhbh fmbqgs pnxzqgp svrvv mdx klzdr zjh tsbffm srxrn glcfml rglbcpq hcg gtjmd glljh zck pngs jczm lxqbsc pccmj glvv (contains dairy, peanuts) +znqbr hnvrfvm svrvv kbszttf bctn jccqsxs drzm rlsqd jlnrn srxrn rjds gjt skqbbj qrgvj kjcdgh vghkr svcmg gxbs xcfpc rtjxbbd zfl ndhx lzfmghs qdnh xkpm snsnj bqc lblbm dptl fcbvh gtjmd ccvsl txzv jfvltdz kdxvzqm mtpfk bph tjrm xpmmdc jqqbnzz cnhbh czbhh dtqplpj fgrmrqhp nmxdsnc gpgrb pggzp glcfml hrkf ttmcq mfcrq jczm zlhlq cmtq mdx txr vjcbtd mggk qzqdq skks svcs sndrzm bjqt hsxp tmgfr dkzz jg zck tjlz spbxz pnxzqgp klzdr mdsg zfsmv xbp (contains fish, wheat) +vjcbtd jdvtlsv ccvsl krxj qlzxbc fmfnh zjh hcg jxrlzm spbxz txzv sgh flzmlbf hsdqb nhhgb srpqk xlcgr pggzp skqbbj dlvdt mdsg gzngn pmhxl jfvltdz dptl fgrmrqhp bjqt hsxp tvk gnzr xcfpc qkvrf gtjmd glljh bdj tmgfr jg pgrc hrnzq nnfps jlnrn svcmg zbj klzdr pccmj jqqbnzz gpgrb tmjltg mrnd hnvrfvm znqbr mbqpfm qzqdq snsnj kbtkrcf smjhxg qdnh hrkf mfvxhv srxrn tgclx tjlz fjsgm sndrzm jccqsxs xsndjl (contains eggs) +ngl hjbs tsvfrt brjd zfl lflzqr jrrgck pbztj jxdbh srxrn mfvxhv thprs nkshjm tmgfr jqqbnzz rglbcpq drzm cdntx pggzp kdxvzqm mtpfk gpgrb klzdr vjcbtd mkz jnd kvcc znqbr qzqdq tgclx pdss bskstb skqbbj xkpm spbxz hsxp sgh bdj ccvsl gdsk svcs bqc lblbm gnkr gxbs tvk xpmmdc klh czbhh pccmj jxrlzm pnxzqgp pfdkkzp xzrdx fmfnh tjlz zlhlq mdnchc bctn dptl xcfpc snptbf rtjxbbd txzv bjqt mggk jqkxx flmm nklc cmtq (contains dairy) +jxrlzm pnxzqgp rdbdd frgnkt znqbr gpgrb lblbm srxrn jfvltdz mrnd jkzxn kjcdgh skks bjrbknjm nmxdsnc zjh tjrm xlcgr kdxvzqm fmfnh jnd spbxz nndr zfl dvfqqz xcfpc tmgfr mfvxhv bdj nhhgb hsxp glljh dlvdt txzv vtqhqs zck nnfps gtjmd jrrgck jczm jlnrn drzm cmqjlb fddx xpmmdc hsdnz hqxdv qdnh vjcbtd dptl svcmg bnrf xbp qkvrf kbszttf pznt mfcrq stnb mzjvq pgrc xkpm fcbvh vdgsz mxmvt hjbs hnnz pmhxl tlbj hnvrfvm bncfz zfsmv xsndjl xmcsr bjqt vmrf tjlz bskstb mdx jxdbh gzngn ndhx vlpq (contains fish, wheat, nuts) +ttmcq txr pmhxl frgnkt xbp gxbs zlhlq szzbr crfxz fmfnh smjhxg hmngm xclff glvv tmgfr thprs glcfml fjsgm tsvfrt znqbr spbxz svrvv nrdv lzfmghs tgclx jczm fgrmrqhp bctn mtpfk cdntx gtjmd fcbsv mkz rglbcpq mbqpfm rjds bph jfvltdz ngl zfl rdbdd tjlz gjt nmxdsnc hsdqb qrgvj gfpnx txzv hdt pfdkkzp tvk sckhr snptbf flmm vtqhqs lhqxr fcbvh hnnz mfvxhv nmpp bjrbknjm nkshjm fmbqgs svcs jqkxx gpgrb mtjlb zfsmv dlvdt pngs svqz hbqhvk hmnt ccvsl (contains peanuts, dairy, wheat) +nmxdsnc txzv pggzp pznt cmqjlb hsdnz snsnj ndhx dlvdt ttmcq zbj xmcsr zlhlq flzmlbf tmjltg mdnchc qdnh pngs pmhxl cmtq skqbbj bph czbhh fmbqgs spbxz xclff drzm gdsk znqbr dfllfp tjlz zjh fcbvh pfdkkzp rjds glvv mkz nndr hbqhvk krdmn xcfpc skks mtpfk gtjmd rlsqd hrnzq svcs fcbsv lmvx ctbmdg frgnkt zfsmv sckhr (contains nuts, wheat, eggs) +nrdv zlhlq mzjvq nnfps tmgfr fcbvh jccqsxs xcfpc cnhbh gpgrb brjd hnvrfvm tjlz xzrdx vmrf lmvx skllln zsjlp snsnj szzbr lxqbsc dvfqqz pdss spbxz zfsmv mggk gtjmd tgclx cmqjlb zck rjds hjbs gdsk mfvxhv thprs fcbsv lblbm srxrn jqkxx flmm jnd qdnh lzczv fjsgm xlcgr snptbf znqbr txzv stnb czbhh gnzr (contains wheat) +vlpq svcs hqxdv mxfrnq zfl frssvh mggk kdbx ctbmdg tbptvzf zck xzrdx krdmn klh fcbsv znqbr sgh frgnkt lzfmghs cmtq xcfpc txzv rtjxbbd rjds fcbvh xclff pfdkkzp jccqsxs dvfqqz gtjmd hrkf hsdqb gnzr jqkxx lmvx flmm xlcgr mdsg tjlz jlnrn hnvrfvm hcg bdj lzczv gzngn fmbqgs spbxz bskstb jg nklc hdt gjt jrrgck skks srpqk ngl vxx (contains eggs, wheat) +znqbr rdbdd jfvltdz gnzr mdx glcfml vtqhqs lblbm frssvh hsdnz jxdbh xsndjl pccmj kdxvzqm fgrmrqhp krdmn hnnz mtpfk gtjmd jccqsxs nklc vlpq svcs brjd xcfpc srxrn cdntx smjhxg pggzp fmfnh pdss nmxdsnc kbszttf xzrdx bnnt tvk fcbsv zfl mbqpfm xlcgr nnfps spbxz kdbx dlvdt gnkr tlbj vmrf hbqhvk mrnd dvfqqz tjlz gpgrb cnhbh hnvrfvm qrgvj snptbf tmjltg txzv mdnnfp nrdv jg xclff crfxz mdsg tsvfrt hdt dptl lflzqr hsdqb (contains shellfish) +tjlz srxrn gpgrb blbfl dvfqqz nrdv fmfnh smjhxg jlnrn tvk hbqhvk bdj hsdqb klh qrgvj jczm spbxz jnd lxqbsc rglbcpq jxdbh fgrmrqhp zbj znqbr pfdkkzp pngs dkzz mbqpfm hmngm vjcbtd mrnd jfvltdz jccqsxs xmcsr mfvxhv bqc mdsg pgmqs stnb svcs xcfpc kvcc skqbbj zlhlq svcmg gtjmd glcfml dtqplpj bjrbknjm gdsk nnfps qdnh hrkf ngl mdnchc bncfz gnzr srpqk sgh gjt fcbsv hnvrfvm hmnt (contains nuts, dairy, peanuts) diff --git a/www/statics/aoc/2020/21_solution.rs b/www/statics/aoc/2020/21_solution.rs new file mode 100644 index 0000000..ff09b0d --- /dev/null +++ b/www/statics/aoc/2020/21_solution.rs @@ -0,0 +1,110 @@ +use crate::common::AdventOfCodeDay; + +use std::collections::HashMap; + +#[derive(Debug)] +struct Food { + ingredients: Vec, + allergens: Vec, +} + +impl Food { + fn parse(line: String) -> Food { + let split = line.split(" (contains ").collect::>(); + + return Food { + ingredients: split[0].split(" ").map(String::from).collect(), + allergens: split[1].replace(")", "").split(", ").map(String::from).collect(), + } + } +} + +#[derive(Debug)] +pub struct Day21 { + input: Vec, +} + +impl Day21 { + pub fn new() -> Self { + let input_bytes = include_bytes!("../res/21_input.txt"); + let input_str = String::from_utf8_lossy(input_bytes); + + let data = input_str + .lines() + .map(|p| Food::parse(String::from(p))) + .collect::>(); + + Self { + input: data + } + } +} + +impl Day21 { + fn find_allergen_candidates(&self) -> Vec<(String, Vec)> { + let mut ag_map = HashMap::>::new(); + + for food in &self.input { + for allergen in &food.allergens { + + if let Some(candidates) = ag_map.get_mut(allergen) { + + candidates.retain(|c| food.ingredients.contains(c)) + + } else { + ag_map.insert(allergen.clone(), food.ingredients.clone()); + } + } + } + + loop { + let mut changed = false; + + for rm in ag_map.iter().filter(|(_,v)| v.len()==1).map(|(_,v)| v[0].clone()).collect::>() { + + for (_, cand_mut) in ag_map.iter_mut() { + if cand_mut.len() == 1 { continue; } + + let l1 = cand_mut.len(); + cand_mut.retain(|v| *v != rm); + if cand_mut.len() != l1 { changed = true; } + } + + } + + if !changed { break; } + } + + return ag_map.iter().map(|(k,v)| (k.clone(), v.clone())).collect::>(); + } +} + +impl AdventOfCodeDay for Day21 { + + fn task_1(&self) -> String { + + //for v in &self.input { verboseln!("{:?}", v); } + + let candidates = self.find_allergen_candidates(); + + if is_verbose!() { + for (k,v) in &candidates { verboseln!("{: <9} ({}) := {:?}", k, v.len(), v); } + } + + let allergen_ingred = candidates.iter().flat_map(|p| p.1.iter() ).collect::>(); + + return self.input.iter().flat_map(|p| p.ingredients.iter()).filter(|ig| !allergen_ingred.contains(&ig)).count().to_string(); + } + + fn task_2(&self) -> String { + + let mut candidates = self.find_allergen_candidates(); + candidates.sort_by(|a,b| a.0.cmp(&b.0)); + + if is_verbose!() { + for (k,v) in &candidates { verboseln!("{: <9} ({}) := {:?}", k, v.len(), v); } + } + + return candidates.iter().map(|(_,v)|v[0].clone()).collect::>().join(","); + } +} \ No newline at end of file diff --git a/www/statics/aoc/2020/22_challenge.txt b/www/statics/aoc/2020/22_challenge.txt new file mode 100644 index 0000000..0f80e8d --- /dev/null +++ b/www/statics/aoc/2020/22_challenge.txt @@ -0,0 +1,375 @@ +It only takes a few hours of sailing the ocean on a raft for boredom to sink in. Fortunately, you brought a small deck of space cards! You'd like to play a game of Combat, and there's even an opponent available: a small crab that climbed aboard your raft before you left. + +Fortunately, it doesn't take long to teach the crab the rules. + +Before the game starts, split the cards so each player has their own deck (your puzzle input). Then, the game consists of a series of rounds: both players draw their top card, and the player with the higher-valued card wins the round. The winner keeps both cards, placing them on the bottom of their own deck so that the winner's card is above the other card. If this causes a player to have all of the cards, they win, and the game ends. + +For example, consider the following starting decks: + +Player 1: +9 +2 +6 +3 +1 + +Player 2: +5 +8 +4 +7 +10 + +This arrangement means that player 1's deck contains 5 cards, with 9 on top and 1 on the bottom; player 2's deck also contains 5 cards, with 5 on top and 10 on the bottom. + +The first round begins with both players drawing the top card of their decks: 9 and 5. Player 1 has the higher card, so both cards move to the bottom of player 1's deck such that 9 is above 5. In total, it takes 29 rounds before a player has all of the cards: + +-- Round 1 -- +Player 1's deck: 9, 2, 6, 3, 1 +Player 2's deck: 5, 8, 4, 7, 10 +Player 1 plays: 9 +Player 2 plays: 5 +Player 1 wins the round! + +-- Round 2 -- +Player 1's deck: 2, 6, 3, 1, 9, 5 +Player 2's deck: 8, 4, 7, 10 +Player 1 plays: 2 +Player 2 plays: 8 +Player 2 wins the round! + +-- Round 3 -- +Player 1's deck: 6, 3, 1, 9, 5 +Player 2's deck: 4, 7, 10, 8, 2 +Player 1 plays: 6 +Player 2 plays: 4 +Player 1 wins the round! + +-- Round 4 -- +Player 1's deck: 3, 1, 9, 5, 6, 4 +Player 2's deck: 7, 10, 8, 2 +Player 1 plays: 3 +Player 2 plays: 7 +Player 2 wins the round! + +-- Round 5 -- +Player 1's deck: 1, 9, 5, 6, 4 +Player 2's deck: 10, 8, 2, 7, 3 +Player 1 plays: 1 +Player 2 plays: 10 +Player 2 wins the round! + +...several more rounds pass... + +-- Round 27 -- +Player 1's deck: 5, 4, 1 +Player 2's deck: 8, 9, 7, 3, 2, 10, 6 +Player 1 plays: 5 +Player 2 plays: 8 +Player 2 wins the round! + +-- Round 28 -- +Player 1's deck: 4, 1 +Player 2's deck: 9, 7, 3, 2, 10, 6, 8, 5 +Player 1 plays: 4 +Player 2 plays: 9 +Player 2 wins the round! + +-- Round 29 -- +Player 1's deck: 1 +Player 2's deck: 7, 3, 2, 10, 6, 8, 5, 9, 4 +Player 1 plays: 1 +Player 2 plays: 7 +Player 2 wins the round! + + +== Post-game results == +Player 1's deck: +Player 2's deck: 3, 2, 10, 6, 8, 5, 9, 4, 7, 1 + +Once the game ends, you can calculate the winning player's score. The bottom card in their deck is worth the value of the card multiplied by 1, the second-from-the-bottom card is worth the value of the card multiplied by 2, and so on. With 10 cards, the top card is worth the value on the card multiplied by 10. In this example, the winning player's score is: + + 3 * 10 ++ 2 * 9 ++ 10 * 8 ++ 6 * 7 ++ 8 * 6 ++ 5 * 5 ++ 9 * 4 ++ 4 * 3 ++ 7 * 2 ++ 1 * 1 += 306 + +So, once the game ends, the winning player's score is 306. + +Play the small crab in a game of Combat using the two decks you just dealt. What is the winning player's score? + +--- Part Two --- + +You lost to the small crab! Fortunately, crabs aren't very good at recursion. To defend your honor as a Raft Captain, you challenge the small crab to a game of Recursive Combat. + +Recursive Combat still starts by splitting the cards into two decks (you offer to play with the same starting decks as before - it's only fair). Then, the game consists of a series of rounds with a few changes: + + Before either player deals a card, if there was a previous round in this game that had exactly the same cards in the same order in the same players' decks, the game instantly ends in a win for player 1. Previous rounds from other games are not considered. (This prevents infinite games of Recursive Combat, which everyone agrees is a bad idea.) + Otherwise, this round's cards must be in a new configuration; the players begin the round by each drawing the top card of their deck as normal. + If both players have at least as many cards remaining in their deck as the value of the card they just drew, the winner of the round is determined by playing a new game of Recursive Combat (see below). + Otherwise, at least one player must not have enough cards left in their deck to recurse; the winner of the round is the player with the higher-value card. + +As in regular Combat, the winner of the round (even if they won the round by winning a sub-game) takes the two cards dealt at the beginning of the round and places them on the bottom of their own deck (again so that the winner's card is above the other card). Note that the winner's card might be the lower-valued of the two cards if they won the round due to winning a sub-game. If collecting cards by winning the round causes a player to have all of the cards, they win, and the game ends. + +Here is an example of a small game that would loop forever without the infinite game prevention rule: + +Player 1: +43 +19 + +Player 2: +2 +29 +14 + +During a round of Recursive Combat, if both players have at least as many cards in their own decks as the number on the card they just dealt, the winner of the round is determined by recursing into a sub-game of Recursive Combat. (For example, if player 1 draws the 3 card, and player 2 draws the 7 card, this would occur if player 1 has at least 3 cards left and player 2 has at least 7 cards left, not counting the 3 and 7 cards that were drawn.) + +To play a sub-game of Recursive Combat, each player creates a new deck by making a copy of the next cards in their deck (the quantity of cards copied is equal to the number on the card they drew to trigger the sub-game). During this sub-game, the game that triggered it is on hold and completely unaffected; no cards are removed from players' decks to form the sub-game. (For example, if player 1 drew the 3 card, their deck in the sub-game would be copies of the next three cards in their deck.) + +Here is a complete example of gameplay, where Game 1 is the primary game of Recursive Combat: + +=== Game 1 === + +-- Round 1 (Game 1) -- +Player 1's deck: 9, 2, 6, 3, 1 +Player 2's deck: 5, 8, 4, 7, 10 +Player 1 plays: 9 +Player 2 plays: 5 +Player 1 wins round 1 of game 1! + +-- Round 2 (Game 1) -- +Player 1's deck: 2, 6, 3, 1, 9, 5 +Player 2's deck: 8, 4, 7, 10 +Player 1 plays: 2 +Player 2 plays: 8 +Player 2 wins round 2 of game 1! + +-- Round 3 (Game 1) -- +Player 1's deck: 6, 3, 1, 9, 5 +Player 2's deck: 4, 7, 10, 8, 2 +Player 1 plays: 6 +Player 2 plays: 4 +Player 1 wins round 3 of game 1! + +-- Round 4 (Game 1) -- +Player 1's deck: 3, 1, 9, 5, 6, 4 +Player 2's deck: 7, 10, 8, 2 +Player 1 plays: 3 +Player 2 plays: 7 +Player 2 wins round 4 of game 1! + +-- Round 5 (Game 1) -- +Player 1's deck: 1, 9, 5, 6, 4 +Player 2's deck: 10, 8, 2, 7, 3 +Player 1 plays: 1 +Player 2 plays: 10 +Player 2 wins round 5 of game 1! + +-- Round 6 (Game 1) -- +Player 1's deck: 9, 5, 6, 4 +Player 2's deck: 8, 2, 7, 3, 10, 1 +Player 1 plays: 9 +Player 2 plays: 8 +Player 1 wins round 6 of game 1! + +-- Round 7 (Game 1) -- +Player 1's deck: 5, 6, 4, 9, 8 +Player 2's deck: 2, 7, 3, 10, 1 +Player 1 plays: 5 +Player 2 plays: 2 +Player 1 wins round 7 of game 1! + +-- Round 8 (Game 1) -- +Player 1's deck: 6, 4, 9, 8, 5, 2 +Player 2's deck: 7, 3, 10, 1 +Player 1 plays: 6 +Player 2 plays: 7 +Player 2 wins round 8 of game 1! + +-- Round 9 (Game 1) -- +Player 1's deck: 4, 9, 8, 5, 2 +Player 2's deck: 3, 10, 1, 7, 6 +Player 1 plays: 4 +Player 2 plays: 3 +Playing a sub-game to determine the winner... + +=== Game 2 === + +-- Round 1 (Game 2) -- +Player 1's deck: 9, 8, 5, 2 +Player 2's deck: 10, 1, 7 +Player 1 plays: 9 +Player 2 plays: 10 +Player 2 wins round 1 of game 2! + +-- Round 2 (Game 2) -- +Player 1's deck: 8, 5, 2 +Player 2's deck: 1, 7, 10, 9 +Player 1 plays: 8 +Player 2 plays: 1 +Player 1 wins round 2 of game 2! + +-- Round 3 (Game 2) -- +Player 1's deck: 5, 2, 8, 1 +Player 2's deck: 7, 10, 9 +Player 1 plays: 5 +Player 2 plays: 7 +Player 2 wins round 3 of game 2! + +-- Round 4 (Game 2) -- +Player 1's deck: 2, 8, 1 +Player 2's deck: 10, 9, 7, 5 +Player 1 plays: 2 +Player 2 plays: 10 +Player 2 wins round 4 of game 2! + +-- Round 5 (Game 2) -- +Player 1's deck: 8, 1 +Player 2's deck: 9, 7, 5, 10, 2 +Player 1 plays: 8 +Player 2 plays: 9 +Player 2 wins round 5 of game 2! + +-- Round 6 (Game 2) -- +Player 1's deck: 1 +Player 2's deck: 7, 5, 10, 2, 9, 8 +Player 1 plays: 1 +Player 2 plays: 7 +Player 2 wins round 6 of game 2! +The winner of game 2 is player 2! + +...anyway, back to game 1. +Player 2 wins round 9 of game 1! + +-- Round 10 (Game 1) -- +Player 1's deck: 9, 8, 5, 2 +Player 2's deck: 10, 1, 7, 6, 3, 4 +Player 1 plays: 9 +Player 2 plays: 10 +Player 2 wins round 10 of game 1! + +-- Round 11 (Game 1) -- +Player 1's deck: 8, 5, 2 +Player 2's deck: 1, 7, 6, 3, 4, 10, 9 +Player 1 plays: 8 +Player 2 plays: 1 +Player 1 wins round 11 of game 1! + +-- Round 12 (Game 1) -- +Player 1's deck: 5, 2, 8, 1 +Player 2's deck: 7, 6, 3, 4, 10, 9 +Player 1 plays: 5 +Player 2 plays: 7 +Player 2 wins round 12 of game 1! + +-- Round 13 (Game 1) -- +Player 1's deck: 2, 8, 1 +Player 2's deck: 6, 3, 4, 10, 9, 7, 5 +Player 1 plays: 2 +Player 2 plays: 6 +Playing a sub-game to determine the winner... + +=== Game 3 === + +-- Round 1 (Game 3) -- +Player 1's deck: 8, 1 +Player 2's deck: 3, 4, 10, 9, 7, 5 +Player 1 plays: 8 +Player 2 plays: 3 +Player 1 wins round 1 of game 3! + +-- Round 2 (Game 3) -- +Player 1's deck: 1, 8, 3 +Player 2's deck: 4, 10, 9, 7, 5 +Player 1 plays: 1 +Player 2 plays: 4 +Playing a sub-game to determine the winner... + +=== Game 4 === + +-- Round 1 (Game 4) -- +Player 1's deck: 8 +Player 2's deck: 10, 9, 7, 5 +Player 1 plays: 8 +Player 2 plays: 10 +Player 2 wins round 1 of game 4! +The winner of game 4 is player 2! + +...anyway, back to game 3. +Player 2 wins round 2 of game 3! + +-- Round 3 (Game 3) -- +Player 1's deck: 8, 3 +Player 2's deck: 10, 9, 7, 5, 4, 1 +Player 1 plays: 8 +Player 2 plays: 10 +Player 2 wins round 3 of game 3! + +-- Round 4 (Game 3) -- +Player 1's deck: 3 +Player 2's deck: 9, 7, 5, 4, 1, 10, 8 +Player 1 plays: 3 +Player 2 plays: 9 +Player 2 wins round 4 of game 3! +The winner of game 3 is player 2! + +...anyway, back to game 1. +Player 2 wins round 13 of game 1! + +-- Round 14 (Game 1) -- +Player 1's deck: 8, 1 +Player 2's deck: 3, 4, 10, 9, 7, 5, 6, 2 +Player 1 plays: 8 +Player 2 plays: 3 +Player 1 wins round 14 of game 1! + +-- Round 15 (Game 1) -- +Player 1's deck: 1, 8, 3 +Player 2's deck: 4, 10, 9, 7, 5, 6, 2 +Player 1 plays: 1 +Player 2 plays: 4 +Playing a sub-game to determine the winner... + +=== Game 5 === + +-- Round 1 (Game 5) -- +Player 1's deck: 8 +Player 2's deck: 10, 9, 7, 5 +Player 1 plays: 8 +Player 2 plays: 10 +Player 2 wins round 1 of game 5! +The winner of game 5 is player 2! + +...anyway, back to game 1. +Player 2 wins round 15 of game 1! + +-- Round 16 (Game 1) -- +Player 1's deck: 8, 3 +Player 2's deck: 10, 9, 7, 5, 6, 2, 4, 1 +Player 1 plays: 8 +Player 2 plays: 10 +Player 2 wins round 16 of game 1! + +-- Round 17 (Game 1) -- +Player 1's deck: 3 +Player 2's deck: 9, 7, 5, 6, 2, 4, 1, 10, 8 +Player 1 plays: 3 +Player 2 plays: 9 +Player 2 wins round 17 of game 1! +The winner of game 1 is player 2! + + +== Post-game results == +Player 1's deck: +Player 2's deck: 7, 5, 6, 2, 4, 1, 10, 8, 9, 3 + +After the game, the winning player's score is calculated from the cards they have in their original deck using the same rules as regular Combat. In the above game, the winning player's score is 291. + +Defend your honor as Raft Captain by playing the small crab in a game of Recursive Combat using the same two decks as before. What is the winning player's score? diff --git a/www/statics/aoc/2020/22_input.txt b/www/statics/aoc/2020/22_input.txt new file mode 100644 index 0000000..537fcb7 --- /dev/null +++ b/www/statics/aoc/2020/22_input.txt @@ -0,0 +1,53 @@ +Player 1: +42 +29 +12 +40 +47 +26 +11 +39 +41 +13 +8 +50 +44 +33 +5 +27 +10 +25 +17 +1 +28 +22 +6 +32 +35 + +Player 2: +19 +34 +38 +21 +43 +14 +23 +46 +16 +3 +36 +31 +37 +45 +30 +15 +49 +48 +24 +9 +2 +18 +4 +7 +20 diff --git a/www/statics/aoc/2020/22_solution.rs b/www/statics/aoc/2020/22_solution.rs new file mode 100644 index 0000000..4cd1b4e --- /dev/null +++ b/www/statics/aoc/2020/22_solution.rs @@ -0,0 +1,187 @@ +use crate::common::AdventOfCodeDay; + +use regex::Regex; +use std::convert::TryInto; +use std::collections::HashSet; +use std::collections::hash_map::DefaultHasher; +use std::hash::{Hash, Hasher}; + +#[derive(Debug)] +pub struct Day22 { + cards_p1: Vec, + cards_p2: Vec, +} + +impl Day22 { + pub fn new() -> Self { + let input_bytes = include_bytes!("../res/22_input.txt"); + let input_str = String::from_utf8_lossy(input_bytes); + + let rex_lines = Regex::new(r"(\r?\n){2}").unwrap(); + let split = rex_lines.split(&input_str).collect::>(); + + Self { + cards_p1: split[0].lines().skip(1).map(|p| p.parse::().unwrap()).collect(), + cards_p2: split[1].lines().skip(1).map(|p| p.parse::().unwrap()).collect(), + } + } +} + +#[derive(Hash)] +struct Game { + cards_p1: Vec, + cards_p2: Vec, +} + +impl Game { + fn play_one(&mut self) { + let c1 = self.cards_p1.remove(0); + let c2 = self.cards_p2.remove(0); + + if c1 > c2 { + self.cards_p1.push(c1); + self.cards_p1.push(c2); + } else { + self.cards_p2.push(c2); + self.cards_p2.push(c1); + } + } + + fn play(&mut self) -> usize { + verboseln!("Round[0]:"); + verboseln!(" P1: {:?}", self.cards_p1); + verboseln!(" P2: {:?}", self.cards_p2); + verboseln!(); + + let mut winner = 0; + for i in 1.. { + + self.play_one(); + + verboseln!("Round[{}]:", i); + verboseln!(" P1: {:?}", self.cards_p1); + verboseln!(" P2: {:?}", self.cards_p2); + verboseln!(); + + if self.cards_p1.is_empty() { winner = 2; break; } + if self.cards_p2.is_empty() { winner = 1; break; } + } + + return winner; + } + + fn score(&self, player: usize) -> u128 { + + let cards = match player { + 1 => &self.cards_p1, + 2 => &self.cards_p2, + _ => panic!(), + }; + + return cards.iter() + .rev() + .enumerate() + .map(|(i,v)| ((i+1) as u128, *v as u128)) + .map(|(i,v)| i*v) + .fold(0, |a,b| a + b); + } + + fn play_recursive(&mut self, game_id: u32) -> usize { + + verboseln!("=== Game {} ===", game_id); + verboseln!(); + + let mut history = HashSet::::new(); + + let mut winner = 0; + for i in 1.. { + + let mut dhasher = DefaultHasher::new(); + self.hash(&mut dhasher); + let hash = dhasher.finish(); + + if history.contains(&hash) { + verboseln!("Player 1 wins inf-recursion-protection in game: {}", game_id); + return 1; + } else { + history.insert(hash); + } + + verboseln!("-- Round {} (Game {}) --", i, game_id); + verboseln!("Player 1's deck: {:?}", self.cards_p1); + verboseln!("Player 2's deck: {:?}", self.cards_p2); + + let c1 = self.cards_p1.remove(0); + let c2 = self.cards_p2.remove(0); + + verboseln!("Player 1 plays: {}", c1); + verboseln!("Player 2 plays: {}", c2); + + if self.cards_p1.len() as u32 >= c1 && self.cards_p2.len() as u32 >= c2 { + + verboseln!("Playing a sub-game to determine the winner..."); + verboseln!(); + let mut subgame = Game { + cards_p1: self.cards_p1.iter().take(c1.try_into().unwrap()).map(|p|*p).collect::>(), + cards_p2:self.cards_p2.iter().take(c2.try_into().unwrap()).map(|p|*p).collect::>() + }; + let sg_winner = subgame.play_recursive(game_id+1); + verboseln!(); + verboseln!("...anyway, back to game {}.", game_id); + + if sg_winner == 1 { + verboseln!("Player 1 wins round {} of game {}!", i, game_id); + self.cards_p1.push(c1); + self.cards_p1.push(c2); + } else { + verboseln!("Player 2 wins round {} of game {}!", i, game_id); + self.cards_p2.push(c2); + self.cards_p2.push(c1); + } + + } else { + if c1 > c2 { + verboseln!("Player 1 wins round {} of game {}!", i, game_id); + self.cards_p1.push(c1); + self.cards_p1.push(c2); + } else { + verboseln!("Player 2 wins round {} of game {}!", i, game_id); + self.cards_p2.push(c2); + self.cards_p2.push(c1); + } + } + + if self.cards_p1.is_empty() { winner = 2; break; } + if self.cards_p2.is_empty() { winner = 1; break; } + + verboseln!(); + } + + verboseln!("The winner of game {} is player {}!", game_id, winner); + + if game_id == 1 { + + verboseln!(); + verboseln!("== Post-game results =="); + verboseln!("Player 1's deck: {:?}", self.cards_p1); + verboseln!("Player 2's deck: {:?}", self.cards_p2); + } + + return winner; + } +} + +impl AdventOfCodeDay for Day22 { + + fn task_1(&self) -> String { + let mut game = Game { cards_p1: self.cards_p1.clone(), cards_p2: self.cards_p2.clone() }; + let winner = game.play(); + return game.score(winner).to_string(); + } + + fn task_2(&self) -> String { + let mut game = Game { cards_p1: self.cards_p1.clone(), cards_p2: self.cards_p2.clone() }; + let winner = game.play_recursive(1); + return game.score(winner).to_string(); + } +} \ No newline at end of file diff --git a/www/statics/aoc/2020/23_challenge.txt b/www/statics/aoc/2020/23_challenge.txt new file mode 100644 index 0000000..cbc12ca --- /dev/null +++ b/www/statics/aoc/2020/23_challenge.txt @@ -0,0 +1,87 @@ +The small crab challenges you to a game! The crab is going to mix up some cups, and you have to predict where they'll end up. + +The cups will be arranged in a circle and labeled clockwise (your puzzle input). For example, if your labeling were 32415, there would be five cups in the circle; going clockwise around the circle from the first cup, the cups would be labeled 3, 2, 4, 1, 5, and then back to 3 again. + +Before the crab starts, it will designate the first cup in your list as the current cup. The crab is then going to do 100 moves. + +Each move, the crab does the following actions: + + The crab picks up the three cups that are immediately clockwise of the current cup. They are removed from the circle; cup spacing is adjusted as necessary to maintain the circle. + The crab selects a destination cup: the cup with a label equal to the current cup's label minus one. If this would select one of the cups that was just picked up, the crab will keep subtracting one until it finds a cup that wasn't just picked up. If at any point in this process the value goes below the lowest value on any cup's label, it wraps around to the highest value on any cup's label instead. + The crab places the cups it just picked up so that they are immediately clockwise of the destination cup. They keep the same order as when they were picked up. + The crab selects a new current cup: the cup which is immediately clockwise of the current cup. + +For example, suppose your cup labeling were 389125467. If the crab were to do merely 10 moves, the following changes would occur: + +-- move 1 -- +cups: (3) 8 9 1 2 5 4 6 7 +pick up: 8, 9, 1 +destination: 2 + +-- move 2 -- +cups: 3 (2) 8 9 1 5 4 6 7 +pick up: 8, 9, 1 +destination: 7 + +-- move 3 -- +cups: 3 2 (5) 4 6 7 8 9 1 +pick up: 4, 6, 7 +destination: 3 + +-- move 4 -- +cups: 7 2 5 (8) 9 1 3 4 6 +pick up: 9, 1, 3 +destination: 7 + +-- move 5 -- +cups: 3 2 5 8 (4) 6 7 9 1 +pick up: 6, 7, 9 +destination: 3 + +-- move 6 -- +cups: 9 2 5 8 4 (1) 3 6 7 +pick up: 3, 6, 7 +destination: 9 + +-- move 7 -- +cups: 7 2 5 8 4 1 (9) 3 6 +pick up: 3, 6, 7 +destination: 8 + +-- move 8 -- +cups: 8 3 6 7 4 1 9 (2) 5 +pick up: 5, 8, 3 +destination: 1 + +-- move 9 -- +cups: 7 4 1 5 8 3 9 2 (6) +pick up: 7, 4, 1 +destination: 5 + +-- move 10 -- +cups: (5) 7 4 1 8 3 9 2 6 +pick up: 7, 4, 1 +destination: 3 + +-- final -- +cups: 5 (8) 3 7 4 1 9 2 6 + +In the above example, the cups' values are the labels as they appear moving clockwise around the circle; the current cup is marked with ( ). + +After the crab is done, what order will the cups be in? Starting after the cup labeled 1, collect the other cups' labels clockwise into a single string with no extra characters; each number except 1 should appear exactly once. In the above example, after 10 moves, the cups clockwise from 1 are labeled 9, 2, 6, 5, and so on, producing 92658374. If the crab were to complete all 100 moves, the order after cup 1 would be 67384529. + +Using your labeling, simulate 100 moves. What are the labels on the cups after cup 1? + +--- Part Two --- + +Due to what you can only assume is a mistranslation (you're not exactly fluent in Crab), you are quite surprised when the crab starts arranging many cups in a circle on your raft - one million (1000000) in total. + +Your labeling is still correct for the first few cups; after that, the remaining cups are just numbered in an increasing fashion starting from the number after the highest number in your list and proceeding one by one until one million is reached. (For example, if your labeling were 54321, the cups would be numbered 5, 4, 3, 2, 1, and then start counting up from 6 until one million is reached.) In this way, every number from one through one million is used exactly once. + +After discovering where you made the mistake in translating Crab Numbers, you realize the small crab isn't going to do merely 100 moves; the crab is going to do ten million (10000000) moves! + +The crab is going to hide your stars - one each - under the two cups that will end up immediately clockwise of cup 1. You can have them if you predict what the labels on those cups will be when the crab is finished. + +In the above example (389125467), this would be 934001 and then 159792; multiplying these together produces 149245887792. + +Determine which two cups will end up immediately clockwise of cup 1. What do you get if you multiply their labels together? diff --git a/www/statics/aoc/2020/23_input.txt b/www/statics/aoc/2020/23_input.txt new file mode 100644 index 0000000..4d7256f --- /dev/null +++ b/www/statics/aoc/2020/23_input.txt @@ -0,0 +1 @@ +872495136 \ No newline at end of file diff --git a/www/statics/aoc/2020/23_solution.rs b/www/statics/aoc/2020/23_solution.rs new file mode 100644 index 0000000..b4ec195 --- /dev/null +++ b/www/statics/aoc/2020/23_solution.rs @@ -0,0 +1,135 @@ +use crate::common::AdventOfCodeDay; + +pub struct Day23 { + input: Vec, +} + +impl Day23 { + pub fn new() -> Self { + let input_bytes = include_bytes!("../res/23_input.txt"); + let input_str = String::from_utf8_lossy(input_bytes); + + let cups = input_str + .chars() + .map(|p| p.to_string().parse::().unwrap()) + .collect::>(); + + Self { + input: cups + } + } +} + +impl Day23 { + fn do_move(cups: &mut Vec) { + + verboseln!("Cups: {:?}", cups); + + let n1 = cups[1]; + let n2 = cups[2]; + let n3 = cups[3]; + + verboseln!("pick up: {}, {}, {}", n1,n2,n3); + + let mut dest = (cups[0] + 9-1-1) % 9 + 1; + while !cups.iter().skip(4).any(|p| *p == dest) { + dest = (dest + 9-1-1) % 9 + 1; + } + let dest_idx = cups.iter().position(|p| *p==dest).unwrap() + 1; + + verboseln!("destination: {}, (idx: {})", dest,dest_idx); + + cups.insert(dest_idx, n3); + cups.insert(dest_idx, n2); + cups.insert(dest_idx, n1); + + cups.remove(1); + cups.remove(1); + cups.remove(1); + + let f = cups.remove(0); + cups.push(f); + + verboseln!(); + } + + fn do_move_linkedlist(cups: &mut [u32; 1_000_000], currcup: u32) -> u32 { + let n0 = currcup; + let n1 = cups[n0 as usize]; + let n2 = cups[n1 as usize]; + let n3 = cups[n2 as usize]; + let n4 = cups[n3 as usize]; + + let mut dest = (n0+(1_000_000-1)) % 1_000_000; + while dest == n1 || dest == n2 || dest == n3 { + dest = (dest+(1_000_000-1)) % 1_000_000; + } + + let d1 = cups[dest as usize]; + + //verboseln!("Cups [ptr]: {:?}", cups.iter().take(16).collect::>()); + //verboseln!("current: {}", currcup); + //verboseln!("picked: {},{},{}", n1,n2,n3); + //verboseln!("destination: {}", dest); + + // remove after curr + cups[n0 as usize] = n4; + + // insert after dest + cups[dest as usize] = n1; + cups[n3 as usize] = d1; + + return n4; + } +} + +impl AdventOfCodeDay for Day23 { + + fn task_1(&self) -> String { + + let mut cups = self.input.clone(); + + for _ in 0..100 { + Self::do_move(&mut cups); + } + + let c1idx = cups.iter().position(|p| *p==1).unwrap(); + + let mut r = String::new(); + for idx in 1..9 { + r = r + &cups[(idx+c1idx) % 9].to_string(); + } + + return r; + } + + + fn task_2(&self) -> String { + let mut cups = [0u32; 1_000_000]; // at cell[x] is the value of the cup right to the cup with the value x (-> single-linked-list) + + for idx in 0..1_000_000 { + if idx == (1_000_000-1) { + cups[idx] = (self.input[0]-1) as u32; + } else if idx > 8 { + cups[idx] = (idx+1) as u32; + } else if idx == 8 { + cups[(self.input[idx]-1) as usize] = 9; + } else { + cups[(self.input[idx]-1) as usize] = (self.input[idx+1 as usize]-1) as u32; + } + } + + let mut curr = (self.input[0]-1) as u32; + for _ in 0..10_000_000 { + curr = Self::do_move_linkedlist(&mut cups, curr); + } + + let n1 = cups[0 as usize] as u128; + let n2 = cups[n1 as usize] as u128; + + verboseln!("{} * {}", n1+1, n2+1); + + return ((n1+1)*(n2+1)).to_string(); + } + +} diff --git a/www/statics/aoc/2020/24_challenge.txt b/www/statics/aoc/2020/24_challenge.txt new file mode 100644 index 0000000..8c8ef38 --- /dev/null +++ b/www/statics/aoc/2020/24_challenge.txt @@ -0,0 +1,78 @@ +Your raft makes it to the tropical island; it turns out that the small crab was an excellent navigator. You make your way to the resort. + +As you enter the lobby, you discover a small problem: the floor is being renovated. You can't even reach the check-in desk until they've finished installing the new tile floor. + +The tiles are all hexagonal; they need to be arranged in a hex grid with a very specific color pattern. Not in the mood to wait, you offer to help figure out the pattern. + +The tiles are all white on one side and black on the other. They start with the white side facing up. The lobby is large enough to fit whatever pattern might need to appear there. + +A member of the renovation crew gives you a list of the tiles that need to be flipped over (your puzzle input). Each line in the list identifies a single tile that needs to be flipped by giving a series of steps starting from a reference tile in the very center of the room. (Every line starts from the same reference tile.) + +Because the tiles are hexagonal, every tile has six neighbors: east, southeast, southwest, west, northwest, and northeast. These directions are given in your list, respectively, as e, se, sw, w, nw, and ne. A tile is identified by a series of these directions with no delimiters; for example, esenee identifies the tile you land on if you start at the reference tile and then move one tile east, one tile southeast, one tile northeast, and one tile east. + +Each time a tile is identified, it flips from white to black or from black to white. Tiles might be flipped more than once. For example, a line like esew flips a tile immediately adjacent to the reference tile, and a line like nwwswee flips the reference tile itself. + +Here is a larger example: + +sesenwnenenewseeswwswswwnenewsewsw +neeenesenwnwwswnenewnwwsewnenwseswesw +seswneswswsenwwnwse +nwnwneseeswswnenewneswwnewseswneseene +swweswneswnenwsewnwneneseenw +eesenwseswswnenwswnwnwsewwnwsene +sewnenenenesenwsewnenwwwse +wenwwweseeeweswwwnwwe +wsweesenenewnwwnwsenewsenwwsesesenwne +neeswseenwwswnwswswnw +nenwswwsewswnenenewsenwsenwnesesenew +enewnwewneswsewnwswenweswnenwsenwsw +sweneswneswneneenwnewenewwneswswnese +swwesenesewenwneswnwwneseswwne +enesenwswwswneneswsenwnewswseenwsese +wnwnesenesenenwwnenwsewesewsesesew +nenewswnwewswnenesenwnesewesw +eneswnwswnwsenenwnwnwwseeswneewsenese +neswnwewnwnwseenwseesewsenwsweewe +wseweeenwnesenwwwswnew + +In the above example, 10 tiles are flipped once (to black), and 5 more are flipped twice (to black, then back to white). After all of these instructions have been followed, a total of 10 tiles are black. + +Go through the renovation crew's list and determine which tiles they need to flip. After all of the instructions have been followed, how many tiles are left with the black side up? + +--- Part Two --- + +The tile floor in the lobby is meant to be a living art exhibit. Every day, the tiles are all flipped according to the following rules: + + Any black tile with zero or more than 2 black tiles immediately adjacent to it is flipped to white. + Any white tile with exactly 2 black tiles immediately adjacent to it is flipped to black. + +Here, tiles immediately adjacent means the six tiles directly touching the tile in question. + +The rules are applied simultaneously to every tile; put another way, it is first determined which tiles need to be flipped, then they are all flipped at the same time. + +In the above example, the number of black tiles that are facing up after the given number of days has passed is as follows: + +Day 1: 15 +Day 2: 12 +Day 3: 25 +Day 4: 14 +Day 5: 23 +Day 6: 28 +Day 7: 41 +Day 8: 37 +Day 9: 49 +Day 10: 37 + +Day 20: 132 +Day 30: 259 +Day 40: 406 +Day 50: 566 +Day 60: 788 +Day 70: 1106 +Day 80: 1373 +Day 90: 1844 +Day 100: 2208 + +After executing this process a total of 100 times, there would be 2208 black tiles facing up. + +How many tiles will be black after 100 days? diff --git a/www/statics/aoc/2020/24_input.txt b/www/statics/aoc/2020/24_input.txt new file mode 100644 index 0000000..a65f7ae --- /dev/null +++ b/www/statics/aoc/2020/24_input.txt @@ -0,0 +1,535 @@ +swsenenwneswnewseswwseswnwsweeswnw +esweeeeneeeneeeweeeenenenee +ewewsewswnewnwnewwwwsew +nwnwnwnwnenwwnwsenwnwnwnwnwnwnw +nwswseswneswseswswneswswseneseswswsenwswse +swswswneswswswswwneseswwswsw +newnwwnwnenenenenwsweenenwnenwnenese +senwsewseneneseneenenwwneneeswnewsw +eeeeneweeeseeeeeenewneswe +wnwswwewwwsewnwnwwnwnwwwnwnwnww +nenwnwnwnesenwwnwnwwneswnwnenesweneenwnw +nwwnwwwwenwwswnwwwwwewsesew +swnwswwswswewswseswnwne +wswnewswnwwwwenewsewwwwneswe +nwnwnenenewneneneneneenenesenwneswneswse +nwewsenwnwneseswwwwwwswwswwwwe +nesenwseneswseswnwneseseseseseswnwse +wnesweseswenwnenwnweseeseseeswnwse +swswnenenenenewneneeeneneeneneenenene +seseseseeweseeesee +wwwwwwwwwnewnwwwswww +sesenwesenwseeseseseewswneseseesesw +wnewwwsewnwwnwnwewnwswnwwwwnwe +nwnwnenwnwneneenewswnwnenwswnwnesenwsw +eeswwneeneneeneeneeeeesw +seneenesewneeneswwnenenweeenenewwe +seswseswsenwswswseswswswswenwswsesesw +nwnwnenwnenwnenwnwnwnenwswnenwwwnwese +wnwwwwwnwwwnwwnwnwseneenwnwnww +ewnwnwnwnwnwnenwnwnwnenenwsenenwnwnene +neneweeeeneeneesweseswswneseswse +seswseeneswswswseseewsewnwswswwnwne +swwneneneweseswnenwneeneneeeeeeee +swwwwwwwwwwwwswswwswswnesew +eewenwseeeeeweeeeneeese +neneneneneeneswneeenee +sewnwnwwswnwseenwwnenenwwnw +swsweswswswswsewseneseswswsesweswnwsw +nenewewwwwwwwwwnewwswsesewww +enwsweneseseeesese +swneseseseneeseesenwwseneswseseseseew +nwswswneeeewneseenwnwnesewwswnwesw +nenenwneenwneneneneneneneneneswenewne +nwneneseeenwnwnwneneneswneswwnenwnwnenw +neseenenwneeneneneeeeneene +sesesewseseseswneseesesesesenewseswsese +senwnewseneneeeneeeeeenesenwnene +eeweneneeenweeeseesweeeee +esesenwswnwseewseswseeeseswenenwse +neeneeeseswseeesweneeseeesweee +swweswnwneswswwswswneswswswswswsw +wwswwwnwnwnenewnwenwswnwsesenwnwe +neseneenwneeeeeneneeeewneeene +swsenwsesesweswsewswswswsenwneseswsesw +wewwwwwnwwwwwnwwwnw +swseweeenwswneseseesenese +senwsesesesesesesewseesewe +sewnwnwnweswnwnwsenwnwnwnwsenwnwnwnwnw +swswswswswswswswswseswswswswswswwswnesw +wswnwnwsewwnwewwewwnesewwne +enenenwnewnenwnenenwwneswneseswnenwsenwnw +seseseswswseswsewnwsewswswseeseeswse +nwseswnweswnwneseweswsesweseseswne +seseswwnwswneneseneneseeseesenwswnwww +wswswwwwswwneswseswnwswswsew +senwnwwnwnwesewswnewswwsenwwnwnwwnw +swsewneswswswswwswswwswswswsw +eneseeeswneswneeseesenwewsenwewnwnw +neneneeeneweneneeswe +neeeseeenwnweewswnewneseneenenee +senewesesenweseseeesewsesesesesesee +eseeeseseseenwseeneseseeewse +nwnwseseenwenwnenwwswnwnwnwwnwnwnwnwnw +senewweseeenwsesesenesewsesesesee +enenenwswnenewswenwnwneenwwnwswnenene +eswseseneswsenwswseseseswsesesewsenwsesee +wnwneswneseneneneneeneneswenenenenewne +seswneewsenesesewnwwswnesewswesenwne +eswwesenwwenwnwnweseseeeeeese +neeneswneeswnenesenwnwneswnenwneneswsene +swswneseseswswswswwewnwsenwesweneswnwe +nwenwwwnwnwnenwnenwnwnwnwnwsweneswe +seseneneeseseeeeswsenwwwesesenwe +sweswseswwnwsesesewseseseseswseneswnene +seswseseseseseswwseswsenesesesesesesese +sesesenwswswseswswsw +senwseeeeseseeseseseenwewswesee +wwsenwewwnewwswwwwwswwwwwne +nwnwnwneswnwnwnwsenwwwnwwnwnwnwenwse +swwwswswswwwsewnenwswwswwswseww +enweenesesesenewnwnwwswswswseseese +swnenenenenenenenwnenesenewnenwnenenwnene +enenesweeeeseneeneeeneeneeew +wnweseeswnwwenwnenwnwnwwenwnwsenwwnw +neswswswseswswswwswnesw +neswseeneseswsewseseswseseswswwswswse +seeneswsesenweeeseeseswsewenesee +wewewwnenesewsenwwnenwnwseswsww +nwnwsesewnwseeeswnwnwseewseenw +nwwwwwnwwnwnwwwwnwsenwwwwsew +eenwneseeeneeneenenwseeeeeee +nwenwnwnenwswnwneesenwwwnwnwnwsenwnw +swswswswseswswswswwseswswswswswswswswne +swwwwwwwwwwnwwewwwnwwww +esweeeeeeneeenwnwenesw +eeenweeeseese +wwwnewwsewewwwwwwwwww +seseseeseseesesenwesewseeseseseswnesese +senwnwwneswwswwnenwwwewnwnwwnww +swnwsesewneenwenwseenwneeseeseewsw +eneeneneneneneneswsewswsenenenwnenenenw +wneesweseswswwsewswnweswswewswswse +neseneneeewneneenewnenenenenenenenene +wswnesewwsenewswswswswneswswswsweesw +swswsesenwseswsewseswneseseseswsesw +seswwswwwseswswswswswweswneswswnewsww +neneesenewewnenwneneneswnwweswswnese +swswswwwswswswswswwneswswwwswseww +neenenenenenenenenenwsewneneneneswnenene +eneeeeseenenwwesenesweeseeesw +swswswswswswwswnwswswwswseswswswsw +eneseseseswsesesewsesesesesenwseseswenese +nenesweenenenewneneeeneswnweenene +eneswsenwseenwenwene +swsewnenwenwwwwseseseswnwwne +seeseseseseseseswsewsesesenwseseseewse +swenewswnenwswsweswneswswswse +wnwwnwwwswwwwnwsenenwnwwwnwwww +eswswwswswnwswswwwswswsewsweeswww +nwwnwenwnwnwwnwsewnwwwnwnenwnwnwnwnw +seswwseeswswseenwneseswnewwswseswsw +enewwwswesewwnenwseswseweenwnwnew +swseswseesenwseseseseseseseswseswwsee +neneneneneneneneneneneenwnewneswe +wnwswswnewnwnwwwsenewweeswnwnenww +swenweenweeneswneeeeneneee +nesweswswseeswswsenwswsewwseneneswse +nwneswewnwnenwnwnenesenenenwnwnwneswnene +wenwswnwnwnwnwnenwnwnwenenwnwnwnwnwnwnwne +seseneesewnwnwneenwseeswswsesewnese +swnewswnwswnwnwnwwenwnwseewnwnenenww +seesesewenwneeeenwnesenenwsweseswnwsw +swnenenwnwnwnenenwnwnwnwswnenenenenwnwse +ewewnwwswesewsweswnweswswnwnwwnesw +neseneewwswwwwnwwwewwwwwsww +enwnwnwwswnesewwnwnwsewswnw +sewwwwwsweswnwswswnwwwwewsesw +neneneseweneenenwesewnenenenenenese +eeeenweeeeswseewnweewneswnew +wnwnenwnweneneswnenwenenenwnesenwne +eseseseseswsenwseseswsesesesesesesesese +eseeseeseeesesenwwseene +nenwnwnwnewnwnesenwnwsenwnwneneseesw +ewwnwnewnwwnwnwnwnwnwswswswwwnwenw +senwwneeneeeneneneenewneswenwnene +nwnenwnenwewenwnenewseeeenwswswwswe +wwewwwwnwwnwwwnw +eeeeeeseseeeeeeeeeew +wnwneeeseeneeneeneeneweseeenesw +nwwnwsweswwwseww +swswwswneswseswswswseswswseswsesweswwsw +newneneeneseenenenenenenenenenenewwne +nesewwwwswwnwwwnwwwneewwwsee +enwseseseseeseseseeeseesese +seeseseseseseeseseswneseswseseesesesenwse +nwseeseeesesewswseswwsenwseswneseesw +wneseenwnenwenwneeneneneneneeseesee +nwneesenwsweeneneneeseeneesenwww +nenenwswnwswnwnwnwnwnwnenwnenenwnenwnwnwnw +nwnwnwenwnwnwnwnwnwnwnwnewnenwnwswnwnw +wwwwnwwnwwnwewnwnwnwwnwwwswnw +neewneenewseneneeneneneneneneneene +neneneneneneneneneneswnenwnenenwnesenwnene +eeeeeeeseeeeeeeneeweee +ewwsweswsweseswswswswnwnwewnwnesw +weswswseseenweneesenenwnwnwneswswse +nwswswseswwswswswswwwswsww +seswseswwseseswswswneseswseswswswneseswswsw +eneeneewnenwneeseeneneeneneneseeee +eenwnweswenwenenwswswneeeewese +nenenenesweneswneswnenwne +enweseeseeneesweswnwsee +swnesesenenwwswnwsesenweneenenweswwew +nenwnwnwnwnwnwnwnwnwwnwnesenwswnwenwnw +nwwnenwnwnwswnwswsenwnwenwnwswnwenwnwe +swweeenwneswnwnwwswsewwswswseneew +esewnwseenwseseenweseseseesesesenwse +enweseeeeseseeneeseeeseweee +eeseeeeseseseeeewneeeseeeswe +swswwwnewswwswwswwswwswsw +eewseeenwsweenweneesewnweew +wswswsenweswnwsenwnwswswwneseweneww +nenewswnenesenenenenenwnwnenewneenenene +nwnwnwnwnwenenwnwnwwnwnwnw +sweweesweseeeswnweenwseneeenwee +ewesesenweseenwseseseeseneseeeswe +eneenenewnenenenenesenenene +eeeesesweeewseseeeneesewenesew +wswwwswswswwswswnwsweswswwswnewseswsw +swswswseswswswswswswswswswseseseswswenw +neenenwenenweseweneenesenwswneswnwswne +seswwwwwwwwwwwwwwwwnesenewne +swswswswswsweswswseswswswswswswseenwnwswsw +eneeeseeseseeseeseewseseseseee +swneswswwnewewswswsewwswwswnewse +wnwnwwwswwnwwewwwwwseewnewsw +senweeneeseeewenwsew +nwnwnwnwseswnwnwnwnwenwnwenwnwnwnwwwwsw +eeseneeeswewenwneeseeeeeee +wnwenwwnwnwnwnwe +wswwswswwwwwwsewswwneswswswsww +nwnwnwnwnenwnwnenenesw +nenewwnwnwswnwesenwneseneenenwneewne +nwneneswnwnenenwnwwsenwnenwnenenwnenenw +swwwwswswnenwsweswenwswseneswwswnese +eeeeewneweeeeswsewesweenwene +seswsewnwwnenwwsesenesewnwweeswswnwse +senweeseseswnewseseswsenesese +nwsenwnwnwnwnwnwenwnwnwnwwnwwwnwww +wseseseseseswswswswneswse +nwneneswnenenenenwnenwne +esenwseeswseseseseseseswsesenesenwswse +seswswswswnenwswenewenwneswseswwswswswse +sweswwwnwswwswwnweswww +swwswsewswwswwswwswswwnewneww +swseneswwnwweswswseswseeswwneswswswew +eseseseesesesenweeseseseweeseswese +swswnwnwnweswswswswswswswee +swseneswsesenesweewwseneswseswswnwnw +sewseeseseseeeseseesesesenese +seswnesesesesesesewseseseswsesesesesese +seseseseswseswseseseseswsesewseswsenese +enwnenwenwnenwnwswsenwnwswne +enenewnenwneneneneneneneewnenenenene +nwwsweneswwswwsewswwswwswwenwswsw +swsewseseneswswswseseswseeswseswsesese +neneseewneseneneneeneneenwnenewe +wwnwwwewswewwwwwwwswwswww +eeswneneneneneneneeneneneswswnenenwnw +nwnwnenenwnwsenwnwnenenwnenw +eeseseseesenwseseeesesesewseseseseesw +wewwwswwwswwwwwwswnwsewwnw +nwwnwnwwwnwnwewnwnwwnwswswnwwnwe +nenwnenwnwnenwnwnwswnwnwwnwnesenwnweswnenw +wwneweenenwswnesesewnewswswwwse +seswswsesesesewswseseseseseseneseswsese +swswseswseseswseswseneeswswseswsesewse +eneneenweeewnwesenenwseswseewwe +swenenweeeneeeneewseeswenwee +enesenewwwswseseswsese +eswneseweneneeneneeenweneneeee +eseseeseseeweswswenwneeeeneewne +wnwwneenwwwwsenwwwwnwwwwww +nwnweseenweewneswesweeeeeneew +swswswwnewswwswseneswwwswwwswsww +nenwswnwnwnwenwnwnwnenenwnwnenwnwnwnene +nwnwwwwnwnwwnwnewnwnwnwnwsenwwww +wswnwwseswwswwswwnwwewswsewswew +wneeweneneneseneswnewnenesesenenwnee +sesesesenwseswseswsesesesenwsewseneesese +swseswsenwsweseswsewswsweswse +nesesesweewwsweswseseswnwnwnwswsee +nenwnenwnwnenenwneswseseenw +sesenwswsenenwseswnew +sewseseseseeseseseseseesesesesenwseseswse +sewwenwnwnwwnenwnewswnwwwwnwwwnww +nwnenesewnwnwnwnwnwnenwsenwnwnwnwnwnwnwnw +nenwseneswnweseseswneweswnesenweewne +sesenwseseseewseseewseneseesesesesw +wwnwwnwnwwseswwnwenwnwwwnwnwewww +seseswsenwseswswseswwneseswsese +sweeswnenenenwneneenweeeneeeeene +seseseseswneswseswseswsenwseseseswsese +enenenenenenwnwnwnwnenesenenwnwneswnwnene +swwsweswwswwwswswswsw +wwswwnwsewswwnenwwwwwnwenwnww +eenwnwseseseseeeeeeeeeweeswswe +nwsenwnwnwnwnwnwnwnwnenwnwnenwwne +swwswswsweswswswswwesweseswswswswsww +seseesenwseweseeeseseewseseswsese +nwseeeesweeeeeseeweeenweeee +seeswneseseseseseswsesesesesesesesenw +eswenewsenwwneeeneeneeneenenee +wswenwnwenwwnenwwswesewseneweewsw +sweswenwswnwswswnwnwwnweenenwnwe +nwenweeswswwww +nwneneneswnwnenenenwnwneneswnwnwnesenenene +swseeesweeewsesenwweseenweenee +nenwneswneswneneenesenesewnwnesenewnenene +sewsesesesesesesenwseseeseneseewwsese +seswswswswwswwneswwswswswswwswwwnw +eeesenweeewseweeeswweneswnenw +eeeeeneeeweseeweeeeeeee +seswnesesewwseseeenesenewseswwnesw +eeeeeeseeewseeeeeneseeee +nwwwnwenwwswwnwenwwsenesenwwnw +wwwwwwwwwsenwwnwwnwwnwwwsew +seswswswseswseseswswswseswnwesenwseswsesw +eneeneeneneeeeweneneneseweneee +swwwwewswnwswewnwswwswwswwwswsw +eswneseeneneewneswseeweeeneenwnenw +swswnwwwseswnwnesewseswwnwswsenwswe +swswswwsewnwwwewswwneswsewwwnw +nwnwwnwnwwnwnwsenwnwnwnwnwnwseenwnwnwnw +seseseewsesesesesesenenewsesesesesesesese +nesenenenenenwnwwnwnenwnenenewneneneene +wesesesenweseseseswseseswsenwswsesewse +eseeswseeeswenweeseseeeneeee +neswwnwwwwnwwwewwnwswwenwww +nwswnwnenwnwnwnwnwnwnweswne +nwwwsenwnwnwwnwsenenwswnenwwnwnewwse +seenwseeenwweseeeweesweeeese +swswsweswswswneswswseswswwwswswswswneswne +ewwwswwwwswwwwnwwwwwswww +seswsenwseseseswsesesese +neneeswewnenwswneneseswenwseewenene +swnwnwenenenwnwnwnwseenwnwsenenwnwwnw +nwneswneneneneneneseneneswnenenwnenw +nwnwnwnwnwnwsewnwnwseenwnwnwnenwnwswnww +seswseseswseseswneswneswswseswswseswswsese +wnwnwnwnwnwnwnwnenwnwnwnwnwnwsesenwnwnwnw +seseseeesesewsenenwseweeseesesee +nwnenwwweseswnwwwnewwswseneseww +swnwseseseesesesesesewseneseseseseswsesw +seseseseesewneseseseneseeeseseeswsese +nwnwwnwnenwewwnwneseswwwwnwww +esesesesewseseseseseeseesenwsesesese +eswswnwswswneswswswseweseseswswswswne +swneenenenenenwnenenenenenwnenwnesenene +nwwswnwswswnwnenweeenenesenwwsenesw +eeeeeeeeeenweeeeenwswswee +nwnenenenwswnenenwnenenenw +nwwwnwnwenwnwnwsenwwwnwwnwwnwnwnwnw +ewneweseeseseseseese +nwnenwnwnwnewsesenwnw +nenenwnewnwnwnenwsenwswneenese +wnwwwwwnwwwwnewsewwwnwwswwnenw +enweseeeeseseeeee +wesweseneswsewnewwneewenenenwnwse +eseeswseeseeseseseseeseenweeee +wnwnweweswsesenweseseseseseswewsese +eeeneeseeenwseeeneenwseweeee +esenwseswseswswseswseseseswseseseswswse +wwseswnewwwswewwwswnewwwew +eeeneeeeeeenweeseenweeswee +sesenwneewswweneswnewsenenwenwswnw +nwnwneseenenewewnenewswneesenenene +swweswswwswswwnwwwswswwwswnwwesww +swnenenenwneneenwnwnwnenesweswnwnenenwnw +nenwnwwewwnwnwnwsewswneenwswswnwnw +nwwwsewwnwnewnesewwwwnwnwnwnww +wswwnwsenwswnweswweswswwwwenenw +neswswswneseswwswwwsewswwswnwnwneesw +newewwswwswwewwwwwwwwseswne +neenenweesweneneeneneneneneneneenese +eseseseeswseweenweseseeesesesesee +swseswseswswswseswseswswswnwsw +nenenenenenesewneewsenenenenenenenenene +eeswneseenweseeeeeeseewsewseee +nwewswswwswswwswswwswswswswswswnwse +nwnwnwnwnwnenwnwnwnenwswnwnwnw +eeeseeeeeeweenweseseseeese +swswwwswnewsewswwwnwswswsenwswsesw +seseswsesewsenesenesenw +seseswswseneswswswneswseswswnwsesesesesese +nwnwwnwnwnwenwnwnwnwnwnwnwnwnwnwnwnw +neeneseeneneneneeneenewneneneswnenew +nwsenwnwnwnwwnwsenwnwnwnwnwenwnwnw +swswswnwswswswswneswneswswswswewseswnwsw +seswneswswswswswswswseswswswswswswenwsw +wwwwnewnewnewswwswwswwwseswww +swenweswseswseneseswswsesewsese +ewswseswwsewsweswwswwswsenenenesene +swwnwnwnwseneseenenenwneswwwwwseswse +nesweneneeseneneneneneenenenenenwnwnenee +enwnwwwnwnwnwnwnwnwnwnenwsenwnwwwnwnw +wwwwwswwwwwnwwwewwnew +nenenesenenwnwswenwnwnenenwneneneneeswne +eeneeneneesweeneneneneeeeewene +eeseseenwnwsesesenwesenwesesesewese +neeeeswswneeeeeeenweeene +seseesewnesewseseeseseswseneseswnwsene +sesesewseeeneeseeseseseseeseeese +wswwnwwnewsewnwnwnwesewwnwnesene +eseeneenenewnenenwseesenwnwnesewnene +eseeneeswnwneesesewwneswewwneesw +neneswseneenwnenenenewneneneneneneseneene +sesesweseswsesesewseswsesewsesweswse +sewsesesesesewseseseneseeseneesesese +swwwenwwnwswnwnwneswwwnenwsewnwww +swwswswseseswswnwseswswswswsweseswsesw +senwenwnewweneneswswnwswwsenwenwenwnw +nenwnenenenenenenenenwneneneneneneenwwsw +wwnwwsewsewswnewsenwneesw +nenwnwseswnwnwenwesewnwneeswswnwnwswnw +nenwswnenenenenweneseneewseeneewswene +esenwwsenenenewnwnwswnwnwnwwwwnwnwnww +sesenweeeseseeeseseeseeeseswese +neneneneneenenenewsenenenenenenenenene +eeeseeeesweneneneeeeeenenwe +eswwwwnwneewwswwnwwneswwseswswwsw +wseseeeesesesesenweeneseseseseeee +esesesenweeeeeweeeswenwne +wwwwswneenwsww +seseswseneswswswseswseswswsewswswswseese +weseswseeeneseseewnweseesesesee +swswswswswswswswneswswsw +swwswswswswswswswwswswenwwswww +nweneneneeeneneeneeseneneneneene +swwswwwneneswswwswwswwseswnewswsw +eeeewenwweeeesweeeee +wnwseeewswswwwswsewwswnewnenew +ewseneeswswneswenweswnwwwwneswwe +eswseswnenwswseswwseseesesesenesesesw +senweeseseesesesesesw +nwsesesewsewnweweseseeseswsesesw +sewwwseseswswneenewenenwsenwseww +nwnenwnwneswswsenweswneneneenenenenene +eswnweeeeneeseneeeswenweneenw +wsenwnwwnwnwnwnwnwnwnwnwwnw +nwnwenesewenwnwnwwwnwwnwnwwnwew +nwsenwnenwnesenwnwnwnww +wnewneswnwwsesenwwweweseneneww +swseseseneeseswsewse +nenwsenwnwsenenwwnwwnwnenwnesenwnwnwnw +neswswswswnweewnenwswswswswswswseswswne +nwseseseseseeeseseseeeeseeeswsese +wnwnwnwwwenwsewnwnwwnwnwwnwnwnenw +wwwwwnwwewnwww +nwswswswswswswswswswswswswswneswseswneswsw +nenesweneneeneneneneneeneneenenee +swswswswswswwseswwswwswsweswswswnwwsw +nwwewswwnwwwwnewwnw +eeewenweeeseneeeseeeeeeeswe +swswenweswseseswneswswswsewsesesenenww +eeseeeeeeneswseseseeeweeeee +eeeseseeeeeeeeseenwenenweswesw +neswseswswseseseswsesw +sesenwwseneesewseneseseewneswswneswne +senenwswswwwsewwsenenwwenwewnew +neeseeweeeneeenenweeseeeee +nwswwswswswseswwswswswnewswswwswsesw +swneeneneeneswnwsesesesewnwesewsesesw +swswenwneneewneswwswswesesewsesw +nwnwsenenwnenwsenwnwnenwneneeswwnenewnwnw +swsenenewswswsewwnewwwnwsewswwsw +swenenenwseseneweenene +wswwswneswsewswswswswswswsw +wsenwsenwwwsewwnwswwnenwwnwnwnwew +nesweweeswwseseseseeeeneenwew +wseseneswnwswseseswseswswsenwwswswswesw +wwnwnwnewswenweswenwnwenwnwswnww +seswneswswseswwseswswseneswswnweswswswsesw +swwwnewswwswswwwwwsww +enwswswneeneneeneneneeneee +swswwswswswswswswswneswswswswswsw +sweseneswwseeeneeenwnenweswnenwne +eseeeeweneeseesewseswnewe +enwesweseenwseseeeesweeeenese +eswsweesenwenweeeeseeeeeenwee +eeeesenweseeeeeesweeseeee +wwseenenwnwwnwnwwwwnwswsenwwnwenw +sesenwseseseeseseswseswseswseswnwsenwsese +eeeeneeneswnenwee +seswneseswseswnwswswesesewseswswswswsenwse +nwnwwnwwenwnwnwnw +eenenenwneneeswneeneneseneneenenene +seeseseseswseseesesene +seseseswseseswnwswswwseswsweseswsesesenw +nenenenenenesenenwnenenenenenesenenenewnenw +nwenwnenenwnwenwswnwnwnwnwnwnwneneswsw +nwneswswnenenwnwnenwnenwnenwnwswnenwnwnw +eneneneeeeneeeweneeneenene +enenenenwnenenesenenenenewneenenenene +seseseseseswsesesesesesesesesesewnenesese +nwnwenwwnwenwwwenwnwnwnwwwnwwsw +eeseeesweeeseeeseeeeewnwenee +sweneneeneeeeneeewneneeneneenw +nenewnwneseseneneenwwswneneenenwwse +nwswwwwneswsewwswwneweweswnwsew +swswnwswswsweswsesw +nwwnwnwnenwnwnwswnwnwwnwnwnwnwwnwwew +swwwwwswswwwwneswwswsewwwwsw +seswsenenenewewnenenwnenewenenenenesee +wwnwwewnwnwenwwnwnwwnwswwwsww +wswswswswswswneswswseswswswswswswwswsw +sweseeeeeeeeenwneneeeenweee +eneneneeneneneswnenenenewenenenenwnesw +swseeesewsenwswsesesw +eeneneenenwneeneweswsweneneeene +swseseseseseseseseseeeenwswseesesesenese +eneweeneeneneseenenenewseeeneenew +eeswswseenenwnewe +ewenwwsesesesenwnwwesenenwnesesew +wwwwnwwwwnwenwwwnwwwwsenww +swnwsesewnenwsesesesene +sewnenenenwneenewsenwnenewneeesesw +swswswswswswswswseswnwswsww +seswswsenwwswseswnesweseseswswseseesenwse +eswswwswswnwseswswswswswsweswswswswsw +nwnweswwnesenwnwnwnweswnwnwnw +eswnewwswesewwwnwewwesenwnwwsww +eswnwneneneeeeswnesewnesweeeee +ewswwnwnwnwwwnwnw +eeneneeeneneneeenweneesweswnese +seswseseseswseneseseswweseseswswswseswsw +nwnwnwnwnenwwwenwenwnwnwesenwwnwnw +sewwnwwenwswnwnww +wseneseswseseswswenwseseswswswswswwse +seseeneseweneneswnwseenwswnenenenwnene +nenewswnwseseneeneneneseneneneewnenw +eneeeneeneeeeneeneweese +wwewwswwwwwwswswwww +seswseseseseseswseseneseswnesesesesese +neneswseswnwwseswswswwswswsweswnwwswe +newwswswswswwswswneeswnewswsewese +eseeeseeseeeeeseewe +enenewnenesesenewnwswsenesenenwneneneesw +neeseeeeesesweseseseeseseenweese +nweswswswswswseeneswwsewswswswswswe +wwwwwwsenwwwnwwenewwwnwwsww +swsesewnwswswswneweswswseeswswneswsew +swseswswswswswswswnesweeswswswsenwswswnw +eeeneseeneweneeeweeeneeneenee +nwnwnwnwnwenwnwnwnwswnwenwnwnwnewnwswswnw +nwwnenwwenwnwwwsenwnwnwswnwwneww +senewswswnenenenwneeneneneneneeenenenene +eeseseeseesesenweseeseeseewse +neswnesenenwswnenwswnenwswnwneswswnewseee +senwnwnenenwnwnwnenenwnwnenwnwnenene +wwnwwwwwwwwsenewnwww +nwnwnwnwwnwnenwnenwnwneneenwswenwnwse +wwwwnwsewswswwswenwswwswswwwww +nwwwwnwwswenwwwnwenwnwnwnwswnww +nenwesenwewneneseeseenwenewnenee diff --git a/www/statics/aoc/2020/24_solution.rs b/www/statics/aoc/2020/24_solution.rs new file mode 100644 index 0000000..f3f972b --- /dev/null +++ b/www/statics/aoc/2020/24_solution.rs @@ -0,0 +1,208 @@ +use crate::common::AdventOfCodeDay; + +use std::collections::HashMap; +use std::cmp; +use strum::IntoEnumIterator; +use strum_macros::EnumIter; + +#[derive(Debug, PartialEq, Clone, EnumIter)] +enum HexDir { + EAST, + SOUTHEAST, + SOUTHWEST, + WEST, + NORTHWEST, + NORTHEAST, +} + +#[derive(Debug)] +pub struct Day24 { + input: Vec>, +} + +impl Day24 { + pub fn new() -> Self { + let input_bytes = include_bytes!("../res/24_input.txt"); + let input_str = String::from_utf8_lossy(input_bytes); + + let data = input_str + .lines() + .map(|p| String::from(p)) + .map(|p| Self::parse_line(p)) + .collect::>(); + + Self { + input: data + } + } + + fn parse_line(line: String) -> Vec { + let mut r = Vec::new(); + + let mut skip = false; + for u in 0..line.len() { + if skip { skip = false; continue; } + + let chr = line.chars().nth(u+0).unwrap(); + let nxt = line.chars().nth(u+1).unwrap_or(' '); + + r.push(match (chr,nxt) { + ('e', _) => { skip=false; HexDir::EAST }, + ('s', 'e') => { skip=true; HexDir::SOUTHEAST }, + ('s', 'w') => { skip=true; HexDir::SOUTHWEST }, + ('w', _) => { skip=false; HexDir::WEST }, + ('n', 'w') => { skip=true; HexDir::NORTHWEST }, + ('n', 'e') => { skip=true; HexDir::NORTHEAST }, + + _ => panic!(), + }); + } + + return r; + } +} + +#[derive(Debug, PartialEq, Copy, Clone, Hash, Eq)] +struct HexCoordOddR { + q: i32, + r: i32, +} + +impl HexCoordOddR { + pub fn zero() -> Self { + return Self { + q: 0, + r: 0, + } + } + + pub fn move_by(&self, d: &HexDir) -> Self { + return match d { + HexDir::EAST => Self{ q: self.q+1, r: self.r }, + HexDir::SOUTHEAST => Self{ q: self.q+realmod(self.r,2), r: self.r+1 }, + HexDir::SOUTHWEST => Self{ q: self.q+realmod(self.r,2)-1, r: self.r+1 }, + HexDir::WEST => Self{ q: self.q-1, r: self.r }, + HexDir::NORTHWEST => Self{ q: self.q+realmod(self.r,2)-1, r: self.r-1 }, + HexDir::NORTHEAST => Self{ q: self.q+realmod(self.r,2), r: self.r-1 }, + } + } +} + +fn realmod(v: i32, m: i32) -> i32 { + return ((v % m) + m) % m +} + +#[derive(Clone)] +struct HexGrid { + data: HashMap, + min_r: i32, + min_q: i32, + max_r: i32, + max_q: i32, +} + +impl HexGrid { + pub fn new() -> Self { + return Self { + data: HashMap::new(), + min_r: 0, + min_q: 0, + max_r: 1, + max_q: 1, + } + } + + fn update_coords(&mut self, c: HexCoordOddR) { + self.min_r = cmp::min(self.min_r, c.r); + self.max_r = cmp::max(self.max_r, c.r+1); + self.min_q = cmp::min(self.min_q, c.q); + self.max_q = cmp::max(self.max_q, c.q+1); + } + + fn get(&self, c: HexCoordOddR) -> bool { + return *self.data.get(&c).unwrap_or(&false); + } + + fn set(&mut self, c: HexCoordOddR, v: bool) { + self.update_coords(c); + self.data.insert(c, v); + } + + fn flip(&mut self, c: HexCoordOddR) { + self.update_coords(c); + self.data.insert(c, !*self.data.get(&c).unwrap_or(&false)); + } + + fn neighbours(&self, c: HexCoordOddR) -> usize { + return HexDir::iter().filter(|d| self.get(c.move_by(d))).count(); + } + + fn step_automata(self) -> Self { + let mut a = Self { + data: HashMap::with_capacity(self.data.len()), + min_r: 0, + min_q: 0, + max_r: 1, + max_q: 1, + }; + + for r in (self.min_r-2)..(self.max_r+3) { + for q in (self.min_q-2)..(self.max_q+3) { + let coord = HexCoordOddR{r:r, q:q}; + let old = self.get(coord); + let nc = self.neighbours(coord); + + if old && (nc == 0 || nc > 2) { + a.set(coord, false); + } else if !old && (nc == 2) { + a.set(coord, true); + } else { + a.set(coord, old); + } + } + } + + return a; + } +} + +impl AdventOfCodeDay for Day24 { + + fn task_1(&self) -> String { + + let mut grid = HexGrid::new(); + + for path in &self.input { + + let mut coord = HexCoordOddR::zero(); + for step in path { + let coord2 = coord.move_by(step); + verboseln!(" Move [{},{}] --[{:?}]--> [{},{}]", coord.q, coord.r, step, coord2.q, coord2.r); + coord = coord2; + } + + let state = !grid.get(coord); + + verboseln!("Set [{},{}] -> {}", coord.q, coord.r, state); + + grid.set(coord, state); + } + + return grid.data.iter().filter(|(_, v)| **v).count().to_string(); + } + + fn task_2(&self) -> String { + let mut grid = HexGrid::new(); + + for path in &self.input { + grid.flip(path.iter().fold(HexCoordOddR::zero(), |a,b|a.move_by(b))) + } + + for _ in 0..100 { + verboseln!("Black: {} (Size: {}..{} | {}..{})", grid.data.iter().filter(|(_, v)| **v).count(), grid.min_r, grid.max_r, grid.min_q, grid.max_q); + grid = grid.step_automata(); + } + + return grid.data.iter().filter(|(_, v)| **v).count().to_string(); + } +} \ No newline at end of file diff --git a/www/statics/aoc/2020/25_challenge.txt b/www/statics/aoc/2020/25_challenge.txt new file mode 100644 index 0000000..ca782b8 --- /dev/null +++ b/www/statics/aoc/2020/25_challenge.txt @@ -0,0 +1,52 @@ +You finally reach the check-in desk. Unfortunately, their registration systems are currently offline, and they cannot check you in. Noticing the look on your face, they quickly add that tech support is already on the way! They even created all the room keys this morning; you can take yours now and give them your room deposit once the registration system comes back online. + +The room key is a small RFID card. Your room is on the 25th floor and the elevators are also temporarily out of service, so it takes what little energy you have left to even climb the stairs and navigate the halls. You finally reach the door to your room, swipe your card, and - beep - the light turns red. + +Examining the card more closely, you discover a phone number for tech support. + +"Hello! How can we help you today?" You explain the situation. + +"Well, it sounds like the card isn't sending the right command to unlock the door. If you go back to the check-in desk, surely someone there can reset it for you." Still catching your breath, you describe the status of the elevator and the exact number of stairs you just had to climb. + +"I see! Well, your only other option would be to reverse-engineer the cryptographic handshake the card does with the door and then inject your own commands into the data stream, but that's definitely impossible." You thank them for their time. + +Unfortunately for the door, you know a thing or two about cryptographic handshakes. + +The handshake used by the card and the door involves an operation that transforms a subject number. To transform a subject number, start with the value 1. Then, a number of times called the loop size, perform the following steps: + + Set the value to itself multiplied by the subject number. + Set the value to the remainder after dividing the value by 20201227. + +The card always uses a specific, secret loop size when it transforms a subject number. The door always uses a different, secret loop size. + +The cryptographic handshake works like this: + + The card transforms the subject number of 7 according to the card's secret loop size. The result is called the card's public key. + The door transforms the subject number of 7 according to the door's secret loop size. The result is called the door's public key. + The card and door use the wireless RFID signal to transmit the two public keys (your puzzle input) to the other device. Now, the card has the door's public key, and the door has the card's public key. Because you can eavesdrop on the signal, you have both public keys, but neither device's loop size. + The card transforms the subject number of the door's public key according to the card's loop size. The result is the encryption key. + The door transforms the subject number of the card's public key according to the door's loop size. The result is the same encryption key as the card calculated. + +If you can use the two public keys to determine each device's loop size, you will have enough information to calculate the secret encryption key that the card and door use to communicate; this would let you send the unlock command directly to the door! + +For example, suppose you know that the card's public key is 5764801. With a little trial and error, you can work out that the card's loop size must be 8, because transforming the initial subject number of 7 with a loop size of 8 produces 5764801. + +Then, suppose you know that the door's public key is 17807724. By the same process, you can determine that the door's loop size is 11, because transforming the initial subject number of 7 with a loop size of 11 produces 17807724. + +At this point, you can use either device's loop size with the other device's public key to calculate the encryption key. Transforming the subject number of 17807724 (the door's public key) with a loop size of 8 (the card's loop size) produces the encryption key, 14897079. (Transforming the subject number of 5764801 (the card's public key) with a loop size of 11 (the door's loop size) produces the same encryption key: 14897079.) + +What encryption key is the handshake trying to establish? + +--- Part Two --- + +The light turns green and the door unlocks. As you collapse onto the bed in your room, your pager goes off! + +"It's an emergency!" the Elf calling you explains. "The soft serve machine in the cafeteria on sub-basement 7 just failed and you're the only one that knows how to fix it! We've already dispatched a reindeer to your location to pick you up." + +You hear the sound of hooves landing on your balcony. + +The reindeer carefully explores the contents of your room while you figure out how you're going to pay the 50 stars you owe the resort before you leave. Noticing that you look concerned, the reindeer wanders over to you; you see that it's carrying a small pouch. + +"Sorry for the trouble," a note in the pouch reads. Sitting at the bottom of the pouch is a gold coin with a little picture of a starfish on it. + +Looks like you only needed 49 stars after all. diff --git a/www/statics/aoc/2020/25_input.txt b/www/statics/aoc/2020/25_input.txt new file mode 100644 index 0000000..ae2e4c4 --- /dev/null +++ b/www/statics/aoc/2020/25_input.txt @@ -0,0 +1,2 @@ +14082811 +5249543 diff --git a/www/statics/aoc/2020/25_solution.rs b/www/statics/aoc/2020/25_solution.rs new file mode 100644 index 0000000..d2ac959 --- /dev/null +++ b/www/statics/aoc/2020/25_solution.rs @@ -0,0 +1,76 @@ +use crate::common::AdventOfCodeDay; + +pub struct Day25 { + pkey_card: u64, + pkey_door: u64, +} + +impl Day25 { + pub fn new() -> Self { + let input_bytes = include_bytes!("../res/25_input.txt"); + let input_str = String::from_utf8_lossy(input_bytes); + + let lines = input_str + .lines() + .map(|p| String::from(p)) + .map(|p| p.parse::().unwrap()) + .collect::>(); + + Self { + pkey_card: lines[0], + pkey_door: lines[1], + } + } +} + +impl Day25 { + fn transform(subjectnumber: u64, loopcount: usize) -> u64 { + let mut v = 1; + for _ in 0..loopcount { + v *= subjectnumber; + v %= 20201227; + } + return v; + } + + fn transform_back(subjectnumber: u64, pkey_dest: u64) -> usize { + let mut v = 1; + for lc in 1.. { + v *= subjectnumber; + v %= 20201227; + + if v == pkey_dest { + return lc; + } + } + panic!(); + } +} + +impl AdventOfCodeDay for Day25 { + + fn task_1(&self) -> String { + + verboseln!("card public key: {}", self.pkey_card); + verboseln!("door public key: {}", self.pkey_door); + verboseln!(); + + let loopsize_card = Self::transform_back(7, self.pkey_card); + verboseln!("card loop size: {}", loopsize_card); + let loopsize_door = Self::transform_back(7, self.pkey_door); + verboseln!("door loop size: {}", loopsize_door); + verboseln!(); + + let skey_card = Self::transform(self.pkey_card, loopsize_door); + verboseln!("card encryption key: {}", skey_card); + let skey_door = Self::transform(self.pkey_door, loopsize_card); + verboseln!("door encryption key: {}", skey_door); + verboseln!(); + + return skey_card.to_string().to_owned(); + } + + fn task_2(&self) -> String { + return "".to_owned() + } +} \ No newline at end of file diff --git a/www/statics/aoc/__all.php b/www/statics/aoc/__all.php index 2594e64..a6c8924 100644 --- a/www/statics/aoc/__all.php +++ b/www/statics/aoc/__all.php @@ -89,14 +89,14 @@ return ['day' => 14, 'parts' => 2, 'title' => 'Docking Data', 'language' => 'rust', 'solutions' => ['12408060320841', '4466434626828'] ], ['day' => 15, 'parts' => 2, 'title' => 'Rambunctious Recitation', 'language' => 'rust', 'solutions' => ['273', '47205'] ], ['day' => 16, 'parts' => 2, 'title' => 'Ticket Translation', 'language' => 'rust', 'solutions' => ['29019', '517827547723'] ], - ['day' => 17, 'parts' => 2, 'title' => 'Conway Cubes', 'language' => 'rust', 'solutions' => ['276', '2136'] ], - ['day' => 18, 'parts' => 2, 'title' => 'Operation Order', 'language' => 'rust', 'solutions' => ['75592527415659', '360029542265462'] ], - ['day' => 19, 'parts' => 2, 'title' => 'Monster Messages', 'language' => 'rust', 'solutions' => ['142', '294'] ], - ['day' => 20, 'parts' => 2, 'title' => 'Jurassic Jigsaw', 'language' => 'rust', 'solutions' => ['64802175715999', '2146'] ], - //['day' => 21, 'parts' => 2, 'title' => '', 'language' => 'rust', 'solutions' => [] ], - //['day' => 22, 'parts' => 2, 'title' => '', 'language' => 'rust', 'solutions' => [] ], - //['day' => 23, 'parts' => 2, 'title' => '', 'language' => 'rust', 'solutions' => [] ], - //['day' => 24, 'parts' => 2, 'title' => '', 'language' => 'rust', 'solutions' => [] ], - //['day' => 25, 'parts' => 1, 'title' => '', 'language' => 'rust', 'solutions' => [] ], + ['day' => 17, 'parts' => 2, 'title' => 'Conway Cubes', 'language' => 'rust', 'solutions' => ['276', '2136'] ], + ['day' => 18, 'parts' => 2, 'title' => 'Operation Order', 'language' => 'rust', 'solutions' => ['75592527415659', '360029542265462'] ], + ['day' => 19, 'parts' => 2, 'title' => 'Monster Messages', 'language' => 'rust', 'solutions' => ['142', '294'] ], + ['day' => 20, 'parts' => 2, 'title' => 'Jurassic Jigsaw', 'language' => 'rust', 'solutions' => ['64802175715999', '2146'] ], + ['day' => 21, 'parts' => 2, 'title' => 'Allergen Assessment', 'language' => 'rust', 'solutions' => ['1913', 'gpgrb,tjlz,gtjmd,spbxz,pfdkkzp,xcfpc,txzv,znqbr'] ], + ['day' => 22, 'parts' => 2, 'title' => 'Crab Combat', 'language' => 'rust', 'solutions' => ['32495', '32665'] ], + ['day' => 23, 'parts' => 2, 'title' => 'Crab Cups', 'language' => 'rust', 'solutions' => ['27865934', '170836011000'] ], + ['day' => 24, 'parts' => 2, 'title' => 'Lobby Layout', 'language' => 'rust', 'solutions' => ['459', '4150'] ], + ['day' => 25, 'parts' => 1, 'title' => 'Combo Breaker', 'language' => 'rust', 'solutions' => ['3217885'] ], ], ];