From c433076f408975f0e6a27b3d8386b0aad75c088a Mon Sep 17 00:00:00 2001 From: Keenan Tims Date: Sat, 21 Dec 2024 21:57:52 -0800 Subject: [PATCH] day22: part 2 solution. 38s runtime but works. --- .aoc_tiles/tiles/2024/22.png | Bin 3307 -> 8228 bytes README.md | 5 +- src/day22.rs | 115 ++++++++++++++++++++++++++++++++--- 3 files changed, 111 insertions(+), 9 deletions(-) diff --git a/.aoc_tiles/tiles/2024/22.png b/.aoc_tiles/tiles/2024/22.png index 3b27ddce2972c9aff648b152d45b0ac025bb476c..56fdee5eed79bfb438dcedd535316e53cef665eb 100644 GIT binary patch literal 8228 zcmY*;1yEFP)c#5c5-PDEARtIL(j|g)3ohL$-MJu23KB}g(y$;bEFrOUE=WsDcP`z% z-~PUD=0EeFd2h_zd(WAB-uFG{d7cxcrJ+bnKurJu0Em^9-3lzaMm*8C(RfN0Qk`>0RnK5L}091yOht(`#+S;q=rpOE+`4vqv&DHr_~y?A{3`fVo4p$04jsF}Oj=;lePsMUoYVU)UAt z%`z=Q|LENgTu-a^V#QtWqcpD@Cr);}*yAjzUe0Vk|4pt7>ezD019t!bJ~<IX7e(;5)=>6 zdurz0^72xYPc{}cgdaT=l-O@;;;rgccDUkh5pDqFa?%Ho%OmOL*_Q4ZLk91{C-eln zrJmOI>7KUux{bXecW?$yYPPPRnv#fxXv%v`eX>92*d?ZAaDBeRbv7_5H8z{8%eAl> zK`MvB%XG~~&C47w7aF!31GUFYYs)+T-KF*DhOctWifpv`$6bh@Ea!80-w#ML5Xt+Z zuiK6!Q#s5o2aRr`72MT(4l^V#4w`w>8;G%zxBf8!b%#vNKL!W@wEdTr`bz--Kf33I zzib>!0qI$p8+ntTK~OQr~c$ReFOZmG<1jYZxJaRD`YW+ z8Z2F;Iv+CABnW$V`cZ=N&=OL+%hcAU1qW5-^E?rqi`07ETF?^}lLe%!)vyI%xnZ5L z0rMC$0Dn*Hg1^HGu{FUg3tQ4fEO@pWZ^g8(@8Vyna3R7W1= zk6@jG;;Ox-?oY_vieZ^*EGMk&3#6nBu9!f5+0tiO*4-IQa3GgYb^!<6(?|=6`1EVa zzTnzuGIcwDx%R^FfgR2;qtA4zXXF=$3s|Lj36SeKL~+uPJN6%bmXtWei_R4&iYc8q z>C$Tgfh13#0+d(|0nbSngi=&y>h(-MQqVOs@Z_-({5K^M(J-zdBP{G`WDX;nVb$U7 zhu+*abaX?NYX9VpmTWvP!uess;vTG^H{+(+m?ikhW$$dEiAk&w;VGRbA}xB{%1HSrECVru zW1M95V@tofd9>M`)uN_>H;@CKK2_-jJm+@3=MGs}-N91TNn8pf0wj3~3QOg2!^!*i z=bp~hzb$ZU!2*0qTl<=4(R0M@teIxy^Xlp@{ZVhZ0*n!#(G!#W6t^bsp|?PXeV*LB>GVb-e1H|oT3_+odyh)$xPps&pX%$tX(kG?R7^mXL*_R; zR;A~CYRtH&nmhurirNC zEN_ftPDeNjf@H(7P710gRE$QKXRO~)N2?S2S7c{g?V))JKo-mpsQvRo|y?PZ6P^ zBB5RNNHP|dJ^H&dN+jgJjI=Cn^@f`0+)P;kJ0roNPdVY^ANSpseDzx)sL&U{e)^e- zv~$qj&PQDF<^K6)FGG7>p_4f@Pr6P&(zD?n(ig!=Svoa)Nxza1b9>j@i4Ap{RZW>J zJ+n<-bkd(@gRJ7joQ+e3P@ zE#ta(&?)%c^JRaWF5+{DU|qV|JEs6fs_&cKz?!i#hYdIW@;oOr2~VGB+rtmlH#-RE zTy~wHi_b-1dPZ}k;%&F)%%k@Cf1s+Z{DAIf)5OGCl90lCjpMI= z;tnbOC8^x|U^Q+D?O-BY^(E2U$_7&IR8aEX{Ueo6_*Op=eWqxNe1wxj2| z#>9Y^Thiy3X6fLZ2eUjz5oSzfqM~jjI;V}eQ3teNEx>=bL0>*A-0%OJJ=kyM<)6K_ z{UTrc_c7ZB_4(p;oJSn_7swbj0=p;kb#!8E()^b6a02YALaQ^DXd#AZAt{jjvm1A& zyG>mFFG*s~Hq#3)`t!1=(V%XVACP#9^2I40ZoT8_%&*|Xdo{g`y@r`jGq?U0U9upD z>OvJOm=?r2tfO>{iocek!wmd`YgTIqLa1#w(Lzd!L%`_70ONvzXBlLA zaFA5vz#nx-eFx8~DxZS9QUfF7bQfh>5J@g0U-?(IYV4X$7IUkWqvhDY?Lyb@`<)D% z*8g%f?9|LE`cgG$|L54#su=43yT>rQcZR>bquIUQzH6m_Rj7c$oR2|9eQqf(-B)fl9OPiR#5u~)WJ}ue4o*}aQOI z={JXP}@}a-+_!#-jO$D)N{CS&ukR_<|_0;>21Yj&K%I1Ag@^#w#~gRQpKOJPZtny++lkWTweL$O(i;co4`KSx96X3s{35U-MG{od;| zYG^!JXj^UZko7CC1Eo#5>KN=HA__z4f|sEFunNmAf~SkdC;Slxa{))k= zo#78UK}|OIR)KG1@QN^i$74gK&~NC+6;joD>GMDR-xj;8TS{DV6EBatW}?>e2T7@LN$FhOl!b;Hz;(ne2M;^e%?y(bfHtQ5NiMXU!|Pp zf!|xvK#4;N+mzN)Wj$TkQAhQ=7qlZPxZn1>7*a zj@#xu&a-91etre67EqWRp9$f{O5pQqtWL<@)>V%q4=vmvYMVT@t2L-qim8k-TJ3Ewo4y|k;7 z98qzF*h@T@9Nt|?eV^r_KC3ostnt;Gj8zUC`0FR%(4JqAw=hxQm#5Ke4bBBvCr+2dRx0YR;}JV#B`oHF=-O3`W`bxt#5Zd%MYGMndL~wxx`2 z$uRiS%LgpTlZW-rZ8=gGnC@-dqaQ|LyXfYs-#a>;}W%b%^TCqq&lL(l)=IEw9Ww zJx|o|DlM-$wMha&ugU9iN_1AN>ZM8^HLV1ClkL;$-r-W?~7@d`x7&(`7diK)91BUhGmzCB(WHP)(t(|*@q~cEtdIha? zX>Yz95YZyVq`YabUout74NZ59Muy#0k{3Ymyp$2qCuiB320*|zCj>t+R+SIGNP9<} zi`K3{W~EJ=aS!QjD@-R3k~@yudQP6|l-?iJl&kBT>HFT>^8&9&Dp7T8);RBo4{Y#q zR|6`LzB@awr{V7!G{C$H$YqufrnS|pBOyOEzIo$z+w46s{=*bDUHU5CC@-y)yJUYzORuorI=G9Fba`}fosv##vhXf%5$;HkKJAK-M#X_B8$_7po| zA9*E4?hO4_8Uoe)ej0YGT)wiY#aQs-Owu|B4c+t??LCVpI=3|wqZQHnxu-dDKL~MK^-EIAuSOfi*ZxD|jRX{e@zk z;xWh8W+6}rgGx;PRjyCuPtg|LTtI^PPF zyDY5Kd-jWWT$vo4(toEcqD=Ba2g_ibY8dtvG{qR>b|vWW*ZM371jB`As(UenW-HxH z)yKs;#Y?{6m6n(YYxxo8@8Mo?P;*dN(PnzRXF#+pn0EMg8%gA{sn&^iHP*Y0`OJ^i z?%-n|`)sOgbq}?eCjmP9};6akb7T-C^IT&ySHGbSS0Ga{Yf-*B$T)`H(6& zb{-O(1+f~C%V`ZxRGXMh$2k%!8&p!u5V$W2$=jf^uLX=Dpxmc%QMWFcPo$Ml&Ht&lr z^GK!2ExEBBbBQ_-&-CYal384`%uXlpzC>#;PH~Gbd3NuB=MLaYNo&@Yevi8}h?E-P z@N22C4)ix$IS)rh>)3Ay7q)Uuu16j^VO}ze4)v;XDsC4bxk&AeFVQPU#~8XI{*F@kq^u0MOp)cNplB9}>Dy)_|1l^nUOL0KCxiK^F5&$dE5V%dA! zl@nDJt!nUTCb%FMR5T*sfVc=eut7%Wp9XgGMsuOn&%?oHD-NTU)&9I5zMQGK3woMh zSF;~UsZtM_e%GmXiHUa7q-a=wy9r;1y@S^WV;lHk+RXvs1{wRt7=v=cmMBgy;LEXk zRTUrE5daYKs(nc6Gl)ocjb?{3$6=pFcd>t@)K9ptrv$MCOh?fBxxJ^$7-)1aeopIE z^tLxH=i1rH=OzI!HRENa*Bhex#r>E-U%!VVOCFCa^LOk_AV>6P>PRvLnRd>^e%hgdhDLSj>ci^sqAYX> z&%9qKWt=Yir6jmR3p^myNDxMb2YUiuXnX_i+r;kEmpiGr_-QdTKGu^@LMZcrTrXl@BdZ%^rK>wuLp&P2^3x8Qb(}DG9ab zYB{_zQCwm!RJT7eS9>ET_`;h=J@8&a+44{^LZ~>>4y4NI9x_fe{fDT^(stN$Ywjq^ zHCdV(K|!Ykd7u0Qp{Nn`<9a=QQ(wT4TbFrCP}L%9g$~G>7ZQBc6qFwgBP#|1}YKp6*s_F$Z*;fak@!Zmd2zTObe$ z(}C+4S&fH03}S%0nLi+_ZcpsStqx%ZzOmLf!QLOz#$-yucfcB9#AXo>`W}`bizI@D zJMkK5n@lu@a+NE9aMnC;T(c9c83cu;iz=LTsG?uw=p0POp<+_hZ)=%Re#=$|Po_7> zR_)@1mcWYqW;y@LKUcXgp1$=F@?aj*A8>YV5}c~W@cBpWXXgS@pV&+yK(k_nRns>W zIZ>MNs3~VYVJ~+lMv}7|cyMw$Rzv;t`~;}=G`!us;`c3Kt)Z3EtoFtFGuHSP2!22q zK}uXuQHt}!;_sLx=1YfO!N!x~MO&hZ$+f@N?d`k#vgK@) zGn(|VZ`{RZljm2Oqto44XuX3; zjFQ>$yKlt`t@+27(witBFaBRWJ>A0|z1^@h#75)Ce0ergpQPTR-taa&kf-N&XDc{c zJ(mssW>!nqsCn&rwb$&O8x}%Mg7I{1OeWqO)M=D$mHx#DDnRJ!EmSTEiHRAM5_n2% z45BLEol)=HWdu)%aSZ2gH=WWNXsfeb_l69Xn=adekz>=fM#2Yl=silgp9>R>Mn;B1 zqg6YLu6MuV$~i)zg{Uv^G7K$E`w{687l47Ve>#~eq+qM0L?J6X2?nG%4Ae@aT0LTFvoP5n z1o*+wRmzweD<3E_oJ1R#7^^6NS)-l*PySZ)`<@sRvNH*I;)Yu`pAJ2u`=3P@;wLWOUD+p z_dGTCH5s;5@!Ma)I~5zpdEGAO+AdGcsAP;&HU5+n07zE=8!u~JrPb1$e)fG$b5yI2 z{;gZ?5bntzJKTDRzweFXGHgSrxizVQD_J7m+9ZV;X&Kh(FODP)42c0zZttQY-muhq z5u+~4Pmcll_SoQ)*S!zOv6>nErqS6(Y(TzFSN5W(EWtW(Y=AQo!qBx#>hYm=suhi& zYK@U6H|4=jWB#?{GCOzd$&q?yGu>lV|L&6c(!624FTxjo`}g>#ez!|(ZO#74i*7j7 zLwoP7-{ObBCGP6#5FW_5gV{|>!}r%6^d}fIo73}mN6H=*KF%hJ^Qdp%_Z03VRiFaE z+JmEcN!}d7(jjCSS6_9mzg}7XF!oKO&r)qgw|!`}J$E!2engcQ5x`HFDn0P|r5MBv zJ<@ZMarDKtqYGI3Si!de@&Aj&=?kQTI4w?GT*nT2sX}SHvpsTjc^IA&Efu`lfa$I^ z;3t+NJk1#QPT8HuSkHqS$*A;@kFq(r|97iwnqDwn6o# zjK>+w4Y^noCjppY;k7`0^)>w9dyaPP2__padwCRl)4kLaGb zt7$AF07$lM>FDADW~;@MNBdc+aJt;b{;;e@eUpA4F$tPpgk+cDX?ajL_X`o7 z%*#kcAd19S-DAARKls-~5}o@r2d0-^nyWZ3Gc{o(<8yD&wcLae%_OC#m0;eDh7o>AbjSRjqSkmJ-BWk zVF!1sxkYCP%O?gndU~2IKW{E@{Jwnxo#S!Sa3prn^Ulr=kw{EPNHBacRFa0OA(N5amT{)kh}dpFXGceo9zTlg#fv!?oy17wpGX>A z6Kz|lcmK8X=Q8W@dYrwP8PAPV;^NKtDZL%kz2rfFNo!sDM9OSsWhFmMrzvm^)B1MF zzl=!S;ECJb-e%HA1`2ew_4Hbci;F8NjzD}Fi&rB){{9`1)tB+)$&Y~MX>oUVcZ~}d z*dR4G+Vs3e&$jxqRwsmog_|bMlD&-ZKk#v|)P;AC#SahmW92@V+wwqU<>Xvm-;+~P zQc_cU5qWqp`|h#!y}9_lpVBX$VhJdXVod`|kf*Kf0HEXMO;=Y}G#YJa*imE{ii$Emr2#Hr`STANkPu^XbYSRx}VTP33zhP*ttO2on5ML9VxmDb>`d0NhSOf73=ys;-mQiz&5uu%H% z+lO9mLLmvJlOn2^WR*7)KK`fJx%Bt;_jg5H>c?01lA<|yX7a=v00h3{h~^2sz}4^H zzdNHh8B3oZK70t!cRl^`>rPJ7Grz`OvO%`yKPIK5oUF$E z040yC`Cc+LeYdqR(ACv7t;Y@dG&uMol;s04u(tkK4|2ucK33bNKxb@hj8{ZPMn)Gl0N~tAcy1q& zPJkW|Erj>_=1q#pcs#|JtgEZ5tgP(Q7z*f0I;kAOT9w=@Pd%*<#899Y{sw5Yxp}wi zkpPbXOegd=;y|8ECVLK7`!!F%QhR1Mz&o#%Zw>qZGGmpB@Ro6+c3hCCUHE2F##vk6 zRHAQq*S7ZMj2GX$G*V`zrKRTw3fsKLH4dx}zg9WMsPY)HW+-2?^kJk7_iT8_AfFl2 zf$c!TQq9xH$0s1*)r5~(o6d~P2}2h2(_kxQLI~R z5N>{n?1BP4pYKfs0wGPtj9*M$0jN+~x^vohZ)a$6l)%f&>*wd^Wd~PH;kNINE$HhKo>Z15A?5S% zZ~$}pYhRXXY2(-rR3xX1#Uk@jQ3i=Wu9s1xVb8UWwPbI9HxOt{PzEXWboE;Uy+2=@ zw)Xdi3j#~|qQ&0(0j1C{6FP7UrW^8hZ}lKPK3+jVAzQ;cw@uhccA^nq_`pHzV*&Y+ z@j%t7nlnQoezMEs;?+)#K59p0j|d2;Dk!WsI@y`PqiyWF+pzCZi+{q)%gaUIU!({L z3B9~C02_?7Gg%gJDNlR^car*}-G5S)R8{Y2n9tsOEpJTAcW0!*x;mPvNKnNs(}r(iyOzIqvNi%8hGtYr2 zqHrK^ZBp00NF=+Kw$Aw#-r)Tlo!CQ6w_q3n)S$o}Y8;%~rd0#O-jO zRanFslJSh)g=kTZ5%r%*Stq%GMQd>Ihc#taHPS3&Kkej4<{}uUw4C?2DkKH);YYVQSJBO$@KK}4~=(y ze7HL*lw;KuFdDR_4DEs4>T56GYlZ<5uH3a$;=0>d$J_Fy!-%}Jw6th^jm>bO;^yxm z3*d7|JTU5|7&!{)ue7l7ckfJt97?#DcII?C-30&O&iYVE+$3_)@-Ia6ec<#%j+UIx z%>j?Y+#)g8mmZ62juP6Bw^Ws6siWCF{r&wh7})F4*$oQUQ6^lT%XG;_xW%}mlN=lz z?3)=N2sF%^?Ge~ynzZy@_EQzkUH%i_q8_zCRio7aH}_assy8ewEkBHiFyS)YEe;;! zKqQ0v6z(lqR8&+ua8)*NH>`DUZ?C3CWz*WX_MF{!CBBt`lg9-96_O`mr^!0*wCv7K zBmaZe;zrs(Y*kp?zk9HJQTqPRyfubE{(M=cR z<;$9y{!vs+aGn|+ZMxa@@J3ri8eV$+KloGt9~v9yR9ae^l$3;1odDfY)F{l!dHRgK zL1HNBQv~?xpallQk>=*SU;QCIjoO-;BKf1be{Z*1u>Hv-0x~tSoTPjnCnW*9k(%<} z4r{e9w~^G3_&${$VEk85M%oMp&KPQjhe#e&$MOiMC@P9xxO-w+{C+^d{Li0A6v}Ri z>%Zb8nV`75iu-Tl|8jG4o0Htz-k2p?X7yTS04goxT0{n z)Q^Peg>Cm{DAl|Ezjov?dm{9Q%$iO4%ZiG4UxT`ml9^A%mw*S?qYS~ebc zKflPsF9GaEpvle5tY@&)%=7NulG4%-kGi$Bwc8>ORVtKUGj>^PU=-d;XSWB;Pfn7g z9|@esU@$g%j%pkLBsjNuB%B-S?CdP6Ki9>=vPc7lVfGtOw{GgToaBAF(y7uRkgv68C}Qn8X3->_ zKyqL+r1(#O<6}uE;%i~AY>_591n>4Tcw-BGA1vF;5`|rZ$EYz5xM`9VyYYOmV|(u{ z@Spw z^;KnOxfZbgzAi_hzFU9VzXfxy(nr+Zqyj_WnSdw$yzo?WU1zPBGK0p%26NE1VA55P zmLPKZxwOyXi1T0mobMY*u5oBgX-M}%us}mb&!*Vuu6{HEku})y1P^{

- 2024 - 40 ⭐ - Rust + 2024 - 42 ⭐ - Rust

@@ -65,4 +65,7 @@ + + + diff --git a/src/day22.rs b/src/day22.rs index b6ff2e8..6b044b1 100644 --- a/src/day22.rs +++ b/src/day22.rs @@ -1,9 +1,17 @@ use aoc_runner_derive::{aoc, aoc_generator}; +use itertools::Itertools; +use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; + +#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)] +struct Change { + price: i8, + delta: i8, +} fn evolve_secret(mut n: i64) -> i64 { n = ((n * 64) ^ n) % 16777216; n = ((n / 32) ^ n) % 16777216; - n = ((n * 2048) ^ n) % 16777216; + n = ((n * 2048) ^ n) % 16777216; n } @@ -14,6 +22,54 @@ fn rounds(mut secret: i64, n: i64) -> i64 { secret } +fn prices(mut secret: i64, n: i64) -> Vec { + let mut prices = vec![(secret % 10) as i8]; + for _ in 1..n { + secret = evolve_secret(secret); + prices.push((secret % 10) as i8); + } + prices +} + +fn changes(prices: &Vec) -> Vec { + prices + .windows(2) + .map(|a| Change { + price: a[1], + delta: a[1] - a[0], + }) + .collect() +} + +fn profit_for_sequence(changes: &Vec>, seq: &[i8]) -> i64 { + changes + .par_iter() + .filter_map(|inner| { + if let Some(buy) = inner + .windows(seq.len()) + .find(|window| window.iter().zip(seq).all(|(w, z)| w.delta == *z)) + { + Some(buy[seq.len() - 1].price as i64) + } else { + None + } + }) + .sum() +} + +fn find_best_sequence(changes: &Vec>) -> [i8; 4] { + let mut best_seq = [0, 0, 0, 0]; + let mut best_profit = 0; + for seq in (0..4).map(|_| (-9..=9 as i8)).multi_cartesian_product() { + let profit = profit_for_sequence(changes, &seq); + if profit > best_profit { + best_seq = seq.try_into().unwrap(); + best_profit = profit; + } + } + best_seq +} + fn parse(input: &str) -> Vec { input.lines().map(|l| l.parse().unwrap()).collect() } @@ -27,9 +83,14 @@ fn part1(input: &str) -> i64 { #[aoc(day22, part2)] fn part2(input: &str) -> i64 { - todo!() -} + let secrets = parse(input); + let price_changes = secrets.iter().map(|s| changes(&prices(*s, 2000))).collect_vec(); + + let seq = find_best_sequence(&price_changes); + println!("found best seq: {:?}", seq); + profit_for_sequence(&price_changes, &seq) +} #[cfg(test)] mod tests { @@ -37,6 +98,11 @@ mod tests { const EXAMPLE: &str = "1 10 100 +2024"; + + const EXAMPLE2: &str = "1 +2 +3 2024"; #[test] @@ -44,21 +110,54 @@ mod tests { assert_eq!(evolve_secret(123), 15887950); assert_eq!(evolve_secret(15887950), 16495136); assert_eq!(evolve_secret(16495136), 527345); - } + } #[test] fn test_rounds() { assert_eq!(rounds(1, 2000), 8685429); assert_eq!(rounds(10, 2000), 4700978); - } + } + + #[test] + fn test_prices() { + assert_eq!(prices(123, 10), vec![3, 0, 6, 5, 4, 4, 6, 4, 4, 2]); + } + + #[test] + fn test_profit() { + assert_eq!( + profit_for_sequence(&vec![changes(&prices(123, 10))], &[-1, -1, 0, 2]), + 6 + ); + let secrets = parse(EXAMPLE2); + + let price_changes = secrets.iter().map(|s| changes(&prices(*s, 2000))).collect_vec(); + assert_eq!( + profit_for_sequence(&price_changes, &[-2, 1, -1, 3]), + 23 + ); + } + + #[test] + fn test_changes() { + let changes = changes(&prices(123, 10)); + assert_eq!( + changes.iter().map(|c| c.delta).collect_vec(), + vec![-3, 6, -1, -1, 0, 2, -2, 0, -2] + ); + assert_eq!( + changes.iter().map(|c| c.price).collect_vec(), + vec![0, 6, 5, 4, 4, 6, 4, 4, 2] + ); + } #[test] fn part1_example() { - assert_eq!(part1(EXAMPLE),37327623); + assert_eq!(part1(EXAMPLE), 37327623); } #[test] fn part2_example() { - assert_eq!(part2(EXAMPLE), 0); + assert_eq!(part2(EXAMPLE2), 23); } -} \ No newline at end of file +}