Advent 2015 Day 7, 8 & 9 Parts 1 & 2

This commit is contained in:
Jos van Goor 2025-12-07 18:18:40 +01:00
parent 96b06c7bee
commit de1a181ba5
40 changed files with 1158 additions and 0 deletions

16
advent_of_code_2015/Cargo.lock generated Normal file
View file

@ -0,0 +1,16 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "advent_of_code_2025"
version = "0.1.0"
dependencies = [
"paste",
]
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"

View file

@ -0,0 +1,7 @@
[package]
name = "advent_of_code_2025"
version = "0.1.0"
edition = "2024"
[dependencies]
paste = "1.0"

View file

@ -0,0 +1,14 @@
binop_separator = "Back"
brace_style = "PreferSameLine"
edition = "2024"
enum_discrim_align_threshold = 120
fn_single_line = false
group_imports = "StdExternalCrate"
imports_granularity = "Module"
indent_style = "Block"
max_width = 160
reorder_impl_items = false
struct_field_align_threshold = 120
unstable_features = true
use_small_heuristics = "Max"
where_single_line = true

View file

@ -0,0 +1,339 @@
bn RSHIFT 2 -> bo
lf RSHIFT 1 -> ly
fo RSHIFT 3 -> fq
cj OR cp -> cq
fo OR fz -> ga
t OR s -> u
lx -> a
NOT ax -> ay
he RSHIFT 2 -> hf
lf OR lq -> lr
lr AND lt -> lu
dy OR ej -> ek
1 AND cx -> cy
hb LSHIFT 1 -> hv
1 AND bh -> bi
ih AND ij -> ik
c LSHIFT 1 -> t
ea AND eb -> ed
km OR kn -> ko
NOT bw -> bx
ci OR ct -> cu
NOT p -> q
lw OR lv -> lx
NOT lo -> lp
fp OR fv -> fw
o AND q -> r
dh AND dj -> dk
ap LSHIFT 1 -> bj
bk LSHIFT 1 -> ce
NOT ii -> ij
gh OR gi -> gj
kk RSHIFT 1 -> ld
lc LSHIFT 1 -> lw
lb OR la -> lc
1 AND am -> an
gn AND gp -> gq
lf RSHIFT 3 -> lh
e OR f -> g
lg AND lm -> lo
ci RSHIFT 1 -> db
cf LSHIFT 1 -> cz
bn RSHIFT 1 -> cg
et AND fe -> fg
is OR it -> iu
kw AND ky -> kz
ck AND cl -> cn
bj OR bi -> bk
gj RSHIFT 1 -> hc
iu AND jf -> jh
NOT bs -> bt
kk OR kv -> kw
ks AND ku -> kv
hz OR ik -> il
b RSHIFT 1 -> v
iu RSHIFT 1 -> jn
fo RSHIFT 5 -> fr
be AND bg -> bh
ga AND gc -> gd
hf OR hl -> hm
ld OR le -> lf
as RSHIFT 5 -> av
fm OR fn -> fo
hm AND ho -> hp
lg OR lm -> ln
NOT kx -> ky
kk RSHIFT 3 -> km
ek AND em -> en
NOT ft -> fu
NOT jh -> ji
jn OR jo -> jp
gj AND gu -> gw
d AND j -> l
et RSHIFT 1 -> fm
jq OR jw -> jx
ep OR eo -> eq
lv LSHIFT 15 -> lz
NOT ey -> ez
jp RSHIFT 2 -> jq
eg AND ei -> ej
NOT dm -> dn
jp AND ka -> kc
as AND bd -> bf
fk OR fj -> fl
dw OR dx -> dy
lj AND ll -> lm
ec AND ee -> ef
fq AND fr -> ft
NOT kp -> kq
ki OR kj -> kk
cz OR cy -> da
as RSHIFT 3 -> au
an LSHIFT 15 -> ar
fj LSHIFT 15 -> fn
1 AND fi -> fj
he RSHIFT 1 -> hx
lf RSHIFT 2 -> lg
kf LSHIFT 15 -> kj
dz AND ef -> eh
ib OR ic -> id
lf RSHIFT 5 -> li
bp OR bq -> br
NOT gs -> gt
fo RSHIFT 1 -> gh
bz AND cb -> cc
ea OR eb -> ec
lf AND lq -> ls
NOT l -> m
hz RSHIFT 3 -> ib
NOT di -> dj
NOT lk -> ll
jp RSHIFT 3 -> jr
jp RSHIFT 5 -> js
NOT bf -> bg
s LSHIFT 15 -> w
eq LSHIFT 1 -> fk
jl OR jk -> jm
hz AND ik -> im
dz OR ef -> eg
1 AND gy -> gz
la LSHIFT 15 -> le
br AND bt -> bu
NOT cn -> co
v OR w -> x
d OR j -> k
1 AND gd -> ge
ia OR ig -> ih
NOT go -> gp
NOT ed -> ee
jq AND jw -> jy
et OR fe -> ff
aw AND ay -> az
ff AND fh -> fi
ir LSHIFT 1 -> jl
gg LSHIFT 1 -> ha
x RSHIFT 2 -> y
db OR dc -> dd
bl OR bm -> bn
ib AND ic -> ie
x RSHIFT 3 -> z
lh AND li -> lk
ce OR cd -> cf
NOT bb -> bc
hi AND hk -> hl
NOT gb -> gc
1 AND r -> s
fw AND fy -> fz
fb AND fd -> fe
1 AND en -> eo
z OR aa -> ab
bi LSHIFT 15 -> bm
hg OR hh -> hi
kh LSHIFT 1 -> lb
cg OR ch -> ci
1 AND kz -> la
gf OR ge -> gg
gj RSHIFT 2 -> gk
dd RSHIFT 2 -> de
NOT ls -> lt
lh OR li -> lj
jr OR js -> jt
au AND av -> ax
0 -> c
he AND hp -> hr
id AND if -> ig
et RSHIFT 5 -> ew
bp AND bq -> bs
e AND f -> h
ly OR lz -> ma
1 AND lu -> lv
NOT jd -> je
ha OR gz -> hb
dy RSHIFT 1 -> er
iu RSHIFT 2 -> iv
NOT hr -> hs
as RSHIFT 1 -> bl
kk RSHIFT 2 -> kl
b AND n -> p
ln AND lp -> lq
cj AND cp -> cr
dl AND dn -> do
ci RSHIFT 2 -> cj
as OR bd -> be
ge LSHIFT 15 -> gi
hz RSHIFT 5 -> ic
dv LSHIFT 1 -> ep
kl OR kr -> ks
gj OR gu -> gv
he RSHIFT 5 -> hh
NOT fg -> fh
hg AND hh -> hj
b OR n -> o
jk LSHIFT 15 -> jo
gz LSHIFT 15 -> hd
cy LSHIFT 15 -> dc
kk RSHIFT 5 -> kn
ci RSHIFT 3 -> ck
at OR az -> ba
iu RSHIFT 3 -> iw
ko AND kq -> kr
NOT eh -> ei
aq OR ar -> as
iy AND ja -> jb
dd RSHIFT 3 -> df
bn RSHIFT 3 -> bp
1 AND cc -> cd
at AND az -> bb
x OR ai -> aj
kk AND kv -> kx
ao OR an -> ap
dy RSHIFT 3 -> ea
x RSHIFT 1 -> aq
eu AND fa -> fc
kl AND kr -> kt
ia AND ig -> ii
df AND dg -> di
NOT fx -> fy
k AND m -> n
bn RSHIFT 5 -> bq
km AND kn -> kp
dt LSHIFT 15 -> dx
hz RSHIFT 2 -> ia
aj AND al -> am
cd LSHIFT 15 -> ch
hc OR hd -> he
he RSHIFT 3 -> hg
bn OR by -> bz
NOT kt -> ku
z AND aa -> ac
NOT ak -> al
cu AND cw -> cx
NOT ie -> if
dy RSHIFT 2 -> dz
ip LSHIFT 15 -> it
de OR dk -> dl
au OR av -> aw
jg AND ji -> jj
ci AND ct -> cv
dy RSHIFT 5 -> eb
hx OR hy -> hz
eu OR fa -> fb
gj RSHIFT 3 -> gl
fo AND fz -> gb
1 AND jj -> jk
jp OR ka -> kb
de AND dk -> dm
ex AND ez -> fa
df OR dg -> dh
iv OR jb -> jc
x RSHIFT 5 -> aa
NOT hj -> hk
NOT im -> in
fl LSHIFT 1 -> gf
hu LSHIFT 15 -> hy
iq OR ip -> ir
iu RSHIFT 5 -> ix
NOT fc -> fd
NOT el -> em
ck OR cl -> cm
et RSHIFT 3 -> ev
hw LSHIFT 1 -> iq
ci RSHIFT 5 -> cl
iv AND jb -> jd
dd RSHIFT 5 -> dg
as RSHIFT 2 -> at
NOT jy -> jz
af AND ah -> ai
1 AND ds -> dt
jx AND jz -> ka
da LSHIFT 1 -> du
fs AND fu -> fv
jp RSHIFT 1 -> ki
iw AND ix -> iz
iw OR ix -> iy
eo LSHIFT 15 -> es
ev AND ew -> ey
ba AND bc -> bd
fp AND fv -> fx
jc AND je -> jf
et RSHIFT 2 -> eu
kg OR kf -> kh
iu OR jf -> jg
er OR es -> et
fo RSHIFT 2 -> fp
NOT ca -> cb
bv AND bx -> by
u LSHIFT 1 -> ao
cm AND co -> cp
y OR ae -> af
bn AND by -> ca
1 AND ke -> kf
jt AND jv -> jw
fq OR fr -> fs
dy AND ej -> el
NOT kc -> kd
ev OR ew -> ex
dd OR do -> dp
NOT cv -> cw
gr AND gt -> gu
dd RSHIFT 1 -> dw
NOT gw -> gx
NOT iz -> ja
1 AND io -> ip
NOT ag -> ah
b RSHIFT 5 -> f
NOT cr -> cs
kb AND kd -> ke
jr AND js -> ju
cq AND cs -> ct
il AND in -> io
NOT ju -> jv
du OR dt -> dv
dd AND do -> dq
b RSHIFT 2 -> d
jm LSHIFT 1 -> kg
NOT dq -> dr
bo OR bu -> bv
gk OR gq -> gr
he OR hp -> hq
NOT h -> i
hf AND hl -> hn
gv AND gx -> gy
x AND ai -> ak
bo AND bu -> bw
hq AND hs -> ht
hz RSHIFT 1 -> is
gj RSHIFT 5 -> gm
g AND i -> j
gk AND gq -> gs
dp AND dr -> ds
b RSHIFT 3 -> e
gl AND gm -> go
gl OR gm -> gn
y AND ae -> ag
hv OR hu -> hw
1674 -> b
ab AND ad -> ae
NOT ac -> ad
1 AND ht -> hu
NOT hn -> ho

View file

@ -0,0 +1,2 @@
pub mod part1;
pub mod part2;

View file

@ -0,0 +1,102 @@
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub enum Value {
Literal(u16),
Identifier(String),
}
#[derive(Debug, Clone, Copy)]
pub enum Operator {
And,
Or,
RShift,
LShift,
Not
}
#[derive(Debug, Clone)]
pub enum Expression {
Assign(Value), // 1 token before arrow
Binary(Operator, Value, Value), // 3 tokens before arrow
Unary(Value), // always not // 2 tokens before arrow
}
fn parse_operator(name: &str) -> Operator {
match name {
"AND" => Operator::And,
"OR" => Operator::Or,
"RSHIFT" => Operator::RShift,
"LSHIFT" => Operator::LShift,
_ => panic!("unexpected operator: {}", name)
}
}
fn parse_value(value: &str) -> Value {
if let Ok(num) = value.parse::<u16>() {
Value::Literal(num)
} else {
Value::Identifier(value.into())
}
}
fn solve_value(value: &Value, expressions: &HashMap<String, Expression>, cache: &mut HashMap<String, u16>) -> u16 {
match value {
Value::Literal(num) => *num,
Value::Identifier(name) => {
let result = calculate_wire(name, expressions, cache);
cache.insert(name.clone(), result);
result
},
}
}
fn calculate_wire(ident: &String, expressions: &HashMap<String, Expression>, cache: &mut HashMap<String, u16>) -> u16 {
if let Some(num) = cache.get(ident) {
return *num;
}
match expressions.get(ident).unwrap() {
Expression::Assign(value) => {
solve_value(value, expressions, cache)
},
Expression::Binary(operator, lhs, rhs) => {
match operator {
Operator::And => solve_value(lhs, expressions, cache) & solve_value(rhs, expressions, cache),
Operator::Or => solve_value(lhs, expressions, cache) | solve_value(rhs, expressions, cache),
Operator::RShift => solve_value(lhs, expressions, cache) >> solve_value(rhs, expressions, cache),
Operator::LShift => solve_value(lhs, expressions, cache) << solve_value(rhs, expressions, cache),
Operator::Not => todo!(),
}
},
Expression::Unary(value) => {
!solve_value(value, expressions, cache)
},
}
}
pub fn solve(input: &str) {
let mut value_cache: HashMap<String, u16> = HashMap::new();
let expressions = input.lines().map(|line| {
let (expr, into) = line.split_once(" -> ").unwrap();
let parts = expr.split(" ").collect::<Vec<_>>();
let parsed = match parts.len() {
1 => { // assignment
Expression::Assign(parse_value(expr))
},
2 => {
Expression::Unary(parse_value(parts[1]))
},
3 => {
Expression::Binary(parse_operator(parts[1]), parse_value(parts[0]), parse_value(parts[2]))
},
_ => panic!("unexpected number of parts: {line}")
};
// println!("parsed: {into} -> {parsed:?}");
(into.to_string(), parsed)
}).collect::<HashMap<_, _>>();
println!("solve for a: {}", calculate_wire(&"a".into(), &expressions, &mut value_cache));
}

View file

@ -0,0 +1,105 @@
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub enum Value {
Literal(u16),
Identifier(String),
}
#[derive(Debug, Clone, Copy)]
pub enum Operator {
And,
Or,
RShift,
LShift,
Not
}
#[derive(Debug, Clone)]
pub enum Expression {
Assign(Value), // 1 token before arrow
Binary(Operator, Value, Value), // 3 tokens before arrow
Unary(Value), // always not // 2 tokens before arrow
}
fn parse_operator(name: &str) -> Operator {
match name {
"AND" => Operator::And,
"OR" => Operator::Or,
"RSHIFT" => Operator::RShift,
"LSHIFT" => Operator::LShift,
_ => panic!("unexpected operator: {}", name)
}
}
fn parse_value(value: &str) -> Value {
if let Ok(num) = value.parse::<u16>() {
Value::Literal(num)
} else {
Value::Identifier(value.into())
}
}
fn solve_value(value: &Value, expressions: &HashMap<String, Expression>, cache: &mut HashMap<String, u16>) -> u16 {
match value {
Value::Literal(num) => *num,
Value::Identifier(name) => {
if let Some(num) = cache.get(name) {
return *num;
}
let result = calculate_wire(name, expressions, cache);
cache.insert(name.clone(), result);
result
},
}
}
fn calculate_wire(ident: &String, expressions: &HashMap<String, Expression>, cache: &mut HashMap<String, u16>) -> u16 {
match expressions.get(ident).unwrap() {
Expression::Assign(value) => {
solve_value(value, expressions, cache)
},
Expression::Binary(operator, lhs, rhs) => {
match operator {
Operator::And => solve_value(lhs, expressions, cache) & solve_value(rhs, expressions, cache),
Operator::Or => solve_value(lhs, expressions, cache) | solve_value(rhs, expressions, cache),
Operator::RShift => solve_value(lhs, expressions, cache) >> solve_value(rhs, expressions, cache),
Operator::LShift => solve_value(lhs, expressions, cache) << solve_value(rhs, expressions, cache),
Operator::Not => todo!(),
}
},
Expression::Unary(value) => {
!solve_value(value, expressions, cache)
},
}
}
pub fn solve(input: &str) {
let mut value_cache: HashMap<String, u16> = HashMap::new();
let expressions = input.lines().map(|line| {
let (expr, into) = line.split_once(" -> ").unwrap();
let parts = expr.split(" ").collect::<Vec<_>>();
let parsed = match parts.len() {
1 => { // assignment
Expression::Assign(parse_value(expr))
},
2 => {
Expression::Unary(parse_value(parts[1]))
},
3 => {
Expression::Binary(parse_operator(parts[1]), parse_value(parts[0]), parse_value(parts[2]))
},
_ => panic!("unexpected number of parts: {line}")
};
// println!("parsed: {into} -> {parsed:?}");
(into.to_string(), parsed)
}).collect::<HashMap<_, _>>();
let a = calculate_wire(&"a".into(), &expressions, &mut value_cache);
value_cache.clear();
value_cache.insert("b".into(), a);
println!("value for a: {}", calculate_wire(&"a".into(), &expressions, &mut value_cache));
}

View file

@ -0,0 +1,8 @@
123 -> x
456 -> y
x AND y -> d
x OR y -> e
x LSHIFT 2 -> f
y RSHIFT 2 -> g
NOT x -> h
NOT y -> i

View file

@ -0,0 +1,300 @@
"sjdivfriyaaqa\xd2v\"k\"mpcu\"yyu\"en"
"vcqc"
"zbcwgmbpijcxu\"yins\"sfxn"
"yumngprx"
"bbdj"
"czbggabkzo\"wsnw\"voklp\"s"
"acwt"
"aqttwnsohbzian\"evtllfxwkog\"cunzw"
"ugvsgfv"
"xlnillibxg"
"kexh\"pmi"
"syvugow"
"m\"ktqnw"
"yrbajyndte\\rm"
"f\"kak\x70sn\xc4kjri"
"yxthr"
"alvumfsjni\"kohg"
"trajs\x5brom\xf1yoijaumkem\"\"tahlzs"
"\"oedr\"pwdbnnrc"
"qsmzhnx\""
"\"msoytqimx\\tbklqz"
"mjdfcgwdshrehgs"
"\"rivyxahf\""
"ciagc\x04bp"
"xkfc"
"xrgcripdu\x4c\xc4gszjhrvumvz\"mngbirb"
"gvmae\"yiiujoqvr\"mkxmgbbut\"u"
"ih"
"ncrqlejehs"
"mkno\x43pcfdukmemycp"
"uanzoqxkpsksbvdnkji\"feamp"
"axoufpnbx\\ao\x61pfj\"b"
"dz\\ztawzdjy"
"ihne\"enumvswypgf"
"\"dgazthrphbshdo\\vuqoiy\""
"dlnmptzt\\zahwpylc\\b\"gmslrqysk"
"mhxznyzcp"
"rebr\"amvxw\x5fmbnfpkkeghlntavj"
"lades\x47ncgdof\"\"jmbbk"
"dwxuis\xa5wdkx\\z\"admgnoddpgkt\\zs"
"g\\k\x27qsl\x34hwfglcdxqbeclt\xca\\"
"lhyjky\\m\"pvnm\\xmynpxnlhndmahjl"
"c\"uxabbgorrpprw\"xas\\vefkxioqpt"
"rfrvjxpevcmma\x71gtfipo"
"fgh\"kcwoqwfnjgdlzfclprg\"q"
"onxnwykrba"
"hkkg\x60f\"tjzsanpvarzgkfipl"
"\"aintes\"ofq\"juiaqlqxmvpe\\a"
"wiyczzs\"ciwk"
"mfqeu"
"v\xe1z\x7ftzalmvdmncfivrax\\rjwq"
"k\"vtg"
"exhrtdugeml\xf0"
"behnchkpld"
"mhgxy\"mfcrg\xc5gnp\"\"osqhj"
"rlvjy"
"awe"
"ctwy"
"vt"
"\x54t"
"zugfmmfomz"
"cv\"cvcvfaada\x04fsuqjinbfh\xa9cq\xd2c\"d"
"oj"
"xazanf\"wbmcrn"
"\\\\zkisyjpbzandqikqjqvee"
"dpsnbzdwnxk\\v"
"sj\"tuupr\\oyoh"
"myvkgnw\x81q\xaaokt\\emgejbsyvxcl\\\xee"
"ejeuqvunjcirdkkpt\"nlns"
"twmlvwxyvfyqqzu"
"\"xwtzdp\x98qkcis\"dm\\\"ep\"xyykq"
"vvcq\\expok"
"wgukjfanjgpdjb"
"\"mjcjajnxy\\dcpc"
"wdvgnecw\\ab\x44klceduzgsvu"
"dqtqkukr\"iacngufbqkdpxlwjjt"
"\"xj\"\x66qofsqzkoah"
"nptiwwsqdep"
"gsnlxql\x30mjl"
"yeezwokjwrhelny\""
"bjauamn\\izpmzqqasid"
"tvjdbkn\"tiziw\x82r"
"w"
"xwoakbbnjnypnaa\xa9wft\"slrmoqkl"
"vwxtnlvaaasyruykgygrvpiopzygf\"vq"
"qdancvnvmhlmpj\\isdxs"
"xzc\\elw"
"b\"wxeqvy\"qf\"g\xcaoklsucwicyw\"dovr"
"yomlvvjdbngz\"rly\"afr"
"bfb\"x\"aweuwbwmoa\x13\"t\"zhr"
"\"dmfoxb\"qvpjzzhykt\xd2\"\"ryhxi"
"psqef\"yu\\qiflie\"\x79w"
"arzewkej\"lqmh\\sayyusxxo\\"
"vuvvp"
"hc\"lg\x6bcpupsewzklai\"l"
"cjdfygc\"auorqybnuqghsh\x10"
"j"
"wqjexk\"eyq\\lbroqhk\\dqzsqk"
"dws\"ru\"dvxfiwapif\"oqwzmle"
"agcykg\\jt\\vzklqjvknoe"
"kksd\"jmslja\\z\"y\\b\xaagpyojct"
"nnpipxufvbfpoz\"jno"
"dtw"
"xlolvtahvgqkx\\dgnhj\\spsclpcxv\\"
"mxea\\mbjpi"
"lgbotkk\"zmxh\\\\qji\"jszulnjsxkqf"
"lwckmhwhx\"gmftlb\x91am"
"xxdxqyxth"
"\"lmqhwkjxmvayxy"
"tf"
"qy"
"wdqmwxdztax\"m\"\x09\x11xdxmfwxmtqgwvf"
"\xcbnazlf\"ghziknszmsrahaf"
"e\x6aupmzhxlvwympgjjpdvo\"kylfa"
"\x81vhtlillb\xactgoatva"
"dvnlgr"
"f"
"xg\xfacwizsadgeclm"
"vnnrzbtw\"\\prod\\djbyppngwayy\""
"lrt\xf4jahwvfz"
"aqpnjtom\"ymkak\\dadfybqrso\\fwv"
"gz\"aac\"mrbk\"ktommrojraqh"
"wycamwoecsftepfnlcdkm"
"nrhddblbuzlqsl\x9cben"
"vckxhyqkmqmdseazcykrbysm"
"sil\xbbtevmt\"gvrvybui\"faw\"j"
"cjex\\tp\x45pzf"
"asjobvtxszfodgf\"ibftg"
"gkyjyjdrxdcllnh\"sjcibenrdnxv"
"oswsdpjyxpbwnqbcpl\"yrdvs\\zq"
"\"\"tyowzc\\fycbp\"jbwrbvgui"
"cbpcabqkdgzmpgcwjtrchxp"
"iyrzfh\x45gw\"fdlfpiaap\x31xqq"
"evgksznidz"
"b\\w\\"
"loufizbiy\x57aim\"bgk"
"qjfyk"
"g\"anmloghvgr\x07zwqougqhdz"
"usbbmwcxd\\bdgg"
"htitqcpczml"
"eke\\cqvpexqqk\"to\"tqmljrpn\xe6lji\""
"g\xd2ifdsej"
"h\"sk\"haajajpagtcqnzrfqn\xe6btzo"
"wfkuffdxlvm\\cvlyzlbyunclhmpp"
"myaavh\"spue"
"hqvez\x68d\"eo\"eaioh"
"s\"qd\"oyxxcglcdnuhk"
"ilqvar"
"srh"
"puuifxrfmpc\"bvalwi\x2blu\\"
"yywlbutufzysbncw\\nqsfbhpz\"mngjq"
"zbl\\jfcuop"
"hjdouiragzvxsqkreup\\"
"qi"
"ckx\\funlj\xa7ahi"
"k"
"ufrcnh\"ajteit"
"cqv\"bgjozjj\x60x\xa8yhvmdvutchjotyuz"
"hkuiet\"oku\x8cfhumfpasl"
"\"\\sbe\x4d"
"vhknazqt"
"eyyizvzcahgflvmoowvs\\jhvygci"
"kki\x3ewcefkgtjap\"xtpxh\"lzepoqj"
"wvtk"
"\"ynet"
"zh\\obk\"otagx\x59txfzf"
"ocowhxlx\xe6zqg\x63wx\\tclkhq\\vmaze"
"w\"cf"
"qpniprnrzrnvykghqnalr"
"jctcqra\"\x05dhlydpqamorqjsijt\\xjdgt"
"sig"
"qhlbidbflwxe\"xljbwls\x20vht"
"irmrebfla\xefsg\"j"
"nep"
"hjuvsqlizeqobepf"
"guzbcdp\"obyh"
"\"mjagins\xf9tqykaxy\""
"knvsdnmtr\"zervsb"
"hzuy"
"zza\"k\"buapb\\elm\xfeya"
"lrqar\"dfqwkaaqifig\"uixjsz"
"\"azuo\x40rmnlhhluwsbbdb\x32pk\\yu\"pbcf"
"dplkdyty"
"rfoyciebwlwphcycmguc"
"ivnmmiemhgytmlprq\\eh"
"lhkyzaaothfdhmbpsqd\\yyw"
"tnlzifupcjcaj"
"\\qiyirsdrfpmu\\\x15xusifaag"
"\\lcomf\\s"
"uramjivcirjhqcqcg"
"kkbaklbxfxikffnuhtu\xc6t\"d"
"n\xefai"
"\"toy\"bnbpevuzoc\"muywq\"gz\"grbm"
"\"muu\\wt"
"\\srby\"ee"
"erf\"gvw\"swfppf"
"pbqcgtn\"iuianhcdazfvmidn\\nslhxdf"
"uxbp"
"up\\mgrcyaegiwmjufn"
"nulscgcewj\\dvoyvhetdegzhs\""
"masv\"k\\rzrb"
"qtx\x79d\"xdxmbxrvhj"
"fid\\otpkgjlh\"qgsvexrckqtn\xf4"
"tagzu"
"bvl\\\"noseec"
"\\xgicuuh"
"w\"a\"npemf"
"sxp"
"nsmpktic\x8awxftscdcvijjobnq\"gjd"
"uks\"\"jxvyvfezz\"aynxoev\"cuoav"
"m"
"lkvokj"
"vkfam\"yllr\"q\x92o\x4ebecnvhshhqe\\"
"efdxcjkjverw"
"lmqzadwhfdgmep\x02tzfcbgrbfekhat"
"cpbk\x9azqegbpluczssouop\x36ztpuoxsw"
"cqwoczxdd\"erdjka"
"cwvqnjgbw\\fxdlby"
"mvtm"
"lt\"bbqzpumplkg"
"ntd\xeeuwweucnuuslqfzfq"
"y\xabl\"dbebxjrlbmuoo\\\x1au"
"qjoqx\\a"
"pu\"ekdnfpmly\xbago\""
"fjhhdy"
"arl"
"xcywisim\"bwuwf\"\"raepeawwjub"
"pbe"
"dbnqfpzyaumxtqnd\xc5dcqrkwyop"
"ojv\x40vtkwgkqepm\x8bzft\\vedrry"
"wggqkfbwqumsgajqwphjec\"mstxpwz"
"zjkbem"
"icpfqxbelxazlls"
"pvpqs\\abcmtyielugfgcv\"tjxapxqxnx"
"oqddwlvmtv\"\x39lyybylfb\"jmngnpjrdw"
"gisgbve"
"\"aglg"
"y\"\"ss\xafvhxlrjv"
"qbgqjsra"
"ihshbjgqpdcljpmdwdprwloy"
"djja\\wcdn\"svkrgpqn\"uz\"hc\x43hj"
"cbjm"
"pnn"
"pqvh\"noh"
"\"\\fdktlp"
"ncea"
"pqgzphiyy"
"\xbedovhxuipaohlcvkwtxwmpz\"ckaif\"r"
"arjuzbjowqciunfwgxtph\"vlhy\"n"
"c"
"nrpdxunulgudqzlhtae"
"iefheu\"uru\""
"aqijysxuijud\"np\\opbichhudil\xbesum"
"pfpevmtstl\"lde\"bzr\"vspdxs"
"vparfbdjwvzsocpnzhp"
"g\x4ffxaarafrsjthq\\\xc1rw"
"ng\\rqx\\gwpzucbh\xafl"
"rw\"nf\\dna"
"jkkeahxurxla\\g\xb3czrlsyimmwcwthr"
"twaailoypu\"oas\"kpuuyedlaw\\\xb0vzt"
"hznex\\gdiqvtugi"
"imdibsunjeswhk"
"ta\\icileuzpxro\"cfmv\"mzp"
"coykr\x57luiysucfaflmilhlehmvzeiepo"
"u\x3dfh\xd4yt"
"piw\x1bz\"eowy\"vfk\"wqiekw"
"gan\"y"
"p\"bevidoazcznr\"hddxuuq\""
"bwzucczznutbxe"
"z\"viqgyqjisior\\iecosmjbknol"
"dmlpcglcfkfsctxydjvayhymv\x3c\\gp"
"bfvkqrintbbvgfv"
"xlzntrgdck\"cprc\xadczyarbznqmuhxyuh"
"uqdxnuwioc\"kdytxq\\ig"
"xrafmucpmfi"
"vr\"hltmfrge"
"eonf\"nt\\wtcnsocs"
"j\xb7xoslyjeyjksplkqixncgkylkw"
"njw\"pefgfbez\x9axshdmplxzquqe"
"di\x58bvptfsafirpc"
"l\x1fkco"
"x"
"mprndo\"n"
"psegit"
"svbdnkkuuqs\"sqxu\"oqcyz\"aizashk"
"cwkljukxer\\\"\\nff\"esjwiyaoy"
"ilxrkgbjjxpvhdtq\"cpiuoofdnkpp"
"hlngi\"ulxep\\qohtmqnqjb\"rkgerho"
"gxws\"bcgm\"p"
"bv\"mds\\zhfusiepgrz\\b\x32fscdzz"
"l\xfampwtme\x69qvxnx\"\"\xc4jruuymjxrpsv"
"qqmxhrn"
"xziq\\\x18ybyv\x9am\"neacoqjzytertisysza"
"aqcbvlvcrzceeyx\\j\"\"x"
"yjuhhb"
"\x5em\"squulpy"
"dpbntplgmwb"
"utsgfkm\\vbftjknlktpthoeo"
"ccxjgiocmuhf\"ycnh"
"lltj\"kbbxi"

View file

@ -0,0 +1,2 @@
pub mod part1;
pub mod part2;

View file

@ -0,0 +1,33 @@
pub fn solve(input: &str) {
let lines = input.lines().collect::<Vec<_>>();
let mut code_counter: u64 = 0;
let mut char_counter: u64 = 0;
for line in lines {
let mut caret = 0;
let mut raw = line.as_bytes();
while caret < raw.len() {
match raw[caret] {
b'"' => (),
b'\\' => {
if raw[caret + 1] == b'x' {
caret += 3;
char_counter += 1;
} else {
caret += 1;
char_counter += 1;
}
},
_ => {
char_counter += 1;
}
}
caret += 1;
}
code_counter += line.len() as u64;
}
println!("chars: {char_counter}, code: {code_counter}, result: {}", code_counter - char_counter);
}

View file

@ -0,0 +1,29 @@
pub fn solve(input: &str) {
let lines = input.lines().collect::<Vec<_>>();
let mut additional_characters = 0;
for line in lines {
let mut caret = 0;
let mut raw = line.as_bytes();
while caret < raw.len() {
match raw[caret] {
b'"' => additional_characters += 2,
b'\\' => {
if raw[caret + 1] == b'x' {
caret += 3;
additional_characters += 1;
} else {
caret += 1;
additional_characters += 2;
}
},
_ => {}
}
caret += 1;
}
}
println!("additional characters: {additional_characters}");
}

View file

@ -0,0 +1,4 @@
""
"abc"
"aaa\"aaa"
"\x27"

View file

@ -0,0 +1,28 @@
Faerun to Norrath = 129
Faerun to Tristram = 58
Faerun to AlphaCentauri = 13
Faerun to Arbre = 24
Faerun to Snowdin = 60
Faerun to Tambi = 71
Faerun to Straylight = 67
Norrath to Tristram = 142
Norrath to AlphaCentauri = 15
Norrath to Arbre = 135
Norrath to Snowdin = 75
Norrath to Tambi = 82
Norrath to Straylight = 54
Tristram to AlphaCentauri = 118
Tristram to Arbre = 122
Tristram to Snowdin = 103
Tristram to Tambi = 49
Tristram to Straylight = 97
AlphaCentauri to Arbre = 116
AlphaCentauri to Snowdin = 12
AlphaCentauri to Tambi = 18
AlphaCentauri to Straylight = 91
Arbre to Snowdin = 129
Arbre to Tambi = 53
Arbre to Straylight = 40
Snowdin to Tambi = 15
Snowdin to Straylight = 99
Tambi to Straylight = 70

View file

@ -0,0 +1,2 @@
pub mod part1;
pub mod part2;

View file

@ -0,0 +1,55 @@
use std::collections::{HashMap, HashSet};
fn generate_routes(current: String, mut destinations: HashSet<String>) -> Vec<Vec<String>> {
destinations.remove(&current);
let mut routes = Vec::new();
if destinations.is_empty() {
routes.push([current].to_vec());
return routes;
}
for destination in destinations.iter() {
routes.append(&mut generate_routes(destination.clone(), destinations.clone()));
}
for route in routes.iter_mut() {
route.push(current.clone());
}
routes
}
pub fn solve(input: &str) {
let mut distances: HashMap<String, HashMap<String, u64>> = HashMap::new();
input.lines().for_each(|line| {
let (from, tail) = line.split_once(" to ").unwrap();
let (to, distance) = tail.split_once(" = ").unwrap();
distances.entry(from.into()).or_default().insert(to.to_string(), distance.parse().unwrap());
distances.entry(to.into()).or_default().insert(from.to_string(), distance.parse().unwrap());
});
let cities = distances.keys().cloned().collect::<HashSet<_>>();
let mut routes: Vec<Vec<String>> = Vec::new();
for city in cities.iter() {
routes.append(&mut generate_routes(city.clone(), cities.clone()));
}
let route_lengths = routes.iter().map(|route| {
let mut distance = 0u64;
for idx in 0..(route.len() - 1) {
distance += distances[&route[idx]][&route[idx + 1]];
}
distance
}).collect::<Vec<_>>();
// for (route, length) in routes.iter().zip(route_lengths) {
// println!("route: {route:?}, distance: {length}");
// }
println!("shortest route: {}", route_lengths.iter().min().unwrap());
}

View file

@ -0,0 +1,55 @@
use std::collections::{HashMap, HashSet};
fn generate_routes(current: String, mut destinations: HashSet<String>) -> Vec<Vec<String>> {
destinations.remove(&current);
let mut routes = Vec::new();
if destinations.is_empty() {
routes.push([current].to_vec());
return routes;
}
for destination in destinations.iter() {
routes.append(&mut generate_routes(destination.clone(), destinations.clone()));
}
for route in routes.iter_mut() {
route.push(current.clone());
}
routes
}
pub fn solve(input: &str) {
let mut distances: HashMap<String, HashMap<String, u64>> = HashMap::new();
input.lines().for_each(|line| {
let (from, tail) = line.split_once(" to ").unwrap();
let (to, distance) = tail.split_once(" = ").unwrap();
distances.entry(from.into()).or_default().insert(to.to_string(), distance.parse().unwrap());
distances.entry(to.into()).or_default().insert(from.to_string(), distance.parse().unwrap());
});
let cities = distances.keys().cloned().collect::<HashSet<_>>();
let mut routes: Vec<Vec<String>> = Vec::new();
for city in cities.iter() {
routes.append(&mut generate_routes(city.clone(), cities.clone()));
}
let route_lengths = routes.iter().map(|route| {
let mut distance = 0u64;
for idx in 0..(route.len() - 1) {
distance += distances[&route[idx]][&route[idx + 1]];
}
distance
}).collect::<Vec<_>>();
// for (route, length) in routes.iter().zip(route_lengths) {
// println!("route: {route:?}, distance: {length}");
// }
println!("longest route: {}", route_lengths.iter().max().unwrap());
}

View file

@ -0,0 +1,3 @@
London to Dublin = 464
London to Belfast = 518
Dublin to Belfast = 141

View file

@ -0,0 +1,7 @@
#![allow(dead_code, unused)]
use paste::paste;
mod utility;
solve_day!{9}
// test_day!{9}

View file

@ -0,0 +1,10 @@
use std::fs::read_to_string;
pub fn get_input_string(day: u8) -> String {
read_to_string(format!("src/day{}/input.txt", day)).expect("Failed to read input file.")
}
pub fn get_test_string(day: u8, file: Option<&str>) -> String {
let filename = file.unwrap_or("test.txt");
read_to_string(format!("src/day{}/{}", day, filename)).expect("Failed to read input file.")
}

View file

@ -0,0 +1,6 @@
#![allow(unused)]
mod inputstring;
pub use inputstring::{get_input_string, get_test_string};
mod solveday;

View file

@ -0,0 +1,31 @@
#[macro_export]
macro_rules! solve_day {
($day:literal) => {
paste! {mod [<day $day>];}
pub fn main() {
println!("-- Day {} --", $day);
let input = utility::get_input_string($day);
paste! { [<day $day>] ::part1::solve(&input) };
paste! { [<day $day>] ::part2::solve(&input) };
}
};
($day:literal, $filename:literal) => {
paste! {mod [<day $day>];}
pub fn main() {
println!("-- Day {} --", $day);
let input = utility::get_test_string($day, Some($filename));
paste! { [<day $day>] ::part1::solve(&input) };
println!("\n---\n");
paste! { [<day $day>] ::part2::solve(&input) };
}
};
}
#[macro_export]
macro_rules! test_day {
($day:literal) => {
solve_day!($day, "test.txt");
};
}