summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2023-12-19 02:03:48 -0500
committerJesse Luehrs <doy@tozt.net>2023-12-19 02:03:48 -0500
commit28122a7897219423d70ddd73c7dec0d68cfdec1b (patch)
tree22d9a7ceb89b010f9e4404628e0a871aef1ec5c0
parent364d94c2464165fe2b5ead08a91b33d616e72ffe (diff)
downloadadvent-of-code-28122a7897219423d70ddd73c7dec0d68cfdec1b.tar.gz
advent-of-code-28122a7897219423d70ddd73c7dec0d68cfdec1b.zip
day 19
-rw-r--r--benches/2023.rs5
-rw-r--r--data/2023/19.txt773
-rw-r--r--src/bin/2023/day19.rs429
-rw-r--r--src/bin/2023/main.rs2
4 files changed, 1209 insertions, 0 deletions
diff --git a/benches/2023.rs b/benches/2023.rs
index 0790c95..2a3af58 100644
--- a/benches/2023.rs
+++ b/benches/2023.rs
@@ -37,6 +37,8 @@ mod day16;
mod day17;
#[path = "../src/bin/2023/day18.rs"]
mod day18;
+#[path = "../src/bin/2023/day19.rs"]
+mod day19;
// NEXT MOD
day!(2023, 1, day1);
@@ -57,6 +59,7 @@ day!(2023, 15, day15);
day!(2023, 16, day16);
day!(2023, 17, day17);
day!(2023, 18, day18);
+day!(2023, 19, day19);
// NEXT DAY
fn bench_2023(c: &mut criterion::Criterion) {
@@ -80,6 +83,7 @@ fn bench_2023(c: &mut criterion::Criterion) {
day_combined!(2023, 16, day16);
day_combined!(2023, 17, day17);
day_combined!(2023, 18, day18);
+ day_combined!(2023, 19, day19);
// NEXT DAY COMBINED
})
});
@@ -106,5 +110,6 @@ criterion::criterion_main!(
bench_2023day16,
bench_2023day17,
bench_2023day18,
+ bench_2023day19,
// NEXT GROUP
);
diff --git a/data/2023/19.txt b/data/2023/19.txt
new file mode 100644
index 0000000..94bec27
--- /dev/null
+++ b/data/2023/19.txt
@@ -0,0 +1,773 @@
+cq{a<289:R,a<499:A,m>826:A,A}
+dff{a>2888:R,s>568:rdz,s<288:fg,qcr}
+nsr{a<3259:A,m>1071:A,x<2864:A,R}
+kvb{s<1476:A,m>1488:A,s>1973:A,R}
+phj{m<816:zz,a>3681:nxh,vhk}
+bpj{a<559:A,m<2790:dh,tf}
+zct{s>3504:A,m>2721:A,A}
+tlp{m>925:A,x<1957:R,a>574:R,R}
+cnr{m<1459:kj,s<2429:A,m<1725:R,txz}
+dl{a<1924:A,s<2932:A,A}
+pjb{s<3231:xcm,a>2136:rqt,xdz}
+kkx{a>2443:A,s>3661:R,m>834:R,R}
+lld{a>359:R,x>3481:R,a<224:R,A}
+rf{a<2413:fp,x>894:mvv,ts}
+ctr{a<823:A,s>879:rbg,A}
+rgg{m<2306:A,A}
+dsr{a<1800:A,m<1635:A,R}
+rp{s<3744:gg,s>3861:A,sv}
+mr{x<3095:A,a<2136:A,A}
+xgf{m>2951:R,a>2641:A,A}
+zzr{x>480:R,R}
+mn{m<1402:A,A}
+zn{a>1472:R,x<3560:A,A}
+xjc{a<3034:A,R}
+zgr{a>1717:A,A}
+zbq{m>749:R,a<901:R,A}
+kgp{m<2261:xk,dl}
+cmb{m<3062:gnj,rg}
+hjx{a>1752:hdd,x<3082:fk,R}
+plz{a<623:R,x>1388:A,a>809:R,R}
+fbg{m<908:sn,a>1415:jtg,a>720:shc,xcz}
+ml{s<667:A,m>1278:zfb,R}
+bl{a>3041:A,m<2098:A,R}
+xkt{x>3240:pt,s>1951:kdt,A}
+klp{x<2291:R,R}
+xsm{x<3088:fq,s<1019:ck,rft}
+qcq{a>1762:zct,jmn}
+bg{m<187:rxg,a>1992:rmh,nnd}
+qhz{s<906:mxf,s<1178:xc,s<1411:nn,bgc}
+lcv{m>2885:sp,s<1596:qjt,x>1318:R,qdk}
+tv{a<3603:R,R}
+rqt{x>3360:qmx,A}
+lq{x>3004:djk,A}
+cvr{m>1262:R,A}
+xvl{x<1450:A,s>726:A,x<1563:R,A}
+srq{x>1648:tlp,x<1353:A,a>660:jn,cq}
+ln{m<2598:A,x>392:R,a>102:A,R}
+vlz{x<1287:R,m<504:A,s<2381:R,R}
+gd{s<1696:hd,s<2923:bbh,a>99:jg,qbb}
+jpl{a<2616:R,m>3175:R,m>2917:vd,zj}
+cmj{m<825:pq,R}
+sm{s>2831:A,a>2017:A,A}
+txz{m<1807:R,s>2496:A,x<3553:A,A}
+gg{s>3667:A,s>3630:A,m<1120:R,A}
+np{a<1760:A,m<661:A,a>2943:A,R}
+tr{s>2415:qx,R}
+dr{s<3012:xz,s>3606:jr,s<3283:rvb,cp}
+jn{a<893:R,A}
+tls{a<2747:A,s<1194:qcf,pb}
+zz{m>439:tr,pmq}
+hq{a<1511:fr,m>2398:tkp,ffs}
+gc{s>868:pvt,a>810:cs,s<401:tpn,kxt}
+cgg{m<1180:hhd,x>3730:hxv,a<1008:A,A}
+ndx{x>2486:R,a>3689:A,a>3458:R,R}
+qlk{a<2687:R,A}
+gbg{m>2153:ctr,x>2369:sqs,zp}
+xp{x<1614:R,a>80:A,a>33:A,R}
+zjh{m<299:A,m>445:bk,a>1680:A,mb}
+xkv{a>1934:R,jcl}
+grj{x<3471:A,a>522:R,m>653:clm,A}
+xv{m>979:R,A}
+xzg{a>2632:hv,s<1402:bhz,x>2736:nvl,krl}
+dx{x<3653:R,R}
+phs{x<410:mkb,x>813:qz,s<1238:vt,R}
+pvt{a<434:sxl,m<307:qk,a>741:qzk,ltb}
+gqf{a<1184:rr,R}
+ngv{m<750:bhg,dfj}
+hc{m>3818:R,x>3259:R,A}
+tpn{s>176:npx,s>106:A,pgt}
+cp{s<3442:md,qrq}
+vbd{s>2021:sm,A}
+sx{a<2883:A,x>423:A,a>3152:A,R}
+zjc{s<1631:xpr,ffk}
+gh{a<414:gv,m>2019:A,s<2609:lkt,R}
+rs{m<641:A,x<2176:A,A}
+gfj{s<1409:R,x>672:A,R}
+gmp{a<1470:R,m>732:xv,a<2586:A,A}
+qxk{a<2743:A,x<1530:A,A}
+rmh{x>3281:R,s>1957:A,A}
+bgc{s<1490:ndc,R}
+lf{m>1107:A,A}
+dsb{a>1535:A,x<1119:A,m>1713:A,R}
+gzf{x>2276:A,a<3368:R,A}
+vl{s<1714:R,R}
+fkf{x>863:mt,hk}
+nk{m<3374:R,m<3539:zbv,xmh}
+nq{s>2129:mq,a<2720:zx,hnp}
+ck{m<1470:A,R}
+fh{x>3292:R,x>3224:R,R}
+bhg{x<3257:sl,a>928:jft,A}
+mz{s<2462:R,s<2545:R,R}
+rzd{m>322:mjb,xvl}
+ffs{a<1575:dsb,R}
+xgm{x<3606:dsr,R}
+bv{x>1418:R,m>2241:R,A}
+fzg{m>2069:R,s>3359:R,mm}
+zbd{a>2686:A,A}
+lnh{m>326:A,s<569:R,A}
+sp{a>635:A,s<1023:A,m>3037:A,R}
+ht{s<3055:R,R}
+fjc{m>2800:sg,vss}
+rdz{a>2536:R,A}
+bhz{m<1472:lmt,a<1358:lg,fm}
+cv{a<3705:A,A}
+vq{m<626:R,R}
+jbd{x>2978:xsm,lpr}
+hxv{x<3881:R,a>575:A,a>263:A,R}
+mxf{a<1416:A,s<364:lkx,s>596:tq,qp}
+ztj{m<804:sc,s<2591:cnr,m>1296:xgm,lj}
+mtz{a<1585:lq,m<2121:xl,cjj}
+td{m>2614:qjs,pm}
+tq{m<2636:R,x>3824:R,s>717:R,R}
+lh{x>3298:A,R}
+pbd{x>3273:A,x>3223:R,s<3266:A,A}
+tg{x>2267:R,A}
+lkt{x<1591:R,x<1860:R,s<2307:R,R}
+lxj{x>1181:R,s>1871:A,s<876:A,R}
+qqz{x>1607:R,R}
+nns{x<354:tp,dq}
+kxb{a<2442:R,x<1775:R,R}
+tkp{s<1440:gms,s>2336:R,s<1970:gn,A}
+pmq{m<217:lxj,x>1215:fvk,R}
+hkf{x>1329:R,x<1221:A,m>296:vlz,R}
+xf{s<3858:R,a<3135:R,a>3650:A,R}
+gkh{x>3488:dzv,m>1102:tfz,m>481:hpd,bg}
+qz{s<1268:A,A}
+qpr{s<2254:A,qn}
+zvz{x>3244:A,R}
+cth{m>1342:mf,a>2563:lgc,kkv}
+fzf{x>3735:qhz,a>2603:xj,bff}
+clv{a<2085:R,qj}
+ppp{m>1152:R,R}
+gql{m>3279:A,A}
+ffk{a>2836:xpq,m>611:xh,zbd}
+mt{a>1972:cl,s<1036:A,R}
+bs{a<2559:jfj,x>3678:rq,xtn}
+rr{x>1665:A,a>1157:A,a<1148:A,A}
+ch{a<2012:vqb,a>2343:lx,x<910:cmj,ht}
+vfl{x>3591:A,R}
+nnd{m<374:A,s>1974:R,A}
+sb{x<1052:xm,lbq}
+fqr{a>1341:A,R}
+dlz{a<3124:R,s<616:R,m<2608:A,R}
+xrx{m>2876:sll,a<898:R,x>1194:A,ft}
+pt{x>3271:A,R}
+mkz{x<410:A,lv}
+nv{a<3910:R,s>2311:R,x<1189:gfj,A}
+rvb{x>3490:btk,s<3148:nm,pjb}
+vp{m<400:R,A}
+fq{m>1104:A,s>1207:R,R}
+vkv{m<580:R,s>3829:A,R}
+djf{a<90:A,s<2630:A,A}
+bj{m<2968:A,s<3007:R,A}
+tfx{x>3386:R,s<564:R,s<783:fxv,dz}
+ll{a<788:A,x>3261:A,x>3211:R,R}
+vs{s>1056:lb,x<2392:dff,ml}
+sjz{m>2721:cgq,ltp}
+kvl{a<2121:jjg,s<1872:bl,m>2258:R,R}
+hv{s<938:klv,stp}
+fv{x>987:R,m>257:A,m>98:A,A}
+krl{x<2666:bx,gb}
+fxv{m>1802:A,m<1064:R,A}
+gms{s<670:R,m<3354:R,x>1304:A,A}
+nc{a<2111:R,m<2688:A,A}
+hf{a>884:A,a<413:A,x<3528:R,A}
+xnm{x>1370:A,R}
+jzv{x>3644:R,A}
+jft{s<759:R,m>355:A,R}
+jjg{x<3713:R,x<3832:R,a<1165:A,R}
+cpg{x>3905:R,s<3524:A,s>3560:A,R}
+lnc{s>1742:R,m<3640:R,m<3824:A,R}
+jfh{x<3311:hc,s<3012:dfl,A}
+rk{m<1130:R,a>1155:R,a<999:R,R}
+psp{s<895:A,A}
+vbf{x<1384:A,m>1232:A,R}
+ssf{m>3854:A,m<3740:A,m<3801:R,A}
+szp{s>535:R,R}
+rdm{m>844:R,s<1350:R,a>1879:A,A}
+xdz{s<3255:R,x>3367:A,pbd}
+clm{s>3742:R,s<3683:R,R}
+lg{a<656:nsb,s>711:R,A}
+ntz{s>744:R,R}
+pp{x>3605:pv,m>2330:qcq,fzg}
+tdr{a>1977:R,A}
+ltp{x>1370:hr,m>2643:jt,x>608:A,ln}
+md{s>3355:vdl,xg}
+qbb{m<3542:R,a<64:pj,vkr}
+cbr{x<731:qsl,A}
+qpc{x>1720:pk,a<2995:nq,m<675:xxs,ctd}
+qcr{s<396:A,s>468:A,a>2522:A,R}
+sqs{a<1395:A,rdm}
+dbk{x<2544:A,x>2583:R,m>2929:A,A}
+hvm{a<1661:A,a>1680:R,s<1569:R,R}
+xmk{x>1716:vfm,a<664:zs,a>1020:sz,cf}
+fgc{m>2485:kpn,s<2209:kvl,m>2126:bs,jss}
+js{x>885:bh,vx}
+bh{m<3066:R,m<3661:A,m>3839:A,A}
+fs{x<3349:fc,s>3053:vfq,x>3427:R,R}
+zd{s>1928:R,drv}
+xvh{x<3433:cqn,a>506:A,stz}
+kt{a>1629:A,a>904:A,s>2771:R,A}
+xqs{s<936:tfx,ldb}
+lj{x>3495:kt,s>2789:A,a>2418:A,fh}
+kc{s>2097:vp,fqr}
+qmx{a>2785:R,A}
+fm{s<906:A,x<2721:bgq,s>1133:nc,A}
+ngm{x>3605:A,R}
+skz{s>3971:R,a<879:A,x>3240:R,R}
+qzk{m>391:R,m<361:R,m>376:R,A}
+bgq{m<2519:A,m<3182:R,m>3583:R,A}
+vgp{x>3829:jbq,x>3779:qpr,xkv}
+pvr{m<3543:R,x<3774:R,R}
+pv{s<3452:A,m<2533:pjx,jnb}
+ggg{m>710:R,x>3697:xf,s>3910:lvh,R}
+tf{x<908:R,m>3006:R,R}
+kj{s<2430:A,A}
+vx{x<543:A,ndn}
+lb{s<1484:R,tt}
+ps{m<435:R,m<620:zzr,sx}
+vd{m<3007:A,s<1072:R,A}
+stz{x<3472:A,x>3508:A,m>1620:R,A}
+qk{a>732:A,s>1209:R,s>986:R,A}
+lv{x<601:A,a<1238:A,R}
+qjl{s<3061:sqm,xjc}
+fkr{m<522:A,A}
+kht{a<2924:A,A}
+tfz{a>1482:jjq,x<3293:zvz,s<2014:R,mn}
+mjb{m<492:R,A}
+jnb{a<2184:A,A}
+pb{a>2945:R,a<2869:R,a>2917:R,A}
+jzl{s<1920:rnq,s>3023:fv,a<2271:sr,xzr}
+dz{x>3249:R,m<1906:A,m<2989:A,A}
+djk{s>2955:R,s<2591:R,R}
+bq{m<2857:A,m>2955:R,R}
+vt{m>1149:A,R}
+vn{m>2238:R,s>1251:R,A}
+bqz{m<1013:R,m>1451:R,x<3905:R,R}
+xs{m<661:qfs,m>953:pzk,s<2458:fkf,ch}
+zbv{x<3533:R,A}
+dh{m>2691:A,x<1110:R,A}
+qrq{x>3717:gjm,m>1204:tbx,x>3450:gmp,crx}
+cs{x<1444:A,a>1064:A,A}
+qdk{x<476:A,R}
+jvd{a<1918:hxp,bp}
+pk{x>2009:jtf,mrp}
+qj{x<3770:R,s>3188:A,A}
+skh{m>2531:A,x>994:A,A}
+jb{x>2893:kh,x>2871:gsf,R}
+gkd{x>1470:A,a<3175:A,mv}
+pcr{a>3174:A,R}
+tp{m>1107:vl,tjq}
+jg{a<121:gk,a>142:A,x<786:A,dkj}
+sr{m>240:R,m>124:A,R}
+pzk{x>1140:vbd,a<1875:zhd,tnq}
+fvk{m>338:A,a>3721:R,A}
+tt{a>3061:A,m>1129:A,a>2752:A,R}
+nxj{x>1815:R,a>1391:R,A}
+vss{a<1229:A,m>2269:kgg,m<1897:kq,A}
+bx{a<1397:jsz,x>2643:A,gr}
+bcp{a>1510:R,x>3296:A,R}
+kxt{a<498:R,m>221:A,A}
+fhk{a>2231:R,m>1663:A,R}
+rh{m>1059:A,x>397:R,R}
+xtn{x<3615:R,m>2291:A,R}
+zt{x>3869:R,a>1953:A,pvr}
+kgg{m>2546:R,a<2005:A,m>2430:A,R}
+gsf{m>3432:R,x>2883:A,m<3059:A,R}
+dkj{x<1464:R,m>3616:A,m<3270:R,R}
+vhk{m>1151:gt,vmp}
+sn{s<804:pl,A}
+xl{x>2965:A,x<2845:R,a<3160:A,A}
+pgt{a<363:A,a<657:A,m>215:R,R}
+hjl{m>676:A,x<3233:R,R}
+cjx{m>3639:R,m<3445:A,A}
+sh{a<469:R,s>1129:R,x>1914:R,A}
+zj{s<973:R,a>3116:R,s<1756:A,R}
+sv{s<3798:R,x<3924:R,R}
+bc{x>786:A,a>699:R,x>702:R,A}
+nbh{x<554:A,m<1222:A,x<908:A,R}
+kz{s>2296:qlr,x>2843:ckz,x>2622:xzg,cg}
+dzv{m>1242:ddj,m<672:zgr,m<954:R,A}
+gv{s<3097:A,R}
+npx{s>307:A,a<504:A,m>359:A,R}
+nkl{s>3657:R,A}
+zfg{x>3021:hjx,x>2922:jpl,a>1956:jb,kx}
+lpr{x>2891:qv,s>1116:A,a<2546:dht,nsr}
+xxs{s>1541:hkf,rzd}
+jh{s>1397:xmk,m<544:gc,bmq}
+ddj{s>1907:R,A}
+mf{a>1650:ks,a>978:zsv,m<2547:sb,lm}
+bhh{s>3084:R,a<2095:ssf,s<2138:R,R}
+rj{s>2747:A,x<822:R,A}
+xz{s>2324:ztj,gkh}
+qzx{a<2513:A,R}
+kgf{s<3755:hqk,fvt}
+lx{s>3421:kkx,x>1168:kxb,njs}
+xfq{m<371:A,A}
+fvt{m<950:R,a>3034:R,A}
+gjm{a<2196:cpg,bqz}
+fk{s<797:A,s>1321:R,R}
+hd{x<1111:gm,s<991:R,xp}
+xr{s<1445:R,s>3098:R,A}
+zs{m<515:crz,s>2859:A,R}
+fc{s>3060:A,R}
+xb{s<779:A,a>2032:A,m>1307:A,R}
+fpm{m>502:R,m<280:A,x>1492:R,A}
+lbq{s>1873:gh,s<755:ggx,rx}
+fr{x>957:R,s>1388:R,m>2361:A,A}
+kk{x<619:R,a<895:bc,R}
+bt{s<615:A,R}
+ql{s>663:R,R}
+xbf{m>577:R,s>3643:A,A}
+xzr{s>2489:R,x<1252:R,R}
+vkr{x<926:R,m>3787:A,a>85:R,R}
+pz{m>470:R,x>3658:A,a>1769:A,A}
+fcz{m<1278:R,R}
+pkg{m>792:tdr,m>305:pz,R}
+gr{s>1978:A,m<1615:A,x>2630:A,A}
+fp{m<2319:A,nnz}
+bnt{s>2905:R,x<542:A,a>396:R,R}
+zsv{a>1402:hq,a>1254:gq,xn}
+tb{x<2275:A,R}
+lpz{x<3674:zbq,R}
+vmp{a<3488:hvb,x>879:R,s>1805:ns,cxx}
+nxh{a>3820:nv,mjg}
+pl{a<1030:R,x<3427:R,R}
+cd{x>1842:A,x>1790:R,a<2786:A,R}
+dq{s>2576:R,x>774:A,s<1502:A,R}
+mhx{a<2599:th,a>3474:A,tk}
+sg{s>892:qmt,s<521:A,s>678:bcp,R}
+zp{m<878:tb,kvb}
+bff{m>1637:ngm,m>728:ntz,kdc}
+kpn{m>2806:R,x>3777:dxf,m<2693:R,hmx}
+zfb{x>2516:R,A}
+jfj{a<1147:R,x<3715:R,A}
+qs{s>886:xgf,a<2607:dbk,m>3257:szp,lnm}
+crz{m<197:A,R}
+rnq{m>231:R,x>1003:R,m<128:A,R}
+kkv{a>1238:xs,x>987:jh,kg}
+ldb{x>3336:R,A}
+jhc{x<363:R,A}
+fg{x>2277:A,s<100:A,s<199:R,A}
+qsl{a<2987:A,R}
+cm{s>1965:A,s<1910:A,A}
+ks{a>3187:td,rf}
+lvh{s<3964:A,A}
+lnr{a<1865:R,s<1786:R,R}
+bnh{s>1148:R,A}
+bn{a>1373:gql,s<2070:kv,x<837:fx,R}
+qjt{a<654:R,A}
+kdt{a<769:A,s>2324:A,s<2154:R,R}
+rbg{m<3374:R,a<1368:R,m>3753:A,A}
+nnz{a<2154:R,s>1714:A,R}
+jz{a<2176:R,x<3469:R,m<1596:R,R}
+mrp{a<3034:cd,s>1466:R,m<449:R,cz}
+xdk{x<3354:kll,m>1186:xvh,grj}
+ndn{s>1433:R,m<3486:R,R}
+rx{x<1809:ghq,x<1977:sh,R}
+vqb{x<1437:zcn,a>1630:R,nxj}
+nt{x>568:R,ppp}
+qjs{x>849:R,m<3472:A,jhc}
+jtf{x<2137:R,a<2854:R,rs}
+jsz{m<1495:R,x<2650:A,R}
+lmt{s>835:bnh,R}
+sk{a>506:vm,lnh}
+zcn{a<1535:A,s<3259:R,s>3560:A,R}
+kq{m>1696:A,R}
+xcm{m>1113:xcn,x>3324:A,s>3196:np,hjl}
+xg{m<1147:R,zn}
+sll{m>2975:R,a<856:A,A}
+dc{m>3602:R,A}
+gn{x>1427:R,R}
+nkv{m>1151:A,a>1487:A,s>882:A,A}
+tk{x>3895:R,A}
+tjq{s>2047:A,x>138:A,R}
+pj{a>23:A,a<11:R,s>3304:R,A}
+bp{a<2909:A,R}
+rq{x<3797:R,R}
+kll{m>966:A,s<3783:ll,s<3917:vkv,skz}
+nfh{s>2067:tg,s<1882:qm,s>1982:A,A}
+gq{a<1320:skh,m<2854:zd,bn}
+jbq{s<2004:lnc,x<3908:R,cjx}
+xkp{m>2602:A,a<2827:R,R}
+jt{m>2670:R,A}
+kx{s<1461:psp,a>1188:A,a<420:R,R}
+qv{x<2932:R,m>915:R,R}
+xk{m<1127:xkx,fhk}
+lkx{x<3857:A,R}
+qp{x>3882:A,s<458:R,a>2507:R,A}
+rnp{s>2251:A,R}
+ndc{a>2046:A,A}
+xn{a<1140:rgl,x>777:gqf,a<1214:fl,mkz}
+hp{s>369:R,m>1780:A,a<397:R,R}
+zrx{m<808:A,R}
+xpq{s<2999:gs,xbf}
+tnq{a<2147:R,m<1124:rh,a<2299:A,nbh}
+jr{x>3550:hvx,a>1444:kgf,xdk}
+drv{s<1158:R,A}
+jtg{x>3441:xb,a<1944:R,R}
+gm{m>3646:R,a<62:A,R}
+bk{a>1669:R,R}
+zb{a<3087:R,x<3579:A,x<3664:R,A}
+sqm{s>3037:R,x<3711:R,s<3024:A,A}
+kb{x<2798:A,A}
+vm{m<511:R,a<784:A,R}
+dxf{x<3876:A,x>3936:A,s<2218:R,A}
+lm{a>359:dj,a>161:js,m>3062:gd,sjz}
+gp{a>2462:xqs,m>1568:fjc,x>3364:fbg,ngv}
+kdc{a<1124:bf,x<3653:ql,s>935:R,pn}
+zl{m>1085:R,s>2543:R,R}
+hmx{m>2766:R,x<3664:R,a<1702:R,A}
+cjj{a>2724:A,x>3004:mr,bj}
+mrj{m>833:A,m>614:R,A}
+mm{x<3415:R,a>2361:R,s>2908:R,R}
+rg{x<3716:gj,s>2644:nzs,vgp}
+xxx{m<2803:fd,x>2298:A,x>2252:gzf,A}
+sxl{a<152:A,x>1548:A,s<1089:A,A}
+cqn{m<1568:A,a>729:A,m>1710:A,R}
+pjx{x>3746:A,a<1433:R,s<3640:A,R}
+rgl{s>2456:R,A}
+hnp{s>1078:fpm,x<1412:rkg,s<630:R,A}
+dfl{a<1775:A,a>3138:R,m>3839:A,R}
+mb{s>2293:A,a>1616:A,R}
+lqj{x<1439:A,x<1563:R,a<1189:A,R}
+ckz{m>2477:zfg,jbd}
+vbm{m>1163:R,A}
+sqh{m>672:R,A}
+kn{m>552:R,R}
+kv{a<1353:R,a<1362:A,m>3524:R,R}
+hdd{s>1445:R,s>627:R,s<321:R,A}
+pn{x<3697:A,s<606:A,R}
+mmp{m>3238:ctb,klp}
+klv{m<1867:A,m<3022:dlz,s<594:dc,R}
+hvx{x>3817:rp,s<3752:pkg,a<1988:lpz,ggg}
+fps{s<838:A,m>3394:pcr,a<3103:kht,dx}
+vds{s<2205:R,a>1203:A,x<2788:A,R}
+jkp{m<535:A,a<3139:R,x>3617:R,R}
+mx{x<3834:nkl,a<899:R,a<1663:R,A}
+zhd{s>1882:zlz,nkv}
+gnj{s>2649:pp,x<3505:tlf,fgc}
+mkb{s>1198:R,A}
+xcn{x<3316:A,x>3416:A,x<3381:A,A}
+nn{s<1313:vn,R}
+nzs{s<3351:zt,m>3413:mhx,a>2396:mkn,mx}
+vfm{s>2927:A,kn}
+ltb{a>599:A,R}
+hxp{x<3290:R,x>3375:R,A}
+xm{s<1592:bt,bnt}
+mvv{a<2863:R,m<2935:rnp,a<3046:xr,R}
+qlr{x<2715:kgp,mtz}
+nm{s>3089:jvd,m>925:sd,fs}
+njs{a<2444:R,m<771:A,R}
+crp{a<2001:A,R}
+gj{m<3625:nk,x>3424:bhh,jfh}
+xmh{a>2183:A,a>841:A,s>2501:R,R}
+qx{m>612:A,s>2985:R,A}
+zx{x>1500:R,x>1334:st,m<557:R,R}
+gph{s<834:R,s<915:R,qqz}
+jss{x>3727:mz,R}
+dv{a<620:A,R}
+in{x<2213:cth,zqv}
+bf{m<288:A,R}
+gl{a<511:A,jmp}
+xc{s>1062:qzx,a<1746:R,m>1687:R,zrx}
+stp{s>1452:A,m<1452:nf,A}
+dj{m>3121:plz,s<2549:lcv,a>737:xrx,bpj}
+cz{m<749:R,A}
+xh{s<2961:A,x>445:A,s<3642:qlk,A}
+nf{x>2701:A,m>917:R,R}
+vz{a>3590:A,R}
+xpr{s<642:cbr,m<787:ps,a>3087:nt,phs}
+ft{x>527:R,a>927:A,R}
+fx{s>3289:R,a<1347:R,a<1363:A,R}
+sl{a>917:R,m<387:A,a<599:R,A}
+sz{a>1148:lqj,A}
+cgq{s<2138:A,bq}
+dfj{x>3251:dd,m<1074:A,s<826:R,cvr}
+mjg{x>966:vbm,zl}
+nrh{x>2407:A,R}
+mq{x<1432:A,m>536:qxk,A}
+nsb{a>287:A,m>2674:A,A}
+pm{x<924:cv,m>1872:bv,tv}
+ggx{x>1674:hp,s>433:A,s>154:dv,xnm}
+xqz{m<1066:jkp,s<907:R,jzv}
+rft{a<1896:A,m>1132:R,A}
+pd{a>1690:xfq,a<1638:A,hvm}
+rxg{x<3292:A,x>3407:R,A}
+xt{s>1516:A,A}
+ctd{s>2523:gkd,m<1040:tmm,m>1187:xt,lf}
+kg{m>790:nns,gpk}
+xj{a>3531:vfl,m<2284:xqz,fps}
+xtm{a<181:djf,x<599:R,m>367:rj,R}
+dd{x<3316:A,x<3339:R,R}
+vdt{s<3533:A,m<1626:R,R}
+hr{m<2608:R,m>2646:A,R}
+cf{a<835:A,R}
+prl{s<1001:xxx,a<3171:mmp,s<1741:zq,nfh}
+fl{m>3013:A,R}
+gb{a>949:lnr,R}
+nvl{s<1828:kb,mkk}
+fd{a<3291:R,A}
+sd{m<1467:lh,A}
+sc{a>1807:qgb,a>840:R,A}
+ctb{a>2605:A,s<1862:A,A}
+cg{a<2268:gbg,m<2156:vs,x<2369:prl,ls}
+pvb{m>3373:R,R}
+tlf{x>3320:rgg,a>1691:rd,xkt}
+lnm{a<2857:R,x>2562:R,R}
+btk{s>3130:clv,a<1717:cgg,qjl}
+ts{s<1746:R,xkp}
+jmn{s>3134:R,A}
+dht{a>1029:A,x>2868:R,m>1209:R,A}
+jmp{m>841:A,s>436:R,a>961:A,A}
+gpk{s<1526:sk,a<475:xtm,kk}
+hpd{s>2055:A,a>1631:qzh,a>807:mrj,R}
+hvb{x<1303:R,m>949:R,R}
+ls{a>3127:dn,x>2485:qs,x>2432:tls,nrh}
+hhd{a<708:R,a>1242:A,A}
+st{a<2651:R,a<2678:R,R}
+rd{x>3258:A,a>3127:R,A}
+djd{x<3513:gp,fzf}
+vdl{m>1078:jz,s>3401:sqh,x>3606:fkr,vq}
+zq{a<3521:A,R}
+xcz{s<782:R,x>3418:lld,R}
+zlz{m<1128:R,A}
+kh{a<3311:A,A}
+xkx{s>3312:R,A}
+crx{x<3293:rcc,m>498:R,A}
+qzh{m>888:R,x<3336:A,s>1819:R,A}
+zqv{x<3176:kz,s<1579:djd,m<1868:dr,cmb}
+qfs{a>1845:jzl,a<1538:kc,x>1297:zjh,pd}
+hk{s>1007:crp,s>484:R,A}
+vfq{a<1606:R,A}
+gs{s>2416:A,A}
+qm{x<2304:R,s<1810:R,a<3503:R,A}
+rcc{x<3248:R,a>1959:A,R}
+hqk{m>1223:A,A}
+qcf{m<3194:R,s<451:R,s>751:A,R}
+qn{m<3393:A,a>2036:R,R}
+tbx{x<3413:vdt,a>1739:zb,hf}
+pq{s>3130:R,m>725:A,m<683:R,R}
+th{x>3821:A,a<1610:R,s<3621:A,R}
+mv{x>1244:A,s<3230:R,a>3250:A,R}
+tmm{a<3213:A,A}
+shc{x>3460:R,s>792:A,x<3427:R,rk}
+dn{s>1080:vz,m>3171:A,s<706:R,ndx}
+qmt{a<1258:A,A}
+bmq{s<716:gl,s>1023:srq,gph}
+ghq{m>1856:R,A}
+mkk{s<2037:cm,vds}
+gt{s>2603:R,s<1226:fcz,vbf}
+cxx{m>945:R,a<3575:R,s<1075:R,R}
+mkn{m>3196:A,R}
+jjq{x>3366:R,x>3295:R,m>1451:R,A}
+cl{a<2214:A,R}
+ns{s>2814:A,R}
+gk{m<3647:A,x<1039:A,x<1627:A,R}
+bbh{a<69:R,m>3534:R,m<3248:R,pvb}
+qgb{a>3005:R,s>2733:A,R}
+rkg{x>1266:A,R}
+jcl{x>3757:R,x<3739:A,R}
+lgc{a>3366:phj,x<1117:zjc,qpc}
+
+{x=89,m=520,a=174,s=541}
+{x=30,m=424,a=3199,s=923}
+{x=423,m=857,a=369,s=790}
+{x=359,m=68,a=2444,s=1261}
+{x=3093,m=1500,a=1156,s=43}
+{x=364,m=404,a=101,s=2199}
+{x=2577,m=1996,a=755,s=1079}
+{x=378,m=617,a=29,s=806}
+{x=49,m=2648,a=908,s=128}
+{x=729,m=369,a=1375,s=704}
+{x=1416,m=366,a=1456,s=120}
+{x=391,m=322,a=2694,s=121}
+{x=64,m=382,a=304,s=98}
+{x=273,m=1002,a=2602,s=1822}
+{x=1050,m=759,a=199,s=1176}
+{x=25,m=1872,a=786,s=388}
+{x=569,m=338,a=1155,s=1363}
+{x=958,m=1929,a=1814,s=1343}
+{x=1060,m=2622,a=112,s=65}
+{x=546,m=42,a=2568,s=853}
+{x=237,m=51,a=72,s=1}
+{x=1842,m=2545,a=1193,s=1871}
+{x=2377,m=1476,a=332,s=1384}
+{x=33,m=1396,a=3151,s=2220}
+{x=636,m=20,a=591,s=31}
+{x=139,m=726,a=69,s=2461}
+{x=2060,m=42,a=1385,s=2382}
+{x=473,m=332,a=176,s=1216}
+{x=138,m=656,a=103,s=1107}
+{x=1115,m=367,a=770,s=28}
+{x=1168,m=799,a=2312,s=1518}
+{x=1588,m=2503,a=882,s=2558}
+{x=851,m=52,a=2175,s=2201}
+{x=197,m=1371,a=1198,s=1699}
+{x=338,m=2291,a=1507,s=1974}
+{x=43,m=228,a=278,s=274}
+{x=2587,m=2466,a=1934,s=3409}
+{x=2144,m=436,a=2292,s=252}
+{x=335,m=652,a=228,s=3012}
+{x=872,m=1438,a=189,s=350}
+{x=2323,m=155,a=1286,s=778}
+{x=2068,m=361,a=572,s=664}
+{x=270,m=79,a=4,s=131}
+{x=774,m=167,a=9,s=1832}
+{x=1101,m=3157,a=907,s=37}
+{x=466,m=1645,a=2533,s=369}
+{x=2398,m=1693,a=2858,s=2202}
+{x=85,m=1218,a=286,s=1675}
+{x=2298,m=2213,a=377,s=200}
+{x=24,m=482,a=685,s=829}
+{x=2514,m=1339,a=1924,s=3013}
+{x=576,m=1012,a=974,s=59}
+{x=96,m=112,a=516,s=2329}
+{x=976,m=305,a=485,s=611}
+{x=312,m=139,a=1383,s=2125}
+{x=887,m=1017,a=659,s=2186}
+{x=2324,m=11,a=1477,s=2333}
+{x=2758,m=2436,a=569,s=1237}
+{x=1678,m=2968,a=3212,s=1090}
+{x=5,m=3,a=27,s=927}
+{x=2561,m=417,a=220,s=647}
+{x=1221,m=2518,a=18,s=73}
+{x=412,m=2325,a=903,s=1318}
+{x=466,m=813,a=12,s=1426}
+{x=29,m=246,a=496,s=71}
+{x=850,m=578,a=319,s=1484}
+{x=1830,m=1120,a=699,s=563}
+{x=2204,m=2146,a=886,s=3121}
+{x=848,m=1910,a=688,s=621}
+{x=191,m=1850,a=366,s=425}
+{x=101,m=1227,a=1496,s=2009}
+{x=12,m=1219,a=1554,s=2567}
+{x=1213,m=3025,a=1089,s=2054}
+{x=1612,m=2342,a=3036,s=117}
+{x=12,m=773,a=604,s=869}
+{x=705,m=479,a=2054,s=562}
+{x=1607,m=592,a=2544,s=2729}
+{x=784,m=1269,a=111,s=2345}
+{x=1598,m=274,a=622,s=2786}
+{x=295,m=844,a=680,s=1219}
+{x=108,m=1725,a=1488,s=255}
+{x=2400,m=347,a=942,s=1775}
+{x=360,m=42,a=2943,s=344}
+{x=1827,m=539,a=112,s=1453}
+{x=2856,m=930,a=818,s=1406}
+{x=248,m=2192,a=322,s=642}
+{x=67,m=162,a=2009,s=2941}
+{x=353,m=3317,a=333,s=2225}
+{x=1563,m=988,a=1286,s=363}
+{x=491,m=152,a=597,s=2620}
+{x=379,m=3015,a=1815,s=306}
+{x=65,m=1581,a=509,s=2685}
+{x=311,m=381,a=756,s=1323}
+{x=2718,m=192,a=2053,s=1199}
+{x=897,m=550,a=454,s=262}
+{x=1531,m=661,a=49,s=74}
+{x=594,m=756,a=1713,s=549}
+{x=2020,m=262,a=485,s=375}
+{x=743,m=2756,a=1194,s=962}
+{x=1936,m=1217,a=327,s=1162}
+{x=844,m=513,a=1304,s=1169}
+{x=22,m=1878,a=965,s=1934}
+{x=1395,m=1355,a=392,s=1661}
+{x=270,m=193,a=183,s=1315}
+{x=3256,m=135,a=1559,s=807}
+{x=1719,m=2899,a=964,s=2031}
+{x=1130,m=474,a=1646,s=797}
+{x=2017,m=1772,a=18,s=1095}
+{x=1965,m=2413,a=61,s=1661}
+{x=1435,m=335,a=591,s=704}
+{x=1191,m=607,a=2197,s=3712}
+{x=2111,m=119,a=171,s=126}
+{x=2566,m=28,a=1141,s=1775}
+{x=726,m=72,a=234,s=1696}
+{x=123,m=1326,a=2023,s=1526}
+{x=156,m=1480,a=1070,s=58}
+{x=1569,m=312,a=641,s=2999}
+{x=1761,m=121,a=3078,s=1875}
+{x=1048,m=367,a=386,s=1836}
+{x=120,m=1029,a=998,s=1290}
+{x=344,m=348,a=1823,s=1192}
+{x=958,m=1562,a=1596,s=381}
+{x=1017,m=578,a=121,s=1240}
+{x=814,m=1233,a=2285,s=1863}
+{x=2758,m=3147,a=1234,s=833}
+{x=907,m=324,a=1,s=192}
+{x=407,m=823,a=2607,s=215}
+{x=2777,m=90,a=1344,s=2606}
+{x=1623,m=1603,a=1612,s=194}
+{x=249,m=1377,a=1676,s=1475}
+{x=393,m=659,a=2411,s=401}
+{x=831,m=43,a=2818,s=22}
+{x=1415,m=656,a=32,s=822}
+{x=17,m=2006,a=2218,s=1734}
+{x=1087,m=223,a=214,s=527}
+{x=267,m=688,a=2666,s=2571}
+{x=1567,m=774,a=1729,s=535}
+{x=1505,m=1697,a=1541,s=929}
+{x=405,m=11,a=1122,s=611}
+{x=442,m=644,a=3914,s=99}
+{x=222,m=1,a=2380,s=952}
+{x=2368,m=842,a=278,s=849}
+{x=3831,m=6,a=1846,s=12}
+{x=658,m=168,a=2667,s=1225}
+{x=119,m=625,a=212,s=10}
+{x=12,m=3009,a=3397,s=96}
+{x=615,m=421,a=600,s=1462}
+{x=1998,m=2224,a=153,s=673}
+{x=1088,m=541,a=1107,s=301}
+{x=29,m=2158,a=1528,s=2111}
+{x=3167,m=35,a=565,s=1126}
+{x=951,m=2723,a=1827,s=9}
+{x=477,m=3272,a=2770,s=2031}
+{x=633,m=319,a=99,s=344}
+{x=257,m=1393,a=2204,s=402}
+{x=139,m=844,a=548,s=843}
+{x=1569,m=964,a=162,s=102}
+{x=598,m=115,a=860,s=567}
+{x=1215,m=402,a=636,s=1471}
+{x=964,m=3060,a=124,s=732}
+{x=626,m=292,a=113,s=18}
+{x=174,m=248,a=118,s=3404}
+{x=12,m=158,a=534,s=493}
+{x=939,m=91,a=1330,s=478}
+{x=229,m=884,a=828,s=632}
+{x=1269,m=1300,a=837,s=1687}
+{x=1169,m=838,a=1495,s=784}
+{x=336,m=326,a=1007,s=2509}
+{x=3042,m=639,a=889,s=1019}
+{x=19,m=144,a=86,s=1074}
+{x=287,m=2865,a=2964,s=16}
+{x=1,m=9,a=566,s=390}
+{x=600,m=330,a=755,s=1505}
+{x=782,m=693,a=1539,s=2592}
+{x=385,m=1941,a=156,s=1234}
+{x=973,m=1171,a=399,s=20}
+{x=77,m=2288,a=1587,s=107}
+{x=619,m=1204,a=2456,s=44}
+{x=67,m=998,a=53,s=1662}
+{x=1384,m=362,a=1631,s=562}
+{x=594,m=546,a=1981,s=218}
+{x=906,m=549,a=1420,s=73}
+{x=3243,m=713,a=56,s=1735}
+{x=133,m=946,a=2444,s=94}
+{x=541,m=2117,a=2719,s=378}
+{x=324,m=1497,a=1236,s=39}
+{x=1651,m=738,a=78,s=756}
+{x=744,m=1025,a=1735,s=2854}
+{x=816,m=28,a=2289,s=1346}
+{x=1886,m=385,a=305,s=1920}
+{x=2007,m=2937,a=1725,s=2135}
+{x=514,m=952,a=1008,s=1787}
+{x=204,m=1731,a=104,s=208}
+{x=24,m=2194,a=98,s=149}
+{x=2446,m=692,a=538,s=1091}
+{x=2832,m=1148,a=68,s=1494}
+{x=33,m=1902,a=3349,s=2577}
+{x=1664,m=2270,a=118,s=2217}
+{x=59,m=498,a=730,s=2103}
+{x=1478,m=268,a=745,s=270}
diff --git a/src/bin/2023/day19.rs b/src/bin/2023/day19.rs
new file mode 100644
index 0000000..87fdda0
--- /dev/null
+++ b/src/bin/2023/day19.rs
@@ -0,0 +1,429 @@
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+use advent_of_code::prelude::*;
+
+#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
+pub enum Category {
+ X,
+ M,
+ A,
+ S,
+}
+
+impl std::str::FromStr for Category {
+ type Err = anyhow::Error;
+
+ fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
+ Ok(match s {
+ "x" => Self::X,
+ "m" => Self::M,
+ "a" => Self::A,
+ "s" => Self::S,
+ _ => bail!("unknown category {s}"),
+ })
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum Target {
+ Accept,
+ Reject,
+ Workflow(String),
+}
+
+impl std::str::FromStr for Target {
+ type Err = anyhow::Error;
+
+ fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
+ Ok(match s {
+ "R" => Self::Reject,
+ "A" => Self::Accept,
+ workflow => Self::Workflow(workflow.to_string()),
+ })
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct CategoryRanges {
+ x: std::ops::RangeInclusive<i64>,
+ m: std::ops::RangeInclusive<i64>,
+ a: std::ops::RangeInclusive<i64>,
+ s: std::ops::RangeInclusive<i64>,
+}
+
+impl CategoryRanges {
+ fn new(
+ x: std::ops::RangeInclusive<i64>,
+ m: std::ops::RangeInclusive<i64>,
+ a: std::ops::RangeInclusive<i64>,
+ s: std::ops::RangeInclusive<i64>,
+ ) -> Self {
+ Self { x, m, a, s }
+ }
+
+ fn is_empty(&self) -> bool {
+ self.x.is_empty()
+ || self.m.is_empty()
+ || self.a.is_empty()
+ || self.s.is_empty()
+ }
+
+ fn size(&self) -> i64 {
+ (self.x.end() - self.x.start() + 1)
+ * (self.m.end() - self.m.start() + 1)
+ * (self.a.end() - self.a.start() + 1)
+ * (self.s.end() - self.s.start() + 1)
+ }
+
+ fn with_x(self, x: std::ops::RangeInclusive<i64>) -> Self {
+ Self {
+ x,
+ m: self.m,
+ a: self.a,
+ s: self.s,
+ }
+ }
+
+ fn with_m(self, m: std::ops::RangeInclusive<i64>) -> Self {
+ Self {
+ x: self.x,
+ m,
+ a: self.a,
+ s: self.s,
+ }
+ }
+
+ fn with_a(self, a: std::ops::RangeInclusive<i64>) -> Self {
+ Self {
+ x: self.x,
+ m: self.m,
+ a,
+ s: self.s,
+ }
+ }
+
+ fn with_s(self, s: std::ops::RangeInclusive<i64>) -> Self {
+ Self {
+ x: self.x,
+ m: self.m,
+ a: self.a,
+ s,
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct Conditional {
+ category: Category,
+ less: bool,
+ val: i64,
+}
+
+#[derive(Debug)]
+pub struct Rule {
+ conditional: Option<Conditional>,
+ target: Target,
+}
+
+impl Rule {
+ fn split(
+ &self,
+ range: CategoryRanges,
+ ) -> (Option<CategoryRanges>, Option<(Target, CategoryRanges)>) {
+ let Some(conditional) = &self.conditional else {
+ return (None, Some((self.target.clone(), range)));
+ };
+ match conditional.category {
+ Category::X => {
+ let (remaining, matched) = if conditional.less {
+ (
+ range
+ .clone()
+ .with_x(conditional.val..=*range.x.end()),
+ range
+ .clone()
+ .with_x(*range.x.start()..=(conditional.val - 1)),
+ )
+ } else {
+ (
+ range
+ .clone()
+ .with_x(*range.x.start()..=conditional.val),
+ range
+ .clone()
+ .with_x((conditional.val + 1)..=*range.x.end()),
+ )
+ };
+ (
+ if remaining.is_empty() {
+ None
+ } else {
+ Some(remaining)
+ },
+ if matched.is_empty() {
+ None
+ } else {
+ Some((self.target.clone(), matched))
+ },
+ )
+ }
+ Category::M => {
+ let (remaining, matched) = if conditional.less {
+ (
+ range
+ .clone()
+ .with_m(conditional.val..=*range.m.end()),
+ range
+ .clone()
+ .with_m(*range.m.start()..=(conditional.val - 1)),
+ )
+ } else {
+ (
+ range
+ .clone()
+ .with_m(*range.m.start()..=conditional.val),
+ range
+ .clone()
+ .with_m((conditional.val + 1)..=*range.m.end()),
+ )
+ };
+ (
+ if remaining.is_empty() {
+ None
+ } else {
+ Some(remaining)
+ },
+ if matched.is_empty() {
+ None
+ } else {
+ Some((self.target.clone(), matched))
+ },
+ )
+ }
+ Category::A => {
+ let (remaining, matched) = if conditional.less {
+ (
+ range
+ .clone()
+ .with_a(conditional.val..=*range.a.end()),
+ range
+ .clone()
+ .with_a(*range.a.start()..=(conditional.val - 1)),
+ )
+ } else {
+ (
+ range
+ .clone()
+ .with_a(*range.a.start()..=conditional.val),
+ range
+ .clone()
+ .with_a((conditional.val + 1)..=*range.a.end()),
+ )
+ };
+ (
+ if remaining.is_empty() {
+ None
+ } else {
+ Some(remaining)
+ },
+ if matched.is_empty() {
+ None
+ } else {
+ Some((self.target.clone(), matched))
+ },
+ )
+ }
+ Category::S => {
+ let (remaining, matched) = if conditional.less {
+ (
+ range
+ .clone()
+ .with_s(conditional.val..=*range.s.end()),
+ range
+ .clone()
+ .with_s(*range.s.start()..=(conditional.val - 1)),
+ )
+ } else {
+ (
+ range
+ .clone()
+ .with_s(*range.s.start()..=conditional.val),
+ range
+ .clone()
+ .with_s((conditional.val + 1)..=*range.s.end()),
+ )
+ };
+ (
+ if remaining.is_empty() {
+ None
+ } else {
+ Some(remaining)
+ },
+ if matched.is_empty() {
+ None
+ } else {
+ Some((self.target.clone(), matched))
+ },
+ )
+ }
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct Workflows(HashMap<String, Vec<Rule>>);
+
+impl Workflows {
+ fn accept(&self, part: &Part) -> bool {
+ let mut workflow = "in";
+ loop {
+ for rule in &self.0[workflow] {
+ if let Some(conditional) = &rule.conditional {
+ let left = part.0[&conditional.category];
+ let right = conditional.val;
+ if conditional.less {
+ if left >= right {
+ continue;
+ }
+ } else if left <= right {
+ continue;
+ }
+ }
+ match &rule.target {
+ Target::Accept => return true,
+ Target::Reject => return false,
+ Target::Workflow(new_workflow) => workflow = new_workflow,
+ }
+ break;
+ }
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct Part(HashMap<Category, i64>);
+
+impl Part {
+ fn value(&self) -> i64 {
+ self.0.values().sum()
+ }
+}
+
+pub fn parse(fh: File) -> Result<(Workflows, Vec<Part>)> {
+ let mut lines = parse::raw_lines(fh);
+ let workflows = parse::chunk(&mut lines)
+ .map(|line| {
+ let cap = regex_captures!(r"(\w+)\{(.*)\}", &line).unwrap();
+ let workflow = cap[1].to_string();
+ let rules = cap[2]
+ .split(',')
+ .map(|rule| {
+ if rule.contains(':') {
+ let cap =
+ regex_captures!(r"(\w+)(<|>)(\d+):(\w+)", &rule)
+ .unwrap();
+ let category = cap[1].parse().unwrap();
+ let less = &cap[2] == "<";
+ let val = cap[3].parse().unwrap();
+ let target = cap[4].parse().unwrap();
+
+ Rule {
+ conditional: Some(Conditional {
+ category,
+ less,
+ val,
+ }),
+ target,
+ }
+ } else {
+ Rule {
+ conditional: None,
+ target: rule.parse().unwrap(),
+ }
+ }
+ })
+ .collect();
+ (workflow, rules)
+ })
+ .collect();
+ let parts = parse::chunk(&mut lines)
+ .map(|line| {
+ let line = &line[1..(line.len() - 1)];
+ Part(
+ line.split(',')
+ .map(|category| {
+ let mut parts = category.split('=');
+ let category = parts.next().unwrap().parse().unwrap();
+ let value = parts.next().unwrap().parse().unwrap();
+ (category, value)
+ })
+ .collect(),
+ )
+ })
+ .collect();
+ Ok((Workflows(workflows), parts))
+}
+
+pub fn part1((workflows, parts): (Workflows, Vec<Part>)) -> Result<i64> {
+ Ok(parts
+ .into_iter()
+ .filter_map(|part| workflows.accept(&part).then(|| part.value()))
+ .sum())
+}
+
+pub fn part2((workflows, _): (Workflows, Vec<Part>)) -> Result<i64> {
+ let mut ranges = vec![(
+ Target::Workflow("in".to_string()),
+ CategoryRanges::new(1..=4000, 1..=4000, 1..=4000, 1..=4000),
+ )];
+ loop {
+ let mut new_ranges = vec![];
+ let mut done = true;
+ for (workflow, range) in &ranges {
+ let mut range = range.clone();
+ let Target::Workflow(workflow) = workflow else {
+ new_ranges.push((workflow.clone(), range));
+ continue;
+ };
+ for rule in &workflows.0[workflow.as_str()] {
+ let (old_range, new_range) = rule.split(range);
+ if let Some(new_range) = new_range {
+ new_ranges.push(new_range);
+ done = false;
+ }
+ if let Some(old_range) = old_range {
+ range = old_range;
+ } else {
+ break;
+ }
+ }
+ }
+ ranges = new_ranges;
+ if done {
+ break;
+ }
+ }
+ Ok(ranges
+ .into_iter()
+ .filter_map(|(target, range)| {
+ if target == Target::Accept {
+ Some(range.size())
+ } else {
+ None
+ }
+ })
+ .sum())
+}
+
+#[test]
+fn test() {
+ assert_eq!(
+ part1(parse(parse::data(2023, 19).unwrap()).unwrap()).unwrap(),
+ 449531
+ );
+ assert_eq!(
+ part2(parse(parse::data(2023, 19).unwrap()).unwrap()).unwrap(),
+ 122756210763577
+ );
+}
diff --git a/src/bin/2023/main.rs b/src/bin/2023/main.rs
index b9eb819..1afb78e 100644
--- a/src/bin/2023/main.rs
+++ b/src/bin/2023/main.rs
@@ -29,6 +29,7 @@ mod day15;
mod day16;
mod day17;
mod day18;
+mod day19;
// NEXT MOD
#[paw::main]
@@ -53,6 +54,7 @@ fn main(opt: Opt) -> Result<()> {
16 => advent_of_code::day!(2023, opt.day, opt.puzzle, day16),
17 => advent_of_code::day!(2023, opt.day, opt.puzzle, day17),
18 => advent_of_code::day!(2023, opt.day, opt.puzzle, day18),
+ 19 => advent_of_code::day!(2023, opt.day, opt.puzzle, day19),
// NEXT PART
_ => panic!("unknown day {}", opt.day),
}