From b661de71ed398fc12d0ee6f5300d090ddd3b92b9 Mon Sep 17 00:00:00 2001 From: AKP Date: Wed, 4 Dec 2024 20:44:32 +0000 Subject: [PATCH] Add visualisation for day 4 --- challenges/2024/04-ceresSearch/README.md | 8 +- .../2024/04-ceresSearch/generate-vis.sh | 5 + challenges/2024/04-ceresSearch/heatmap-1.png | Bin 0 -> 13413 bytes challenges/2024/04-ceresSearch/heatmap-2.png | Bin 0 -> 12175 bytes challenges/2024/04-ceresSearch/vis.py | 122 ++++++++++++++++++ challenges/2024/README.md | 4 +- gridutil/coord.py | 4 +- 7 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 challenges/2024/04-ceresSearch/generate-vis.sh create mode 100644 challenges/2024/04-ceresSearch/heatmap-1.png create mode 100644 challenges/2024/04-ceresSearch/heatmap-2.png create mode 100644 challenges/2024/04-ceresSearch/vis.py diff --git a/challenges/2024/04-ceresSearch/README.md b/challenges/2024/04-ceresSearch/README.md index adb5ed9..5d91aad 100644 --- a/challenges/2024/04-ceresSearch/README.md +++ b/challenges/2024/04-ceresSearch/README.md @@ -2,4 +2,10 @@ Part two is: * less than 1976 -* also, somewhat obviously, less than 1978 \ No newline at end of file +* also, somewhat obviously, less than 1978 + +Heatmap of the most overlapped locations + +| Part 1 | Part 2 | +|--------|--------| +| ![heatmap 1](heatmap-1.png) | ![heatmap 2](heatmap-2.png) | \ No newline at end of file diff --git a/challenges/2024/04-ceresSearch/generate-vis.sh b/challenges/2024/04-ceresSearch/generate-vis.sh new file mode 100644 index 0000000..aa7b474 --- /dev/null +++ b/challenges/2024/04-ceresSearch/generate-vis.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -ex + +cat input.txt | PYTHONPATH=../../../ python3 vis.py diff --git a/challenges/2024/04-ceresSearch/heatmap-1.png b/challenges/2024/04-ceresSearch/heatmap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..c7e3f584bac91018e27eb3a3a44681d2fb1ed9de GIT binary patch literal 13413 zcmZvDc|6o@_rF%R6lE;Q(w!R1Ovn;hqC_$FVP-5%h_M@HEMo~R+!|TJj5UN1!zi+i zP_hmwgzUFvFxKol->K*I>wccOe}B0C@W*w1u5-@yKJW8BXYfV_cTSx+cY=k5<&=)L zCX|Kc@a3O>e;j7~=N=ELhJ{7`vX16WQ{NZ!Lo%@w-=nfepS~T`*bu!<2fpvuY%K{H zY?f;Uz8ee>CyA*$5n^-~%eZvgJ5*1jG?xVr|C#7^AcoTFkfvW6Dq5;L^gj4tCAysF zU@bWMV87^KeQEJvXI35GIShYY+JQEoc_SU;F*<5UueoT^`1m(>dTY&D&vSUp>Zpp zSRP*ewJfIJ*XUyZhTzgr7Kc1S@ERd@9X@!lb@bAwC8Ba zNbH?HicQ)6S(NSVBHP4$p4zHN*`RN*6LU_Om%R#9>hfwRDMXnYAhxUi)84g#D#N1e zx_5^cH8WHduLGT>31aBrvnhV0PzQqH^e7@7i{&QzMsu--KV@7h?Ju1_Sl;|vZa-tw zGSqde95mEs!M*VL-3Xr?sm$l4b@)(EzaP<=WhbuWyMKeLLP`w%t4@piW|kr)Jxi>o7}!&F^Ik3OdPiaF5N~ z&Lx2=LLaRm@HpVKs*2@Di2G1;x1ta!(753KUV{7i;5PpiJ3^HP+lBgGG%!eFV8r~7 zB~u^S+;MqHnb-@&ueuKkp~5R3R`Bnzi6Ak)8ZN)zr~EpvWhG?rv2h37GPPBu&?^uD zClTv#3;7#fBQNn5KGF*U5#!cL7l&0>A(_wqSm^}uvH5_c8xC2DH9?(MP$kY%#*kt`rpn*#49uKaDU@IFdE zuRH#fT1Tx|RNjlW%?(Idh=$T}#VBHAa79+@lU?f9eNip6;hl5oAVo;o} zIg;fXK)Tqg*$K@d`HyOLsB0nq*j;Yy;sXX0zB$EogrA=FC^;4Z{~_07F{Sw-kK`5s zh3fIE*W96H>J|7qjHll-qD5BWjI+(ZX=c|qfBxV(qC3&pxO!@MdtnzsY#@pR@R>%< zdmqtzcRi*3gRazRrV}jm9PitFLk{`um|~^zJlVd zOl&7%@TIo-i_cIuSujsEND?L*KSxx}AXoJke(fe+MA1QCr*gL48k}-A24G*moOo0v zs)pBCC5T;M`EXA3|1HTIiwC>%S$ZC>-Gg++hT&Qh>%3iv>xvhyL3 z2&U)!U~AQiYB8+Ib)$;RbFVyG|J8&*L#@MrS19X!KN-}H?@i)0qd_&@qOEI_9xUkG z*O$X`upQum3c4(2XKoMP==$Y+zMx)%n-yPVv06Gt8lRHVV{c_ByNbe zr1Hun&F3oS`N8f$Q|-a}{AMZogESUUH&`Xp1v>?0BUKrgTo{^r>zKK4S9I&_*;1Ag$=w6m=7sPm6Z2iz@*`2ueI&R>FswC(uZc92h8%i**T78aMppNpDw6Dr!&7||z;LtXaV zu0WWJCz?G9$;FW;OoKSohAw6mNA#?v?6>NAc9E2kg(3uji{Q6$se&8z zKC~kYTySDJuipy;JqTyQt1Ur5zG-OE=4Vv)leN)5lOX1)RE2Q*Sy-q*ysxC0d#YY< zy?Y;c+zxcJsVmjs+jVGN3%a>-xoUTPr077aH+Nr4$G~HxxgH5>6Jm1zgr7!-rkYXj zdYDTT62nbn$%ORZfunO>v}#Dgv9bo)ZuPWOikLdPK!q)cavuQz250t$rl3Qw#O(ES zKSwF6nPU2>8MJXYcP%w!pT@NPFYYjYFs@*bHjNMP+r?XWgyUzn0pL00+U%gnde{?j zP_+U`@spRYt$%k=CXjKOJ?qPetceX%e~RHHZ&;_Gp_NNEZRn-P{ePPU$}2T4Qt(6I zhv6W1-1PF|NICowab6B^Ask-|#=Pv(lxnE|SOpsQT9eNwsFhGlOIP3ft*Dm~0kT7R zt$}WcrB9!VG_#xUW!G*-b{PHR(_fBV?#H0hj2b1kxl0in{uY9c%4_w=%kaZN^P{}D z%H8&GGh#m8xL2!S_qubD0xxdnugJysUm;5$sJVZ3t$kimE-M&G8E|zH@iaKoILZVd zx)ibl@o>OOmlbHha=gO*lD~zSNY)E+rxf>XOkNW}C?~^?)zg9JGAdhTSQSa@D4s7_ zs!~HqVqRWuJ3TH=#m_?~pmrJDv`rrBI??G6+R2o)g7?wqM!YTp6^E_}M?=FU6O``Ysvf8ciTbr3*y zOYssI*qLU529mVzZ(a8-^Wjp{2MvKZwl!U^>0fUO|t2$ z6=>ZnPt`+EwGj&j6UT?s-t5r>(m9&-6Tc%+TEqG=Esvju?R-|d2`M%OzWd7KH$<@+ zT(aHO%UkfhW}iJdMcaNcHWJDr%#_$H^u&{!ho>!G2Np)ci&@heBdhf4Ny1ep)B`bM zGyM|utL70+`gtw)1ccz6CXnz-%*$4%V7|sLuE#ithVjHLMdW7to}I**rU??BDS26> zeN8R&4?2NlFGYF}5YEpT&TW+O-s}q95w+;mo6>Ih4uxO(Vd_&Z{s@eE0cp;dU4WU2 zyyVC2v_8>WWeo?d9QI>WA!63QNigHp04mkGJ}VgPMYE~l7xcatpD??g5gc9hIaTQv zQsOFvt@v8IO%C$GxOwo)imYqayy36k_fcJVkmgi+(_ukJnM=Ykx%!;S1F5tatzlte+NL0a5sqT^NUBG{>0v{f3SB#CgU}!6Y(mv* z#rSC+sVN$Jl1R0dJQIpfc3PP6<87rohh=#nhKa%&xjPiOfXl`HGj~0vA_;-p7U(nx z>*WoO^wUx4Og8_r7qT#S!PI=IJRAah3Xs4_04o=Mmw=5+U>%E3hcuXS;P!nD9DGk%sD!J0dPX?C zFPsx)3;)TO{8N)(3-$6`s*(#94}UAA2&AoQRQ1^}tn&j$owg@N{LV-RuT&)2#bCwW z*`?8#+?j-DLlG`Lgv7k=&2%oiEbP6;OKmjO<8!2XHH66KHWU;~i6ZkZAeU0ew0)H- z&r-Wb6;B-ajGc_LUcJ$C*s07>i9^=dP@qTTjsRtt04ga@h);itQ)nNJWRn~0lL5}! zPV7$y)p=End1MEOd~_5++KOz^+W`wT3Z$DGne~rA^Uj0MZzE3LmJzyUx*p(|xrRXe zsekt0u^qg>v}6S^KZBI&mBv~&Ya+qzmYA0i^;dY0hFKA~a|P;&gV=kn-Xw$FWDci_ zJh>uvLIbw={dvVc-O3w%3c2QvV=|h6y+^lKp69UBytUl$KMVGV-{e3vnhoZPQa5V~ zcHm5dApErMp8BHa;A+RwR9VuXJIRJOCli%@k+^-@y7gF1CYkpdb!o)h`o|Sf!YQsw z_q!5fy{0~~Oz|O2Kd6)o&E5-J2k1^vT}p_K<$hIFKl1AXD8ogq&WLgJxbQjf-Rwr0&nNkSwPIY9y{mz-Dh%hwT8Ktcq%S{yv`R zECyU@?q$A)o}5{Z8sr(qFI%CfMOs5V46S=ZUHsgDh4qC=Jv_C38YxMT?xHSv?hR{- z>_i#W0<<=}Fz4iTO`8y!M69~6Y$&ee#FQT%M6qd6lWiL%O>*97NPK#hm~CyQ5M-a( z66WHi6+|KG@>;hpKyhokY*(ijBD934_r>0(AbezrMFhv$_GplkBKqK!3Hqpf7tBMN z%Yd5+0McEWP@}BbCzGKXpJ{NazvL@;eCrT#@HH5q!GB;?SDTx#U)2~K2{3dG$bDVD z%VErwTU?7HvRBC+&=t&)rB*e8yDBQpmmjN~Ih6Vu&v%d(nfD;n!itE*Y5T+yO&jJ+ z3QVO>?$Ca_`#&O0D`3XC-FT~`T6U7wb2W*)N+3sF?C^Ki)}ra7FhVGAm4V^UuCr7d zD7t;_HZ*D^FglEpDp41Pp85J)t6w`#)3`%CZcKFJPDoKlJ<)p*DXwFkbVZHnehl>q z%XhuX-`MNwMJ1tE*~eNrIVRhAuXf4g^Ae37Svp@HaObtcgKUm$gj8K!xGkUpJ0~k) zYcDn^X&#?<$<`a=nO0y6H?X$PG$${l1U)LFCSuwcpHhBNxcoljg%lpHsgiSDk1E2g+oUtp-6hc>MY1dmM6_fKz{$ zm>K(Ei^r3uF~ZWCy8&|#Ppj)ME%qf!HmMpXIF5}`2!am_c(fAY^@#M%z=^VPndnHS zC{`8a_9h-JdWU_}xCnYZ44b#&FCmHfBUIZ84>BTFwga+bA&9Ho8;i(DZ4uy2N%n7% zJ&*lOMf@mrHxrx)YR6o-oMe zq2P+K_v38;{@>6S{Q}6}Wl_hjgo^-=O?myGLVbHX-xpiwfAb;LzbnSbW-aBCpSV*^ zpSxx^>mkfl=bO8E_~%b(>B&Q(>$Lo%hYO2pR9casV8yBjOTRz&*EeUa0rDq~p!fyM z1;r_XYINtl&eE}h%W28#WW(qSPiIv|DlZJ}iMucgkxB$y|?@bMFW3j*b-*xt1mmri1P~)j&1o+j(Z< zZOKPFMTZMy_r0oBP_$|=i{DH;T;3A%r($A)Th<&Y*29PLcDdWMa-{@AC^E6BWqMh^ zq=wm|1!v`0jDY+5ikms&JD5E$LGkdW^OfqIizkp?k$tfwQ#LV8!{%Cy+!fK-YL4hp zHgi-Gz0Be5YEtam1UfZTSx7Y?Lja8B{H|Z6SA%7u7E2839N0Vr+v&o97@}b>)psZS z2WMkT_;O|GBFG7hPAcs>RPvDrB4vPh;HX^gBx35RwCmybK~Yj9Md*nD*~qyEC3-@D zVsjSk*z0ZG=Tddp{SebD4)oI?%E!!wZJ|%n-ytIf&d*ppE|Q-xf`3Wjbh5(t(jrb`|wz|rKjZRo|`}K!-+CGHCM8N>@LApyg$OHFnO=m7Y z>a4k2ThN=4@UEAsDYW%BMQZ<~fd6P=O(BDshG+?e?1;pa9?#~;BQSV4IJ*&qoW5B8 z7!G9n;JqzeWl^FhrmZg)@6B`8l~dO=GoK9k^G#h~bV6-%(3Kp9s%xvn^DXKKiz@%` zdiL`J^$c=D*YvyN$hJTXdsiifKt6{iju}9%E8})vlTunomAovQ?L?hxBnA-o4Um{r zh{uw=qPU8+V)1m^YjU%TR(6AdLi=>2a_Z7#&=kAXRi*%9&~!WqhU{-GfW^~^usM1h zoQ^PMtMzUN-%zDU&BWsx!*b-dquIJ7u~w^~;w)zl_!P~l1!_#2j1cAO;9yPX(3IHu zTz2Ni|KjILL_ek+rE4lH4C;P+mx>wY*Kl;N_H-b(rLK*E4yk6dytLGq$8Jait#Y9? zZEGRgxyAa3vb#HCftfycO{654!kR%poZSVwrsXG2!-BXMqvV#J>{VRbX;pNu?UM8; zkV!XsbS2-e4h5b>$K{eaWcX)aAeOB`Y_L9;p|$iAY8Z#-R76;1Z6ySR95p!-iq=5j(uYJ_BfKaq3xc4 zKEi0uzwo|t-|UZ2<6a$;%nXft%yr?Hr)&~q%C=q=+DLQWFQ)e;V~R!QcwMl!&fq4E zwTd>>DBNoDQ7Su) zQ^FkSZ|ux)%KBQiVD$1;0j8*lYYNFE8)=%FzqpR%UI^dNL}naDJ-`W;&zY4uGLjc} zE@=R;*27KQqon^)?vbvmqgDdn6&pJb@b1o}<_=$1P!x0erWpoGh)ueq{=bFvCIcAn zraQ`u65I-QU#eldj6@W*KKYxt2RYg(*T>G!{t)yjggEG~EZH>%r=%LF(HTS`M4V!= z_@XDOq~Cwf`VJ2@S9S)XRwZXRT|76779pSKnPmSrh{-}mo{}FMQ|o4(Drju2OO~KQ z$HBy}G`$!+AbX-o9JEFwJf&+sOO4? z!$K7L*rv-#ssj*yqKtdPB%E%p9}#4&9N;d}&OH>bZn_ojQOgTTE&s1>#xEG(RlR_7 zlL=?9N8*p=g8PlL-$3mt`Q2VQTJmrEgU)p(`j&L*u0U|SitBQz74b?!!6KACRHlBr z7p9iDX_WAYMS$t?r`u{+GEjq~_j*aH{SqGH`pHc$>y`hYIUbzcY^i+mwA!eC|?9QVn@50R--_G(Q)^b>9!;=?G%YIyx$g_AthbI|t0H2I@}@Rs=Qn zW01x$(x{0K4h9mxZO-9%LA&wy=AU;qMuPV?i^RT7IBuQEw@k}*SrZjd_h0V3i&#tE z%<8nN5ppf!_LvzX`KU3SGe-4>SG_s#X)S5e9P?j862}zfBpjd$HimFTgs4e{}m_W~>pKVJe4O4@v zD$YE<3}4-@+5ybt)wugMyJ}4qm5xrE zFCQErl>09QPyH`zpKQ%Npu%Uw;GfFMB)PR+E>fv z;qsX>6sg->zihgFeZm;H1l}K-;XZv`@<@-Lm70Fpz|=k^t+Lm$XwF{up= zFK;^xpt9K3=x$In0B@9p2Lw2P(LjBNRm*IWx>1g7&W}c>ciFfrZPr34nzj0x1!#7Tmw9qjY7XG@RUM08lbSD(3PC4pCY2O*IQH8NludG&~c& z__7@M0amj;Xkbb_t+K~x3mSg-olRHv_tJw8Hl@p(HZ|kcsf%B&*ozkOT@dh_2t67b z4+Zp=+{(}%yND;nu+fxzDnm`v@{Tx%Wq3~Uh>CgxGG?gDHf`Dnrj)b_ILxwp`PUQu z58c`TP~#VgBhl`XN6#zFT#LN*bWrj2I3UIRl+8gVTOn}02NY?} zg?vKPB}1mr++owgAf?H)hK4b^#jS;FxdL~}g&u0RTrpY>Cv?v{UKbo2<{|c6E-&@o zdPM!q>m4f2q5A^m{pD_#_te7WOVh)u03HcW#k6ZzXr+BiiQ`PEXhq3TybG3{-I5gks)wi=RdkQJikMpZ5Thh3{J8YS6s+ntZghSwG_0y(SL_ z&WuqHS*BpL>OAoLo;y{@OZMP{NlVL*B)R?lm(<|NlfV!0G|oys7s`ikE_&HrI*9ZO zv=G;Zut5%~K8$dq_r6G#je&dJ+);bhx%J7s)n$x?*cEo9gQ8szOn2*5Rb&B2?HFjJ z1sT)J493er8pHy2;N6S}dc3}hkVj^6T(LgzCa8=04Z;!YL!5?k6Oz zoU8IKQ5oBHY=csh+y+;^ZahpMd^xJZtQkvR1U3{m7~v#4KgVC&wWXZ`>3=IB-UWJJ zv^)cclS|xk1j65W-a5>kiO0Mx%@9!6lwBtF=k|zhRmW!q;SMe z-I8XGMlW&-YSCSX}*>N!w?T zPHl+?1fqV4|6zQShjLV`a7=?c$mR*;a&D)o4x2#5USuW%3^jM{Nw;5+uo=WFwvk9{xyvA3jw!Dxw>(cO&%2Ae6Ri21%DYj z@KmsWMECkDsym4!eNblUoj%03F+k+)O8X1Srmi>fReZdn>3O8d76H}&r6n~lfCvix z*?Ro1>98DLfNbwRbbgjdg#9h9>kAz&Sk9p&gCt7lDB;U64es0vVS3p%P=sK1COG#F zzq-JkmYIM(WTl*#bE&ua!3oM0gB_&@bwX0R@Q44)H_z4j+?8M2S&jE@gQ(^}13nMA zBfezd8%E|->&L&G(@Yh%1d55OB$DHlGGgIe`XgtHR+3=m1$Gfbesx*&v|9^7L%p}d z(qH1^?&_TX1sx^-bg;Hwh`n1I_s8wF!WssQklnUGsCt$9jF-H9Zz z!Ro#mZd}=GrBnTtNjB76docVRkLH~J{OlmbDVTU9aWnY@b7~VU5>iY(GC_HfTms{n zX`c&MdE(g@It{wyyIH5r_E6uUP+!w<$S@51L}G0$^V1cbvWtrM^BQn{^fa!7$I+!9}A0pE0v&G;yzP_Zb(2D^^_66n5P4+(FD!@u1%AVG;x-xfME3Wh|UO{ zf`$5^8u{+Q@@Ewm1nnWX1!l;uWoO{hB=IO4ucl07S3Kk8C153CdmHk7vb1P355ww} zm4-ISo^H33ZqR(C;GgOV{Ii!Q$frRjYa)>;QFbhca05;a3=soeKFU){_&ZZ=8U5N! z2lq(|>&u&~9vk%Hj;3%uS?cT5 z3?$Ucu!2OptN%dEVVs>AoyULHYsbE>Yk$zxLyh%rcY&M3i57myQ*k1|8mQ7J;A5>G zqcvV_Yzc{z&@s+EHXGh#^mYw4d2X-1asb?7WA1aVbo_t#&d)D36tA>z>AYHekE|>^=i9}$7Iu3aviQ~ZH!=+fK??Lrt{o_GCIF>BLf5Z4&OX1R`kT4 z_Yg}t|0abA)N`aoxnUr43EMQOG|(f z+iyB8hghtuV8q1JUqZC%uLThT!->hhfb{M48%Wfhg=@wpHO$3+fS*Pe(#GO=#KPU2 zV2#fddT&~?+NinjOA;{(y9;?jA_pQB&a8%0K-cXb-3G?5gz&0Jj;I16qy9<(F$vHs zN}{GMAEv`+H4|=e5VJjju3xpxO^1|^<5H-bVFGuMq)rIdEMCmC1sD!uvx$!6gxv=b zpQX8t5P2N3#qOOwz@F|Xym3uvTk?emQ;o`~(6YDg+%`Y!rt^$$aVgczIbHkpjI43) z!mtORElwx=kg=|tid~b@8YXmaeYb;7cf?C-Aq4tw2 z*unb6Gh)<-P0}Th<3kS)dXFfI{id*ZaQsa-ny^ zO&a+PUNCt{RC>U~98kdh=?lDts5~DAVoz8|B)+uBA@$deTR@Zih+{>5%RgQzNuF58~#-LaSyLTSc#d#9p;rpm3xT`=JtJdEr_p4mh zA0D>UxrN~i1`n9=d?K8FYo)pQZC-aptRN<+Z{Pakn*9}ZlI(eQ~e*y%%kLc0z zTJ!1TFluElsARt)W(~DH_K4SWQMt*!%;Ez~-L;#ubqdsn6-7{RD z`+k6IH)#G<@3osF8`a8?8CjD;j}|Wxv)3V6q8qOyLia&BuHmhU&Jq4TsMbo>torm~ zLv(gPk7mwG?=DKVH27v76<7Mhg4r?e_6+WtTbe>B5(EXM1lH&Q2T}|2SuT0*68KOF z5d!VMm;vVeeQ%%aZr+`|ZZT9~E%j!^&a{f0GL?B7of0JOHdYpNNVvdV1r~ z=OiW{{A_pN-_%c!xgwfxwww+`DzzU>*yTnM#n z0cC{%L=6nGLA^8~*zq}#%H#qGD^{iWkjoP~c0+P)OcotvcpHDD^k_9hBj)$q?!xsO zYFB!u86`bWWc2#j{wXT$8Nq+8gL)VZY^WE?m9-DJv&}vrZXv5J+G#{d7I3>7obUCN zKC_H6K5S1U5FipIbk$tqt8%*LYx25n9cKBrS%0u&Q z)01pUx2ZL<=+L+8sXp0du7OxN#!NoiHcuW%Rl`GG^}H8n+Vh)p6QkA;>t1rkBLeYQWQGTqwORW;Eke2ek8~W9-rEwPWT!f+4 zZJPfx3B(v+fWawQ_;AYvtJz6fh3GaXY8)3TGFV#$95RS5>HJQ2(y=y-;`F}y)mbs{ zh~5reV-oWBXUSDQo|+t{0Q)tEcmAMz?Z|;%Z}=8~H}rz?doyHY6rmkx>8Au9Dj8n( xEGExp&EGa#yezyq!D7>Dz-que6>xBVuL1hUX`#6*jGqs&=x7;ek~OR!{~sxv-N^s| literal 0 HcmV?d00001 diff --git a/challenges/2024/04-ceresSearch/heatmap-2.png b/challenges/2024/04-ceresSearch/heatmap-2.png new file mode 100644 index 0000000000000000000000000000000000000000..23dd4d0b94e9435dc94791f407cbefa2aa14ded0 GIT binary patch literal 12175 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 z grid.Grid: + return grid.parse(instr.upper()) + +def one(instr: str): + wordsearch = parse(instr) + + seq_starts = list( + map(lambda x: x[0], filter(lambda x: x[1] == "X", wordsearch.items())) + ) + detected_sequences = set() + + for start_pos in seq_starts: + for xdir in [-1, 0, 1]: + for ydir in [-1, 0, 1]: + + if xdir == 0 and ydir == 0: + continue + + delta = coord.Coordinate(xdir, ydir) + + ok = True + b = [] + for i, v in enumerate("XMAS"): + if not ok: + break + + x = coord.add(start_pos, coord.mult(delta, i)) + g = wordsearch.get(x, "-") + ok = g == v + b.append(x) + + if ok: + detected_sequences.add(tuple(b)) + + return detected_sequences + + +def check_cross_adjacents(s: str) -> bool: + return s == "SM" or s == "MS" + + +def two(instr: str): + wordsearch = parse(instr) + + seq_starts = list( + map(lambda x: x[0], filter(lambda x: x[1] == "A", wordsearch.items())) + ) + detected_sequences = set() + + for start_pos in seq_starts: + + a = wordsearch.get(coord.add(start_pos, (-1, -1)), "") + wordsearch.get( + coord.add(start_pos, (1, 1)), "" + ) + b = wordsearch.get(coord.add(start_pos, (-1, 1)), "") + wordsearch.get( + coord.add(start_pos, (1, -1)), "" + ) + + if check_cross_adjacents(a) and check_cross_adjacents(b): + detected_sequences.add(start_pos) + + return detected_sequences + + +lowest_colour = (255, 245, 237) +highest_colour = (255, 159, 45) +colour_diffs = tuple(map(lambda x: x[1] - x[0], zip(highest_colour, lowest_colour))) + + +def get_colour_for(n): + return tuple( + map(int, map(lambda x: x[0] - x[1], zip(lowest_colour, map(lambda x: x * n, colour_diffs)))) + ) + + +scale_factor = 4 + +def generate_frame(path: str, wordsearch: grid.Grid, counts: dict[coord.Coordinate, int]): + max_val = max(counts.values()) + + maxx, maxy = grid.get_max_x(wordsearch), grid.get_max_y(wordsearch) + + img = Image.new("RGB", (maxx+1, maxy+1)) + + for x in range(maxx+1): + for y in range(maxy+1): + img.putpixel((x, y), get_colour_for(counts[(x, y)]/max_val)) + + img = img.resize((maxx * scale_factor, maxy * scale_factor), resample=Image.NEAREST) + img.save(path) + + +def main(): + inp = sys.stdin.read().strip() + wordsearch = parse(inp) + + j = defaultdict(lambda: 0) + for state in one(inp): + for s in state: + j[s] = j[s] + 1 + generate_frame("heatmap-1.png", wordsearch, j) + + j = defaultdict(lambda: 0) + for state in two(inp): + for dir in [(0, 0), (-1, -1), (-1, 1), (1, 1), (1, -1)]: + s = coord.add(state, dir) + j[s] = j[s] + 1 + generate_frame("heatmap-2.png", wordsearch, j) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/challenges/2024/README.md b/challenges/2024/README.md index 735acb0..d46556b 100644 --- a/challenges/2024/README.md +++ b/challenges/2024/README.md @@ -10,11 +10,11 @@ Total stars: **8 ★** -A day denoted with a star means it has a visualisation. +A day denoted with an asterisk means it has a visualisation. | Day | Status | Solutions | Notes | |-------------------------------------|--------|----------------------|-------| | 01 - Historian Hysteria | ★ ★ | Python | The reading comprehension was the hardest part of this. | | 02 - Red-Nosed Reindeer | ★ ★ | Python || | 03 - Mull It Over | ★ ★ | Python | The first instance of Advent of Parsing this year! | -| 04 - Ceres Search | ★ ★ | Python | When it says a cross, it does not mean a plus. | \ No newline at end of file +| 04* - Ceres Search | ★ ★ | Python | When it says a cross, it does not mean a plus. | \ No newline at end of file diff --git a/gridutil/coord.py b/gridutil/coord.py index aed3d6f..ba973b8 100644 --- a/gridutil/coord.py +++ b/gridutil/coord.py @@ -80,4 +80,6 @@ class Direction(Enum): return self.value == x.value def __hash__(self): - return hash(self.value) \ No newline at end of file + return hash(self.value) + +directions = [Direction.Up, Direction.Down, Direction.Left, Direction.Right]