Compare commits

..

No commits in common. "2b921b5fb28c9dc03a939cd352d0bc6020394f2e" and "3bc073f9b89976297a2791896d9d8fd2d92ac7c7" have entirely different histories.

6 changed files with 66 additions and 1314 deletions

View File

@ -1 +0,0 @@
max_width = 120

View File

@ -1,7 +1,9 @@
use itertools::Itertools;
use std::collections::LinkedList;
use std::collections::{HashMap, LinkedList};
use std::fmt::{Display, Write};
use std::fs::File;
use std::io::{BufRead, BufReader, Lines};
use std::ops::Range;
use std::time::Instant;
// BOILERPLATE
@ -45,7 +47,12 @@ enum Turn {
impl Direction {
const fn all() -> &'static [Self; 4] {
&[Direction::Left, Direction::Right, Direction::Up, Direction::Down]
&[
Direction::Left,
Direction::Right,
Direction::Up,
Direction::Down,
]
}
const fn opposite(&self) -> Self {
match self {
@ -120,7 +127,13 @@ impl From<&str> for DigInstruction {
let (dir, count, color) = (
parts.next().unwrap(),
parts.next().unwrap(),
parts.next().unwrap().chars().skip(2).take(6).collect::<String>(),
parts
.next()
.unwrap()
.chars()
.skip(2)
.take(6)
.collect::<String>(),
);
Self {
dir: dir.into(),
@ -139,7 +152,7 @@ impl DigInstruction {
"1" => Direction::Down,
"2" => Direction::Left,
"3" => Direction::Up,
s => panic!("`{}` is not a valid direction code", s),
s => panic!("`{}` is not a valid direction code", s)
};
}
}
@ -164,7 +177,9 @@ struct DigTile {
impl Default for DigTile {
fn default() -> Self {
Self { position: (0, 0) }
Self {
position: (0, 0),
}
}
}
@ -173,6 +188,9 @@ type Position = (isize, isize);
#[derive(Debug)]
struct DigHole {
tiles_loop: LinkedList<DigTile>,
tiles_map: HashMap<Position, DigTile>,
x_range: Range<isize>,
y_range: Range<isize>,
area: u64,
}
@ -185,6 +203,9 @@ impl DigHole {
fn new() -> Self {
DigHole {
tiles_loop: LinkedList::new(),
tiles_map: HashMap::new(),
x_range: 0..0,
y_range: 0..0,
area: 0,
}
}
@ -194,7 +215,9 @@ impl DigHole {
fn run_plan(&mut self, plan: &DigPlan) {
let mut cur_pos = (0, 0);
self.tiles_loop.push_back(DigTile { position: cur_pos });
self.tiles_loop.push_back(DigTile {
position: cur_pos,
});
let mut move_offset;
for (idx, i) in plan.instructions.iter().enumerate() {
let prev_instruction = if idx > 0 {
@ -202,14 +225,17 @@ impl DigHole {
} else {
&plan.instructions[plan.instructions.len() - 1]
};
let Some(next_instruction) = plan.instructions.get(idx + 1).or(Some(&plan.instructions[0])) else {
let Some(next_instruction) = plan
.instructions
.get(idx + 1)
.or(Some(&plan.instructions[0]))
else {
panic!()
};
let cur_turn = prev_instruction.dir.turn_kind(i.dir);
let next_turn = i.dir.turn_kind(next_instruction.dir);
// Point needs to live on the 'outside' corner of the character. to achieve this we need to offset the move
// by the following. Found this empirically but there's probably some mathematical principle behind it...
// point needs to live on the 'outside' corner of the character. to
// achieve this we need to offset the move by the following
move_offset = match (cur_turn, next_turn) {
(Turn::RightNinety, Turn::RightNinety) => 1,
(Turn::RightNinety, Turn::LeftNinety) => 0,
@ -218,8 +244,14 @@ impl DigHole {
t => panic!("turn {:?} not allowed here", t),
};
cur_pos = self.pos_offset_n(cur_pos, i.dir.offset(), (i.count as isize + move_offset) as usize);
self.tiles_loop.push_back(DigTile { position: cur_pos });
cur_pos = self.pos_offset_n(
cur_pos,
i.dir.offset(),
(i.count as isize + move_offset) as usize,
);
self.tiles_loop.push_back(DigTile {
position: cur_pos,
});
}
// Shoelace formula
@ -234,15 +266,36 @@ impl DigHole {
}
}
impl Display for DigHole {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for y in self.y_range.clone() {
for x in self.x_range.clone() {
f.write_char(if (x, y) == (133, -267) {
'*'
} else if self.tiles_map.contains_key(&(x, y)) {
'#'
} else {
'.'
})?;
}
writeln!(f)?;
}
Ok(())
}
}
impl<T: BufRead> From<Lines<T>> for DigPlan {
fn from(lines: Lines<T>) -> Self {
Self {
instructions: lines.map(|line| DigInstruction::from(line.unwrap().as_str())).collect(),
instructions: lines
.map(|line| DigInstruction::from(line.unwrap().as_str()))
.collect(),
}
}
}
// PROBLEM 1 solution
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
let plan = DigPlan::from(input);
let mut dig = DigHole::new();

92
19/Cargo.lock generated
View File

@ -1,92 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "day19"
version = "0.1.0"
dependencies = [
"num",
]
[[package]]
name = "num"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af"
dependencies = [
"num-bigint",
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
dependencies = [
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
dependencies = [
"autocfg",
"num-bigint",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
]

View File

@ -1,9 +0,0 @@
[package]
name = "day19"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
num = "0.4.1"

775
19/input
View File

@ -1,775 +0,0 @@
kzq{m<596:R,x<1149:R,A}
in{s<2440:cd,tgz}
rs{m<2118:zx,s>3630:A,m<2297:cx,vfc}
hzz{m<2478:A,R}
ss{a<692:R,A}
sv{x<877:A,m<2320:R,A}
ph{x<2510:mf,x>3150:R,m>624:xtc,fr}
rg{s>440:hj,a>434:lg,ljm}
hdr{m<1158:R,m>1494:vfl,a<1353:A,R}
zhp{x>633:A,x<248:R,A}
fd{s<1838:A,m<3087:A,a>3495:R,jsg}
qvh{x<3002:crs,m<2331:A,s<3294:dh,R}
qbr{m>3556:R,m<3200:R,R}
sql{m<3219:A,zf}
zf{a<633:A,s<1348:A,A}
rr{x<3035:A,s<3096:A,a<2451:R,A}
bng{s>3079:R,a<724:jd,R}
lv{a<3333:tqj,hth}
bcp{a>1296:dtp,m>2875:dnq,x>1453:xjl,gp}
tz{m>3020:R,R}
gnz{m<692:R,m>1130:R,m>877:R,R}
xqg{x>3462:A,s<3298:A,s>3449:R,R}
pxd{s>1539:jvr,m<2976:frj,x>1748:mr,fts}
tj{m>3165:R,m<3044:R,a>1557:R,A}
jqm{x<2410:xf,m>3048:zm,zbl}
pv{a>2330:R,a>2259:A,x>3069:A,A}
qnz{m>1947:bz,x<2553:jr,x<3256:prq,bx}
cn{x>2438:nl,s<193:A,R}
kkb{s>3372:A,a>295:A,R}
rgr{a>707:R,a>400:hrd,npv}
klp{s<2137:jzp,x>1502:qnz,xj}
fm{m>3258:db,qd}
scf{a>490:A,m>3260:R,R}
btz{a>3068:dr,a>2668:hfb,m<2408:cs,fgr}
xqr{m>2286:A,a<2390:tf,x>3254:R,fkk}
tp{x<1044:A,a>2510:A,s<1735:A,A}
frj{x>2659:vhd,s>1415:lfl,sll}
kcn{s<1967:R,R}
vrm{a>1620:R,x>1345:A,s>3219:A,A}
vm{x<2777:gnz,m<614:hrg,a>903:shm,R}
bqq{a<994:A,m<2065:vrm,s<3419:bnv,zqt}
dtp{a>2018:cp,tbq}
qk{m>3174:slm,m>2948:jqm,gz}
gzq{m>1755:R,A}
nl{s>174:A,a<3022:A,m>2165:R,A}
mkk{a>2954:A,R}
gp{x>808:bng,nmr}
khf{m<1278:R,a>264:A,x>3812:A,A}
xxf{m>1340:A,s>2282:R,R}
bbk{a>1074:gqc,a>616:mdv,pgv}
nrp{x<2414:R,mjc}
kpt{m<3158:bcp,clt}
snl{m<868:km,m<1182:A,x<715:R,A}
cfm{s<3832:R,A}
pt{m>3354:rkx,A}
bz{a>3073:jz,s>2285:A,a>2653:tt,sgd}
zp{s>3328:R,m<981:R,A}
zkg{a<910:kjc,a<1539:hzz,s<2149:xdc,R}
jxm{x>2135:R,m>1114:R,a<668:A,ghm}
szq{s<450:cn,s>694:sdd,s>567:cm,lk}
vlz{s>584:R,s<287:R,A}
fr{s>1707:A,m<281:A,a<1488:R,R}
cdh{x>1427:R,x>1191:R,A}
brs{s>2803:A,a<821:A,s>2565:R,R}
ghm{s<3298:R,m>738:A,x>868:R,R}
cdn{s<745:R,a<1738:R,R}
vgc{s>3045:A,s>2796:R,A}
mjc{m<1443:R,a<1751:R,a<2183:A,R}
rhs{a<1453:A,m>933:kg,A}
vgh{m>3481:zmk,x>2384:ng,s<3473:pt,xvj}
lfb{x>1099:A,A}
cb{a<2973:qkv,x>2753:knq,R}
vd{a<1578:zbh,x>2560:A,s<1772:R,A}
dh{m<2492:R,m>2532:A,A}
tqj{m>1459:R,m>649:R,m>261:A,A}
sch{m<1650:R,A}
brm{x<2245:rm,vsm}
xqc{x>1906:R,s<2586:R,m>1404:R,A}
vmx{m<2123:qsd,s<2169:R,s<2335:R,A}
nrj{s>2051:ml,a<3354:A,x<772:tjm,czr}
zpq{a<805:R,s<2733:A,x<2371:R,R}
lq{m<2008:nxh,m<2296:vmx,zkg}
lfn{m>2015:R,A}
vhv{s>2798:A,m<2650:R,hsz}
rxq{a>2045:A,a>2002:A,R}
gv{x>3571:R,m>3216:A,R}
kjg{x>2443:R,s>3563:A,A}
qv{a>903:A,a<755:A,m<2822:R,A}
dqb{s<1310:A,s<1331:R,s<1351:R,A}
pll{s<1875:R,s<1928:A,a>3979:A,R}
cct{x>2015:cb,m<1524:vqc,a>3121:sdz,rs}
dq{a>3084:R,a>2989:A,x<1241:A,R}
xzx{a>2077:A,a<2023:A,a>2046:A,R}
nmr{s>3420:R,A}
klr{m<1060:A,m>1274:A,ms}
dr{s>1739:qvk,m<2207:R,a>3629:R,gk}
qvk{s<1772:A,a>3599:R,R}
gbj{a>855:R,m>2778:R,A}
drj{s<2725:R,A}
th{s<219:R,s>361:R,R}
dd{x<1745:zgq,a<2006:R,s<3396:tlq,vn}
cpr{x<2287:R,a>3768:R,A}
ntn{a<1603:R,x<3513:A,x<3736:R,A}
zlg{a<2254:xbz,m>1915:xqr,qhg}
mv{m<1685:A,s<2921:A,s<3099:nrm,A}
tnz{m>1738:R,R}
hql{m<1446:rj,qn}
bxk{x>1683:A,m<3826:R,x>1019:A,R}
pg{x>2110:A,A}
vsm{m<1847:R,x<2870:A,R}
qcs{m>3409:xh,x<948:A,x>1273:R,R}
zxz{a<961:gzj,x>900:bg,m<796:nn,A}
mp{a>2922:R,x<1561:A,A}
nb{m>1334:lq,a<942:kjq,s<2216:vcc,zd}
kjc{x>2597:R,m<2416:R,s<2114:R,R}
nz{a>349:A,x<1677:R,A}
cj{x<2805:kjg,x<3336:A,R}
kq{m<1306:R,s<3407:gmg,A}
jp{x<2530:hd,pmn}
vhj{s<2857:A,s<3029:A,x<3204:A,A}
zcr{s>3421:R,A}
kgq{m<2273:bqq,m>2432:mmf,x>1209:zxp,dzs}
crs{a<302:R,A}
fq{m>2037:vgj,m<1874:kfg,m>1968:jx,dtq}
rjx{x<2876:sf,xlc}
qsg{x>2668:A,s<2509:R,R}
gz{a<1575:tvn,a<1927:ljt,a>2208:vmj,nqk}
fzj{s>2118:A,R}
jtn{s<3102:A,m<2129:R,s>3609:A,R}
htb{x<1752:lf,s<2690:zb,a>3052:ntg,chm}
nqk{m>2784:A,x>2006:rxq,xzx}
ktz{a>1145:lnr,zz}
cl{s>2245:R,A}
pp{x>3144:R,a>1054:A,A}
km{s<3596:R,a<217:R,a<378:A,A}
btd{a>328:R,x>3186:R,s<2776:R,R}
nv{a<3170:A,x<1822:A,R}
zqt{a<1992:R,s>3757:A,R}
zvh{x<3431:A,x<3695:R,a<181:A,khf}
rjc{s>3558:rxs,ngt}
fvr{s<1819:A,a>3820:R,A}
gdh{a<1044:A,m>3889:R,a<1313:A,R}
xjl{m>2748:zfc,x>2350:hkv,qdk}
dzs{a<1516:tbs,m<2379:zcr,x>802:A,lvn}
hnk{m<1382:cqm,x<618:R,m>2969:A,ck}
sl{s<2067:R,rq}
bn{m>2044:R,x>1947:R,s>2494:A,A}
klj{m>595:zs,a>1587:A,A}
hd{m<814:rt,hdr}
pm{x>1330:rjf,s>3318:snl,m<757:lgm,jhh}
xn{m>894:R,s<486:R,A}
zxp{s>3057:mnb,A}
bt{x>2338:R,s<2515:R,A}
qdh{x<1435:dfm,m>3320:sn,m<2950:knb,xcq}
zsf{x>3119:R,s<3965:A,R}
lxs{x<1891:R,R}
fp{a>839:A,a<370:A,x>3697:R,A}
fb{x>1576:A,x>1383:R,R}
ssq{x>1389:R,x<683:A,R}
psl{s>1912:nb,mdx}
gzd{a<286:R,m>2048:R,A}
cm{x<2249:R,R}
ps{m<3057:A,a<192:A,R}
ql{x<1455:R,s<2316:A,dz}
tl{s>2746:R,a<2925:jth,s<2631:R,dq}
fl{m<871:R,R}
dnd{s<3340:R,a<1631:A,R}
hpk{x<2148:nbd,kq}
hrd{m>2977:A,R}
cqm{a<3300:A,s<2326:R,R}
vhx{a>264:sx,czq}
hpb{m<1744:bkc,x<1249:cf,vkm}
ms{x>3633:R,a>279:A,x>3536:A,A}
qkk{a<2687:A,s<2740:R,A}
vfc{a<2771:R,A}
rjf{s<3472:br,x<1970:A,a>216:R,A}
xbz{x<3190:lkc,gvr}
mx{s>1027:R,A}
fxr{a<3952:R,R}
sz{m>3436:R,a>3677:R,a<3578:A,R}
qsd{s>2211:A,s>2062:A,x<1916:R,R}
jxd{a>3568:A,x>2134:R,hr}
xlc{m<3646:ntn,m>3749:vb,a<829:hmk,gc}
zmb{x<854:A,tv}
dxx{a>796:brs,m<1206:gq,R}
jj{m<1020:xhs,a<758:ghs,dxx}
jd{s>2702:A,a>437:A,x<1198:A,A}
vb{a<1183:A,x>3584:R,R}
zg{a<1774:R,rp}
fjl{m<1926:A,A}
sx{m>412:rlx,m<224:hsm,ts}
clt{m>3707:kbk,vgh}
sdd{x>1333:A,s>792:ffv,qc}
ltl{s<2747:A,A}
qd{a<1088:A,a>1543:R,R}
lnr{s>1491:A,tgm}
hr{s<2837:A,R}
tbn{m>1412:A,x<1334:ltl,bbq}
db{x<1961:R,R}
dfm{m>3324:R,A}
mdx{s>1504:cc,sb}
xvj{x<1523:R,R}
zm{x>3061:txs,x<2826:R,R}
bkc{s<3439:R,s<3712:R,R}
sp{a>996:A,R}
ftd{x>2631:R,m>2447:R,x>2241:R,R}
qxl{m>591:R,x>508:A,R}
ngs{x<1410:R,A}
nvl{m>836:R,A}
kbd{m>2655:jxd,shz}
bzz{m>2969:R,A}
hth{x>532:R,x<263:A,A}
dtq{x<1785:fjl,qpt}
qbz{m<1913:kkb,m<2018:R,x<2884:tvj,gzd}
tr{x<1816:zxz,s<3159:gj,a>942:vtz,vm}
pdr{a>3495:R,x<960:A,A}
sfd{m<1983:R,a>3730:A,A}
qm{a<3400:A,R}
vlx{x<1628:R,x>2516:A,R}
ztb{s<1848:A,s<1862:R,A}
tlq{m<3961:A,A}
mtx{x<628:R,s<2839:A,R}
dp{m<631:R,x>3424:R,A}
bch{x>544:R,s<1473:A,A}
qkv{s>3614:A,a<2756:R,A}
tlz{s<1526:R,A}
nr{a<1406:R,s>1965:ls,a<1804:R,kmj}
rn{m<3158:R,x>1428:R,A}
fn{s>2334:R,R}
fv{s>496:R,m>2847:A,R}
kdt{x<1651:qx,mn}
dt{s<1907:R,A}
fxp{s>1444:R,x<1151:R,s<1432:R,A}
skp{s<2684:ff,a>3661:grc,kbd}
sf{a<1342:R,R}
vn{x<2642:A,m>3964:A,x>3188:R,R}
cc{m<1326:ph,vd}
st{m>2033:kv,x>2199:mh,qs}
tt{s<2228:R,m>2870:A,x<2943:R,A}
zxc{x<2549:A,a<790:fl,a>821:hs,rv}
nzg{a>721:R,a<709:R,m<1312:R,R}
dpm{x<2029:dvz,tkb}
xzp{x<1033:zhp,m<3650:vk,s>1404:cdh,R}
kmt{x>1508:A,m>3316:sdt,ngs}
jr{x<2063:zvg,x<2340:A,m>945:cl,R}
slv{m<658:A,m>699:R,x<1549:R,R}
txs{x>3387:R,x>3223:A,A}
jbj{x<1080:R,R}
slm{s>2107:qgv,x>1425:pbp,nr}
xj{s<2246:lv,hnk}
rxs{a>3208:R,s>3711:tz,bvt}
sgd{m>2799:R,m<2302:A,s>2226:A,A}
gng{m>1061:xqc,m>382:A,s<2565:A,rkh}
tq{m>3700:R,m>3578:A,m<3552:R,R}
gqc{m<751:vc,m<1228:trs,qln}
bzg{a<3173:A,x>2040:A,A}
gr{s>1874:A,A}
sm{x>1443:fc,m<3252:pqp,lh}
vt{x<324:sch,m<2405:zdb,s<2751:A,mtx}
rrz{a<2925:A,m<1807:A,A}
dvm{s>3793:R,a<714:R,a>723:A,R}
ns{a>216:fzj,s<2226:A,pl}
tsn{m<1180:R,x<1442:ss,a<693:A,dvm}
lgm{m<295:mt,qxl}
gq{a>772:R,s>2860:A,A}
tv{x<1247:R,m>2373:A,R}
shm{a>923:R,R}
tc{m>1326:pd,x<2176:A,A}
zs{a>956:R,x<1552:A,m<1047:A,A}
kbk{a<1245:zr,m>3892:dd,a>1823:hf,rkz}
gc{s>1625:A,x<3456:R,A}
vv{m<1670:jp,a<1470:tvs,dx}
dv{a<3900:dt,x<2401:R,a>3952:pll,A}
rh{x>1522:md,zmb}
bv{s<813:R,x<1898:A,m<2291:A,A}
dfs{a>2165:A,x<2625:A,m<905:A,R}
sq{m<1537:A,a>3700:R,s>3518:R,R}
zbh{m>1984:R,s>1714:A,s>1589:R,A}
pmn{x>3353:mxr,xn}
fc{m<3293:A,R}
hj{m>2607:nz,bv}
cjt{s<3222:R,a>778:A,R}
md{a<2755:A,a<2974:bqz,m<1812:A,R}
jcn{x<3486:A,A}
tm{x<1626:R,x>2473:A,R}
rp{s<2043:A,A}
dtt{x<2469:A,x>2652:A,R}
rkh{a<3899:R,a<3939:A,a>3972:A,R}
vtz{x<3222:jnj,A}
dz{a>1273:R,x<2592:R,a>1109:R,A}
zbl{x<3369:A,a<1301:A,A}
xcc{x<1386:R,x>2717:A,A}
snz{x>1513:R,A}
pnp{m>2870:R,s<1615:R,A}
nzs{x<2228:svh,a>3290:drm,qck}
dx{m<2704:st,bnq}
ml{m>2093:A,m<723:R,x>705:A,A}
nrm{x<2693:R,x>3329:R,a<1508:A,R}
ls{a>2023:R,x<645:A,x<1062:R,R}
zbk{s<3432:A,R}
pcx{a>133:A,R}
xc{a<2881:A,m>2239:R,R}
bvt{x>2521:R,m>3250:A,A}
vfl{a>1549:A,A}
gb{s>2827:fxr,a<3925:vp,tk}
nt{a<3562:R,s>1880:R,A}
qh{s<2766:R,m>1823:R,m<1032:R,R}
vkb{m>3657:R,a<1604:A,R}
qdk{a>446:vrt,a>237:R,A}
nx{s<3053:A,x>2661:A,s<3652:A,A}
ffv{m>2118:A,x<591:A,R}
gnx{m>3550:A,s>340:R,A}
xdc{s<2011:R,a<1886:A,m<2525:R,R}
rnx{x>1741:A,R}
vgj{a<1194:R,a>1316:A,mjf}
rz{m<245:A,R}
jzp{x<1378:nrj,qm}
dhz{m<2327:dnd,x<3029:ftd,m<2461:R,A}
mmf{x>1349:R,m>2512:A,R}
chm{m<1360:sh,a>2753:dmf,x<2850:zdz,rd}
bb{a<1712:R,s<1716:A,fgd}
lfl{s>1480:R,fxp}
vkm{a<944:fb,cdz}
shz{x>2518:R,s>2824:pdr,x<1098:A,R}
lvn{a<1975:A,A}
ng{m<3372:pjq,R}
ntg{x<2896:bvx,hql}
qck{a>2892:R,x>2827:gx,m<1542:njr,R}
xg{m<274:R,R}
qs{a<1914:cdn,R}
bd{m>3657:jbj,m<3576:R,x>715:hk,R}
mnb{m>2328:A,s<3622:A,a<1275:A,A}
lkc{s>3247:R,A}
jz{a<3649:A,a<3878:R,R}
pgv{x<2543:pm,m<747:vhx,s<3269:kb,hx}
vfk{s>2335:sd,R}
mxr{s<525:pz,fp}
qln{s<3057:tbn,m>1379:nrp,tc}
hsm{a<391:A,R}
mdv{a>842:tr,s<3143:jj,mfx}
tgm{x<1435:R,A}
bj{x>2353:R,A}
frk{s>1770:A,lfb}
tnt{a>228:R,x<307:A,A}
bx{s<2240:R,m>928:gf,x<3724:gm,fn}
vr{s<3307:R,m>3549:R,A}
zd{a<1856:ql,vfk}
jth{s<2601:A,A}
tbq{s>3089:A,s<2692:bzz,A}
zz{x>1544:tlz,bch}
mq{m>1048:R,s<3046:dfs,m<905:nvl,R}
xsb{a>968:A,s>3282:R,R}
ctf{m>2182:dhz,s>3326:cj,m<1769:mv,xxb}
cd{a>2405:qjl,s<1247:vv,m<2651:psl,cz}
sdt{m<3413:A,s<1386:A,R}
nm{m>1061:A,m<861:R,a<1430:R,zp}
kbp{a>257:R,R}
czq{s>3301:A,pcx}
rv{x<3177:R,x<3631:R,m>605:R,R}
lg{x<2664:A,fqp}
rq{s<2141:R,x<1452:A,x<2322:A,A}
rkx{m>3406:R,s>2856:R,a>1356:R,R}
rxz{a>3491:ft,m>1104:R,s<1879:A,A}
tqc{s>2638:A,R}
kb{m<1115:btd,a<356:zvh,nh}
svh{m>2131:A,s>1205:A,sdj}
gzj{s>3413:R,m<563:R,R}
tgz{a>2498:nc,m<1536:bbk,m>2606:kpt,dpm}
nc{s>2973:mml,a>3390:skp,htb}
zr{m>3877:A,a<786:zbk,sp}
hf{m<3830:A,R}
rj{s>2812:A,R}
lvf{s<2217:ghz,m<352:fg,s<2328:R,R}
tvn{x<1573:A,ct}
pqp{a<1606:A,s>1424:R,x>1211:A,A}
fpm{a<3321:A,a>3380:A,R}
lpq{a<2688:A,m>550:A,R}
skb{a>496:R,a>370:A,m>3052:A,R}
vqc{a>2824:A,mdj}
sk{s>3032:R,a>1895:kzq,A}
fqp{x<3283:R,x>3734:R,m>2573:A,A}
kv{x<1403:R,A}
jhh{a<365:zv,s>2937:R,a<532:A,A}
qx{m<216:A,m<345:A,R}
tvj{m>2055:R,x>2595:R,R}
fkk{s<3440:A,R}
nh{s>2904:R,x>3474:A,R}
bnq{x<1726:qcs,x>2609:xjj,pg}
bhv{s<1815:btz,a<3302:rh,m<1426:xs,dfq}
grc{a>3883:gb,a>3753:brm,a<3710:vhv,xr}
pl{x<1731:R,a<138:R,m<1085:R,R}
ngt{x>2573:xqg,a>3461:sz,m>3259:vr,vmf}
jnq{m<2176:R,m>2968:R,x>3137:A,R}
sb{m>1679:lfn,s>1408:snz,klj}
jvr{a>1008:bb,s<1695:np,ln}
kjq{m<593:lvf,m<873:bcs,a>378:djc,ns}
hh{s>2869:R,A}
kj{x>1634:rrz,s<2750:A,m>2365:mp,R}
xf{m<3098:A,m<3128:cr,a<995:rn,vj}
zv{x<860:A,a>221:R,x>1038:A,R}
rm{a>3836:A,A}
tbs{a>927:A,R}
gm{m<317:A,A}
sdz{s>3569:R,m<1986:tnz,fpm}
lf{x<960:vt,x<1466:tl,kj}
qhg{m<1782:vgc,a<2401:A,rr}
nxh{a<1275:R,gzq}
tk{x<2449:A,R}
cp{s<3395:R,s>3741:cfm,tm}
zdb{x>591:A,s<2781:A,R}
mhm{x<3419:R,x<3710:A,m>2686:A,A}
pz{m>885:R,a<1395:A,R}
jxl{a<1824:rz,A}
vmr{a>570:jqd,m>2081:qvh,m>1814:qbz,dkx}
kmj{s<1935:R,A}
prq{m>920:xxf,R}
cf{s>3313:A,x>700:A,m>1872:A,R}
qgv{a>1042:vlx,a>596:rqd,R}
mr{x>3011:gv,x>2379:mjx,fm}
cx{a>2892:A,A}
xz{m>2929:R,s<2814:R,s>2986:A,A}
ck{x<994:A,s>2364:A,m>2064:A,R}
zdd{s>911:nzs,szq}
vj{s>2138:A,m>3156:A,R}
jnj{a<996:A,s<3488:R,R}
kfg{s<786:qtq,A}
tjm{s<2018:R,s<2038:R,R}
dkx{x>2834:R,x<2537:R,nx}
zfc{m<2823:gbj,crk}
ff{m>1893:dc,a>3780:gng,xjz}
vmf{x<1019:A,A}
ghs{a<703:A,a>738:R,nzg}
gs{a<393:R,a<477:R,s<3909:R,zsf}
zvg{s>2319:A,x>1801:A,A}
gk{x<2559:R,A}
xjz{s<2581:R,x>2364:R,a<3606:A,tqc}
sd{x<2625:R,A}
mdj{s>3552:A,x>946:A,R}
nbd{x<1042:sq,m<915:A,tmj}
tmj{m>1880:A,x>1503:R,A}
drm{x>3299:R,s<1171:mx,R}
cs{m>1405:A,x>2157:A,tp}
xtc{x<2884:R,A}
gj{a>929:vhj,a<885:R,A}
mml{m>2426:rjc,a>3449:hpk,cct}
hfb{x<1738:xc,R}
vk{m<3572:A,m>3601:A,s>1380:R,R}
dmf{a<2866:A,R}
jx{m<1993:R,R}
vz{m<408:R,A}
cr{m>3114:R,x<927:A,R}
rqd{a>827:R,m<3616:A,R}
hxm{a<2012:A,a<2147:R,s>1974:R,R}
fgr{m>3145:A,R}
ljm{a>175:th,x>2267:R,s>203:A,R}
sh{x<2556:A,s<2802:qkk,x>3244:R,lpq}
mh{x<3136:R,jcn}
jcv{x>3293:A,A}
xh{m<3719:A,x<825:A,R}
nn{s>3158:R,a>1035:A,m>397:A,A}
np{m<3051:pnp,scf}
xd{m<3074:A,s<2935:A,a>2618:A,R}
njr{m>623:R,x<2518:A,R}
vmj{x>1396:pv,a<2288:bfk,R}
rt{a>991:xg,a>395:R,a>238:A,vz}
lmf{a<941:tq,s<1601:R,R}
zdz{s>2837:R,m<2501:cvx,a<2586:R,A}
gmg{a>3638:A,a>3540:R,A}
zmk{m>3609:vkb,jc}
skj{a>908:R,a>564:R,x<489:tnt,R}
mb{m>3811:ktz,x<1811:gl,rjx}
rl{x<2034:R,m>1003:A,a<3236:A,R}
dvz{m>1954:kgq,hpb}
hmk{x>3265:R,s>1639:A,s>1393:R,R}
dfq{s>1884:hjr,a>3606:bq,m<2391:hvz,fd}
jqd{x<2830:cjt,jtn}
vhd{m>2806:pp,a<962:dsd,A}
knb{a>1140:R,qv}
br{x<1778:R,R}
zkt{s>3133:R,m<3860:R,A}
zgq{a>1715:R,m<3933:R,A}
xjj{a<1879:R,x>3421:qbr,x<3014:R,R}
bg{m<731:A,m<1261:R,a<1026:A,A}
ct{x<2963:A,s<2119:R,x>3312:A,A}
bvx{x>2177:R,m<1910:rl,x>1943:bzg,nv}
hg{x>2696:jnq,x>2077:bt,bn}
hs{x<3271:R,A}
tvs{a<654:rg,m<2741:fq,qdh}
qtq{a<982:R,a<1234:A,R}
gcg{m>3101:R,a<480:R,A}
vp{a>3910:R,s>2776:A,a>3898:A,A}
pd{x>1921:A,A}
xt{a>967:R,m>3516:A,a>776:R,A}
qc{a>3321:R,A}
tkb{a<1063:vmr,a>1959:zlg,ctf}
bcs{s>2230:lxs,s>2030:R,m<743:slv,A}
qn{a<3266:A,a>3348:R,m<2667:R,A}
cvx{x>2282:A,m<2005:R,a<2628:A,R}
hrg{m>356:R,s>3696:R,A}
hvz{s<1848:A,a<3490:A,s<1870:A,xcc}
lh{s>1362:R,x>1231:R,a>1747:R,R}
vc{m<422:jxl,x>2315:zdg,sk}
fts{x<952:skj,a>1143:sm,x<1335:sql,kmt}
jsg{x>2596:R,x>1393:A,m>3518:R,A}
hk{x>1083:R,m>3604:R,A}
mt{s>2812:R,x<595:R,s>2688:R,A}
cdz{x>1644:R,m>1862:R,A}
pxv{a<3725:nt,a<3830:A,A}
njd{m<2225:R,mkk}
mjx{s<1366:dqb,tj}
bfk{a>2248:R,R}
xs{m<518:pxv,a<3589:rxz,a>3783:dv,gr}
djc{s>2174:A,js}
zx{x<1016:A,x<1528:R,R}
mzd{a>2015:R,R}
knq{a>3143:R,x>3377:R,R}
bq{s>1846:A,s>1827:cpr,fvr}
zdg{s>3443:A,a>1681:mzd,s<2909:dp,A}
sll{m<2763:R,s<1342:ssq,R}
ft{m<1121:A,s>1882:A,s>1847:R,R}
dnq{x>1487:bl,s<3256:tpk,m<3063:rgr,gmd}
bqz{a>2865:R,A}
sdj{m>1268:A,s<1037:R,a<3341:A,R}
dc{s>2554:A,m<2684:R,qsg}
bbq{s>2709:A,s>2586:A,R}
js{m<1039:A,A}
hjr{x<1882:R,s>1927:R,jcv}
lk{a>3257:bj,a>2920:A,m>1832:fv,R}
ts{a>401:R,a<339:A,s<3429:A,R}
xr{x<1991:sv,s<2852:qh,s<2893:hh,sfd}
bl{m<2988:A,a>784:xsb,a>295:skb,ps}
kg{x<1065:R,x>1534:A,R}
gf{x<3539:A,a<3041:R,R}
ckj{s<2886:A,s>2893:A,A}
fg{s<2314:A,m<139:R,x>1421:A,R}
mn{x<3000:A,m>315:R,m<177:A,R}
vrt{s>3263:A,a<878:R,x>2044:A,R}
npv{x<687:R,A}
ljt{x<2374:R,A}
pbp{a>1398:hxm,a>588:xt,a<333:kcn,R}
fgd{s>1796:R,x>2219:R,m<3069:A,R}
xhs{a<752:R,zpq}
tf{m<2132:A,m>2187:A,A}
qjl{s<1624:zdd,s>1981:klp,bhv}
gx{s<1192:A,s>1376:R,R}
hsz{m>3435:R,s<2747:A,A}
rkz{a>1486:bxk,m<3808:R,a>1388:A,zkt}
mjf{x>2320:A,x<1139:A,R}
gl{a>1425:bd,s>1660:frk,s>1500:lmf,xzp}
gvr{m<2241:R,R}
bnv{s<3071:R,R}
vcc{m<618:sl,x>2269:zg,rhs}
ghz{x>1927:A,a<394:A,m<231:A,R}
crk{m<2842:R,x>2970:A,x<2213:R,R}
mfx{a>731:zxc,m<547:kdt,s>3502:tsn,jxm}
pjq{m<3273:A,a<945:A,A}
tpk{m>2975:drj,xz}
qpt{x>2909:A,a>991:A,a<810:R,R}
jc{m>3552:R,R}
rd{s<2850:R,x>3613:A,s>2904:xd,ckj}
rlx{x>3373:R,A}
hkv{a>502:mhm,s>3324:R,A}
dsd{s<1357:R,x<3340:R,R}
ln{s>1813:ztb,m>3116:rnx,A}
czr{m>2538:R,A}
xxb{s>2993:R,x>2787:R,dtt}
mf{s<1679:A,m<538:A,R}
zb{s>2579:njd,hg}
sn{m>3668:gdh,x>2740:A,s>624:R,gnx}
trs{a<1933:nm,mq}
xcq{m>3184:vlz,x<2483:R,R}
hx{s>3738:gs,x<3448:kbp,klr}
cz{s>1882:qk,m<3508:pxd,mb}
gmd{x>924:A,x<437:A,gcg}
{x=363,m=218,a=594,s=411}
{x=973,m=37,a=2533,s=132}
{x=2768,m=1537,a=645,s=580}
{x=2079,m=168,a=502,s=656}
{x=38,m=145,a=3452,s=1162}
{x=70,m=1238,a=99,s=560}
{x=1261,m=1540,a=283,s=28}
{x=1194,m=780,a=1538,s=2681}
{x=1236,m=1847,a=1403,s=1086}
{x=2227,m=163,a=716,s=410}
{x=9,m=369,a=572,s=1418}
{x=201,m=1472,a=943,s=3541}
{x=2730,m=1777,a=127,s=3031}
{x=329,m=139,a=1310,s=2983}
{x=54,m=981,a=1378,s=783}
{x=658,m=410,a=482,s=490}
{x=1555,m=1246,a=365,s=2769}
{x=1075,m=95,a=806,s=750}
{x=408,m=125,a=2296,s=1599}
{x=715,m=1257,a=1287,s=1638}
{x=63,m=1295,a=169,s=1802}
{x=2068,m=4,a=768,s=365}
{x=1390,m=3366,a=1730,s=1631}
{x=1900,m=622,a=761,s=1108}
{x=1857,m=678,a=136,s=965}
{x=3295,m=47,a=303,s=63}
{x=2853,m=700,a=315,s=647}
{x=379,m=304,a=914,s=59}
{x=2591,m=385,a=1410,s=1473}
{x=140,m=1237,a=769,s=2670}
{x=747,m=395,a=1988,s=633}
{x=30,m=381,a=1966,s=2597}
{x=1969,m=1191,a=501,s=328}
{x=127,m=1200,a=47,s=2408}
{x=1409,m=2136,a=205,s=3122}
{x=150,m=88,a=1082,s=3059}
{x=320,m=2917,a=1371,s=22}
{x=2237,m=1186,a=466,s=2252}
{x=2460,m=7,a=1758,s=874}
{x=421,m=126,a=1338,s=1479}
{x=150,m=675,a=2555,s=267}
{x=1007,m=1178,a=2927,s=2435}
{x=902,m=190,a=77,s=1279}
{x=1393,m=716,a=686,s=569}
{x=339,m=1199,a=275,s=338}
{x=116,m=1997,a=739,s=142}
{x=1332,m=69,a=74,s=1953}
{x=2324,m=2089,a=101,s=1595}
{x=2966,m=696,a=305,s=1221}
{x=810,m=1860,a=141,s=49}
{x=995,m=382,a=1020,s=756}
{x=899,m=133,a=746,s=952}
{x=325,m=1880,a=554,s=1749}
{x=506,m=1478,a=897,s=597}
{x=659,m=424,a=20,s=1447}
{x=4,m=310,a=1121,s=286}
{x=3357,m=396,a=1204,s=2886}
{x=1209,m=614,a=2397,s=408}
{x=505,m=339,a=72,s=709}
{x=3478,m=1412,a=1777,s=1}
{x=2271,m=136,a=83,s=477}
{x=3008,m=280,a=2167,s=1522}
{x=543,m=772,a=433,s=3560}
{x=227,m=2037,a=1444,s=272}
{x=869,m=80,a=2585,s=1212}
{x=893,m=1207,a=124,s=126}
{x=2178,m=2030,a=3000,s=1438}
{x=450,m=1798,a=1307,s=2147}
{x=469,m=1554,a=1080,s=393}
{x=49,m=389,a=813,s=39}
{x=3041,m=607,a=379,s=1435}
{x=62,m=121,a=47,s=2394}
{x=1589,m=2474,a=1599,s=3}
{x=439,m=1493,a=284,s=3}
{x=619,m=1377,a=1107,s=3452}
{x=1802,m=1132,a=851,s=111}
{x=2154,m=464,a=2611,s=2147}
{x=843,m=423,a=355,s=838}
{x=3,m=423,a=139,s=857}
{x=42,m=843,a=2219,s=3695}
{x=1068,m=575,a=88,s=222}
{x=3097,m=238,a=913,s=2452}
{x=109,m=206,a=291,s=728}
{x=3635,m=1815,a=26,s=19}
{x=49,m=115,a=2998,s=26}
{x=2093,m=391,a=267,s=2896}
{x=282,m=2364,a=62,s=62}
{x=361,m=719,a=1679,s=137}
{x=631,m=1131,a=203,s=2281}
{x=794,m=1004,a=868,s=636}
{x=1702,m=415,a=35,s=236}
{x=63,m=1690,a=682,s=2009}
{x=1815,m=3459,a=144,s=374}
{x=91,m=590,a=1651,s=1681}
{x=1561,m=2303,a=307,s=1463}
{x=842,m=927,a=868,s=455}
{x=51,m=23,a=427,s=247}
{x=2431,m=187,a=267,s=184}
{x=1596,m=1904,a=668,s=1553}
{x=922,m=1435,a=336,s=1301}
{x=1038,m=1632,a=220,s=117}
{x=1935,m=1433,a=2988,s=316}
{x=21,m=1158,a=1988,s=1242}
{x=840,m=1272,a=418,s=1198}
{x=1227,m=1811,a=158,s=10}
{x=1836,m=56,a=19,s=1573}
{x=461,m=621,a=532,s=92}
{x=2082,m=1292,a=1032,s=322}
{x=2094,m=249,a=865,s=2030}
{x=1092,m=265,a=1745,s=1720}
{x=2361,m=1087,a=209,s=1934}
{x=92,m=111,a=3188,s=2172}
{x=248,m=2163,a=1351,s=1194}
{x=1675,m=2194,a=324,s=1764}
{x=2148,m=3124,a=854,s=1823}
{x=520,m=617,a=649,s=49}
{x=2497,m=12,a=270,s=161}
{x=248,m=2,a=1026,s=1196}
{x=367,m=860,a=1141,s=61}
{x=411,m=90,a=3401,s=2156}
{x=284,m=265,a=421,s=866}
{x=2152,m=2245,a=1206,s=1056}
{x=1578,m=74,a=93,s=1494}
{x=225,m=50,a=2223,s=1888}
{x=2448,m=372,a=587,s=820}
{x=1222,m=215,a=31,s=1753}
{x=2906,m=1170,a=1120,s=291}
{x=1253,m=329,a=478,s=2489}
{x=563,m=150,a=103,s=1051}
{x=212,m=980,a=1325,s=882}
{x=580,m=754,a=555,s=1470}
{x=522,m=397,a=1018,s=763}
{x=2327,m=1100,a=975,s=511}
{x=324,m=1719,a=48,s=569}
{x=1872,m=3353,a=54,s=1330}
{x=2082,m=1209,a=2390,s=747}
{x=1510,m=2290,a=591,s=45}
{x=60,m=1482,a=924,s=598}
{x=775,m=675,a=1635,s=1560}
{x=316,m=170,a=168,s=1335}
{x=1821,m=79,a=2073,s=92}
{x=612,m=1814,a=1651,s=3496}
{x=116,m=2643,a=1073,s=301}
{x=313,m=92,a=2892,s=109}
{x=1109,m=279,a=701,s=763}
{x=86,m=214,a=1910,s=99}
{x=1049,m=320,a=530,s=216}
{x=192,m=366,a=887,s=1516}
{x=353,m=107,a=257,s=225}
{x=117,m=72,a=810,s=147}
{x=341,m=17,a=190,s=2748}
{x=1397,m=572,a=2275,s=1494}
{x=386,m=1691,a=346,s=985}
{x=603,m=584,a=1464,s=291}
{x=49,m=46,a=2277,s=1200}
{x=3116,m=1,a=500,s=166}
{x=310,m=1054,a=1271,s=1423}
{x=1690,m=721,a=1555,s=232}
{x=1713,m=2002,a=1132,s=611}
{x=229,m=1721,a=1590,s=42}
{x=16,m=1444,a=2296,s=144}
{x=371,m=339,a=1073,s=1585}
{x=1025,m=10,a=491,s=196}
{x=58,m=1161,a=492,s=1401}
{x=305,m=1366,a=919,s=236}
{x=1427,m=654,a=2052,s=2399}
{x=1312,m=723,a=408,s=173}
{x=589,m=703,a=29,s=126}
{x=2609,m=1461,a=266,s=129}
{x=299,m=253,a=857,s=2220}
{x=259,m=600,a=494,s=546}
{x=2978,m=988,a=1660,s=2661}
{x=193,m=478,a=213,s=1631}
{x=3378,m=2275,a=534,s=2317}
{x=654,m=2641,a=284,s=1768}
{x=50,m=76,a=672,s=120}
{x=85,m=630,a=1446,s=1321}
{x=306,m=986,a=808,s=1724}
{x=782,m=1554,a=741,s=2220}
{x=1115,m=48,a=3283,s=958}
{x=214,m=2498,a=996,s=981}
{x=1437,m=53,a=2052,s=914}
{x=3256,m=441,a=47,s=108}
{x=689,m=1954,a=60,s=133}
{x=1,m=2270,a=903,s=13}
{x=2373,m=956,a=2739,s=860}
{x=1270,m=357,a=2115,s=1868}
{x=114,m=587,a=349,s=62}
{x=186,m=491,a=464,s=46}
{x=2001,m=99,a=649,s=1854}
{x=408,m=386,a=681,s=774}
{x=697,m=775,a=2740,s=1582}
{x=525,m=2075,a=11,s=822}
{x=621,m=1069,a=233,s=255}
{x=979,m=2750,a=241,s=199}
{x=2006,m=665,a=2211,s=1776}
{x=483,m=213,a=2042,s=67}
{x=1181,m=1199,a=1513,s=919}
{x=1378,m=274,a=438,s=546}
{x=59,m=224,a=3034,s=254}

View File

@ -1,424 +0,0 @@
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufRead, BufReader, Lines};
use std::ops::Range;
use std::time::Instant;
// BOILERPLATE
type InputIter = Lines<BufReader<File>>;
fn get_input() -> InputIter {
let f = File::open("input").unwrap();
let br = BufReader::new(f);
br.lines()
}
fn main() {
let start = Instant::now();
let ans1 = problem1(get_input());
let duration = start.elapsed();
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
let start = Instant::now();
let ans2 = problem2(get_input());
let duration = start.elapsed();
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
}
// DATA
const INPUT_RANGE: Range<u64> = 1..4001;
fn empty_counters() -> HashMap<char, Vec<Range<u64>>> {
HashMap::from([
('x', vec![INPUT_RANGE]),
('m', vec![INPUT_RANGE]),
('a', vec![INPUT_RANGE]),
('s', vec![INPUT_RANGE]),
])
}
#[derive(Debug)]
struct RulePredicate {
op: PredicateOperator,
var: char,
}
#[derive(Debug, Clone)]
enum RuleAction {
Terminate(bool),
Jump(String),
}
impl From<&str> for RuleAction {
fn from(s: &str) -> Self {
match s {
"A" => Self::Terminate(true),
"R" => Self::Terminate(false),
s => Self::Jump(s.into()),
}
}
}
#[derive(Debug)]
struct Rule {
pred: RulePredicate,
action: RuleAction,
}
#[derive(Debug)]
enum PredicateOperator {
Always,
Lt(u64),
Gt(u64),
}
fn range_overlap<T: num::Num + Ord + Copy>(r1: &Range<T>, r2: &Range<T>) -> Option<Range<T>> {
let new_start = std::cmp::max(r1.start, r2.start);
let new_end = std::cmp::min(r1.end - T::one(), r2.end - T::one());
if new_start <= std::cmp::min(r1.end - T::one(), r2.end - T::one()) && new_end >= std::cmp::max(r1.start, r2.start)
{
Some(new_start..new_end + T::one())
} else {
None
}
}
fn range_exclude<T: num::Num + Ord + Copy>(keep: &Range<T>, exclude: &Range<T>) -> Vec<Range<T>> {
let mut residual = Vec::new();
if let Some(overlap) = range_overlap(keep, exclude) {
if keep.start < overlap.start {
residual.push(keep.start..overlap.start);
}
if keep.end > overlap.end {
residual.push(overlap.end..keep.end);
}
} else {
residual.push(keep.clone());
}
residual
}
impl From<&str> for PredicateOperator {
fn from(s: &str) -> Self {
let (op_s, val_s) = s.split_at(1);
match op_s {
"<" => PredicateOperator::Lt(val_s.parse().unwrap()),
">" => PredicateOperator::Gt(val_s.parse().unwrap()),
s => panic!("unknown operator {}", s),
}
}
}
impl From<&str> for RulePredicate {
fn from(s: &str) -> Self {
let (var_s, pred_s) = s.split_at(1);
Self {
op: pred_s.into(),
var: var_s.chars().next().unwrap(),
}
}
}
impl RulePredicate {
fn check(&self, part: &Part) -> bool {
match self.op {
PredicateOperator::Always => true,
PredicateOperator::Gt(val) => part.0[&self.var] > val,
PredicateOperator::Lt(val) => part.0[&self.var] < val,
}
}
fn matching_range(&self) -> Range<u64> {
let res = match self.op {
PredicateOperator::Always => INPUT_RANGE,
PredicateOperator::Gt(val) => val + 1..INPUT_RANGE.end,
PredicateOperator::Lt(val) => INPUT_RANGE.start..val,
};
println!(" matching range for predicate {:?}: {:?}", self, res);
res
}
}
impl From<&str> for Rule {
fn from(s: &str) -> Self {
if let Some((predicate_s, action_s)) = s.split_once(':') {
Self {
pred: predicate_s.into(),
action: action_s.into(),
}
} else {
Self {
pred: RulePredicate {
op: PredicateOperator::Always,
var: '\0',
},
action: s.into(),
}
}
}
}
fn count_states(ranges: HashMap<char, Vec<Range<u64>>>) -> u64 {
['x', 'm', 'a', 's'].iter().map(|c| ranges[c].iter().map(|r| r.end - r.start).sum::<u64>()).product()
}
impl Rule {
// Returns (matching_ranges, unmatching_ranges for next rule)
fn possible_ranges(
&self,
wfs: &Workflows,
ranges: HashMap<char, Vec<Range<u64>>>,
) -> (u64, HashMap<char, Vec<Range<u64>>>) {
return match &self.action {
RuleAction::Terminate(true) => {
if let PredicateOperator::Always = self.pred.op {
// Always predicate is terminating and returns empty ranges
(count_states(ranges), empty_counters())
} else {
// other predicates will pop up the stack and return unmatched ranges
let (mut matching, mut unmatching) = (ranges.clone(), ranges.clone());
if let Some(relevant_ranges) = ranges.get(&(self.pred.var)){
println!(" relevant: {:?}", relevant_ranges);
matching.insert(
self.pred.var,
relevant_ranges
.iter()
.filter_map(|range| range_overlap(range, &self.pred.matching_range()))
.collect(),
);
unmatching.insert(
self.pred.var,
relevant_ranges.iter().flat_map(|range| range_exclude(range, &self.pred.matching_range())).collect());
println!(" matching: {:?}", matching);
(count_states(matching), unmatching)
} else {
// relevant_ranges is empty so this is a failed state with no possibilities for one of the values
// probably we should never get here
(0, empty_counters())
}
}
}
RuleAction::Terminate(false) => {
if let PredicateOperator::Always = self.pred.op {
// Always predicate is terminating, with false returns 0 count and empty ranges
(0, empty_counters())
} else {
let (mut matching, mut unmatching) = (ranges.clone(), ranges.clone());
if let Some(relevant_ranges) = ranges.get(&(self.pred.var)){
matching.insert(
self.pred.var,
relevant_ranges
.iter()
.filter_map(|range| range_overlap(range, &self.pred.matching_range()))
.collect(),
);
unmatching.insert(
self.pred.var,
relevant_ranges.iter().flat_map(|range| range_exclude(range, &self.pred.matching_range())).collect());
(0, unmatching)
} else {
// relevant_ranges is empty so this is a failed state with no possibilities for one of the values
// probably we should never get here
(0, empty_counters())
}
}
}
RuleAction::Jump(wf) => {
if let PredicateOperator::Always = self.pred.op {
// always predicate before a jump will always jump, so has no unmatching ranges
(wfs.0[wf].possible_ranges(wfs, ranges), empty_counters())
} else {
let (mut matching, mut unmatching) = (ranges.clone(), ranges.clone());
if let Some(relevant_ranges) = ranges.get(&(self.pred.var)){
matching.insert(
self.pred.var,
relevant_ranges
.iter()
.filter_map(|range| range_overlap(range, &self.pred.matching_range()))
.collect(),
);
unmatching.insert(
self.pred.var,
relevant_ranges.iter().flat_map(|range| range_exclude(range, &self.pred.matching_range())).collect());
(wfs.0[wf].possible_ranges(wfs, matching), unmatching)
} else {
// no relevant ranges = no possible continuations
(0, empty_counters())
}
}
}
};
}
}
#[derive(Debug)]
struct Workflow {
name: String,
rules: Vec<Rule>,
}
impl From<&str> for Workflow {
fn from(s: &str) -> Self {
let (name_s, rest_s) = s.split_once('{').unwrap();
let rules = rest_s.split_once('}').unwrap().0.split(',').map(|r| r.into()).collect();
Self {
name: name_s.into(),
rules,
}
}
}
impl Workflow {
fn execute(&self, part: &Part) -> RuleAction {
for r in &self.rules {
if r.pred.check(part) {
return r.action.clone();
}
}
panic!("unhandled part {:?}", part);
}
fn possible_ranges(
&self,
wfs: &Workflows,
mut ranges: HashMap<char, Vec<Range<u64>>>,
) -> u64 {
let mut accum = 0u64;
println!("Entering {} with ranges {:?}", self.name, ranges);
for r in &self.rules {
println!(" evaluating rule: {:?} with {:?}", r, ranges);
let (count, next_ranges) = r.possible_ranges(wfs, ranges);
ranges = next_ranges;
println!(" result of {:?}: count<{}> remaining<{:?}>", r, count, ranges);
accum += count
}
println!("Count of {}: {}", self.name, accum);
accum
}
}
impl Workflows {
fn execute(&self, part: &Part) -> bool {
let mut action = RuleAction::Jump("in".into());
loop {
match &action {
RuleAction::Terminate(b) => return *b,
RuleAction::Jump(j) => {
let next_workflow = &self.0[j];
action = next_workflow.execute(part)
}
}
}
}
fn count_possible_states(&self) -> u64 {
let ranges = HashMap::from([
('x', vec![INPUT_RANGE]),
('m', vec![INPUT_RANGE]),
('a', vec![INPUT_RANGE]),
('s', vec![INPUT_RANGE]),
]);
let possible_ranges = self.0["in".into()].possible_ranges(self, ranges);
println!("possible_ranges: {:?}", possible_ranges);
possible_ranges
}
}
#[derive(Debug)]
struct Workflows(HashMap<String, Workflow>);
#[derive(Debug)]
struct Part(HashMap<char, u64>);
impl From<&str> for Part {
fn from(s: &str) -> Self {
let (_, vars_s) = s.split_once('{').unwrap();
let vars = vars_s.split_once('}').unwrap().0.split(',');
let mut part = HashMap::new();
for var in vars {
let (name, val) = var.split_once('=').unwrap();
part.insert(name.chars().next().unwrap(), val.parse().unwrap());
}
Self(part)
}
}
type Parts = Vec<Part>;
// PROBLEM 1 solution
fn problem1<T: BufRead>(mut input: Lines<T>) -> u64 {
let mut wfs = Workflows(HashMap::new());
let mut parts: Parts = Vec::new();
while let Some(Ok(line)) = input.next() {
if line != "" {
let wf: Workflow = line.as_str().into();
wfs.0.insert(wf.name.clone(), wf);
} else {
break;
}
}
while let Some(Ok(line)) = input.next() {
parts.push(line.as_str().into());
}
parts
.iter()
.filter(|part| wfs.execute(part))
.map(|part| part.0.values().sum::<u64>())
.sum::<u64>()
}
// PROBLEM 2 solution
fn problem2<T: BufRead>(mut input: Lines<T>) -> u64 {
let mut wfs = Workflows(HashMap::new());
let mut parts: Parts = Vec::new();
while let Some(Ok(line)) = input.next() {
if line != "" {
let wf: Workflow = line.as_str().into();
wfs.0.insert(wf.name.clone(), wf);
} else {
break;
}
}
while let Some(Ok(line)) = input.next() {
parts.push(line.as_str().into());
}
wfs.count_possible_states()
}
#[cfg(test)]
mod tests {
use crate::*;
use std::io::Cursor;
const EXAMPLE: &str = &"px{a<2006:qkq,m>2090:A,rfg}
pv{a>1716:R,A}
lnx{m>1548:A,A}
rfg{s<537:gd,x>2440:R,A}
qs{s>3448:A,lnx}
qkq{x<1416:A,crn}
crn{x>2662:A,R}
in{s<1351:px,qqz}
qqz{s>2770:qs,m<1801:hdj,R}
gd{a>3333:R,R}
hdj{m>838:A,pv}
{x=787,m=2655,a=1222,s=2876}
{x=1679,m=44,a=2067,s=496}
{x=2036,m=264,a=79,s=2244}
{x=2461,m=1339,a=466,s=291}
{x=2127,m=1623,a=2188,s=1013}";
#[test]
fn problem1_example() {
let c = Cursor::new(EXAMPLE);
assert_eq!(problem1(c.lines()), 19114);
}
#[test]
fn problem2_example() {
let c = Cursor::new(EXAMPLE);
assert_eq!(problem2(c.lines()), 167409079868000);
}
}