commit 0d483e22516804375c804b931c4d8c1c8b85b6cc Author: xenia Date: Fri Dec 1 16:07:19 2023 -0500 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed3a37f --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.envrc +/.status.rktd +*.zo +*.dep diff --git a/1.rkt b/1.rkt new file mode 100644 index 0000000..bd86b88 --- /dev/null +++ b/1.rkt @@ -0,0 +1,39 @@ +#lang curly-fn racket + +(require "scripts/aoc.rkt") + +;; solution for day 1 + +(define (part1 input) + (for/sum ([line (in-list input)]) + (define nums (regexp-match* #px"[0-9]" line)) + (string->number (string-append (first nums) (last nums))))) + +(define (part2 input) + (define (line->result line) + (define match1 + (first (regexp-match #px"([0-9]|one|two|three|four|five|six|seven|eight|nine)" line))) + (define match2 + (string-reverse (first (regexp-match #px"([0-9]|eno|owt|eerht|ruof|evif|xis|neves|thgie|enin)" + (string-reverse line))))) + (match-define (list num1 num2) + (for/list ([z (in-list (list match1 match2))]) + (match z + ["one" "1"] + ["two" "2"] + ["three" "3"] + ["four" "4"] + ["five" "5"] + ["six" "6"] + ["seven" "7"] + ["eight" "8"] + ["nine" "9"] + [v v]))) + (string->number (string-append num1 num2))) + (apply + (map line->result input))) + +(module+ main + (define input (file->lines "inputs/1")) + (answer 1 1 (time (part1 input))) + (answer 1 2 (time (part2 input))) + (displayln "meow")) diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/inputs/1 b/inputs/1 new file mode 100644 index 0000000..f888ae8 --- /dev/null +++ b/inputs/1 @@ -0,0 +1,1000 @@ +8eight1 +98126 +fourfourthreehnbhkmscqxdfksg64bvpppznkh +8fivenvvtrlj +six3zbhvrfhsevennine +427nine6chnqrssxfour +threevvxhvx38rktdqm3 +eightzgqzr3eight +xgjjmnlvznf2nineltmsevennine6 +ninethree15seven +37cjnsfbfkqpkxpdvgk8 +sgeightwo3 +9sbxg +1spnthree59ninejjgjdlx +six9six2gxmn +twothreefdbl6five3zcqvcqxkcvdfkl4 +46six47seven27one +four15 +7sixvmsrrzqnngonethree +3fvsghvkqkbfivenine +zhthfghk6ppc48bdx6two +1fouronesixsvhbglmvxx +7lcsixmzmseven +two37sixccrpqngpvthree +86fivelqmlmbnhq +bvcz4 +6fivendr7seven31nine4 +jmkhtgklhpxxblc2slhlnfkoneonefour +8smpnsc29threesix +r795vgnhqhs92one +eightfive6 +4threeqzslpcvkpfdjh +8cthp65 +twoonenine87 +dzttdmpfxtnine6onefourone3vnnz +8tnnfrsdffpthree67xh +seven5seven27hf +3sevenone +seven9foursskfhnchhf481 +vrfbrcsgp81vsztr +six9dnqqgxtvrngpz7879two +lkvzzdxmr71lglsixfour +two6jkpz9 +1sevenpmjfv +nlvrdmdhxsix7three7frmdlckfjninesix +gfb89qrhtzsfvbnpbp6two +f8mbbtzjvrqkrszlgrlzrlrgmbmmrdqv8seven +sphkkpptpvjzbflkzz2vbndc3foureighttbn +eightnine5zpbzhltpmsxrggdcmbrzkvczqbfsevendtjsr +2snpbrhpnine3sevensevenhftpqgk5 +seventjxr91sevenseveneightwojf +1hfkvhjxrtjfivefive +3fxgmlxtwo +stwoeighttwo3 +eight45t +sixthreecdhbfive3sevensrskjm +fiveklmj94sixlhpfztlk95 +fivefive6 +fiventjm7tndhd57 +teightwo87nine83 +6jskjmxrttwo93four7 +dftzgsdc19threesevennine3twonevl +zmpcgkonethree1cspnkkpjr9 +hmsfrjtxpgn9dqkr9dqvrtq4 +3eightmfggjleight +qfglzvvrrtpfl4 +7eightonefpqq3 +tgtbsmpftwo4hvnvsixfrdqbvqbhspcczfhvqcslvfszvrtzbks +twofivesix34nine +dhlhkjcjsbgnxd6sgrdnzchtxtplltbqlk +oneonegcndlfourdngmbgdeightsix2 +twotj9l8onetwoned +jpz2fourjgrjzf44 +9fivesixmlqr8rxqpvpfzfive2nine +6xkfkrfnine196 +four7gppqtzvbftzcbzt8nqq1nineqdlrff +2threekxgcqjzt4qdbthmjx +three61eightrnkckq +9knfvqgmdsmdqlkfzl +mxsqv6twojgmhpmlfq +7fouronelngndbsmljbfzmsix +fjm8fdpnlldlgvkqdcdcdjpxzdt +7five2 +tsp9seven +eight2hzpkpqrjgcrnxksix +jfourcgjbpzbgdn61dzqbgthree +7threefive +1ncmzhqghthree3sixllvknhf +one5six9 +krzkzmbccr1 +74mqnzmqnf6 +four9pfhjktmvxtwo +6bl21bpx2 +4threefdpfqck +jjksjbsjlgdonefour5 +2hbthreegfh1 +threegzbn1four4hbqkmtmoneightrhg +fiveeightnine83 +3five49jvrhvmnjmmzlzmhpbpsfpn4 +3vvhshsixone3 +55three7svtlzzggkqjhjx +fxdmnjsvpjbg69gcknlzgrqhqdsxvk3p +eightfcnmbzl2jhlklgmlmsevenkjbgzhstwo +6sevengdmtlfjmns63 +ktgqthreedfmrpdvnkfvs3jsgcvtdkh +4seven1 +34onexkninex6pnldxrfs +threenine3five9eightrvg9 +xqbnmtrlsjninenine57rpcsjpqfdcbd6 +216two +xhrdmfcvjzt4sixfkjsvkfhtldfqckj +2six8zeight1 +cmpklgjgf19twoqstfhphbxxtfdgj2 +lvgqnkqhltwo9r +twosevenfive2rgfsgmzqjbnine +7ddpjxmfschtqdgnjqc18one +oneninefiveeight6 +qs4five5 +rpxbcff9vpmlvvrlonefourdnczqzjbvnine3 +7592r3qjtwothree +sixtwoninegzrfp9hq6six9oneightp +f8seven1dcrjqchxchfour8 +bnhmfmsbzbhfive1rfqqkzkptjnnxpone2jqhrfnvkfk +qlhpvzdkcfsq84 +dfour5one +hcvxnfm32kpzxkhvmvkjsevenllpjpgdhl +dlhhnk2ctvxqmbmsc9five +one7sevenninesix +two4rkb5sixtx17 +28three7 +msixeightnqmtfmtftsix9 +zff8nineflfpz1six1 +vk9 +86ninelzskddf9784 +mrntnhjrvkjgmntone715ktgb7 +sevensixthreegkldpptbmteightsix2nfnljvkfkgc +nineonenine3ssnjhkhdplvq3six +jrdgsz8 +5nine6bglkndgfnineq +nineone8seven5zhdd2eight +17qjzvtwo +4rncnvtp5ssznhncdnnzndr9 +6srf +5two6xxkzdrbfsix +five314sevenseven +eightsix7lhfqone +gdz3one +6sdplqg +rsnnm3twoqlxjjvzeightvxszxhmnck +7onelvrtdktmcmrm55 +1eightzvcgfqgfh +ssgrzpb6jntxrdhvmrkeight +5oneninetwo +gjktwopxxql4gxfourseven9 +four55sevenvglcrqsdt +nsqrjfhs2eight +seventhree5g9 +threehvmrmvglvvsix7pqxzfjvv +cfgfmgg5vmqnnqrxdxone35 +two2fxsmdjmb +rrlxrkjkxmfrbvxsevenrlllvclhvvfourlp4seven +djdoneightthree82eight6five6 +two4threecdbgnmzvdd53oneeightkmx +one5qdtnrpcmrnnsbeighttwotwoninegtpv +86htqkfrkmone217 +onelqd5jvlbm4 +eightone3rpnkglzfcveight12one +fourqfxndmpgbqrcpclbnn86hxsxqrrkjcgtgxbdxjdjlzcrhkp +1one18tjcsjzpmzmpmstzmcn9 +threesevenpgt3 +four9sixthree1 +twoninethreesxxqgqlqmqxkmkl2qdrqpftwo +seven678 +two29six958kqxq3 +dbpjzgdrhnsixfjvs9eightsjdgtckdtsjmhplkjeightwodd +7fourninenine +fourthreedlhf9rf +mjkvfivekltmfourone2 +7twozrrtg498one +4eightcxnx +one62eightdktgeight2five +bnpxcdxpzp4tklvsm +d8sixninegrbx +threefourfivetwo23 +nine3onemqtbrhlp8jqslv66ssjrkh +1four9fournine2 +xfsl83two4 +65twonine +1twofivevctxpfvr18 +819gc4six79 +27vtvmsix1phzrone2nine +boneight1mskkndkgfive +1xmpkmg3 +one8sixthree9zjtmqjjjtc1nine +six36gqjctdsevenlnmmbr7dplrsdptwo +8jjvgmffgxr5 +fivehgkc5 +2qmbvphfivexggrxljhj9qmjrzmrx8eight +3rndntwoseven +boneight6tworgxffournine +htbvm1grtsgdgbl +1hkndcqv +32sl9six9 +894 +vrhxnstqqmflm6glgfnpfour +5ninekrfivesix8 +5six5 +eightpdzjhvbgm5oneonetwothmnkflz +vnfttnhcs892rmpvjvqvfftmzlkcrzthkbhfour2 +9twoeight +73553bkzzhq +fvxmvs47 +3bhmjpqvzs +pcftqc671 +sixtwo8 +threesdhhzmxtzpsfgs286nmqpvrtkbktcblqqb +7pmhlfcmdxthree11gxpncfqntjtwoone +8fivel3sevenxqtpxjntbjbtxhxtqdfnfour +6seven72zzseven +seven9kcthreetwo2five7br +kvkhl1fzvpseven +5oneoneeighteight6 +lvfx6onefour +ftjzq4 +slbgthc5xsxvplbskk +64nkjjvrmsqzdone +twoonelgcnrmrm52 +gnfmrdkzoneseven7twotxgsjsix1one +1xlrpbbdbdgftkd +8jmphpvclbf87two +724threesixthreetwozsix +bcxdnrd91cprdfcqfive +zxjcgbhfr3 +scfklbckxjggbgz9txqnzf6 +1twohctsdfkgsdteight2 +7threethree +jdj9 +99 +sixfzv24nine2bz +onefour1frf79tcfjchqeight +onethreenkgjgtpxfkmncvmsqs2bsqppgg +fourfourtksqrmnmqfour351lrsnv +6559hthdpeightkfive3 +sixone7 +eightoneeightjcsggnqthree5qqmp +sixeightonegltz7 +three4plz3kls +8sixmssvtthreeseventhreenskzq6 +tbzxjqxkspseven9dtbqvchseven8mbpznrrh1tdmqs +1b7eight +thk23eightfivekvzphvmsfour +7cnlrjzvk66threefxzrtgrbvmbp +bhvponeonefouronedcstbnl8 +eightninesix4fourbrpfp +four29eight +kqh5zkgqphzjvz +4zvh +fivesixnzbsvfjhj2 +rkrnbpsqjdthreez78mg +eight4gzxfdjpnjnskzghlzfdmjhz +seven8fourxzdmlcq1mnine7qbblrqtrsq +gd369 +hgtqgfive8 +pcbgddgvvzpmone4onethreeoneonefive +95nnjhmhrqgkkstwo66 +723sixone9threefiveone +threekfvqsscfjr8 +3vzltxllq65jvthree +4977d +35pgnlsjjpbgseven33 +g25twonineeight +three8eight3six +8five8vjnzglnrbsbxmjqzfvrsoneightlpx +3bksdkncgtmdrlvkgboneffkszhfive8 +five1hfh6 +fourfoursix2nine9t +6onetkhqqonetwo +26hdfljh8 +6onethreefvgnoneoneninefour1 +jghct6rzcbjsfivefourtsrbsjkgmtfive +nine93eightxqknsqhrmjthree2 +fivenine44sixsixlxdkpm +threeeight16jjhdkbhlninekvdvlpbq +onethpbzthhlqxnlrmtwo8 +seveneight1eight +5two8 +4four8vdpmqvf3onenmfg9 +eight9jtxgdzdrtwovznpmnqvnnlffsix +456four +9hxkq +713kthreexfbdrtbx +1five59 +1mxpmfive63 +sixfour1ffivezjj +97eightthreecjnxblrnine +kgqcxfzc4sixnineoneone3eight +9fbklklqqsfourbfhmfmgnbtls3three +xxjnbdxzeightjqvvd82kfchrthmgkfive +zfdeightwokbq3seven +6four696ninezfhrbg +zrznfshdvlxcstqtghjnjvxq1dlklzghbh +steightwoxfbfzlnzvlj7919four +nine48oneeightseven89five +ninesxtdnjkmg7rn32qdljqprj3 +five6xkcg1qmpkddfbsnlhzltlqqjr8 +99sgptmns4five +2ninejdstk +gvclfcg9 +n9lmv +jrftwo3 +sxrxlnvdhr47dppck +jvtwonesixlzdshrfjtzgqddsix7 +7peightoneeightwobsc +three6txdjgqqmsdeightcxmljmmzxksseven +fqpx9three96xrvjvjjnrhknsvfour +9fournjmslzbmx34cnt +f3twovfc +shbtwone3kzdsdrxgr +4five1tfhvd27 +rdccbvkr9gjsmxhfdzgvjcbkdmsdeightlvjkdgtdqmbvscvhpmdz +pzsqhqthreetwo1qxfbhreight +threeeightxonenineninepmjfgzsdhd1 +nine7sevenone +hbsqqtlqcxkjjccmmpv5 +6nineltr5plmbgzfqbxninerxzbzrblmfsmjggvr +5eightwolxp +5cscpfqm +four3nthbmbxfbvtrqqkfmltmtjh +pvxtx89jp9onesevennbxmjlzmfk +threetwoeightzcgkbv1 +7rxxfpgvl3eight8dmhkf +nine6two +tpnr21five1eight +ktsx6threeseven +8four31drvszglmv +fgkmbcgsrjgs6eightfivefqqdksrndrtdbsxgmfgtggmrc +sixnineninefzvthdq5tkzrhrgdqblzndmv +7lfdrntqsm +seven8dgxgqvgvmtdkhqsfkhtqcjpvqlfnine +znltfour6twopsdmcthree +oneeightvvvxxptmk4eight2n +5six1jmmqtknpveight +eightsixxxpbvqhpknz27mqxvf +rbdchcmqhseightnine9 +944five8gxsjf98 +smdhcnbmone9 +one64six +seven4fivesevenfournine +fivetjt27qqxncqcone +five49655onet5 +mlqgmhfgsix3two2 +jxdfkbvdgnjqznineh1rdqsv7 +fqdvcktwoeightsixsevenkkczb3 +3krndk27 +qjpmscfqf2gzgvzgksc +5zs11fourqqzfour +5h +fourtjzxtgrtd2twokrkpfm +fourgxprrlvmhgpggsmzbone7 +ldbprdzrqkgqkx23pjvgrc6 +ninevfh2seven4four +23gfmpvvsrjr4vlntkxkeight +sevensixonefivefour9two +vmchfrmfntwo3sv1twoonenngblvmjsf9 +sqhzppseven79kzdppfnk8foureighttwo +1ljltwo8xhszxqmtponethreesevendkx +4fourfive +5fpzhcd7pmbcxcrkp +cdhqgkhfive61seven +eightqtzrscqhr3 +brrftwothreethree1 +r145pbthqtvxd63 +ninebdnxdvchzf57oneightpp +7one1three68 +five8nknine341msfflpnz +sixxmsevennm6 +2n5cdvvtghfg2lmfrbjbvtwothreefour +39one16 +l3two +xsmtghfiveonesix6lkzfgq4threethree +6onettqbfp +nhxlqqp3vkcgsjgkgmjrpll +xgbzrtkbthbfour7mptxqnbrkvhninetwo +7foureight55cvpgsvsr +3twonine +gsqhbhfrzfour9twovjjbskdonegseven4 +2fourthreedcxrcmjmkprdsbone5one +519955six +two8fjgvtwo7vnttwo5qzlgxcfkz +rvk4eightthree +9six6 +clpxqfn3kcn3 +1pzbkzdn9sixxlq89tcnm +nineninetwogtsjfour2twollrrllvk +three5ql7hdjkxdbrcqsfouronekqhc +ltgeightwothree5ccxbhssxrsbj +42three3 +dkmm8eightnine4five +vqmvzpb9tmmsfgscfive6mtjjbleightfour +ms39zmtbptwofive +4xxxkdxlhjjx +6p +threejfqfjhxp9txlrlrbczdxzpmrkz9sevensjlgstbpffhtb +three2zqtrtpzvsffdkjsevencjmrdqthree6three +two681 +fourlhcsspzf5fivezgzkclbrdrqdjcksfive8 +ss3 +znrzctdlgjpzszsixzssrfpcvhlbpg8spfxsgbctpttbxxxsc +mjfsxjtthljlzzjlxspdsgsstltmlxf6 +48zvpktkpk3 +7khsdbtp43rgggnxf +2ninedkttzmpqddsix +xjcqvkcnbpbqsmclfnsdbnnine3eightfive +7eight6 +eight8zqcdbzqfour3 +one8eight27 +ninemmheight3jdkktmthree +oneeight3lbsrnqrn +8ninefive71 +hd58sixtmdj +fivesevenfourtwo4 +fivecdsvgkfgbntwo42 +593jxn +sevenfxkvdxfjgskjhhphnjrgfhs8sixcnine2 +fourtwo2sixthreefive7rq4 +threesixdhlkvz3fvdslkbs3 +nine3fkrzbjbmjbsr +nine7seven36 +sevenbnncfhrnzq52eight6lvfdmqhxkdqjl6 +zshsmpsmbzpnfthree1five72fivetwo +threenine59seventkthreeflgkvtp +nine9nine6 +8five4foursix4 +jnz1m3fmzzgt9kbtpr +81btdvrcspvfour +three1smvpjdnhveight1sevenfour5rqkqvq +49fiveeightonefive +2xmdtnineczgbqmhfivef1six +638nine +eightsix6twooneseven +jgtwone6gzchdrkts +93tsrvf48 +1qkrdfhpseightninelddrnffp2gc +nqvkkprztqsqfk74threeseven5six +14two +dmhnlgxqpjxxvpshqt2sevenplzbgvsz6 +bffour72 +zgkgvone8bxsnnlninegmjtnsqtdp +19oneninezm88blmdhbcrns +2fivessqk1fonevghgnz +ddszqsldhxpsbprdbqkmhs6ztkbzbkm8cddpqm2 +7eight5xhdtpfive6mbf +qxcnnmdt5vctqqhmvrmqblsixfour72 +6onetworpstxdq3tvrcmssmkfhbr +7twoeight1 +64two3sixsixckbkshnkjmtwo +7csixonegdbrvreight +bfdptjcjdq4five7sevenfdhhqhseveneight +8one8dzbninethrmdldmpn +three7xghxhr1threerqfxseven +two9xrhvzkgcck3vfour +5lvtrgmpttk3fourfour +five581cjndb +3clp81dhzcbzxc +threesixsixbtst27 +fivesixnines146 +gppzks5cqggtq +4rgdzsnqlcxone8vninegkgqh5fcbsfl +jfpdpfcccrjpcfive2threeseven +ninefoursix6sixtwooneone7 +twothree3njhxgc5rhntgnckg +3twopvtmvrcrnr238 +k4mgzqbnkrthreeseven9 +bzkoneight2jxllsevennmhxpgbdkfive +886svgcltdl222 +sevenqjgkjdfrrskhklvrg9fourtwofive +cdsfdkdsvtcjhzdpqdgtwo454five +lmksxbv8foureightbxskfblhllsdrxfs4v6 +49sixfour9nine15two +75mtcmthreelvmsksnine9 +foureight849zgl69 +92eight6ninezjfive +8onejsfvnjktqksixlfnxqrjmdvt8vhttwo +48three +onesixcksvcdeight3tr +hvxqb1fourseven4 +four755grdsixthree +seventwokzpljzth6mzkvsdbgldfbdc +ninexjgzkcxl3sevenfive +949klmgj3 +53threethree +lzczjzsftmcmclqqbrgjftfhxz3 +9rpzfnrseven3tsqxxgtrsq +fcndgzmtsj86psclvsdvggbhfhd8five +qxkd2lxzhhcjlxonel48ndktqt4 +2five5twovplrbfxfjzvmdvjs96 +4drtzsix5phvgbqjsknnine9fk +btmdjvnkrqxvjzchkkdpqcnldljs7eight6znfphg +xtrjonefour8threexksbbvkxmkthree +sixhtxkz7pnfzsnpnxnine79 +eight5826 +hrxqbqq5sixkrdjszbblnpdhfour +xlcmcgprrp2 +seven4vfm3 +bztngjjhfivethreenineeight5 +oneonedvgbrpgqrnh77 +jfnphpvcggfour5zoneeighttjxhcqhsml +796fcone4 +7fivetrmdsb +2fiveseven +fmtdrcczngfivefour6fiveqbkn +eight25lxjdzkrrqj +fiveninefour373 +fournr2kzbls1tghseven +3nlmhvbninenine1fourpppthree1 +j4fourtwo8 +one2f1oneightc +8g2six8 +nineqzlsxdktwokdhsevenpkqqhjb4jz +cqsnztq6hjvkcnpxhmplfxfv +6svktmthzeight1nfxldggeightqfmhhzzsdthreesix +five7six9 +thlhmgvvrmqv9 +fourpvksthrjlxxdddseighteight55 +qsccghmztwosevengcrfqnzzmrhbgrxlrsxqxtmthbv7three1 +onetwoj19eight1 +8xgtltlrbnscvtone5nine4 +ftx5 +knsvnknplxrgtnrlqcl5 +nflmxkm2dznjhp7three8 +five2tttpdfnmdx3fdrtmxzqx38three +two3onegkj +47fivekd +six9one5nine +l3onegpj8threekkgdkfzscrrx +four4ninekfndgvhrrbfzpzrnvpzlxss2l +ltgsxcrgzqrfpkkb3oneeightfive91knzsppbbx +sevenvplfzkncmzninenine1 +sixhjjsxgrkgstwoeight1knhgsmscrnpcsone4 +1jbm89two63two +onedmpxhvvcjssixeightkpvdmzjltwo3eight +fivevjjtfeight6nine6 +thffrjkhsixsix1one7one +dbpvngh3eighteight86foursix +pppcpjmbmhsvhjmkfour2onedlnrg +2onev8 +55gpvxsvsnpfrpmn +lfsmfbone58 +tv48threetf3 +8threeonefour71 +ghfslsb73dtlgjnj +565twofive7 +sixljhfccjg5eighthpskg +5four2four988rd +xtgtb99 +kkzfxjszrfjvqllzlhzsninehzbfbvnhtzjf2 +165 +3jtklkpsfxpxlrgltwojxcpqjdsfbs +three7vknxbtthree +7fourfourfive +sevengseven71nklkzdeightsevenfive +eight37one +onenine2 +8nine9vkxxhnm6threethree +7one96fivesix +58bjnfhjxsm146six2mzv +99jdqbtb5seven +8mqztm7bdjh4 +6ninevninenvxflxvgg +k2twonek +gzmtwokrk9ptrsixfjbktjc9 +8fivesix +onesqqkvdtrs5vrsbgnvkjseven +bnbxpqhqxthree79 +nine5l96ninesixqhtxpkzb6 +sevenfive8tklnkqtwo6three +qb2onenldzvsixdjmjzdfourqgjsssr +thqmrjnjg3dbnksktvk +318 +three71blglscfrzql3six +9nine6nine4 +sfive1seven1m +five3dj16 +5ninetwotwo8srrvkx3 +spcsttljpl7 +6rslsdkfs4834 +dshfour8knjplkghpfpzcszqsix1 +ninephtlxnnl8hzn +bmr5 +tm4czfdfbhps +sevenseven4three9sixtsmg +sevenprdqm1six47cnbskdfivethree +7one6gzfdvfvfourtwoninelbndhdkqeight +jzxczvgjgxdfrzn2nineseven +zpcspqvhbfxlcgt1onesevenqktvgjhm +bmzdhnljms4nkjzhkrtfzngbn +nine6mjfbftpcfh4five9eight +qrvsldss4nine4 +lffkvnhbpbtnxzncjs4 +76ckghqnbsnlnjftwo72 +7jrqrkdksixsixtwonett +3xc +mzveightwofive2onesix7five2 +74five6mrqx464 +qtwoqlrkvlmpqfjvm8onetwo +41bchstnlzkntwonineseven1pskh +twoonejtjph15three +fzmkkgdq6 +21one +eight59fivenine +jbfmfbseightmzlknl84 +four4rlzplmmmcplfour4mllmtxx1 +q349j +6dbpqgttninepx623bpbhsnxcmg +52hvsvpk +8fivesevengzz +3fourfnfldsxngrknxnvts +18s +three2561b1onethree +zlppzxzzsixtwo4hksclkzhtkdsldfgjhtfhxcdsmdbr +26eight65five9threeeight +seven178 +fvljxzhdln11eight +49four6fourqmspqkbphjzvgzgbvrbmjfsm +onelnmplhjtjtfivesqzn7qmcpchjtxfcc +hd8 +9pnneight +five1qgdzkj9eight +rfhbnhbkzteightfivesixtwo3 +bczljcceight2 +145sevenhmfive +8lbgkvdxlccgzzvvttcfgmthreehhmqfivexcdhdd +6bqxzzzgpdk48 +twobcxchbfour5m2two1seven +twotwotwo6513fg +48one6tmjxclchtnpltmjkpmmm +vhkcklgdhk9xmvtbktdvjmhjtwoned +eightfourfour9one7 +fourqhgjdpr4p3sevennine +vlctnqfour4724 +9spbtvbsh7scvvx7hvbxlh +eightone1ccdhppbsninejfktrxst +448fourhjk3r3mhstwones +hbgfourtkvg87sixlcvtjz +fivesphnkzrn5threeninefive27five +92two95seven5 +twosix84zjqtp +9bxppvsjgdmbqvkstrqdsixtwofourfour +fourfive3sixnine9gmrdhfhkjtrnbl8 +gxcdvsjxgll46mrrdfpdkdl +4foursevenzklvhrdvpj +seven1rz24rfmnjxjkthreenfvjdsjtgqkd +2xbfivelpfhvhsttgjqfsqkffctppeight +6vxfjbssixfkjqsdh83xgzdmtntgm +5four98two +xdk6 +ptxtvnlpxbpkxptbhxheightfour7 +6four5sqgfour +eight8rbngtqpvninelzhffxpmtwoonefourfour +three1eight2 +1two8nine +9eight82 +5fourshdfivefpfd3 +two667dsmv3lvhszg4 +kcxpmrv99threeone +seven7five3ninerhjbmtfbzsevenfive +4four1threegvxkdsfour +qdqrgf6fourfour46 +7nlztdphcjdnqm4zddjhfreight +sixthree62 +vs86four +sssbdgzsjnlftms8 +3ninethree45twofsfsvtnl3three +four7zcfjtngsninethreeninethree +gcjxkcnsevenfivefourhrxzvxftnine4sixzm +thsdcone23bvrfour71five +fiveeight5fourrlhjtmrtwo36 +61lxhrpfvbqkd +55three5seven1 +sixsix9 +gklpxzmcmnnbhsgeight63 +fourninelxm5cpkqvbpbsvjndn4 +hcjghqfssevenxzdljnvqsix1sjvrhxxhxthreesix +rtfttcqmxszrsixtwo37scglpjfjt5 +eighthvbsldnhfzxr7eightsrmqhsgonebx +zcvqxjn1vdddlsevenninefourninethree +qr7three3two4tdrqd +qbjttlfsrrrhrmkhpvgc7zkone +6fiveseven7ndfhzxzrrf +fkxhpzb568eightspdxfngrp82 +seven4sixtwo +nineddhgjn4 +37chjlxcbbjrjghzjdsix4threeone +jhngdhntvfmcbjjvlgx979 +9thpnx12835one +onesixfzjgpfourseven1nine2jrxjp +5rzvhjqnlvnt1lone +9dmftktf9 +eight5eight +grkfgrhnkjm9 +23ksknkqrdthreecvg2rbxkkhlqttfivefive +3foureightshnff5six72 +19ninethreebcgxkmjqhgpmfx3 +28rdsm5fiveeightthree +dmgpjdzfl1two819 +pbrvnfpftb3vptbqncmqszbbctnj363 +fzdc29331 +bnkjk9m289rxgqn +fivenine4seven6plsczmxr4 +fourmxrltjgdleight1three +nvjxvpgtplgszgbeightcccxxjhbsfqdrj7 +5stjbvxglkdrbp6kllbbnptdfzl +dmtpxndvvrbksfournine5one6 +vnlhxcssevenjlfgfournine69hmnddrthree +blchmddjmktwo4fxsqlpfn69xhbpblrlmone +17qdxzqlpllfourszcpxmtcxhrqzqqhm45 +fchdhsjzt6two9 +srs3vcq7three +twotwofour4seven +three4six8lsdg1 +1fdvdhxrxmmvzonehmkzspfdlrdvlnfzfive9 +7threeone +96ninegjcxpstqhxbdzfsrczm2 +xthree19 +bgptbh73sixfour +eight82 +sevenb3sixthree9zjflmmdjfour +kcninefour2ninetzqgrztwojq +eightfourhfqttttxteight5 +zghnvzdpfivevvgfjzfzvcbvccmtwo5tkzj7 +33qxzctgqsvxnine9 +6onejdndbcjsseven +294xqcrnine3844 +two6ssqvnvm889 +rzfbhbr15jpnfqmzthreepnine41 +eightjlltprrrtv63twoptg4 +threetwolzdbgcpkm3seven1five +mcbjrtbtbp7twoseven7vdttjvmxbxkfmgmvhrs +three5hfivesevenqrc6sbst +eightdvvtsvmfqeightfz5six +kklpnghzsfv88two86eightplfgjz +bcgntz6gqxbxxtnnonegqlz4fivexmjxqf +mvbgjpsmhntf7mmshslgvv17thlknqfivel +fourmjflcbtwo7fivetdntjstntv8 +89fctlsxz8eight +1twosix57sevenfive +3ninefivencdgmlqxlnine96 +twofoursevensixeightpmpfpfljqtnm9six +5hqnxvlmnh1bxxhnpkjhgzxlhgffv +nine9fourtwo8tzseven +grcfkddgseven55g +seven8nineeight4one7lnntwonebc +one1ktgggr +76eighttwoqzfnllqnkq +cgjkzlksl1823749 +9twonvhlhrlxnine7eight +qtzmndkrqqcpmjcxz98kklrtjgbbnzglstnnlnqksrgkzz +cqxknrmb5cfhfgpk +9lhrnlqrnninethree +ftlpbv55nine +2nine5tfqhqtwo +mqcfgssixtwofour6cvncgmxnlq +946eight84kvflb +h1nineglvgmh9txxg8 +lxqqqdfive5mcgrjkxmlzdqbkldjqkhlxnbg +jjkvdzzkpxqp1three59dqthvgkfmfjvlvnrtlzlmqvcspjfc +sixfoursix87oneoneseven +1ptrtgd6 +5threeeightqqjrmchfoureight +one42mdmfkrzln5ck8qxbfqf +seven819ninejzrddsevensix +vfpeight4pngqpbvsbz +threesixseven1 +7twoonetwo9eight88slpctv +fqfsixtwofpm14seven +6xcdvsftlsrsrgseven5seven +mhmgzdgrc6lnnzv6pnr4stxnmrreightblzp +9glsqqcrttdgsdqkfour +82two +ftqzqnlddctlxmb3rdlg +sevencxbpxvznqmjqgglfccqkvjqmjbpthreenineeightnhszbvnff7 +twosixplgdjplfthree9kvhvnzzqzk +1pfvkfblrmz +2n +threeeighteighttwo7qmlnjx +6sevendhc6 +nineklzvllx3fivesix +2nrrx5fourfcljkdhpk +eightone9eight +gqhsmccbpjc46twooneighttbv +sixtwo2bxpdqfour5fivexkjxzb8 +six4nineggtqsxjd16mhgpjflprmsix +tndgkrpmfour1foursevensflkzt +bpxtdkrcr5nsevendltgfgkzxdtbxsghkkninesixone +one22threefivetwo +lzq7fzbqsd49 +cgthgcsix1 +389seven +cmgctmtwo8eight +2qvrbrnvp559 +eightjpkjnpgplseven7oneightdv +cdzoneightsevensixeightmfjsevenk2eightfour +2sgtftmrrlfhgqxdmhtfqncslmnlvdhnjpdtpg45 +fiveone1 +ps2threeeight9hvmjrc3 +pdsr2xphzmmztnqxpzq +nineeight7ninevhlksv +jjbsm55fscpfpklq1sixseven +fivefive1nkpzcxrxbfour +fivesixdkxvbtzvtlsevensix3fivekh +twovrzxlmnxnhonedpdmvn9 +hmqccxh6 +five6nine8vcbzzqrvn29 +5nfmfthree4nthreenine5four +kpsbqshc21dzrpktfseven +cdfsszrtpnsfhgsix9bzqjdltbtzjsz +twofive4eighttxjxoneeightninet +six4tppbxfiveblktrzgdvks1 +eightzmvmdbbfnft2 +7npgl9vvtdl2 +3twoone +seventhree6skl +onepdfjql18nine631 +jpjtvxck3sncsvnsix112 +njrkcgznhvfour1 +gfmtkdr2pvvlnh9one2qgvmxfm +4jfxzmcdonep +one9threenine +544 +one5sevenzhmljdbfb8pncqtdkch +nine72eightxvjtrbzpzvcqvlone +sixfive8hpnvvjzld4 +24f8 +6bqtwothreectlcqkkzfiveppvbgbvspncldjhb +ljmrlhxvsone1qdsfhqqqlljd6seven2one +mfksxgxhrqxbtg73r1eight +ztwogdpcgllnpp516ztdkj +two8fivefourbs5jlzfnleightwoqvk +seven5qnrvpqtrvlt4 +ninedbnd8mrchlnineqhhqjnznts +onethreezmhshprm2jb98three +3sixfivesix +two6dfgpzqrhzp8z368 +twoonesixfscgflrlkmbtmv5893 +fiveninegkfbgczqjhnine7g +rbvknineflmkl4btbqbkpsd1eight4 +39324 +sjrgxtxppvxsseveneight4fourkdcdsmfhnnqjpbtxg +6threevcgjmclnhcfxvvbncnhjkmmsqqhqffivetwo4 +foursix1four +zbztwoxptgdffourgzgzzhhmhg78ljlchqh +dcpbt25vcdf3three611 +v58dtgrpl +rntgtrrc67mdlfxzgkvjjpqtfournineninefour +lpcts8vjznknlj +bpmv3 +5z +zmsevenbnckdjhpbsvglrfsskcsevenfour2nine +6threesevenprcjlk5644 +nineczcd6922 +2vksfctzbjz +kz93 +twopfhlqplngsj6z13four +8nm3sevenxqzj +cjgoneightthree5kmpndvrmkljeight6sflmeight +three3b3seven55xgrrkssnzsghd +5lvxlnpc24fbrbtg5 +7qgmhfnine +sixpbvfjzkdsqdpsthreekj91nine +sbmxhcxonefggt4f95oneseven +onemgkvjpgfdjmhcsxsmlfjgzqqrftgxgx2jdmbvbfdf4 +bvzcskfrlg8jseight +hzltjqmxjt98eightfseven +2seven7vbfm44four +3bvfnine +4mqprdhhrdqz +twothree2 +seven3threeeightsllttbrdcthree +gmpxgkvv4four +vntmvnd4two +fqhvkqrxdtwo1threeqrmg5 +5f +fivenscdbpvlz1 +vzdcg921fivelplfsbdccrsdsq +sixnine2rnrdqkfpmdfives2 +5seveneight4sr9gffive +hknjrm5eight34nine +7965 +2t34two73xlfzpd +626 +1kdfnbjgtshsonenine1eight1kzp +two8mxrlgchctdtflkknonezstpfgxsdx28 +sixfdjgvfm1sevengg656vqcql +threesevenbjcfxlbml8lhxjmzgspfour +4phlqzbhvk5four +1lkccpmxmlxlqrxzz8lkmbpmdncgpzsxgqdcb +klqcnhjvone75 +5two7 +2ninecgrltzpgzpfourfour47seven +threeoneeight758threegtwo +54j +seven9lqbfgrsthreefivefour +six7kjm2fzcrdeightfour84 +four198766 +six3mfgmcrmlnine6lhddlhgl9 +rkpksqvfiverxvbseven7 +734six +five5one9qd4bkgfdjgtxzlxfjr +17eightsmjzbgdbd2nine +eightqnthjhlnfive7nddfjcxq +fourxkn6two6three5 +twoseven2 +eightrbhdkpxpbsvmfivethreetwox4f +4bpgpdngvnineh +lvpxjhgkz77pthnktwomvonekjvkkbr +gqpcqlzfive2threejfknlchf +zgjslb74two +sixhxmt4 +4bcqxrcf +onesix59jktnrtlone9one +9seven1msixkhxbkgbnqkpfjrr +four1lhslrtdrnxxsmptbjjgj5 +eightcvbzqczt9ninegxlpsevenfour +threenine2foursixtwo2bldhzmsdvj +two8dmzmbnkjqfdqtmzxndrsnkrvdnl +9lqtcrvkvhdkmbfivenine6tkqh +foureightjdpqhldvzeight17vbkmjvfs +vkzvsphbltfxjfxxsl9 +shdgdlft27 +87twopsix7eightwoj +57threeone +pshspdc9fourone5eight79sxrjkcmcb +sevenhmzvvbpdktxxjrlvntx1 +ninethreendlnnine9 +nine2tkmkrpccone +7sixsixvdv +vpktkldsjcpsxjztmthree3onefdbcxkrvhcm +9lqmbltfoursnsbrqn22sdnrpxfsjfour +five8mgctnvstcone24fcfbcqtknjmddknkzeightwod +8xfbqxtwonmjthm24twofivelckrr +xhnldpddxcjnm5twoddtqkqd +sevensixdrcvgfxqpmvrtmgqdjqvclgnqjsfhnbbs3jvxnmjqcbtshp +mfour1zcpnpfcdeight +6twofour +r1seven7tdjgxshntl +eight5sixh +xntwonetwofqpxsgshnbhjcsrld75fourfjbllqscg +three3vbvqklcp7pfkngtnineslmrlq +7six3onenmttntsfq3 +fivefive1seveneight +p2rpjkcpcsix75fivednd +ninekkzpsone167hnqlhvmtbffive +2qmtbkslqgjkrqhnine3eightonefour +2nlfivefive6 +xjvbkbtdqhgvsseven719fiveseven +prbtnineqdvknxkblzgj7 +lkgvhtfreightninegtfrmqhd4njvsgdrhdqfxrjrcvvcz4zs +25four24dhqqkpbprx +29two +7xsbfsfivexrrxhthree +fivesrnvbdtnqnfourninelctfnxkbtv6eight +9kkpzgthree1stb +sevenhzxdbbb81one +2jszvqhv +zkvq25sj2 +hxxfg4kqjbjpjczzddrx9spkgdcvcsvmblvfxxcn +486l2clmtcgfive47 +dfhkfnfour76 +52hnpcc +kmktwonejdpgch9tthree +x6bkqrlhhcm96 +tf7kndclhgjsoneoneightxcx +mdzmsfkl5pnine8 +ghzv2three +vctrqxfsxhtblghfchthzhninefk3eightqjjjjg +three2jmvkmfour +rlkbtjpnlctsxpfp521rxbjdfsixhvp1 +7vxlkff32mdfsqrmbnmtwotwo2nine +gl6seven35two1 +two2rjtvndrzvthreethree +tjpxszlthree54hsftvc +jsthree48 +seven6fourtwotwo +threetpnh5ninernztgb +18pvqllhjf5eight9vldjjqcjfmlhnddone +two9nine6hgbprcpxvmntdjkfivetwonept +7four8eightktlhdpmptone +rrzbgtfrrqkspsix3rkpzddzrbcrzvxzstjbqhmqq +84qxbnxdpqppjfiveeightfive +n6two1brpjhf +plmkvpjbqr1 +sixsixqbksfrndvg42hclgpgfggpxmts9 +1htlmmvbnsix +dleightwolvbvmsggs9njseven5fivethreenine +eight6kxqqdnqp +5eightgdvgthfiveshthreesixfive +6seventntzffjkkvvhtgtwoonethreefivekzvptvxfjg +three6blrfsgdqsxgkbqj3 +eight1eighteight8 +8four419eighteight1bpv diff --git a/scripts/ansi-color.rkt b/scripts/ansi-color.rkt new file mode 100644 index 0000000..09292bc --- /dev/null +++ b/scripts/ansi-color.rkt @@ -0,0 +1,228 @@ +#lang racket/base + +;; original source: https://github.com/renatoathaydes/ansi-color +;; modified to provide font-style because i need that bold + +(require racket/match) + +(provide color-display + color-displayln + ansi-color? + with-colors + background-color + foreground-color + font-style + erase-line) + +;; Color and decoration escape definitions + +(define reset "\033[0m") +(define erase-line "\033[K") + +(define (bkg-color256 code) + (string-append "\033[48;5;" (number->string code) "m")) + +(define (fore-color256 code) + (string-append "\033[38;5;" (number->string code) "m")) + +(define decoration-map + #hasheq( + (underline . "\033[4m") + (bold . "\033[1m") + (reversed . "\033[7m"))) + +(define fore-color-map + #hasheq( + (black . "\033[30m") + (red . "\033[31m") + (green . "\033[32m") + (yellow . "\033[33m") + (blue . "\033[34m") + (magenta . "\033[35m") + (cyan . "\033[36m") + (white . "\033[37m") + (b-black . "\033[30;1m") + (b-red . "\033[31;1m") + (b-green . "\033[32;1m") + (b-yellow . "\033[33;1m") + (b-blue . "\033[34;1m") + (b-magenta . "\033[35;1m") + (b-cyan . "\033[36;1m") + (b-white . "\033[37;1m"))) + +(define bkg-color-map + #hasheq( + (black . "\033[40m") + (red . "\033[41m") + (green . "\033[42m") + (yellow . "\033[43m") + (blue . "\033[44m") + (magenta . "\033[45m") + (cyan . "\033[46m") + (white . "\033[47m") + (b-black . "\033[40;1m") + (b-red . "\033[41;1m") + (b-green . "\033[42;1m") + (b-yellow . "\033[43;1m") + (b-blue . "\033[44;1m") + (b-magenta . "\033[45;1m") + (b-cyan . "\033[46;1m") + (b-white . "\033[47;1m"))) + +;; customization parameters + +(define background-color (make-parameter "" + (lambda (arg) (as-escape-seq #t arg)))) + +(define foreground-color (make-parameter "" + (lambda (arg) (as-escape-seq #f arg)))) + +(define font-style (make-parameter "" + (lambda (arg) (as-style-seq arg)))) + +(define no-reset (make-parameter #f)) + +;; implementation + +(define (ansi-color? x) + (or + (and (integer? x) (<= x 255) (>= x 0)) + (and (symbol? x) (hash-has-key? fore-color-map x)))) + +(define (as-escape-seq bkg? arg) + (define (raise-arg-error) + (raise-arguments-error 'color + "Cannot convert argument to color (not a valid symbol or integer in the 0-255 range)" + "color" + arg)) + (define map (if bkg? bkg-color-map fore-color-map)) + (match arg + [(? null?) ""] + ["" ""] + [(? symbol? s) (hash-ref map s (lambda () (raise-arg-error)))] + [(? integer? x) + #:when (and (<= x 255) (>= x 0)) + ((if bkg? bkg-color256 fore-color256) x)] + [_ (raise-arg-error)])) + +(define (as-style-seq arg) + (define (raise-arg-error) + (raise-arguments-error 'style + "Cannot convert argument to style (not a valid symbol)" + "style" + arg)) + (match arg + ["" ""] + [(? null?) ""] + [(? symbol? s) (hash-ref decoration-map s (lambda () (raise-arg-error)))] + [_ (raise-arg-error)])) + +(define (needs-reset? bkg fore style) + (cond [(no-reset) #f] + [else (not (and (equal? "" bkg) + (equal? "" fore) + (equal? "" style)))])) + +(define (color-display datum [out (current-output-port)]) + (let* ([bkg (background-color)] + [fore (foreground-color)] + [style (font-style)] + [-reset (if (needs-reset? bkg fore style) reset "")]) + (display (string-append bkg fore style datum -reset) out))) + +(define (color-displayln datum [out (current-output-port)]) + (color-display datum out) + (newline out)) + +(define with-colors + (case-lambda + [(bkg-color fore-color proc) + (parameterize ([background-color bkg-color] + [foreground-color fore-color] + [no-reset #t]) + (color-display "") ; sets the colors in the terminal + (proc) + (display reset))] ; reset colors in the terminal + [(fore-color proc) + (with-colors null fore-color proc)])) + + +;; TESTS + +(module+ test + + (require rackunit) + + (check-eq? (needs-reset? "" "" "") #f) + (check-eq? (needs-reset? "red" "" "") #t) + (check-eq? (needs-reset? "" "blue" "") #t) + (check-eq? (needs-reset? "red" "green" "") #t) + (check-eq? (needs-reset? "red" "green" "underline") #t) + (check-eq? (needs-reset? "" "" "underline") #t) + (check-eq? (parameterize ([no-reset #t]) + (needs-reset? "" "" "")) #f) + (check-eq? (parameterize ([no-reset #t]) + (needs-reset? "red" "green" "reversed")) #f) + + (check-eq? (ansi-color? 'red) #t) + (check-eq? (ansi-color? 'white) #t) + (check-eq? (ansi-color? 'black) #t) + (check-eq? (ansi-color? 'b-red) #t) + (check-eq? (ansi-color? 'b-white) #t) + (check-eq? (ansi-color? 'b-black) #t) + (check-eq? (ansi-color? 'some) #f) + (check-eq? (ansi-color? 'foo-bar) #f) + (check-eq? (ansi-color? 0) #t) + (check-eq? (ansi-color? 1) #t) + (check-eq? (ansi-color? 10) #t) + (check-eq? (ansi-color? 200) #t) + (check-eq? (ansi-color? 255) #t) + (check-eq? (ansi-color? 256) #f) + (check-eq? (ansi-color? -1) #f) + (check-eq? (ansi-color? -10) #f) + (check-eq? (ansi-color? "blue") #f) + (check-eq? (ansi-color? #t) #f) + + (define (wrap-in-color color text) + (string-append (hash-ref fore-color-map color) text reset)) + + (define (get-output proc) + (let ([out (open-output-string)]) + (parameterize ([current-output-port out]) + (proc) + (get-output-string out)))) + + ; tests for color-display + (let ([hello-uncolored (get-output (lambda () (color-display "hello")))] + [world-fore-red (get-output (lambda () + (parameterize ([background-color 'red]) + (color-display "world"))))] + [tree-fore-blue (get-output (lambda () + (parameterize ([foreground-color 'blue]) + (color-display "tree"))))] + [animal-yellow-black (get-output (lambda () + (parameterize ([background-color 'yellow] + [foreground-color 'black]) + (color-display "animal"))))] + [something-bold (get-output (lambda () + (parameterize ([font-style 'bold]) + (color-display "something"))))]) + + (check-equal? hello-uncolored "hello") + (check-equal? world-fore-red "\033[41mworld\033[0m") + (check-equal? tree-fore-blue "\033[34mtree\033[0m") + (check-equal? animal-yellow-black "\033[43m\033[30manimal\033[0m") + (check-equal? something-bold "\033[1msomething\033[0m")) + + ; tests for with-colors + (let ([blue-and-white (get-output (lambda () (with-colors 'blue 'white (lambda () (display "b-a-w")))))] + [red-and-green (get-output (lambda () (with-colors 'red 'green (lambda () (display "r-a-g")))))] + [blue (get-output (lambda () (with-colors 'blue (lambda () (display "b")))))] + [white (get-output (lambda () (with-colors 'white (lambda () (display "w")))))]) + + (check-equal? blue-and-white "\033[44m\033[37mb-a-w\033[0m") + (check-equal? red-and-green "\033[41m\033[32mr-a-g\033[0m") + (check-equal? blue "\033[34mb\033[0m") + (check-equal? white "\033[37mw\033[0m")) + +) diff --git a/scripts/aoc-lib.rkt b/scripts/aoc-lib.rkt new file mode 100644 index 0000000..1ef6fef --- /dev/null +++ b/scripts/aoc-lib.rkt @@ -0,0 +1,117 @@ +#lang racket + +;; library to interact with the AoC API and track solutions progress + +(require net/uri-codec net/http-client json) +(provide aoc-fetch-input aoc-fetch-challenge aoc-submit-answer aoc-fetch-leaderboard + aoc-complete? aoc-set-complete!) + +(define *host* "adventofcode.com") +(define *status-file* ".status.rktd") + +;; generates API paths +(define/contract (puzzle-path year day endpoint) + (-> string? string? (or/c "input" "answer" false/c) path?) + (define base (build-path "/" year "day" day)) + (if endpoint (build-path base endpoint) base)) + +(define/contract (leaderboard-path year lb) + (-> string? string? path?) + (build-path "/" year "leaderboard" "private" "view" (string-append lb ".json"))) + +;; sets up necessary headers for API +(define (make-headers session) + (list (string-append "Cookie: session=" session) + "Content-Type: application/x-www-form-urlencoded")) + +;; http request helper +(define (aoc-request endpoint session [method 'GET] [data #f]) + (define (parse-headers hlist) + (for/list ([h (in-list hlist)]) + (match h + [(pregexp #px"^([^:]+): (.*?)$" (list _ k v)) + (cons (string->symbol (string-downcase (bytes->string/utf-8 k))) + (bytes->string/utf-8 v))] + [x (cons 'unknown x)]))) + + (define (do-request path headers method data) + (define-values [status headers-out content] + (http-sendrecv *host* path #:ssl? #t #:headers headers #:method method #:data data)) + (define headers-out/parsed (parse-headers headers-out)) + + (match status + [(pregexp #px"^HTTP/1\\.[10] 200") content] + [(pregexp #px"^HTTP/1\\.[10] 302") + (define location (cdr (or (assoc 'location headers-out/parsed) + (error "got 302 with no location")))) + (printf "got redirect to ~a\n" location) + (close-input-port content) + (do-request location headers 'GET #f)] + [(pregexp #px"^HTTP/1\\.[10] 404") + (error "endpoint returned 404\n response: " (port->bytes content))] + [stat + (error "endpoint returned unexpected data\n status: " stat "\n response: " + (port->bytes content))])) + (do-request (path->string endpoint) (make-headers session) method data)) + +;; gets the input file for a challenge +(define/contract (aoc-fetch-input year day session) + (-> string? string? string? input-port?) + (aoc-request (puzzle-path year day "input") session)) + +;; submits an answer to the server +(define/contract (aoc-submit-answer year day session part answer) + (-> string? string? string? (or/c 1 2 "1" "2") string? (or/c symbol? bytes?)) + (define data `((level . ,(~a part)) + (answer . ,answer))) + (define resp + (port->bytes (aoc-request (puzzle-path year day "answer") session 'POST (alist->form-urlencoded data)))) + + (match resp + [(pregexp #px"That's the right answer") + (aoc-set-complete! day part) + 'answer-correct] + [(pregexp #px"That's not the right answer") 'answer-incorrect] + [(pregexp #px"You gave an answer too recently") 'rate-limited] + [(pregexp #px"fifty stars") + (aoc-set-complete! day part) + 'year-complete] + [(pregexp #px"Did you already complete it?") + (aoc-set-complete! day part) + 'already-completed] + [x x])) + +;; fetches the HTML page for a challenge +(define/contract (aoc-fetch-challenge year day session) + (-> string? string? string? input-port?) + (aoc-request (puzzle-path year day #f) session)) + +;; gets a private leaderboard as json +(define/contract (aoc-fetch-leaderboard year lb session) + (-> string? string? string? jsexpr?) + (read-json (aoc-request (leaderboard-path year lb) session))) + +;; helper to generate entries for the challenge status file +(define (day+part->key day part) + (when (string? day) + (set! day (string->number day))) + (when (string? part) + (set! part (string->number part))) + (cons day part)) + +;; get the challenge status file +(define (aoc-get-status) + (cond [(file-exists? *status-file*) + (call-with-input-file *status-file* read)] + [else '()])) + +;; is a challenge complete already? +(define (aoc-complete? day part) + (set-member? (aoc-get-status) (day+part->key day part))) + +;; mark a challenge as completed +(define (aoc-set-complete! day part) + (define status (set-add (aoc-get-status) (day+part->key day part))) + (call-with-output-file + *status-file* (lambda (out) (write status out)) + #:mode 'binary #:exists 'replace)) diff --git a/scripts/aoc.rkt b/scripts/aoc.rkt new file mode 100644 index 0000000..b39ecb0 --- /dev/null +++ b/scripts/aoc.rkt @@ -0,0 +1,83 @@ +#lang curly-fn racket + +;; utilities for every challenge script + +(require "aoc-lib.rkt" (prefix-in is: data/integer-set) graph threading syntax/parse/define + (for-syntax racket/syntax)) +(provide answer aoc-finish dbg memoize define/memoized + band bor bxor bnot bshl bshr bset? bfield + string-reverse + maximum-bipartite-matching/stable + (all-from-out data/integer-set graph syntax/parse/define threading) + (for-syntax (all-from-out racket/syntax))) + +;; in-expression debug print, uwu +(define (dbg x) + (pretty-write x) + x) + +(define band bitwise-and) +(define bor bitwise-ior) +(define bxor bitwise-xor) +(define bnot bitwise-not) +(define bshl arithmetic-shift) +(define bshr #{arithmetic-shift %1 (- %2)}) +(define bset? bitwise-bit-set?) +(define bfield bitwise-bit-field) + +(define (string-reverse x) + (list->string (reverse (string->list x)))) + +;; makes a memoization wrapper around a function +(define (memoize func) + (define memo (make-hash)) + (lambda args + (hash-ref! memo args (λ () (apply func args))))) + +(define-syntax-parse-rule (define/memoized (name:id arg:id ...) body:expr ...+) + (define name (memoize (λ (arg ...) body ...)))) + +(define-syntax-parse-rule (define/memo (name:id arg:id ...) body:expr ...+) + (define name (memoize (λ (arg ...) body ...)))) + +;; helper for maximum-bipartite-matching +;; given an edge list where each first item corresponds to the left set and each second item +;; corresponds to the right set, return a matching list where the first item is from the left set +;; and the second item is from the right +(define (maximum-bipartite-matching/stable edges) + (when (empty? edges) (error "provided empty edges list")) + (define left (list->set (map first edges))) + (define G (undirected-graph edges)) + (define matching (maximum-bipartite-matching G)) + (define num-first-lefts + (for/sum ([m (in-list matching)] #:when (set-member? left (first m))) + 1)) + ;; if the first set contains more elements belonging to lefts than rights, then assume it's in + ;; the right order. otherwise, swap + (if (> num-first-lefts (- (length matching) num-first-lefts)) + matching + (map #{list (second %) (first %)} matching))) + +;; submit a solution to the server if not already submitted +(define (answer day part answer) + (printf "answer ~a.~a: ~s\n" day part answer) + (unless (aoc-complete? day part) + (printf "submit? [Y/n]: ") + (match (string-downcase (string-trim (read-line))) + [(or "" "y" "yes") + (printf "submitting...\n") + (define resp + (aoc-submit-answer (getenv "AOC_YEAR") (~a day) (getenv "AOC_SESSION") (~a part) + (~a answer))) + (printf "server responded: ~a\n" resp)] + [_ (printf "not submitting\n")]))) + +;; submit 25 part 2 +(define (aoc-finish) + (unless (aoc-complete? 25 1) + (error "submit 25.1 first")) + (unless (aoc-complete? 25 2) + (printf "submitting done for 25.2...\n") + (define resp + (aoc-submit-answer (getenv "AOC_YEAR") "25" (getenv "AOC_SESSION") "2" "done")) + (printf "server responded: ~a\n" resp))) diff --git a/scripts/get-challenge b/scripts/get-challenge new file mode 100755 index 0000000..6968a43 --- /dev/null +++ b/scripts/get-challenge @@ -0,0 +1,91 @@ +#!/usr/bin/env racket +#lang racket + +(require html xml "ansi-color.rkt" "aoc-lib.rkt") + +;; finds a given element of an xexpr +(define (find-element el doc) + (match doc + [(list (== el) _ ...) doc] + [(list tag attrs children ...) + (ormap (curry find-element el) children)] + [_ #f])) + +(struct style-ast [fg bg fs children] #:transparent) +;; convert xexpr tree to an ast with lower-level styling +(define (xexpr->style-ast doc) + (match doc + [(? string?) (style-ast #f #f #f doc)] + [(list (or 'script 'form) _ ...) #f] + [(list-no-order 'p (list 'span (list-no-order '(class "share")) _ ...) _ ...) #f] + [(list 'li _ children ...) + (define out-children (filter identity (map xexpr->style-ast children))) + (style-ast #f #f #f (cons (style-ast #f #f #f "- ") out-children))] + [(list tag attrs children ...) + (define-values [fg bg fs] + (match* (tag attrs) + [('main _) (values #f #f #f)] + [('article _) (values #f #f #f)] + [('p (list-no-order '(class "day-success") _ ...)) (values 'yellow #f 'bold)] + [('p _) (values #f #f #f)] + [('pre _) (values #f #f #f)] + [('h2 _) (values #f #f 'bold)] + [('ul _) (values #f #f #f)] + [('a _) (values 'green #f #f)] + [('code _) (values 'white 234 #f)] + [('span _) (values #f #f #f)] + [('em (list-no-order '(class "star") _ ...)) (values 'yellow #f 'bold)] + [('em _) (values #f #f 'bold)] + [(_ _) + (printf "warning: unhandled ~a ~a\n" tag attrs) + (values #f #f #f)])) + (define inner-children (filter identity (map xexpr->style-ast children))) + (define new-children + (if ((or/c 'h2 'pre 'p) tag) + (let ([nls (list (style-ast #f #f #f "\n") (style-ast #f #f #f "\n"))]) + (append nls inner-children nls)) + inner-children)) + (style-ast fg bg fs new-children)])) + + +(define (output-style-ast ast) + (define num-newlines (make-parameter #f)) + + (define (helper ast [prev-bg ""] [prev-fg ""] [prev-fs ""]) + (match-define (style-ast fg bg fs children) ast) + (when bg (background-color bg)) + (when fg (foreground-color fg)) + (when fs (font-style fs)) + (match children + ["\n" + (unless (or (false? (num-newlines)) (>= (num-newlines) 2)) + (num-newlines (add1 (num-newlines))) + (display "\n"))] + [(? string? str) + (num-newlines 0) + (if (string-contains? str "\n") + (for ([i (in-naturals)] [line (in-list (string-split (string-trim str "\n") "\n"))]) + (color-display (format (if (zero? i) "~a~a" "\n~a~a") erase-line line))) + (color-display str))] + [_ (map (lambda (item) (helper item (or bg prev-bg) (or fg prev-fg) (or fs prev-fs))) + children)]) + (when prev-bg (background-color prev-bg)) + (when prev-fg (foreground-color prev-fg)) + (when prev-fs (font-style prev-fs))) + + (num-newlines #f) + (helper ast)) + +(command-line + #:program "get-challenge" + #:args (day) + (define in (aoc-fetch-challenge (getenv "AOC_YEAR") day (getenv "AOC_SESSION"))) + (use-html-spec #f) + (define doc-xmls (read-html-as-xml in)) + (close-input-port in) + (define doc `(top-element ,@(map xml->xexpr doc-xmls))) + + (define main (find-element 'main doc)) + (define ast (xexpr->style-ast main)) + ; (pretty-write ast) + (output-style-ast ast)) diff --git a/scripts/get-input b/scripts/get-input new file mode 100755 index 0000000..33c4668 --- /dev/null +++ b/scripts/get-input @@ -0,0 +1,10 @@ +#!/usr/bin/env racket +#lang racket + +(require "aoc-lib.rkt") + +(command-line + #:program "get-input" + #:args (day) + (define in (aoc-fetch-input (getenv "AOC_YEAR") day (getenv "AOC_SESSION"))) + (call-with-output-file (build-path "inputs" day) (lambda (out) (copy-port in out)))) diff --git a/scripts/make-day b/scripts/make-day new file mode 100755 index 0000000..78b02a2 --- /dev/null +++ b/scripts/make-day @@ -0,0 +1,28 @@ +#!/usr/bin/env racket +#lang racket + +(require racket/runtime-path + scribble/text (rename-in scribble/text/output [output scribble-output]) + "aoc-lib.rkt") + +(define-runtime-path template "template.rktrkt") + +(define (eval-template file vars [port (current-output-port)]) + (define cs (current-namespace)) + (define output-exp + (parameterize ([current-namespace (make-base-namespace)]) + (for ([mod (in-list '(scribble/text))]) + (namespace-attach-module cs mod) + (namespace-require mod)) + (hash-for-each vars namespace-set-variable-value!) + (eval `(include/text (file ,file))))) + (scribble-output output-exp port)) + +(command-line + #:program "make-day" + #:args (day) + ;; make solution file + (call-with-output-file + (format "~a.rkt" day) + (lambda (out) + (eval-template (path->string template) (hash 'day day) out)))) diff --git a/scripts/plot b/scripts/plot new file mode 100755 index 0000000..b864047 --- /dev/null +++ b/scripts/plot @@ -0,0 +1,102 @@ +#!/usr/bin/env racket +#lang racket + +(require "aoc-lib.rkt" plot/no-gui) +(provide make-plot) + +(define (make-plot plot-func) + (define data + (aoc-fetch-leaderboard (getenv "AOC_YEAR") (getenv "AOC_LEADERBOARD") (getenv "AOC_SESSION"))) + + (define (hash-ref* hash path [failure (lambda () (error "no such key" path))]) + (define (->symbol el) + (match el + [(? string?) (string->symbol el)] + [(? number?) (string->symbol (number->string el))] + [(? symbol?) el])) + (define (do-failure) (if (procedure? failure) (failure) failure)) + (match path + ['() (do-failure)] + [(cons (app ->symbol fst) '()) + (hash-ref hash fst failure)] + [(cons (app ->symbol fst) rst) + (if (hash-has-key? hash fst) + (hash-ref* (hash-ref hash fst) rst failure) + (do-failure))])) + + (define members (hash-ref data 'members)) + (define max-pts (hash-count members)) + (define member-names (make-hash)) + + (struct tl-entry [mid day level] #:transparent) + (define timeline (make-hash)) + + (for ([(mid-in val) (in-hash members)]) + (define mid (string->number (symbol->string mid-in))) + (define name (hash-ref val 'name)) + (hash-set! member-names mid name) + (for* ([day (in-range 1 26)] [level (in-range 1 3)]) + (match (hash-ref* val (list 'completion_day_level day level 'get_star_ts) #f) + [#f (void)] + [(? number? time) + (hash-update! timeline time (lambda (v) (cons (tl-entry mid day level) v)) '())]))) + + (define timestamps (sort (hash-keys timeline) <)) + + (define point-values (make-hash)) + (for* ([day (in-range 1 26)] [level (in-range 1 3)]) + (hash-set! point-values (cons day level) + (if (= day 1) + 0 ; day 1 is worth no points u___u + max-pts))) + + (define point-tls (make-hash)) + (for ([(mid _) (in-hash member-names)]) + (hash-set! point-tls mid (vector))) + + (define (get-last-pts data) + (if (vector-empty? data) + 0 + (vector-ref (vector-ref data (sub1 (vector-length data))) 1))) + + (define (set-pts! mid time pts) + (hash-update! point-tls mid + (lambda (m-tl) + (vector-append m-tl (vector (vector time (get-last-pts m-tl)) + (vector time pts)))))) + + (for ([time (in-list timestamps)]) + (for ([solve (in-list (hash-ref timeline time))]) + (match-define (tl-entry mid day level) solve) + (define key (cons day level)) + (define m-tl (hash-ref point-tls mid)) + (define old-pts (get-last-pts m-tl)) + (define pts (hash-ref point-values key)) + (hash-set! point-values key (max 0 (sub1 pts))) + (set-pts! mid time (+ old-pts pts)))) + + (define now (current-seconds)) + (for ([(mid data) (in-hash point-tls)]) + (define pts (get-last-pts data)) + (set-pts! mid now pts)) + + (plot-x-ticks (date-ticks)) + (define ordered-mids + (sort (hash-keys point-tls) + (lambda (a b) + (>= (get-last-pts (hash-ref point-tls a)) (get-last-pts (hash-ref point-tls b)))))) + (plot-func + (for/list ([mid (in-list ordered-mids)]) + (lines (hash-ref point-tls mid) + #:label (format "~a (~a pts)" (hash-ref member-names mid) + (get-last-pts (hash-ref point-tls mid))) + #:color mid + #:style mid + #:width 2)) + #:x-label "date/time" + #:y-label "points")) + +(module+ main + (require plot) + (plot-new-window? #t) + (make-plot plot)) diff --git a/scripts/plot.css b/scripts/plot.css new file mode 100644 index 0000000..0ea08d6 --- /dev/null +++ b/scripts/plot.css @@ -0,0 +1,5 @@ +html, body { background: #111; color: #dde; font-family: monospace; font-size: 1.05rem; } + +h1, h2, h3, p { font-family: monospace; } + +.tocset { display: none; } diff --git a/scripts/plot.scrbl b/scripts/plot.scrbl new file mode 100644 index 0000000..ba4217c --- /dev/null +++ b/scripts/plot.scrbl @@ -0,0 +1,14 @@ +#lang scribble/base + +@(require plot/no-gui racket racket/date "plot") +@(date-display-format 'iso-8601) +@(define now (current-date)) + +@title[#:style '(toc-hidden no-sidebar no-index no-toc+aux)]{BLÅHAJ score chart} + +meow + +last updated: @(date->string now #t) + +@(parameterize ([plot-width 2048] [plot-height 1024]) + (make-plot plot-pict)) diff --git a/scripts/submit-answer b/scripts/submit-answer new file mode 100755 index 0000000..611abdb --- /dev/null +++ b/scripts/submit-answer @@ -0,0 +1,10 @@ +#!/usr/bin/env racket +#lang racket + +(require "aoc-lib.rkt") + +(command-line + #:program "submit-answer" + #:args (day part answer) + (define resp (aoc-submit-answer (getenv "AOC_YEAR") day (getenv "AOC_SESSION") part answer)) + (printf "server returned: ~a\n" resp)) diff --git a/scripts/template.rktrkt b/scripts/template.rktrkt new file mode 100644 index 0000000..4ebb54b --- /dev/null +++ b/scripts/template.rktrkt @@ -0,0 +1,27 @@ +#lang curly-fn racket + +(require "scripts/aoc.rkt") + +;; solution for day @day + +(define (part1 input) + ;; ... + (void)) + +@(if (equal? day "25") "" "(define (part2 input) + ;; ... + (void)) +") +(define (parse fname) + (define input (file->lines fname)) + (void input)) + +(module+ test + (require rackunit) + (displayln "no tests :(")) + +(module+ main + (define input (parse "inputs/@day")) + (answer @day 1 (time (part1 input))) + @(if (equal? day "25") "(aoc-finish)" (string-append "(answer " day " 2 (time (part2 input)))")) + (displayln "meow")) diff --git a/scripts/watch b/scripts/watch new file mode 100755 index 0000000..af2c87b --- /dev/null +++ b/scripts/watch @@ -0,0 +1,44 @@ +#!/usr/bin/env racket +#lang racket + +(require racket/rerequire racket/runtime-path) + +(define (reinvoke file) + (displayln "invoking module") + (define p (build-path file)) + (dynamic-rerequire p) + (dynamic-require (list 'submod p 'main) #f) + (displayln "invocation complete")) + +(define (watch-forever file) + (sleep 0.2) + (match (filesystem-change-evt file (λ () #f)) + [#f + (displayln "error watching file...") + (sleep 1)] + [chg-evt + (define runner (thread (lambda () (reinvoke file)))) + + (define (handle-break _) + (cond + [(sync/timeout 0 runner) + (displayln "exiting") + (exit)] + [else + (displayln "killing module") + (kill-thread runner) + (filesystem-change-evt-cancel chg-evt)])) + + (with-handlers ([exn:break? handle-break]) + (sync chg-evt) + (kill-thread runner))]) + (watch-forever file)) + +(define-runtime-path aoc "aoc.rkt") +(command-line + #:program "watch" + #:args (day) + (displayln "warming up") + (dynamic-require aoc #f) + (displayln "ready to go!") + (watch-forever (format "~a.rkt" day)))