switched to workspaces.

This should let me make a cross-day library.
This commit is contained in:
Gabe Venberg 2023-11-19 20:32:41 -06:00
parent 1469c3a32b
commit 242989bb95
57 changed files with 156 additions and 89 deletions

6
days/day01/Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "day01"
authors.workspace = true
description.workspace = true
version.workspace = true
edition.workspace = true

2255
days/day01/src/input.txt Normal file

File diff suppressed because it is too large Load diff

14
days/day01/src/main.rs Normal file
View file

@ -0,0 +1,14 @@
mod parse;
mod part1;
mod part2;
fn main() {
let _input = include_str!("./input.txt");
let _structured_input = parse::parse(_input);
println!("Part One");
println!("Result: {}", part1::part1(&_structured_input));
println!("Part Two");
println!("Result: {}", part2::part2(&_structured_input));
}

48
days/day01/src/parse.rs Normal file
View file

@ -0,0 +1,48 @@
#[derive(Debug, PartialEq, Eq)]
pub struct Elf(pub Vec<usize>);
pub fn parse(input: &str) -> Vec<Elf> {
input
.trim()
.split("\n\n")
.map(|group| {
Elf(group
.split('\n')
.map(|line| line.parse().unwrap())
.collect())
})
.collect::<Vec<Elf>>()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse() {
let input = "1000
2000
3000
4000
5000
6000
7000
8000
9000
10000";
assert_eq!(
parse(input),
vec![
Elf(vec![1000, 2000, 3000]),
Elf(vec![4000]),
Elf(vec![5000, 6000]),
Elf(vec![7000, 8000, 9000]),
Elf(vec![10000])
]
);
}
}

27
days/day01/src/part1.rs Normal file
View file

@ -0,0 +1,27 @@
use crate::parse;
pub fn part1(input: &[parse::Elf]) -> usize {
input
.iter()
.map(|elf| elf.0.iter().sum::<usize>())
.max()
.unwrap()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part1() {
let input = vec![
parse::Elf(vec![1000, 2000, 3000]),
parse::Elf(vec![4000]),
parse::Elf(vec![5000, 6000]),
parse::Elf(vec![7000, 8000, 9000]),
parse::Elf(vec![10000]),
];
assert_eq!(part1(&input), 24000);
}
}

27
days/day01/src/part2.rs Normal file
View file

@ -0,0 +1,27 @@
use crate::parse;
pub fn part2(input: &[parse::Elf]) -> usize {
let mut input = input
.iter()
.map(|elf| elf.0.iter().sum::<usize>())
.collect::<Vec<usize>>();
input.sort_unstable();
input[input.len() - 3..].iter().sum()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part2() {
let input = vec![
parse::Elf(vec![1000, 2000, 3000]),
parse::Elf(vec![4000]),
parse::Elf(vec![5000, 6000]),
parse::Elf(vec![7000, 8000, 9000]),
parse::Elf(vec![10000]),
];
assert_eq!(part2(&input), 45000);
}
}

6
days/day02/Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "day02"
authors.workspace = true
description.workspace = true
version.workspace = true
edition.workspace = true

2500
days/day02/src/input.txt Normal file

File diff suppressed because it is too large Load diff

13
days/day02/src/main.rs Normal file
View file

@ -0,0 +1,13 @@
mod part1;
mod part2;
mod utilities;
fn main() {
let _input = include_str!("./input.txt");
println!("Part One");
println!("Result: {}", part1::part1(_input));
println!("Part Two");
println!("Result: {}", part2::part2(_input));
}

62
days/day02/src/part1.rs Normal file
View file

@ -0,0 +1,62 @@
use crate::utilities::*;
pub fn part1(input: &str) -> usize {
parse(input).iter().map(calc_score).sum()
}
pub fn parse(input: &str) -> Vec<Strategy> {
input
.lines()
.map(|line| {
let elf = match line.as_bytes()[0] {
b'A' => Play::Rock,
b'B' => Play::Paper,
b'C' => Play::Scissors,
_ => panic!("your opponent not playing defined strategy!"),
};
let you = match line.as_bytes()[2] {
b'X' => Play::Rock,
b'Y' => Play::Paper,
b'Z' => Play::Scissors,
_ => panic!("you are not playing defined strategy!"),
};
Strategy { elf, you }
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part1() {
let input = "A Y
B X
C Z";
assert_eq!(part1(input), 15);
}
#[test]
fn test_parse() {
let input = "A Y
B X
C Z";
assert_eq!(
parse(input),
vec![
Strategy {
elf: Play::Rock,
you: Play::Paper
},
Strategy {
elf: Play::Paper,
you: Play::Rock
},
Strategy {
elf: Play::Scissors,
you: Play::Scissors
}
]
);
}
}

87
days/day02/src/part2.rs Normal file
View file

@ -0,0 +1,87 @@
use crate::utilities::*;
pub enum GameResult {
Win,
Loss,
Draw,
}
pub struct ResultStrategy {
pub elf: Play,
pub you: GameResult,
}
pub fn part2(input: &str) -> usize {
parse(input)
.iter()
.map(gen_strategy)
.map(|strat| calc_score(&strat))
.sum()
}
fn gen_strategy(input: &ResultStrategy) -> Strategy {
match input.you {
GameResult::Win => Strategy {
elf: input.elf,
you: gen_win(input.elf),
},
GameResult::Draw => Strategy {
elf: input.elf,
you: input.elf,
},
GameResult::Loss => Strategy {
elf: input.elf,
you: gen_loss(input.elf),
},
}
}
fn gen_win(opponent: Play) -> Play {
match opponent {
Play::Rock => Play::Paper,
Play::Paper => Play::Scissors,
Play::Scissors => Play::Rock,
}
}
fn gen_loss(opponent: Play) -> Play {
match opponent {
Play::Rock => Play::Scissors,
Play::Paper => Play::Rock,
Play::Scissors => Play::Paper,
}
}
pub fn parse(input: &str) -> Vec<ResultStrategy> {
input
.lines()
.map(|line| {
let elf = match line.as_bytes()[0] {
b'A' => Play::Rock,
b'B' => Play::Paper,
b'C' => Play::Scissors,
_ => panic!("your opponent not playing defined strategy!"),
};
let you = match line.as_bytes()[2] {
b'X' => GameResult::Loss,
b'Y' => GameResult::Draw,
b'Z' => GameResult::Win,
_ => panic!("you are not playing defined strategy!"),
};
ResultStrategy { elf, you }
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part2() {
let input = "A Y
B X
C Z";
assert_eq!(part2(input), 12);
}
}

View file

@ -0,0 +1,36 @@
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Play {
Rock = 1,
Paper = 2,
Scissors = 3,
}
#[derive(Debug, PartialEq, Eq)]
pub struct Strategy {
pub elf: Play,
pub you: Play,
}
pub fn calc_score(input: &Strategy) -> usize {
//an enum wins if (you-elf)%3 = 1, looses if it = 2
(match (input.you as i8 - input.elf as i8).rem_euclid(3) {
1 => 6,
2 => 0,
0 => 3,
_ => unreachable!("you were {}, elf was {}", input.you as i8, input.elf as i8),
}) + input.you as usize //play enum has value corresponding to its score.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_calc_score() {
let input = Strategy {
elf: Play::Scissors,
you: Play::Scissors,
};
assert_eq!(calc_score(&input), 6);
}
}

6
days/day03/Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "day03"
authors.workspace = true
description.workspace = true
version.workspace = true
edition.workspace = true

300
days/day03/src/input.txt Normal file
View file

@ -0,0 +1,300 @@
PcPlnShmrLmBnmcwBhrmcmbHNGFGpwdFFwGNjNbGqNHH
tzQfRJfWZZztWzVtCTfRzFZjpFjNZjGLHbdHLDdjpb
CCQTzRLzvQVVfRzJfMPsnBlglgPmBgPmvSrl
RMfvbbszHTsssFPzDQPggpQJPQ
NSNcqVtLVGgDlpQBClVB
hmStGNNLhjNrpWLGSjWrZssbZTMMvTfMnThbRRTs
fTrTPGTbfftWBBmLjrJL
DqHwVMqVplDslmlZmpHVwNnShWZFdBBdjWBtWtdtWJSSLS
MNslpDvVHlwsmpQRgQgCfTTcvcRQ
pBBhRgDsMsswprBhvgRglZtFGFFRqZtZmRtNqtZPPN
TdmmzzmdZdqdGFtF
nmSccCVmSCpDCswMwl
NptqDsQtDTQzCvlzCpRlRp
jmZcndmjbZcjrmDvFMFFlwCvzFnF
jjgLVLrGcdDBNhWQTgHg
mLVhhfSMSTmMwClHGdpjDHjGdV
zPrZgJCgbsnrPtZzsCsbpRDjBRHnjGDRldRHppcG
JJrbsFrZqrgWbbqbrgWzJPNTwhTNCmmvfWCShhhmwwfm
ftgfljvgfgBTNvtggFDDGLGRDnMDzcQzncGt
VdbpbVdZwdwrsVVLRrMrDLDBGnBGcM
wmpWwWsHWBCCCPPvjvmSqlfTTmSNgN
jSqmzmmSSDRjLMLDwqjNcMMLTTflffWCCsRsTHnHVrfHWTsr
tdbgZpgBPdgGZGGFTHVpCsCVfVsJpnWl
FnPQFvbvhFFFbvBwScjhzcqSLLSzSN
bWdgrWwwFWbgzFWzrmNbdPqttChMSRnmqSPSnqtMRM
lcPJLDDPPfpMBCRJBtQtMh
lGDGjTGLLDHPPGjlPTsswsbHNFsNrFNFsrzr
VmtHfVhBLHVtlhphjZMdnQQZZqZmQDdzQQ
CPFwPWrvWgrfNgFPCMqZzMDDbznFTqqzDQ
NNPsfffPCsBLjpVltV
ssdBBJqJhlTJLsjTJqFFmnmmnnrcmpprmmmPcRlf
gqtqzSgWQWqmnRPPcNmmQM
GqbSVtGzvgvgWbZjjBhTdhBsTZBJBZ
jhNBsPDzLjsVhLSNzgvcvbcwbBWFcgtWCc
ZQQTTHHnGpMtnpdHpQJfMgrvWWFqbcWWGgrgwCCwwF
nHpmMnQQMmHpRnHRmMJnnTShPzljzjSNmSDhLsNSPtSh
GdqnBGFdlqzFnwdSCQZjZLLDZjZRvZLDVvgQ
PsptsTcftMfcTfhTghVDvvjnRNjVZnvV
WtPfJTfftJcMTrMnpccFwlCSCGFGCbCwJSbqBl
GjFLGhjRwFjNSjSdJCBBdQJddbBc
MVvMMHRzVtHlvlcQBQJHqdpQqCBC
vDgVztvvmrgrVRrMmsrsmZzZnWhGnNhGWTLfnLwTLhLTjngL
VljjQJSsrjjrCglsCjsgjVVfDLdZGMdvvGdQMzmvzcDQMc
HqPBtcpRWwtHbbFwBHZfmfpDfvffDfMfmGvM
PwHNbcwtqFqnwtNNqPNPPWBTThjhhVTCSJTThssVnSlJJV
GCccNCrrnCrpnzrnCDPcDDrvHHTBqTPhswqhPTBTTwBhTj
VfNmRtZgWWHdBdswdjZv
SmtQfgNmVFgVLVLVmrnMpcDLGCGLGDMpCp
CrdZdZmPPjrQdRPRDqDLBqBLBSWgWgLDzF
sQhTNphsVbhhhMJfhNVGqltVSzSllBzStlzFFFWB
hsMpwQhNMZmPmrwHRj
cNVpSVRpLHRLsVWWfnfsCshW
jvqjTgqZPlJZmbPPfbpswsPb
vlqdTZdtJvqdZjgqZrtRpQFtLFRQczHGzt
JJQndVQnQgTfNvGf
ljpbWbmNbDlGTvggGvZf
mpmRbMmmNDFDmScpzCsdzrnJrsCzrrnM
tNFtNFFzzjjzjBtVNZVbjZGlpSvTllpWwvnBlWGGBGCC
fPdcrrgPHrHMMMWlppGJSPwGSnGv
fmrqrhhfhdRddHrhQqQrfnLZjLtNttZjjRtzjFtRNj
sphRcpQRhfmnmfpptg
WVPlGLlSjCjSlGSHJJWZdmbmfvPmmnftbbgDdt
LJjjqVNjlnCTRcRhhsNcFF
vwwqttFjwgClRNCCvGNmZZMmJsPJjJpTdMpsZd
fBLVHHHrFnhHhnrVSTmfdPdPccTTPsMfsJ
QzVWzznzFbWNGNlt
vjMddVVmnWpdMndjvhhWfNLpfBsfLLZLBBSqqTZq
RFlrzQJPSRGzzzzgBZNsgBZTBflfgf
cQFDRHFDDGCJShCnvwVnnhCn
hgjlpRRLlPJJhTLJMDnwBndSPBNvMqnN
FGWVfZsmCbmVzrvtwCSMtMdnDMCw
VsVmVZfVQDmVFrrmzmGrHHTJgJjhHJcllglLQJRL
rrTVcTBgsjTffmfWHZTv
JLdnDlpGlGSLlpwJpHZfFvRZnWzWrHWqFH
wQDpDrdSlSCblCdwdSLlwQGBthPMsghNsVNVtCNNhNPjhs
CtCMvNhDMHfDDdffqtDtCflpJlBpvmWWJWwlpwFFvjwB
rGSbVGZrSsFJjlmBFZWp
rbbQgzVGrFVSPPGqfhftfqztNtqHtt
lMGZCGphllZDNshNNmHHND
PLwjVwJVsHmRrZZw
ffSdzjfZSjtjSjLtLLFFFGqFzznCpCnCBblQ
CqRnlzHCRWTlHPTZVQrcQtFsQFTcrQ
DfJcdBDBcftQjsrsBtjZ
JDfdGhSvNGhNfffGSfRznPvcRWcqCqmlvlcn
JPhBBBQCnCJCMhnhMZRrRZgbDgrWrNbglDgR
jLtSTwtsShwRNpRWrh
FLLSHsjGLGczvfPfJdfhddnHPC
BjHBNrWmTjFgJngbJhWd
vsGttMDtwCMQCJnqqqFJsggqdg
GFtDSwwMpTrzSSfcfm
rnWDQvpwWpDDcPjFPPHZjVDZ
CTJCRmCJcZZZHCCQ
LdlmdQJNpnLWbrfL
VdTdcVTZwCRGVGGMVmttlF
gnrsbngfgQSpBfpMBBBpSgMNNJbmGmlqGDqDNlFFJlGNFz
gprgQhgpMMMPsrRTCdPZwCwZZCRH
cHlCVGbbWHWqRNThhcNcmh
MwQDzpwdJwpBpPDQvrhShfLTTRLfLdjfNRqS
JwMBBrPsPDwQMDPPBPQJwMrvWHFbHHlgbsGnnWHnFnRGlblF
PQPjPDjRRQSFLSlgSmLlfh
zpLdBddbNCdqGbWJGWpJWWlsFsmmFpwfflFgfHwFhgmh
nJLdLVnzqqbjRctcPDQVTP
JdztScztPdSWLJLtgMbCjhvlbPRbjbMvCh
VZrqfQcFQwGVVFqfrTFTNqhljRHDMvMMGhRDRRHGbDhG
NZQNVQQpQmrZFQQFwQQVVZgBszJJgznstnmtcztdBSgs
nFHLNJzFbLJGGLMlTTRZbZRhWRTr
wVmgBBmtmwlqlWTwTM
sdvmgcPsCPPQQSMz
SccCqmQmgBmppLQmpSMjjlJzzsNPMDRbPNPlJM
VHZvwtZwhZHtdTwrVbNsljlRDlJPDhzsbN
dZwftVRftmcgpBCmBf
NTTlVlgNSflqbphFFhNbFp
wmmLmjwzwbWGLjRmtZZdhZLFtQQLQBFh
RvjbMjjvMzMWbDWwvzPjvmWSfVfsTlVVPVgTgPfVsnnnsJ
BsBsZHZNdWwsNdrzgCrMMqsjzzMC
flfhVWFmLrhQzCCh
fVbmFSpnSSmtnPZvdWbwvdvdHZ
NsZWWWWLsBZPhfsLmPhcFCCHCMMrqfqcvHMfHH
nThSllnplGlMpvFRcCqrrr
DnTwSztgzlDnVGTwztmdZhmLdJdNDshBdsWs
RBBGTFZGglMHvrtcgSdnNgjg
DmVcbmbJmwJDJzVVwzJfmfstnztvjnNjvNSpdptvzCnpjj
DsLcfLmbhVQssQJQscWRPBZZMMRLHFHZBGMG
FVvhVnhFnFhmvFhVcMBHLgcPClrqqrtqCppldrRRTppldg
QLWfDNwsQLtlrrCtDdpq
sJwZwLsGJWGGwzzWZNbWNLjQHSVhvHSnhcMFcbVmnvcchSBS
jTMNMrHBJWWDffRqfDBqfD
QmSFphtQqQmVmqVnPnPlpwgfnRnDPl
VqFmLFbLhmZhGFGmCmGtZLtJWzWHcJrNrHMccjMscMHzMZ
hGPGmbfPzbPfgdMdWGqBGQcqpp
nvFTvDrTdNZZlrjnMHHHpBBcppqq
rNlZZNLvRdRCRFFwZwhgbmSJPSmPfhfwhS
vjdbFWTtFRRvtvZZvdWJWbGjLhCcnrrrNqLNCPqchShNqc
QHQVlDsMfmmDMHDBdLdCSLnhNLNNfqCd
VQHsMDpHlzMBBwlsmMzmmlVwptvTWdvJdbvJtRTWgGFJJGtR
nSScBcnbbFSQVdBFBtWpwtvtPbTZthtTvT
pRzHpGjCDGzHGCGsThqqwZwPhCtvhTqZ
NzlzjDDpNldBFrlfFQ
qJlDlPPWppgppqPlplpfdvgnbMfGbdgCghMdCM
QWTWZcSsWbvVvTnhfC
tRFLwZrcrWzzlJmtBqlm
HMNMvvzzNcmfNmfbhs
qVcwCgjCLtWRSLsTPbmPfmTh
RtWCJgddWRtCJdWWgdBjwWWwpzMFpHGprcBGFFnGHQZHQGpF
gZgBDgDVGDGjmDZRtgjvVvtQdnLrcRcrdfdfCcnlscsJsn
WTqzqHqNzpHpwzNhMHNwWPbQCQcCLsnCrLLfcrffNflcNn
zHTwwpTPzTTwlFTFzwqzPbwZGgGZZBtmGGvGmBGZVFStFZ
znlSSzfzTcmmfcCt
PHWWGpqgPShPMwGwqJFTVtwtCVTCmTJcFc
qHqqSggLrRLBbvDDdndzRQ
WBddBQWZWWQqqQFMWfmrWsJnmVJJNDDVJGsLmHmLDN
PTgCjvCCPPPzSZGJVLsVZCHHnH
pzwtPTvzTjRTPtwSjPSzRgBbWMBfMwwZfbWrMrZFqFFM
BqDwVqdqlDlblQMf
ZcCWWcWzvJZjcPjZZZfTHfQJQHThqpMbQQJf
LPCcZcczZLgCjvPWgvstjsjmRRBdmGrdGdmSFGnFrtGmqr
CBvgQssVzfCBQSgvvvfmrlGrCtMGwthJlJtbrh
TpLqLRFpqdRpRTfNPtRmrMMtMlMMmlMJlt
PZTjqFFTHZZNZpqcVWzVvgzcWnSWfBDD
SVSTpgpVpdNbpcVdfjcNfbcJnqsltcJPvRJqRwQqlQsJls
zhWzDLmFHhmrWZmmzHJJQlnswqsvttrstQqs
zGtZFGGCmZmGGFhLBWBGGFdgVjgppMTSTgMfCNfVVSdj
CzjNJGcnzQJltPHttcPHTP
bLVsqLbLmSSVrqmdhVSmsVFFprfrFWrwTTWWWZpFPtlP
ssDsMqLqhvmvhdmdvzRCnQgRzzBjgnlNCM
TzTLzzSGRlRSjWzlWRzHGTpNhPhJPmdnNPPbhlbPbdhfPh
mBCDBVrCqVQvQMBcVcqBrBDsbtJfnZNbJndNNhthZNJfPZPs
wMCrqVvBzmzHTGLw
NbfwfZPPdVNPdBdQBcmQzrQz
nnWqHLWGFMDFDLDjsqnHLsrQGzmJczmQrgJmJGZmQrgJ
FFWRsHMHCZCWFwRwphpvlfTTpp
PclPlVZvLDNvVZSLSMvvDttmtfzFtzHqtqtzzccCFc
jrggQGhjQsTDbrbJjJQqzzCsdtzzFCdHqmBBHz
WGDgngwrQggZMNvMWPMRRV
wNgpMdMMcdSscccNcLLTbtQJtQJQltJwFtlBlzBt
HHGhrLrCvHWHCPhrWDtnBllnQbfQftGnfnBF
HvLjWCLHPZvHHHZjjrqVTTZVcppMgNNNNSpS
QQrwQmvWQjgTfvBjfffrSDcrqSqDDVLctqqcVd
GnHFnGhGplGMlHMNhzBzlLPLVcVNCPDqVNdcqLdqtV
GnMGpslMhGsRzzHzGsZFZQJTTmWfBbvfgfgJRfbwbW
MRCtSwMhvjCGtvMZDVWpVZJlVccNDlpb
gdLQFFwwLfHJWnQlcJJbWc
rdqdmqHLTLmsswsFHLFtMPRMCSSRtSjTPMPSCR
jmCCnLCLZjZjRjQTLZQhGPGhhzHhDRGRDzwzwh
stlJlrlJJcSSfSMMzPfhhGhzpwhpNwhD
rbrbBcSlWmdZWjDnTm
PNBRNnnqQRNfVfRtVVzgFLLttpSwgzzzmFFF
fcWlcbvvCFzLbwLw
rlrMrhTJhDcTTfhRNqHRQPQRQNQB
TrprpprRVVfpRpVqTVpzDdvmvbbCchhcttqcthSMdd
JlnZnFlsMBZnJHlsLsCLbSNtbNhdbbShCScm
FlZjjsHHsnQFQwTDzMRRpGRR
wHWzwCTTqJhzzvJhWHWhqJWrFsFQrrrFCfFfgjjgjprfsp
DBRmZRtZLbnRBGSBmtGSLpjBrrsfrgsTQVrVrrPrgr
DLnbcbtLtmNNmbRcGbcGmHzlThNNhqJTHdvqvWlHJh
GSNqjRcqflNLnCTTWrWn
BmwQtmtJwPwmzMwQtHtVssvrnpWTTnsTTgpVCLCs
DBBQHJJrzhzQDDfSljRfhccfcdZf
wtgtChCwzqgLzjggqtHtjFHHFcnPfdRDfZZVcPfVZZfGnfdm
vBTrRTTWGGmcTDVD
SJMbbpWslJblSSNzNsztRChzqRCj
gBHHCtVCSHMQlfFTQqCfmq
WrpdwjbwbwQGlPqSqblP
wWDncWrDDNdWNRjScScjpzvHZtBMZtJsvLVgvzssBsvs
VppWpVfmZPBlnmrGBzhttMzMpctLLcChSh
FwgLJvRdHcwMzSzjzc
QvbgdQLQgDvsqvqRHRDdDQDBWmBGBflnVbZmZmmnBBWrmW
SqShwLFCQGpDHCtZCWpW
bdHPHjTbJdsMnPHPbdjgtnBlVlBnVgtZpDBpWV
bdmPcjbjMNMvvHbTcQRNfRwRwLffwwqwNF
zdRHTpQTQHQnpnnQRHTsNNlJSJWmzJmJllNmSG
FBbRvLbFRwLqbbVgBVqqLFqJtJNcltsSGmgmGtNtgWmstm
FLhhfvvVwvjqfLRBqLVqbwqZQrTTpHMHjdrpnnDPDQCdCrpC
JgjzvbJCWgbjgGbJWjRhgNPGHHBMtqBStZZsHMSsBqtD
cfQdwQFdQQppnVVnlFLLBsBZMhqPlPMMqBSHDtHM
wnQhcnVddmdWgjvjmvRjjJ
QpcRtndvsLcVJtRSzWSlWjzSbjjWBv
qGZPqCTmGPqgGTCqHgCqZCPFWbbBNBMNBbdBMlWWrbjlMbFl
qhHDGhCmPhZHgDmDVQthttRchLwLdwcc
srpPMwlMmsrGFGswvDRhRWRDJJJchJ
fSgBbCBNnBTTgCNLTCRJhRJVWhTcVVVFFJdR
SbBnnLNZCLFQCZjnCnZFjPrzqmlMmmsrpzrlsmtt
BBsfDfsBDSWRwlLqmWCpWcllrl
nQMgMnnnhdntgMBrCdpNNLNlNqLqLl
FnQFHzPQJjJGRBGvfR
lRnVRFFlgMCRVwLgFZRnZQHWdcftHdmcJHmmMdzzfz
DGBqGQbhhBDbSBpGDBzqdNHJdtmcWdqdmtcm
bjbsBvjhSlVsPRgLQl
dDLbRdTMRJMbFRzZBfzNSjtNBzBD
PmgspqqVrppTVrvrsPhhfQwZBwNjNtNffzqqfwwN
mCcmsngrPvpVTssCVsvsPLRRJllGFlnRGbMJMWWlJJ
fGlGZHRRbwgPbZRRNCdcSWpncnQtQWlWcWpW
JrTLJgVvVLQQvtSvQncQ
JrrrmMTBVTmjBMrVjrshmJzgCfzRPCRZPGHfbwNPzbZHNH
qqqlDDZzVVnNqHDDFFFNlQpzjrTvsvzTbgJQQggjJp
cWPWcCmMfCMWdtPMhMbQQQjGGjpdvjTbjgjr
WtMSBCtCwchChMfBWtcPnNVNqZZLDRNqTRnnlwHn
mvQQnhBvhmvBmncmZBclTZTQccRFNFFdqFFgVqSRrgFrppNR
MjzJPzGPfffMCjVVjfPHLCFRNFStqrdRSdqdNGRqNptq
HDJHPjDJLfjbzfwPjCzCWWTwlmQhBnsWBvVsvBvZ
RVjcshhscQhrVjhvzjVfDNnzGtftmDHFttFGGf
qLcBCCMBJJbTdBDnNtdfnmDG
WpZgLLclTclRwgjgsrwsvj
shhhltNPcDtlNcNMcsctNtppLZvWWFLTFFZpTZDQgFLT
dRgJVzRHbqnLpTWQvLLJfp
mCVCdzqHndbqHCrVqRrmbwtNBsmPwNmScPgtPhBclw
bDDZMDrFPsrsMcsrbJZJdMMGpSzpSbwRSSRGpCHCGzlhCC
BWWNQjBLQVHhlGpSCmwj
ffwnNwfgtnNgVVwfNWBWnFsMJTJTcPFJcTFDsrJstJ
vQbQLQBpBvbvpHplHNTHWGZDngntZCQGgZhGhtjG
rqccPPmcrffRmsmCjVgnrGChChDjgW
fqRJsJMSlSzSWTbT
brsjjJPJwrJJsrRRlllNQGWQpwppCtfGGtWzGGMQ
ncBqqLTDnmLgVDZVnBDmdtVVtMzWWdMCQdpQWdVz
hDZgTSSnTzNPNFSFPF
VZVJJtWTsfTVVWsJhPWrCjzSBJlHSmjJCRlNSSlz
CqMpwccgvvgLnvLbMMRRjBNHzjmGmwNHlmlN
gLqqvpCDfVDrTfVW
CNMDGNPPNJCGbLnTffsTLT
tcBBRlrBdQrtmtWFjjbnrTjjFbjr
cTQQhcmvcBRcwDMVDZZPPCJh
mBCdgPLgZmLfGmfvGhtRQJWjtjQGQhtN
pMwrVwbwHMsqcTWQhQWzggTTWp
nnSMwrlrsmSZgvvmDd
WNSzpCzNzqzNdmqrRHrrLHFrJH
MtPfvnGMPnMcbnRtDHTRFFDrmJRQ
PcBsfPPHPGGfcSzZjNjpNZZdCs
mDCZVLDhWVSDCRvGtsGgGRHl
JjPwPNdcPnjPdcwNltHzzGmgGJzQJJRQ
dqfjnNmwmbmWrZMbMrThhB
qtBpNZFpBGFNfZNPmZPmQmHrmPPPTz
LLwJLvDvlWWLHdwDrVcCRcDVzzVVcV
sMMwvgjnMvjvnlsvNFBqfGHFqHGjtSpS
MmZZsFgwJTdTMdgmZdZRgFhDHhPQPPnRPhCrHhnnrPDD
fBcLlNNpQCDLDJJC
jSbWWlWpBpclWlWpNWlVBbWVdgwswFJmFJsGtdMggZFGbZwd
CMVQVMLLMFGRCMWQttnqqwQwhqsm
pJzlczSpPpPgmsqNhmPGDstq
gZgTccZGGpzdpjclGRVMVRFRMFvHRLRdLf
FMWMSBtStZqZWQtFtScWWSZmHPVJJVHwwlTgmgbzQwbwTJ
jhGLhdjNjsLvLsshzHJPVdVmmbzHzdHJ
jvDRNjnDNGRCzjLzZZpqnrFBSccWrMcB
zggmthDDghHvtrdgrVWfSBRwTHLWHwsBWw
PGGjpCjQnJQGJcJnnQpjFWVSsZWVLRZLBcsWSZBRWS
FGQlpnJCbqqGGRCjjnlCqGMtdNmmmvdNmmmzvhbrmgMz
TstvBTdgBhqTsdTcPlfCSrNMrNnrCNNSNNgp
HwLQwQDZzDjnDbmMhNSnmm
FZLVzLLQHRRzwWHjdPlJctlJtlsllhRs
fBtPsMDDswHvBmmVdBlSBRcGGnhVhg
LWJbrpFqpTLTTjqqNWlhnRGGSnhrcSdlRlsh
JWNbbpjJzTbNNNJNJMvmvfZHvzDsHDCsZw
LPGnPNLtwGhFFnJPfsqpVVszzpsP
TcWdvlrcWddggrDBDDdDMmWzRJqfVQZqmsfZsRQzZfZzQJ
TldWrMrDdlDCDdMTcwSLVCSShLNSwHjhGF
JGsWWWQsJmPwQWbBPmccbcbqFfMMpFDVCDFVFVCDqqfFwD
ZtLnlvLnNtvLndnCmfMVSmVCClfpVp
zTzZtjnZNLNmZvdtznntHHZJbBRGBRQWcJGbGsbsJRPQWT
MLmlMTPtQtMNlhbqbbqhflBB
rcrvjpSvScbRbBvbDBPG
ZZJzSHpzPrJzHFmMVMFmHCLNtV

14
days/day03/src/main.rs Normal file
View file

@ -0,0 +1,14 @@
mod part1;
mod part2;
mod utilities;
fn main() {
let _input = include_str!("./input.txt");
let _structured_input = utilities::parse(_input);
println!("Part One");
println!("Result: {}", part1::part1(&_structured_input));
println!("Part Two");
println!("Result: {}", part2::part2(&_structured_input));
}

54
days/day03/src/part1.rs Normal file
View file

@ -0,0 +1,54 @@
use crate::utilities::*;
pub fn part1(input: &[Rucksack]) -> usize {
input
.iter()
.map(|rucksack| rucksack.0.intersection(&rucksack.1).next().unwrap())
.map(find_char_score)
.sum()
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashSet;
#[test]
fn test_part1() {
let input = vec![
Rucksack(
HashSet::from(['v', 'J', 'r', 'w', 'p', 'W', 't', 'w', 'J', 'g', 'W', 'r']),
HashSet::from(['h', 'c', 's', 'F', 'M', 'M', 'f', 'F', 'F', 'h', 'F', 'p']),
),
Rucksack(
HashSet::from([
'j', 'q', 'H', 'R', 'N', 'q', 'R', 'j', 'q', 'z', 'j', 'G', 'D', 'L', 'G', 'L',
]),
HashSet::from([
'r', 's', 'F', 'M', 'f', 'F', 'Z', 'S', 'r', 'L', 'r', 'F', 'Z', 's', 'S', 'L',
]),
),
Rucksack(
HashSet::from(['P', 'm', 'm', 'd', 'z', 'q', 'P', 'r', 'V']),
HashSet::from(['v', 'P', 'w', 'w', 'T', 'W', 'B', 'w', 'g']),
),
Rucksack(
HashSet::from([
'w', 'M', 'q', 'v', 'L', 'M', 'Z', 'H', 'h', 'H', 'M', 'v', 'w', 'L', 'H',
]),
HashSet::from([
'j', 'b', 'v', 'c', 'j', 'n', 'n', 'S', 'B', 'n', 'v', 'T', 'Q', 'F', 'n',
]),
),
Rucksack(
HashSet::from(['t', 't', 'g', 'J', 't', 'R', 'G', 'J']),
HashSet::from(['Q', 'c', 't', 'T', 'Z', 't', 'Z', 'T']),
),
Rucksack(
HashSet::from(['C', 'r', 'Z', 's', 'J', 's', 'P', 'P', 'Z', 's', 'G', 'z']),
HashSet::from(['w', 'w', 's', 'L', 'w', 'L', 'm', 'p', 'w', 'M', 'D', 'w']),
),
];
assert_eq!(part1(&input), 157);
}
}

78
days/day03/src/part2.rs Normal file
View file

@ -0,0 +1,78 @@
use crate::utilities::*;
use std::collections::HashSet;
struct Group(HashSet<char>, HashSet<char>, HashSet<char>);
pub fn part2(input: &[Rucksack]) -> usize {
seperate_groups(input)
.iter()
.map(|group| {
//manual implementation of intersection because doing chained intersections is annoying...
group
.0
.iter()
.filter(|c| group.1.contains(c))
.filter(|c| group.2.contains(c))
.next()
.unwrap()
})
.map(find_char_score)
.sum()
}
fn seperate_groups(input: &[Rucksack]) -> Vec<Group> {
let mut output: Vec<Group> = Vec::new();
for group in input.chunks_exact(3) {
output.push(Group(
group[0].0.union(&group[0].1).copied().collect(),
group[1].0.union(&group[1].1).copied().collect(),
group[2].0.union(&group[2].1).copied().collect(),
));
}
output
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashSet;
#[test]
fn test_part2() {
let input = vec![
Rucksack(
HashSet::from(['v', 'J', 'r', 'w', 'p', 'W', 't', 'w', 'J', 'g', 'W', 'r']),
HashSet::from(['h', 'c', 's', 'F', 'M', 'M', 'f', 'F', 'F', 'h', 'F', 'p']),
),
Rucksack(
HashSet::from([
'j', 'q', 'H', 'R', 'N', 'q', 'R', 'j', 'q', 'z', 'j', 'G', 'D', 'L', 'G', 'L',
]),
HashSet::from([
'r', 's', 'F', 'M', 'f', 'F', 'Z', 'S', 'r', 'L', 'r', 'F', 'Z', 's', 'S', 'L',
]),
),
Rucksack(
HashSet::from(['P', 'm', 'm', 'd', 'z', 'q', 'P', 'r', 'V']),
HashSet::from(['v', 'P', 'w', 'w', 'T', 'W', 'B', 'w', 'g']),
),
Rucksack(
HashSet::from([
'w', 'M', 'q', 'v', 'L', 'M', 'Z', 'H', 'h', 'H', 'M', 'v', 'w', 'L', 'H',
]),
HashSet::from([
'j', 'b', 'v', 'c', 'j', 'n', 'n', 'S', 'B', 'n', 'v', 'T', 'Q', 'F', 'n',
]),
),
Rucksack(
HashSet::from(['t', 't', 'g', 'J', 't', 'R', 'G', 'J']),
HashSet::from(['Q', 'c', 't', 'T', 'Z', 't', 'Z', 'T']),
),
Rucksack(
HashSet::from(['C', 'r', 'Z', 's', 'J', 's', 'P', 'P', 'Z', 's', 'G', 'z']),
HashSet::from(['w', 'w', 's', 'L', 'w', 'L', 'm', 'p', 'w', 'M', 'D', 'w']),
),
];
assert_eq!(part2(&input), 70);
}
}

View file

@ -0,0 +1,93 @@
use std::collections::HashSet;
#[derive(Debug, PartialEq, Eq)]
pub struct Rucksack(pub HashSet<char>, pub HashSet<char>);
pub fn parse(input: &str) -> Vec<Rucksack> {
input
.lines()
.map(|line| {
let (first, second) = line.split_at(line.len() / 2);
Rucksack(first.chars().collect(), second.chars().collect())
})
.collect()
}
pub fn find_char_score(input: &char) -> usize {
if input.is_uppercase() {
*input as usize - 38
} else {
*input as usize - 96
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_find_char_score() {
static CHARS: [char; 52] = [
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
'Z',
];
for character in CHARS {
println!("{}", character);
assert_eq!(
find_char_score(&character),
CHARS.iter().position(|c| *c == character).unwrap() + 1
)
}
}
#[test]
fn test_parse() {
let input = "vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw";
assert_eq!(
parse(input),
vec![
Rucksack(
HashSet::from(['v', 'J', 'r', 'w', 'p', 'W', 't', 'w', 'J', 'g', 'W', 'r']),
HashSet::from(['h', 'c', 's', 'F', 'M', 'M', 'f', 'F', 'F', 'h', 'F', 'p'])
),
Rucksack(
HashSet::from([
'j', 'q', 'H', 'R', 'N', 'q', 'R', 'j', 'q', 'z', 'j', 'G', 'D', 'L', 'G',
'L'
]),
HashSet::from([
'r', 's', 'F', 'M', 'f', 'F', 'Z', 'S', 'r', 'L', 'r', 'F', 'Z', 's', 'S',
'L'
])
),
Rucksack(
HashSet::from(['P', 'm', 'm', 'd', 'z', 'q', 'P', 'r', 'V']),
HashSet::from(['v', 'P', 'w', 'w', 'T', 'W', 'B', 'w', 'g'])
),
Rucksack(
HashSet::from([
'w', 'M', 'q', 'v', 'L', 'M', 'Z', 'H', 'h', 'H', 'M', 'v', 'w', 'L', 'H',
]),
HashSet::from([
'j', 'b', 'v', 'c', 'j', 'n', 'n', 'S', 'B', 'n', 'v', 'T', 'Q', 'F', 'n',
])
),
Rucksack(
HashSet::from(['t', 't', 'g', 'J', 't', 'R', 'G', 'J',]),
HashSet::from(['Q', 'c', 't', 'T', 'Z', 't', 'Z', 'T',])
),
Rucksack(
HashSet::from(['C', 'r', 'Z', 's', 'J', 's', 'P', 'P', 'Z', 's', 'G', 'z',]),
HashSet::from(['w', 'w', 's', 'L', 'w', 'L', 'm', 'p', 'w', 'M', 'D', 'w',])
),
]
);
}
}

10
days/day04/Cargo.toml Normal file
View file

@ -0,0 +1,10 @@
[package]
name = "day04"
authors.workspace = true
description.workspace = true
version.workspace = true
edition.workspace = true
[dependencies]
once_cell.workspace = true
regex.workspace = true

1000
days/day04/src/input.txt Normal file

File diff suppressed because it is too large Load diff

14
days/day04/src/main.rs Normal file
View file

@ -0,0 +1,14 @@
mod part1;
mod part2;
mod utilities;
fn main() {
let _input = include_str!("./input.txt");
let _structured_input = utilities::parse(_input);
println!("Part One");
println!("Result: {}", part1::part1(&_structured_input));
println!("Part Two");
println!("Result: {}", part2::part2(&_structured_input));
}

27
days/day04/src/part1.rs Normal file
View file

@ -0,0 +1,27 @@
use crate::utilities::*;
pub fn part1(input: &[(Range, Range)]) -> usize {
input
.iter()
.filter(|tuple| tuple.0.complete_overlap(&tuple.1))
.count()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part1() {
let input = vec![
(Range::new(2, 4), Range::new(6, 8)),
(Range::new(2, 3), Range::new(4, 5)),
(Range::new(5, 7), Range::new(7, 9)),
(Range::new(2, 8), Range::new(3, 7)),
(Range::new(6, 6), Range::new(4, 6)),
(Range::new(2, 6), Range::new(4, 8)),
(Range::new(19, 30), Range::new(5, 18)),
];
assert_eq!(part1(&input), 2);
}
}

27
days/day04/src/part2.rs Normal file
View file

@ -0,0 +1,27 @@
use crate::utilities::*;
pub fn part2(input: &[(Range, Range)]) -> usize {
input
.iter()
.filter(|tuple| tuple.0.any_overlap(&tuple.1))
.count()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part2() {
let input = vec![
(Range::new(2, 4), Range::new(6, 8)),
(Range::new(2, 3), Range::new(4, 5)),
(Range::new(5, 7), Range::new(7, 9)),
(Range::new(2, 8), Range::new(3, 7)),
(Range::new(6, 6), Range::new(4, 6)),
(Range::new(2, 6), Range::new(4, 8)),
(Range::new(19, 30), Range::new(5, 18)),
];
assert_eq!(part2(&input), 4);
}
}

View file

@ -0,0 +1,79 @@
use once_cell::sync::Lazy;
use regex::Regex;
#[derive(Debug, PartialEq, Eq)]
pub struct Range {
start: u16,
end: u16,
}
impl Range {
pub fn new(start: u16, end: u16) -> Self {
Self {
start: start.min(end),
end: end.max(start),
}
}
pub fn any_overlap(&self, other: &Self) -> bool {
self.start <= other.end && self.end >= other.start
}
pub fn calc_overlap(&self, other: &Self) -> Range {
let overlap_start = self.start.min(other.start);
let overlap_end = self.end.max(other.end);
Range::new(overlap_start, overlap_end)
}
pub fn complete_overlap(&self, other: &Self) -> bool {
self.calc_overlap(other) == *self || self.calc_overlap(other) == *other
}
}
static PARSE_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"^(\d+)-(\d+),(\d+)-(\d+)").unwrap());
pub fn parse(input: &str) -> Vec<(Range, Range)> {
input
.lines()
.map(|line| {
let cap = PARSE_REGEX.captures(line).unwrap();
(
Range::new(
cap.get(1).unwrap().as_str().parse().unwrap(),
cap.get(2).unwrap().as_str().parse().unwrap(),
),
Range::new(
cap.get(3).unwrap().as_str().parse().unwrap(),
cap.get(4).unwrap().as_str().parse().unwrap(),
),
)
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse() {
let input = "2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8
19-30,5-18";
assert_eq!(
parse(input),
vec![
(Range::new(2, 4), Range::new(6, 8)),
(Range::new(2, 3), Range::new(4, 5)),
(Range::new(5, 7), Range::new(7, 9)),
(Range::new(2, 8), Range::new(3, 7)),
(Range::new(6, 6), Range::new(4, 6)),
(Range::new(2, 6), Range::new(4, 8)),
(Range::new(19, 30), Range::new(5, 18)),
]
);
}
}

10
days/day05/Cargo.toml Normal file
View file

@ -0,0 +1,10 @@
[package]
name = "day05"
authors.workspace = true
description.workspace = true
version.workspace = true
edition.workspace = true
[dependencies]
once_cell.workspace = true
regex.workspace = true

514
days/day05/src/input.txt Normal file
View file

@ -0,0 +1,514 @@
[S] [C] [Z]
[F] [J] [P] [T] [N]
[G] [H] [G] [Q] [G] [D]
[V] [V] [D] [G] [F] [D] [V]
[R] [B] [F] [N] [N] [Q] [L] [S]
[J] [M] [M] [P] [H] [V] [B] [B] [D]
[L] [P] [H] [D] [L] [F] [D] [J] [L]
[D] [T] [V] [M] [J] [N] [F] [M] [G]
1 2 3 4 5 6 7 8 9
move 3 from 4 to 6
move 1 from 5 to 8
move 3 from 7 to 3
move 4 from 5 to 7
move 1 from 7 to 8
move 3 from 9 to 4
move 2 from 8 to 2
move 4 from 4 to 5
move 2 from 5 to 1
move 2 from 5 to 6
move 7 from 8 to 1
move 9 from 3 to 9
move 11 from 6 to 5
move 2 from 6 to 7
move 12 from 1 to 4
move 10 from 2 to 9
move 2 from 3 to 9
move 1 from 7 to 5
move 4 from 7 to 6
move 2 from 6 to 1
move 5 from 1 to 6
move 10 from 9 to 1
move 9 from 9 to 8
move 13 from 4 to 3
move 7 from 6 to 2
move 2 from 8 to 5
move 9 from 3 to 9
move 8 from 9 to 8
move 4 from 8 to 4
move 1 from 7 to 5
move 3 from 9 to 1
move 7 from 2 to 1
move 1 from 3 to 1
move 1 from 3 to 6
move 1 from 6 to 1
move 2 from 3 to 6
move 5 from 4 to 1
move 1 from 6 to 1
move 3 from 8 to 7
move 8 from 8 to 4
move 3 from 5 to 4
move 1 from 6 to 7
move 1 from 5 to 8
move 4 from 5 to 2
move 7 from 5 to 8
move 3 from 2 to 7
move 7 from 4 to 8
move 11 from 8 to 4
move 15 from 4 to 1
move 25 from 1 to 6
move 4 from 8 to 7
move 1 from 2 to 4
move 11 from 6 to 4
move 12 from 6 to 3
move 1 from 1 to 9
move 1 from 9 to 8
move 16 from 1 to 3
move 1 from 8 to 7
move 12 from 4 to 6
move 9 from 6 to 5
move 3 from 6 to 5
move 6 from 7 to 5
move 3 from 3 to 5
move 2 from 6 to 3
move 11 from 5 to 8
move 2 from 8 to 3
move 2 from 1 to 4
move 7 from 3 to 1
move 2 from 4 to 6
move 2 from 6 to 2
move 5 from 7 to 3
move 1 from 1 to 6
move 1 from 1 to 8
move 2 from 2 to 5
move 1 from 7 to 4
move 1 from 1 to 2
move 10 from 3 to 5
move 11 from 3 to 6
move 1 from 4 to 9
move 1 from 9 to 4
move 1 from 4 to 2
move 2 from 5 to 9
move 2 from 2 to 8
move 2 from 1 to 6
move 2 from 1 to 2
move 2 from 3 to 6
move 3 from 8 to 1
move 3 from 1 to 4
move 7 from 8 to 3
move 2 from 9 to 5
move 2 from 4 to 9
move 7 from 5 to 6
move 2 from 8 to 6
move 1 from 4 to 8
move 2 from 2 to 4
move 21 from 6 to 3
move 10 from 5 to 7
move 7 from 7 to 6
move 1 from 9 to 3
move 1 from 4 to 9
move 1 from 9 to 4
move 1 from 8 to 4
move 8 from 6 to 4
move 1 from 4 to 5
move 1 from 5 to 8
move 4 from 3 to 6
move 1 from 8 to 2
move 1 from 4 to 2
move 2 from 7 to 3
move 2 from 2 to 7
move 22 from 3 to 5
move 4 from 6 to 2
move 2 from 6 to 9
move 7 from 3 to 9
move 6 from 9 to 1
move 18 from 5 to 3
move 2 from 5 to 4
move 20 from 3 to 5
move 3 from 7 to 3
move 5 from 1 to 2
move 11 from 5 to 7
move 1 from 1 to 7
move 3 from 9 to 3
move 16 from 5 to 8
move 7 from 8 to 7
move 1 from 9 to 2
move 8 from 2 to 3
move 2 from 2 to 4
move 3 from 3 to 1
move 9 from 3 to 8
move 1 from 6 to 3
move 9 from 7 to 3
move 3 from 1 to 8
move 1 from 7 to 9
move 1 from 9 to 4
move 1 from 7 to 5
move 10 from 4 to 5
move 2 from 4 to 2
move 19 from 8 to 5
move 1 from 8 to 3
move 4 from 3 to 5
move 2 from 4 to 8
move 4 from 7 to 8
move 4 from 3 to 9
move 4 from 7 to 6
move 2 from 2 to 5
move 2 from 3 to 2
move 6 from 8 to 7
move 1 from 8 to 4
move 2 from 6 to 4
move 3 from 4 to 8
move 3 from 9 to 2
move 4 from 7 to 8
move 28 from 5 to 8
move 16 from 8 to 4
move 11 from 8 to 4
move 3 from 3 to 4
move 7 from 5 to 8
move 13 from 8 to 7
move 1 from 5 to 6
move 1 from 6 to 7
move 1 from 9 to 2
move 2 from 6 to 2
move 12 from 4 to 9
move 4 from 4 to 1
move 2 from 9 to 8
move 4 from 8 to 3
move 3 from 4 to 5
move 4 from 4 to 1
move 4 from 4 to 7
move 3 from 7 to 9
move 5 from 9 to 7
move 7 from 2 to 3
move 1 from 5 to 7
move 8 from 1 to 5
move 1 from 2 to 4
move 11 from 3 to 1
move 10 from 5 to 3
move 3 from 9 to 1
move 3 from 9 to 6
move 5 from 1 to 6
move 7 from 6 to 9
move 8 from 9 to 7
move 9 from 3 to 4
move 1 from 6 to 9
move 8 from 7 to 1
move 9 from 4 to 2
move 2 from 1 to 6
move 3 from 2 to 6
move 4 from 4 to 6
move 2 from 9 to 8
move 2 from 1 to 2
move 1 from 3 to 8
move 2 from 8 to 4
move 1 from 6 to 8
move 11 from 1 to 6
move 1 from 1 to 5
move 3 from 2 to 9
move 2 from 9 to 3
move 1 from 1 to 7
move 2 from 4 to 9
move 4 from 2 to 9
move 2 from 8 to 5
move 10 from 6 to 1
move 2 from 5 to 6
move 5 from 9 to 8
move 5 from 8 to 7
move 1 from 2 to 1
move 7 from 1 to 2
move 2 from 9 to 4
move 1 from 3 to 5
move 15 from 7 to 2
move 8 from 6 to 3
move 2 from 4 to 3
move 2 from 6 to 4
move 4 from 7 to 1
move 4 from 7 to 5
move 1 from 6 to 4
move 3 from 1 to 7
move 5 from 7 to 6
move 4 from 7 to 5
move 18 from 2 to 4
move 5 from 6 to 4
move 4 from 1 to 2
move 8 from 3 to 8
move 2 from 8 to 4
move 2 from 3 to 7
move 1 from 5 to 7
move 3 from 8 to 4
move 2 from 7 to 2
move 1 from 3 to 8
move 9 from 2 to 6
move 2 from 8 to 6
move 1 from 7 to 3
move 1 from 3 to 5
move 3 from 6 to 8
move 1 from 8 to 5
move 1 from 5 to 9
move 1 from 1 to 2
move 5 from 4 to 6
move 10 from 6 to 2
move 5 from 2 to 6
move 5 from 6 to 4
move 1 from 6 to 3
move 6 from 4 to 6
move 3 from 2 to 6
move 2 from 2 to 3
move 11 from 4 to 6
move 1 from 9 to 5
move 4 from 6 to 7
move 1 from 4 to 3
move 12 from 4 to 3
move 1 from 8 to 6
move 9 from 5 to 7
move 1 from 5 to 2
move 1 from 8 to 5
move 1 from 4 to 9
move 9 from 7 to 9
move 1 from 3 to 4
move 2 from 3 to 6
move 2 from 5 to 6
move 2 from 8 to 5
move 11 from 3 to 4
move 2 from 3 to 1
move 1 from 2 to 3
move 1 from 3 to 8
move 3 from 7 to 9
move 5 from 4 to 2
move 2 from 5 to 8
move 6 from 4 to 2
move 1 from 1 to 3
move 12 from 9 to 1
move 6 from 1 to 6
move 1 from 8 to 4
move 1 from 8 to 3
move 5 from 2 to 7
move 2 from 3 to 9
move 5 from 7 to 1
move 1 from 7 to 5
move 2 from 9 to 1
move 14 from 1 to 7
move 2 from 4 to 7
move 7 from 2 to 4
move 1 from 2 to 1
move 1 from 1 to 3
move 1 from 5 to 4
move 1 from 9 to 6
move 16 from 6 to 5
move 2 from 5 to 4
move 12 from 6 to 8
move 10 from 4 to 8
move 9 from 7 to 3
move 4 from 7 to 6
move 11 from 5 to 8
move 2 from 5 to 2
move 14 from 8 to 9
move 1 from 5 to 1
move 3 from 9 to 4
move 2 from 2 to 1
move 7 from 8 to 3
move 6 from 3 to 5
move 8 from 9 to 8
move 1 from 6 to 1
move 1 from 4 to 2
move 4 from 3 to 8
move 1 from 7 to 2
move 3 from 1 to 5
move 2 from 5 to 7
move 3 from 9 to 2
move 1 from 1 to 8
move 5 from 5 to 4
move 2 from 7 to 8
move 4 from 2 to 5
move 1 from 2 to 4
move 2 from 7 to 8
move 4 from 6 to 2
move 6 from 5 to 3
move 1 from 6 to 5
move 1 from 5 to 3
move 1 from 3 to 8
move 8 from 8 to 3
move 9 from 8 to 5
move 9 from 8 to 2
move 2 from 8 to 9
move 2 from 3 to 8
move 5 from 5 to 8
move 1 from 3 to 7
move 2 from 9 to 5
move 7 from 2 to 4
move 14 from 4 to 6
move 2 from 2 to 7
move 1 from 7 to 3
move 1 from 7 to 9
move 3 from 5 to 2
move 1 from 7 to 1
move 3 from 2 to 4
move 7 from 8 to 2
move 3 from 6 to 1
move 17 from 3 to 1
move 2 from 8 to 3
move 6 from 2 to 7
move 2 from 7 to 9
move 3 from 6 to 8
move 2 from 8 to 6
move 4 from 2 to 1
move 3 from 4 to 7
move 1 from 8 to 7
move 1 from 8 to 9
move 1 from 4 to 2
move 3 from 5 to 7
move 2 from 3 to 1
move 2 from 3 to 5
move 5 from 7 to 4
move 5 from 7 to 3
move 1 from 4 to 8
move 3 from 3 to 1
move 6 from 1 to 3
move 1 from 7 to 5
move 2 from 9 to 2
move 3 from 5 to 8
move 1 from 8 to 1
move 8 from 3 to 5
move 1 from 4 to 9
move 3 from 6 to 5
move 3 from 6 to 3
move 2 from 3 to 7
move 1 from 4 to 7
move 3 from 6 to 4
move 2 from 7 to 2
move 1 from 7 to 8
move 2 from 5 to 4
move 1 from 6 to 1
move 7 from 4 to 7
move 7 from 5 to 2
move 10 from 2 to 3
move 3 from 2 to 6
move 3 from 8 to 1
move 1 from 8 to 7
move 2 from 6 to 3
move 1 from 6 to 9
move 4 from 7 to 5
move 16 from 1 to 5
move 1 from 9 to 7
move 3 from 7 to 6
move 11 from 5 to 6
move 2 from 7 to 9
move 12 from 6 to 4
move 2 from 6 to 9
move 6 from 3 to 2
move 1 from 5 to 7
move 5 from 9 to 5
move 1 from 9 to 6
move 4 from 3 to 7
move 1 from 4 to 2
move 7 from 2 to 5
move 3 from 5 to 2
move 6 from 5 to 6
move 3 from 2 to 6
move 9 from 6 to 8
move 5 from 5 to 9
move 5 from 7 to 1
move 4 from 1 to 9
move 2 from 9 to 4
move 1 from 6 to 7
move 9 from 4 to 1
move 7 from 5 to 9
move 18 from 1 to 3
move 9 from 9 to 5
move 8 from 8 to 2
move 1 from 2 to 5
move 4 from 2 to 3
move 4 from 9 to 6
move 1 from 4 to 8
move 2 from 5 to 7
move 2 from 9 to 2
move 10 from 3 to 9
move 5 from 5 to 9
move 1 from 7 to 2
move 2 from 8 to 7
move 2 from 3 to 5
move 2 from 9 to 1
move 2 from 7 to 3
move 1 from 2 to 1
move 5 from 5 to 8
move 1 from 2 to 1
move 15 from 3 to 6
move 1 from 7 to 6
move 10 from 6 to 5
move 1 from 7 to 8
move 4 from 1 to 6
move 1 from 8 to 3
move 2 from 1 to 5
move 3 from 8 to 1
move 1 from 4 to 6
move 1 from 4 to 2
move 4 from 9 to 7
move 6 from 5 to 7
move 3 from 1 to 9
move 10 from 6 to 8
move 2 from 1 to 3
move 8 from 7 to 9
move 1 from 9 to 6
move 2 from 7 to 9
move 3 from 3 to 5
move 1 from 2 to 6
move 2 from 6 to 5
move 5 from 9 to 4
move 4 from 8 to 2
move 1 from 1 to 3
move 4 from 5 to 9
move 3 from 6 to 1
move 2 from 1 to 5
move 3 from 5 to 2
move 8 from 8 to 3
move 11 from 9 to 4
move 13 from 4 to 8
move 2 from 9 to 2
move 2 from 3 to 1
move 1 from 4 to 1
move 1 from 3 to 8
move 2 from 6 to 9
move 7 from 8 to 1
move 3 from 2 to 5
move 7 from 2 to 5
move 3 from 4 to 6
move 4 from 9 to 2
move 2 from 3 to 5
move 9 from 5 to 6
move 5 from 2 to 7
move 2 from 9 to 2
move 2 from 9 to 7
move 12 from 6 to 8
move 5 from 5 to 7
move 1 from 9 to 8
move 3 from 1 to 6
move 5 from 5 to 8
move 6 from 1 to 9
move 2 from 1 to 5
move 1 from 6 to 9
move 5 from 9 to 7
move 2 from 5 to 8
move 11 from 7 to 6
move 20 from 8 to 1
move 2 from 9 to 8
move 4 from 7 to 6
move 6 from 8 to 3
move 13 from 6 to 9
move 4 from 3 to 2
move 4 from 6 to 3
move 2 from 3 to 6
move 5 from 9 to 8
move 2 from 7 to 1
move 2 from 6 to 9
move 6 from 8 to 3
move 6 from 3 to 6
move 5 from 2 to 9
move 22 from 1 to 3
move 3 from 2 to 1
move 5 from 9 to 3
move 1 from 1 to 6
move 3 from 6 to 2
move 1 from 2 to 4
move 33 from 3 to 5
move 1 from 8 to 7

14
days/day05/src/main.rs Normal file
View file

@ -0,0 +1,14 @@
mod part1;
mod part2;
mod utilities;
fn main() {
let _input = include_str!("./input.txt");
let _structured_input = utilities::parse(_input);
println!("Part One");
println!("Result: {:?}", part1::part1(&_structured_input));
println!("Part Two");
println!("Result: {:?}", part2::part2(&_structured_input));
}

48
days/day05/src/part1.rs Normal file
View file

@ -0,0 +1,48 @@
use crate::utilities::*;
pub fn part1(input: &(WorkArea, Vec<Move>)) -> Vec<char> {
let (mut work_area, moves) = input.to_owned();
for r#move in moves {
work_area.apply_move_cratemover9000(&r#move)
}
work_area
.get_stacks()
.iter()
.map(|stack| stack.last().unwrap().to_owned())
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part1() {
let input = (
WorkArea::new(vec![vec!['Z', 'N'], vec!['M', 'C', 'D'], vec!['P']]),
vec![
Move {
to: 1,
from: 2,
number: 1,
},
Move {
to: 3,
from: 1,
number: 3,
},
Move {
to: 1,
from: 2,
number: 2,
},
Move {
to: 2,
from: 1,
number: 1,
},
],
);
assert_eq!(part1(&input), vec!['C', 'M', 'Z']);
}
}

48
days/day05/src/part2.rs Normal file
View file

@ -0,0 +1,48 @@
use crate::utilities::*;
pub fn part2(input: &(WorkArea, Vec<Move>)) -> Vec<char> {
let (mut work_area, moves) = input.to_owned();
for r#move in moves {
work_area.apply_move_cratemover9001(&r#move)
}
work_area
.get_stacks()
.iter()
.map(|stack| stack.last().unwrap().to_owned())
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part2() {
let input = (
WorkArea::new(vec![vec!['Z', 'N'], vec!['M', 'C', 'D'], vec!['P']]),
vec![
Move {
to: 1,
from: 2,
number: 1,
},
Move {
to: 3,
from: 1,
number: 3,
},
Move {
to: 1,
from: 2,
number: 2,
},
Move {
to: 2,
from: 1,
number: 1,
},
],
);
assert_eq!(part2(&input), vec!['M', 'C', 'D']);
}
}

144
days/day05/src/utilities.rs Normal file
View file

@ -0,0 +1,144 @@
use once_cell::sync::Lazy;
use regex::Regex;
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Move {
pub to: usize,
pub from: usize,
pub number: u8,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct WorkArea {
stacks: Vec<Vec<char>>,
}
impl WorkArea {
pub fn new(stacks: Vec<Vec<char>>) -> Self {
Self { stacks }
}
pub fn apply_move_cratemover9000(&mut self, action: &Move) {
for _ in 0..action.number {
let cargo = self.stacks.get_mut(action.from - 1).unwrap().pop().unwrap();
self.stacks.get_mut(action.to - 1).unwrap().push(cargo);
}
}
pub fn apply_move_cratemover9001(&mut self, action: &Move) {
let mut crane_holder: Vec<char> = Vec::new();
for _ in 0..action.number {
let cargo = self.stacks.get_mut(action.from - 1).unwrap().pop().unwrap();
crane_holder.push(cargo);
}
for cargo in crane_holder.iter().rev() {
self.stacks.get_mut(action.to - 1).unwrap().push(*cargo);
}
}
pub fn get_stacks(&self) -> &Vec<Vec<char>> {
&self.stacks
}
}
pub fn parse(input: &str) -> (WorkArea, Vec<Move>) {
let mut input = input.split("\n\n");
let work_area = parse_work_area(input.next().unwrap());
let moves = parse_moves(input.next().unwrap());
(work_area, moves)
}
pub fn parse_work_area(input: &str) -> WorkArea {
//decode those bottom index numbers
let index_row = input.lines().rev().next().unwrap();
//some ascii math and array math to get the second to last char and convert it into a number.
let index_max: usize = (index_row.as_bytes()[index_row.len() - 2] - b'0') as usize;
//initalize the work area:
let mut work_area: Vec<Vec<char>> = Vec::new();
for _ in 0..index_max {
work_area.push(Vec::new())
}
//now parse the rest
for line in input.lines().rev() {
for (y, cargo_crate) in line.as_bytes().chunks(4).enumerate() {
let cargo = cargo_crate[1] as char;
//easiest way to filter out that last line is just to filter out digits.
if cargo != ' ' && !cargo.is_ascii_digit() {
work_area.get_mut(y).unwrap().push(cargo)
}
}
}
WorkArea::new(work_area)
}
pub fn parse_moves(input: &str) -> Vec<Move> {
static PARSE_MOVES_REGEX: Lazy<Regex> =
Lazy::new(|| Regex::new(r"^move (\d+) from (\d+) to (\d+)$").unwrap());
input
.lines()
.map(|line| {
let cap = PARSE_MOVES_REGEX.captures(line).unwrap();
Move {
to: cap.get(3).unwrap().as_str().parse().unwrap(),
from: cap.get(2).unwrap().as_str().parse().unwrap(),
number: cap.get(1).unwrap().as_str().parse().unwrap(),
}
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_work_area() {
let input = " [D]
[N] [C]
[Z] [M] [P]
1 2 3 ";
assert_eq!(
parse_work_area(input),
WorkArea::new(vec![vec!['Z', 'N'], vec!['M', 'C', 'D'], vec!['P'],],)
)
}
#[test]
fn test_parse() {
let input = " [D]
[N] [C]
[Z] [M] [P]
1 2 3
move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2";
assert_eq!(
parse(input),
(
WorkArea::new(vec![vec!['Z', 'N'], vec!['M', 'C', 'D'], vec!['P'],],),
vec![
Move {
to: 1,
from: 2,
number: 1
},
Move {
to: 3,
from: 1,
number: 3
},
Move {
to: 1,
from: 2,
number: 2
},
Move {
to: 2,
from: 1,
number: 1
},
]
)
);
}
}

6
days/day06/Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "day06"
authors.workspace = true
description.workspace = true
version.workspace = true
edition.workspace = true

1
days/day06/src/input.txt Normal file
View file

@ -0,0 +1 @@
bhzhtzzsczszsjjjzddfzdfzfjfzfbbnntnzznwzzvfvrrqmrmmdzzfqfhqhsqqpwpgwpppbtbnnstthmhrrsmmvsmmhjmjfmfsfjfnfnjjvcjjszjszjsszbznzbnzndzzmlldsdgdcddmqmfqqlcllbvllztzctzczdzttlmtlthtmhtmhmmszsllvzvdzzzsqzqbqccvfvcffzsfslfsllcglclwlvwvzzdsslggtzzgzdzmzddjljvvztttsgscsstztjztjztzvzwwthtftppnmpmmcpmmjlmjjjsfjsjppgcgwcggzffzwzbbmbrbprpqqpccfncfnffvcffsqqtzqzqwzwvzwwwbjbfbcbfblltnlnhhcthtvvzzfcfgfddlggbbshsggplglqqbrbggsvvzdvvlfvlvpvhhmggbrrnppjfjhffttfpffbdfbfvfqvvtcvvbvnnhbhhglgjgzzghhwrrtntrtwwfdfdmmcmtctftpptllzqllzflfrrgqgvgdvdfdbddprrrgccqvqnnmtmvmffpzzqggfbfnfwwqdqldqqlnqnttnbttrffnmmzwzjjtrjtrtmmqsmqmffqmfqfhhbthbhdhvdhvdvmvdmdhdshsqslldzztvvmzzdcccmbbhfhshrrrpsrrqqmdmmgdmmwdmdjdqqmcmttpgtgwgpwpprbrprhrsrllhsllprlplhppfzpffbhbccwdwbbrpbpvpqqmsspjssmbbmfmrmnrnwwgbwwbpwpjwwhqqgcqcvqccgffzpfftcffqlqjjznnlflhhlcczhzvhzhmzhmhfhnnqznntstwtggqjgjhggsvslltjlttfjjgffjzjwzzqzrrhlhzhbhphmhlmlzmzsmzmccvllgrrpbrbfbjfjttqjttdrdhhggqgddppqgpqgpgtptjptpllwccmwcmcpmcppdrrtstqqczqzvvlsltlddnvdvggcqqblqqsjqjttzhtzzszllqsqfqddqdbqddwqddfzzlczcscfsfpfdpdrpddsggcqchcfcpcssstwstwtggghvhqhzzqssjddwjwbjjsnjnfnwwglwwfnfhnnscsggzgjzzhzmmqfqsqwqrwqqqdtdcttzvvnbngbbcdbdggddnmddgzghhzgghwwbjbttlwlcctlccwwdhhrqrvrjjlglssgttpllwclwwtptwptwtvthtbhbzhbzhhrsrwwwnrwrfwfnwnhhnqqdjqjpqqwdwttzhttcdttvztzltzlzmzddrsdsfdsfftdfffmwffrjrffqrfqfsfqqqgqjggwzzrnnqfnqffdbfbtbbrpbrpbptpwttjmjjzrrhhqppdzdtdjttqwwtddjdzzmgzzhwwwdsdgssprsrgsgbbphhdpdwppnfppdqqwzzpbzzqwqpqsqhqdhqqtwwjnnmvmwvmmwwgjgzjjvcjcvcjcnjcncmmphmmvmwmwpwbbtbffhnhshgssgvgvrrbwbtbddqmqfqvvfqvqdvvdbvdbdcdfdlflmffrwwgmmttrztrrfrqrpqrrzjrjpjdpjprrnhhbhcbbcwwqlwwcssbddfrfjrfjfrjfjvvdmdtdzzlvzlzhzmhmhphchnnfqnffvccfpfbfpfqpprrmttzrzzjzmjmzjmmfvmmrzrqqdllgjlglcchssgllsbllrbrlrjlrrhhfwwsqwsstpssznzcznzqzssvtvtrrqwqvvtssgfsfhssljjnwjnjddjdggclcrrfsfhsstgtdtctfttvvsbvvbtbttcgcssjlslhlpljpppwzwnwdnngmgjjbzznwwdllrrfppshhvdhhldhdbbdbjbdjjrnjjzhzfhhsqqbqgmsbvnjsptlrsszlqfmgprvscphmqztbgtlrqvcgdzcptcqjncrdtfqnghnbmwwmcjgtjlbvqqzslgbbntrdfnvfjvfgcgngndjcspgwmpnsrqzzvzljbzlzzrwflrqqqmhsvqwbmdftnhwwzgqrlhddbbtwvbphljmstcjzvpjqwcnhlvpqvqdgvntgqzqwrlwbwvngwtqgrhznlzcvbwqmwncccjctrdzrmzjsvrmcfpjjcczhbvdfwhqvczggfmrspvprvvthvtqnsphpcsdmbrtbdqljvssdrhwjsrrlzprstpgqcbpmnpdgzgjttwcfrgjnsghmszlclgvmlsjrqfvflbnhwwphtvrnrbhdvdglcvgpzfsjpwwhtlvvdzthsrldfzhnlrblzsjjnwclqsqzgdbflhvpwcrtfbfbjcjttbjpvfgvfcswnqqwshbmqlscdzzwshfqwsvwnwzltbnrmzzhzvtwpzqcgwshpvzgtcmwrtrwctnpzbznnwqphnrgwljtrcwlqmvlndwrdrctztnmswslqmbjcmtlrmcpjvzccqszrnflqnqzttbhqlrhbmqdpscqvfgtdbnwjdcljwcbgbgjfzgrgpwqzqgbnrtpntfthhdbqmswvhnmwmszpghgjjzrbnbbfjblpstdfslmmmqfdcrhblqjqfphnldrvvfpnfrcvprjnqbzbspfpjtgqhnjbhnrwzcjvdbshhqpgrmzqpmjfmqwqvvdbddbsldwzzsrhnhsjjnvljrbwcnjrnjpmrrvfthftgptgtlpbgqffthflgftwcrqcqwqwrmrcmfrcqgmrnqjbscdcgrqlhjzthvzdgjbvpswflqcgsnlmgmvcsttsgmnqdtvwdvrndvfdcvrcwmqlmlhtrvthsndsrmnsfmdmfnpfmfhzjqmtcjzcrnsjdztztvgdtlrmbdmmstbfgpmmzthcslpvgrpgfljfgqlqhldfwvvvdvbzjtdtppbtrnqwsqztjrsjhtfrgmvsdngvsdzjgpwrldqpzdpvhljzpjvttwltdwcrhcbrgrvdrmpwvdwjchqsjfprbgtjtzggvgrgmlvvwqrjfprbbgjjqrtdfnrdffwbswbvqtqtfsrhsgrjhftqldhmcnmsnfflmdrzqdjmbqqgqsttdmtrrvfsjnccnhcpcvqtrzdjzrpwswmjvvgsgwvnmdgqwlctrlhqnsmczbwsjhmtgvdcgsndzlstcwchcztqqbtdwfvlljdvdlzljslgnzpmqvzfcvqhdzvgchffqgfwrnmwqzwgbzblpmvddlvnhglrhdnwzqwztzgjczjpwcjwmpnrnrhncfjfggrbphrjztwtfqmfjlwfhnqfftfghbnvtwgtmdzzrdrtmfrwhrrbhzmcllsgqzwzzqtgdggvzptvtdcpzmtmsfcfbjtzlbdrwhdbtdhhrgggmddnzsvjwgcdcqfppqwphfvlhmgqsznlhmgpnjvcvrwwppnphchgsrhjwjcpjggsrcwrvnllfgrmjltfzwhmbqwpwwzmrtlqcprrqztcgnghcbvzrbfptjmhtdcfhhffdbrswqpnpppnpqwtflrrmqgjzctmmvvvwzllbsfdvpqjtmvpjcpmjztscsgbdznfgcmtjzdqzwqrsvstnnvddcstzqjtnbsnlptpmbmfqmhppgnjrffqrtchgptbmwlwbwbcqqfngpbwtwdmlmdstmqwcwjtbwbbbhghgptmvhfmvqfvpwqzwnbjdhpwlgjgvprdjbnlzhnllssbpvzfzspwsscfpqtpdvtzvqncfrfrgddsdglqvpblmpcczlqfdmwzmgvrljhqtcglcvfhbdwhbttqqrjbqwhsrhrbjwmtqwqddvdggdwfsmnpbpvvgsqnvvrqntwmbzdnqpmmqtbnlsbmslpfmqjtgvbddhwvlvjtlrhqdpfnjwtbhwjwdrpgctbbrdqvbbnvgqwngrhqfvwzmlqtmhfqphnmczlbdpnbmpvwrsjbcnjnvcfgnsvlhpzdgdzgvfbgwdcrswznrggnghzssdwqvvlwftqhbnwdvghhvjlqqmcnqmvbwhrrnsswlwmwbsmpcpdzzgmcmqnzpvjpzqbwcsgdhqtqhcpbtqftvscmntsbdcbrndvlfhprpblzbjcpqhfljtvnvtgvrcgqbsgl

14
days/day06/src/main.rs Normal file
View file

@ -0,0 +1,14 @@
mod part1;
mod part2;
mod utilities;
fn main() {
let _input = include_str!("./input.txt");
// let _structured_input = utilities::parse(_input);
println!("Part One");
println!("Result: {}", part1::part1(_input));
println!("Part Two");
println!("Result: {}", part2::part2(_input));
}

23
days/day06/src/part1.rs Normal file
View file

@ -0,0 +1,23 @@
use crate::utilities::*;
pub fn part1(input: &str) -> usize {
input
.as_bytes()
.windows(4)
.position(|x| !find_dupes_stupid(x))
.unwrap()+4
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part1() {
assert_eq!(part1("mjqjpqmgbljsphdztnvjfqwrcgsmlb"), 7);
assert_eq!(part1("bvwbjplbgvbhsrlpgdmjqwftvncz"), 5);
assert_eq!(part1("nppdvjthqldpwncqszvftbrmjlhg"), 6);
assert_eq!(part1("nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg"), 10);
assert_eq!(part1("zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw"), 11);
}
}

23
days/day06/src/part2.rs Normal file
View file

@ -0,0 +1,23 @@
use crate::utilities::*;
pub fn part2(input: &str) -> usize {
input
.as_bytes()
.windows(14)
.position(|x| !find_dupes_stupid(x))
.unwrap()+14
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part2() {
assert_eq!(part2("mjqjpqmgbljsphdztnvjfqwrcgsmlb"), 19);
assert_eq!(part2("bvwbjplbgvbhsrlpgdmjqwftvncz"), 23);
assert_eq!(part2("nppdvjthqldpwncqszvftbrmjlhg"), 23);
assert_eq!(part2("nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg"), 29);
assert_eq!(part2("zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw"), 26);
}
}

View file

@ -0,0 +1,19 @@
pub fn find_dupes_stupid<T: PartialEq>(slice: &[T]) -> bool {
for i in 1..slice.len() {
if slice[i..].contains(&slice[i - 1]) {
return true;
}
}
false
}
/* #[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse() {
let input = "test";
assert_eq!(parse(input), 0);
}
} */

11
days/day07/Cargo.toml Normal file
View file

@ -0,0 +1,11 @@
[package]
name = "day07"
authors.workspace = true
description.workspace = true
version.workspace = true
edition.workspace = true
[dependencies]
once_cell.workspace = true
regex.workspace = true
thiserror.workspace = true

305
days/day07/src/file_tree.rs Normal file
View file

@ -0,0 +1,305 @@
use std::{
cell::RefCell,
fmt::Display,
ops::Deref,
rc::{Rc, Weak},
};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum FileTreeError {
#[error("Directory operation on file")]
IsFile,
#[error("File operation on directory")]
IsDir,
#[error("File not found")]
FileNotFound,
#[error("File already exists")]
FileAlreadyExists,
}
type WeakNodeRef = Weak<RefCell<Node>>;
#[derive(Debug)]
pub struct NodeRef(pub Rc<RefCell<Node>>);
impl Deref for NodeRef {
type Target = Rc<RefCell<Node>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<Rc<RefCell<Node>>> for NodeRef {
fn from(value: Rc<RefCell<Node>>) -> Self {
NodeRef(value)
}
}
impl From<NodeRef> for Rc<RefCell<Node>> {
fn from(value: NodeRef) -> Self {
value.0
}
}
impl NodeRef {
pub fn add_node(&mut self, mut node: Node) -> Result<NodeRef, FileTreeError> {
node.set_parent(self);
self.borrow_mut().add_children(node)
}
pub fn new_dir(name: String) -> NodeRef {
NodeRef(Rc::new(RefCell::new(Node::new_dir(name))))
}
pub fn add_file(&mut self, name: String, size: usize) -> Result<NodeRef, FileTreeError> {
self.add_node(Node::new_file(name, size))
}
pub fn add_dir(&mut self, name: String) -> Result<NodeRef, FileTreeError> {
self.add_node(Node::new_dir(name))
}
pub fn get_all_dirs(&self) -> Vec<NodeRef> {
let mut ret = Vec::new();
match &self.borrow().contents {
Contents::Size(_) => {}
Contents::Children(c) => {
ret.push(NodeRef(Rc::clone(self)));
for node in c {
ret.append(&mut node.get_all_dirs())
}
}
};
ret
}
}
#[derive(Debug)]
pub struct Node {
pub name: String,
parent: Option<WeakNodeRef>,
contents: Contents,
}
impl Node {
pub fn new_dir(name: String) -> Node {
Node {
name,
parent: None,
contents: Contents::Children(Vec::new()),
}
}
pub fn new_file(name: String, size: usize) -> Node {
Node {
name,
parent: None,
contents: Contents::Size(size),
}
}
pub fn get_total_size(&self) -> usize {
match &self.contents {
Contents::Size(s) => *s,
Contents::Children(c) => c.iter().map(|f| f.borrow().get_total_size()).sum(),
}
}
fn set_parent(&mut self, newparent: &NodeRef) {
self.parent = Some(Rc::downgrade(newparent));
}
// does not set the parent, needs to be done on the NodeRef. (this is why this func isnt pub).
// takes onwership of the node to make sure its not owned by another tree.
fn add_children(&mut self, node: Node) -> Result<NodeRef, FileTreeError> {
match self.contents {
Contents::Size(_) => Err(FileTreeError::IsFile),
Contents::Children(ref mut c) => {
for file in c.iter() {
if file.borrow().name == node.name {
return Err(FileTreeError::FileAlreadyExists);
}
}
let rc = Rc::new(RefCell::new(node));
c.push(NodeRef(Rc::clone(&rc)));
Ok(NodeRef(Rc::clone(&rc)))
}
}
}
pub fn remove_child_by_name(&mut self, name: &str) -> Result<(), FileTreeError> {
match self.contents {
Contents::Size(_) => Err(FileTreeError::IsFile),
Contents::Children(ref mut c) => {
for (i, file) in c.iter().enumerate() {
if file.borrow().name == name {
c.remove(i);
return Ok(());
}
}
Err(FileTreeError::FileNotFound)
}
}
}
pub fn get_parent(&self) -> Option<NodeRef> {
match &self.parent {
Some(w) => Some(NodeRef(w.clone().upgrade()?)),
None => None,
}
}
pub fn get_size(&self) -> Result<usize, FileTreeError> {
match self.contents {
Contents::Size(s) => Ok(s),
Contents::Children(_) => Err(FileTreeError::IsDir),
}
}
pub fn set_size(&mut self, size: usize) -> Result<(), FileTreeError> {
match self.contents {
Contents::Size(ref mut s) => {
*s = size;
Ok(())
}
Contents::Children(_) => Err(FileTreeError::IsDir),
}
}
pub fn get_children(&self) -> Result<impl Iterator<Item = NodeRef> + '_, FileTreeError> {
match &self.contents {
Contents::Size(_) => Err(FileTreeError::IsFile),
Contents::Children(c) => Ok(c.iter().map(|n| NodeRef(Rc::clone(n)))),
}
}
pub fn get_child_by_name(&self, name: &str) -> Result<NodeRef, FileTreeError> {
match &self.contents {
Contents::Size(_) => Err(FileTreeError::IsFile),
Contents::Children(c) => {
for file in c.iter() {
if file.borrow().name == name {
return Ok(NodeRef(Rc::clone(file)));
}
}
Err(FileTreeError::FileNotFound)
}
}
}
}
#[derive(Debug)]
enum Contents {
Size(usize),
Children(Vec<NodeRef>),
}
impl Display for NodeRef {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.borrow())
}
}
impl Display for Node {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "- {} {}", self.name, self.contents)
}
}
impl Display for Contents {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Contents::Size(s) => write!(f, "(file, size = {})", s),
Contents::Children(c) => {
writeln!(f, "(dir)").expect("I have no clue how this could fail");
for node in c {
//padding
for line in format!("{}", node).lines() {
writeln!(f, " {line}")?;
}
}
Ok(())
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_dir_construction() {
let mut root = NodeRef::new_dir("/".to_string());
let mut cursor = root.add_node(Node::new_dir("a".to_string())).unwrap();
cursor = cursor.add_dir("e".to_string()).unwrap();
cursor.add_file("i".to_string(), 584).unwrap();
cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
cursor.add_file("f".to_string(), 29116).unwrap();
cursor.add_file("g".to_string(), 2557).unwrap();
cursor.add_file("h.lst".to_string(), 62596).unwrap();
cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
cursor.add_file("b.txt".to_string(), 14848514).unwrap();
cursor.add_file("c.dat".to_string(), 8504156).unwrap();
cursor = cursor.add_dir("d".to_string()).unwrap();
cursor.add_file("j".to_string(), 4060174).unwrap();
cursor.add_file("d.log".to_string(), 8033020).unwrap();
cursor.add_file("d.ext".to_string(), 5626152).unwrap();
cursor.add_file("k".to_string(), 7214296).unwrap();
assert_eq!(Rc::clone(root.deref()).borrow().get_total_size(), 48381165);
println!("{}", root);
}
#[test]
fn test_size_calcs() {
let mut root = NodeRef::new_dir("/".to_string());
let mut dirs: Vec<NodeRef> = Vec::new();
let mut cursor = root.add_dir("a".to_string()).unwrap();
dirs.push(NodeRef(Rc::clone(&cursor)));
cursor = cursor.add_dir("e".to_string()).unwrap();
dirs.push(NodeRef(Rc::clone(&cursor)));
cursor.add_file("i".to_string(), 584).unwrap();
cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
cursor.add_file("f".to_string(), 29116).unwrap();
cursor.add_file("g".to_string(), 2557).unwrap();
cursor.add_file("h.lst".to_string(), 62596).unwrap();
cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
cursor.add_file("b.txt".to_string(), 14848514).unwrap();
cursor.add_file("c.dat".to_string(), 8504156).unwrap();
cursor = cursor.add_node(Node::new_dir("d".to_string())).unwrap();
dirs.push(NodeRef(Rc::clone(&cursor)));
cursor.add_file("j".to_string(), 4060174).unwrap();
cursor.add_file("d.log".to_string(), 8033020).unwrap();
cursor.add_file("d.ext".to_string(), 5626152).unwrap();
cursor.add_file("k".to_string(), 7214296).unwrap();
assert_eq!(Rc::clone(root.deref()).borrow().get_total_size(), 48381165);
assert_eq!(Rc::clone(dirs[0].deref()).borrow().get_total_size(), 94853);
assert_eq!(Rc::clone(dirs[1].deref()).borrow().get_total_size(), 584);
assert_eq!(
Rc::clone(dirs[2].deref()).borrow().get_total_size(),
24933642
);
}
#[test]
fn test_get_all_dirs() {
let mut root = NodeRef::new_dir("/".to_string());
let mut cursor = root.add_dir("a".to_string()).unwrap();
cursor = cursor.add_dir("e".to_string()).unwrap();
cursor.add_file("i".to_string(), 584).unwrap();
cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
cursor.add_file("f".to_string(), 29116).unwrap();
cursor.add_file("g".to_string(), 2557).unwrap();
cursor.add_file("h.lst".to_string(), 62596).unwrap();
cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
cursor.add_file("b.txt".to_string(), 14848514).unwrap();
cursor.add_file("c.dat".to_string(), 8504156).unwrap();
cursor = cursor.add_node(Node::new_dir("d".to_string())).unwrap();
cursor.add_file("j".to_string(), 4060174).unwrap();
cursor.add_file("d.log".to_string(), 8033020).unwrap();
cursor.add_file("d.ext".to_string(), 5626152).unwrap();
cursor.add_file("k".to_string(), 7214296).unwrap();
let dirs = root.get_all_dirs();
let sizes: Vec<usize> = dirs.iter().map(|d| d.borrow().get_total_size()).collect();
println!("{:?}", sizes);
assert_eq!(Rc::clone(root.deref()).borrow().get_total_size(), 48381165);
assert_eq!(
Rc::clone(dirs[0].deref()).borrow().get_total_size(),
48381165
);
assert_eq!(Rc::clone(dirs[1].deref()).borrow().get_total_size(), 94853);
assert_eq!(Rc::clone(dirs[2].deref()).borrow().get_total_size(), 584);
assert_eq!(
Rc::clone(dirs[3].deref()).borrow().get_total_size(),
24933642
);
}
}

1030
days/day07/src/input.txt Normal file

File diff suppressed because it is too large Load diff

19
days/day07/src/main.rs Normal file
View file

@ -0,0 +1,19 @@
use std::rc::Rc;
use crate::file_tree::NodeRef;
mod part1;
mod part2;
mod parser;
mod file_tree;
fn main() {
let input = include_str!("./input.txt");
let structured_input = parser::parse(input);
println!("Part One");
println!("Result: {}", part1::part1(NodeRef(Rc::clone(&structured_input))));
println!("Part Two");
println!("Result: {}", part2::part2(NodeRef(Rc::clone(&structured_input))));
}

262
days/day07/src/parser.rs Normal file
View file

@ -0,0 +1,262 @@
use std::ops::Deref;
use std::rc::Rc;
use crate::file_tree::*;
use once_cell::sync::Lazy;
use regex::Regex;
static IS_COMMAND_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"^\$").unwrap());
static PARSE_CD_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"^\$ cd (\S*)$").unwrap());
static PARSE_LS_ENTRY_REGEX: Lazy<Regex> =
Lazy::new(|| Regex::new(r"^([[:alnum:]]*) (\S*)$").unwrap());
#[derive(Debug, PartialEq, Eq)]
pub enum Command {
CdRoot,
CdUp,
Cd(String),
Ls(Vec<LsEntry>),
}
#[derive(Debug, PartialEq, Eq)]
pub enum LsEntry {
Dir(String),
File(ParseFile),
}
#[derive(Debug, PartialEq, Eq)]
pub struct ParseFile {
size: usize,
name: String,
}
//parses a single line
pub fn parse_to_commands(input: &str) -> Vec<Command> {
let mut ret = Vec::new();
let mut lines = input.lines().peekable();
while lines.peek().is_some() {
let line = lines.next().unwrap();
if line == "$ ls" {
ret.push(Command::Ls(parse_ls(&mut lines)));
} else {
let captures = PARSE_CD_REGEX
.captures(line)
.unwrap_or_else(|| panic!("invalid line {}", line));
ret.push(match &captures[1] {
".." => Command::CdUp,
"/" => Command::CdRoot,
s => Command::Cd(s.to_string()),
})
}
}
ret
}
fn parse_ls(lines: &mut std::iter::Peekable<std::str::Lines<'_>>) -> Vec<LsEntry> {
let mut ret: Vec<LsEntry> = Vec::new();
while lines.peek().is_some() {
// if the next line is a command, then we are at the end of the ls listing.
let line = lines.peek().expect("no next line");
if IS_COMMAND_REGEX.is_match(line) {
break;
}
let captures = PARSE_LS_ENTRY_REGEX
.captures(line)
.unwrap_or_else(|| panic!("invalid line {}", line));
ret.push(match &captures[1] {
"dir" => LsEntry::Dir(captures[2].to_string()),
_ => LsEntry::File(ParseFile {
size: str::parse(&captures[1]).unwrap_or_else(|_| panic!("invalid line {}", line)),
name: captures[2].to_string(),
}),
});
lines.next();
}
ret
}
pub fn parse(input: &str) -> NodeRef {
commands_to_tree(parse_to_commands(input))
}
pub fn commands_to_tree(input: Vec<Command>) -> NodeRef {
let root = NodeRef::new_dir("/".to_string());
let mut cursor = NodeRef(Rc::clone(&root));
for command in input {
match command {
Command::CdRoot => cursor = NodeRef(Rc::clone(&root)),
Command::CdUp => cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(),
Command::Cd(name) => cursor = cursor.add_dir(name).unwrap(),
Command::Ls(ls) => {
for entry in ls {
match entry {
LsEntry::Dir(_) => {
//dirs dont exist until you cd into them.
}
LsEntry::File(f) => {
cursor.add_file(f.name, f.size).unwrap();
}
};
}
}
}
}
root
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_to_commands() {
let input = concat!(
"$ cd /\n",
"$ ls\n",
"dir a\n",
"14848514 b.txt\n",
"8504156 c.dat\n",
"dir d\n",
"$ cd a\n",
"$ ls\n",
"dir e\n",
"29116 f\n",
"2557 g\n",
"62596 h.lst\n",
"$ cd e\n",
"$ ls\n",
"584 i\n",
"$ cd ..\n",
"$ cd ..\n",
"$ cd d\n",
"$ ls\n",
"4060174 j\n",
"8033020 d.log\n",
"5626152 d.ext\n",
"7214296 k"
);
assert_eq!(
parse_to_commands(input),
vec![
Command::CdRoot,
Command::Ls(vec![
LsEntry::Dir(String::from("a")),
LsEntry::File(ParseFile {
size: 14848514,
name: String::from("b.txt")
}),
LsEntry::File(ParseFile {
size: 8504156,
name: String::from("c.dat")
}),
LsEntry::Dir(String::from("d"))
]),
Command::Cd(String::from("a")),
Command::Ls(vec![
LsEntry::Dir(String::from("e")),
LsEntry::File(ParseFile {
size: 29116,
name: String::from("f")
}),
LsEntry::File(ParseFile {
size: 2557,
name: String::from("g")
}),
LsEntry::File(ParseFile {
size: 62596,
name: String::from("h.lst")
}),
]),
Command::Cd(String::from("e")),
Command::Ls(vec![LsEntry::File(ParseFile {
size: 584,
name: String::from("i")
}),]),
Command::CdUp,
Command::CdUp,
Command::Cd(String::from("d")),
Command::Ls(vec![
LsEntry::File(ParseFile {
size: 4060174,
name: String::from("j")
}),
LsEntry::File(ParseFile {
size: 8033020,
name: String::from("d.log")
}),
LsEntry::File(ParseFile {
size: 5626152,
name: String::from("d.ext")
}),
LsEntry::File(ParseFile {
size: 7214296,
name: String::from("k")
}),
]),
]
)
}
#[test]
fn test_commands_to_tree() {
let input = vec![
Command::CdRoot,
Command::Ls(vec![
LsEntry::Dir(String::from("a")),
LsEntry::File(ParseFile {
size: 14848514,
name: String::from("b.txt"),
}),
LsEntry::File(ParseFile {
size: 8504156,
name: String::from("c.dat"),
}),
LsEntry::Dir(String::from("d")),
]),
Command::Cd(String::from("a")),
Command::Ls(vec![
LsEntry::Dir(String::from("e")),
LsEntry::File(ParseFile {
size: 29116,
name: String::from("f"),
}),
LsEntry::File(ParseFile {
size: 2557,
name: String::from("g"),
}),
LsEntry::File(ParseFile {
size: 62596,
name: String::from("h.lst"),
}),
]),
Command::Cd(String::from("e")),
Command::Ls(vec![LsEntry::File(ParseFile {
size: 584,
name: String::from("i"),
})]),
Command::CdUp,
Command::CdUp,
Command::Cd(String::from("d")),
Command::Ls(vec![
LsEntry::File(ParseFile {
size: 4060174,
name: String::from("j"),
}),
LsEntry::File(ParseFile {
size: 8033020,
name: String::from("d.log"),
}),
LsEntry::File(ParseFile {
size: 5626152,
name: String::from("d.ext"),
}),
LsEntry::File(ParseFile {
size: 7214296,
name: String::from("k"),
}),
]),
];
let tree = commands_to_tree(input);
println!("{}", tree);
assert_eq!(Rc::clone(tree.deref()).borrow().get_total_size(), 48381165)
}
}

37
days/day07/src/part1.rs Normal file
View file

@ -0,0 +1,37 @@
use crate::file_tree::*;
pub fn part1(input: NodeRef) -> usize {
let dirs = input.get_all_dirs();
dirs.iter()
.map(|d| d.borrow().get_total_size())
.filter(|s| *s <= 100000)
.sum()
}
#[cfg(test)]
mod tests {
use std::{ops::Deref, rc::Rc};
use super::*;
#[test]
fn test_part1() {
let mut root = NodeRef::new_dir("/".to_string());
let mut cursor = root.add_node(Node::new_dir("a".to_string())).unwrap();
cursor = cursor.add_dir("e".to_string()).unwrap();
cursor.add_file("i".to_string(), 584).unwrap();
cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
cursor.add_file("f".to_string(), 29116).unwrap();
cursor.add_file("g".to_string(), 2557).unwrap();
cursor.add_file("h.lst".to_string(), 62596).unwrap();
cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
cursor.add_file("b.txt".to_string(), 14848514).unwrap();
cursor.add_file("c.dat".to_string(), 8504156).unwrap();
cursor = cursor.add_dir("d".to_string()).unwrap();
cursor.add_file("j".to_string(), 4060174).unwrap();
cursor.add_file("d.log".to_string(), 8033020).unwrap();
cursor.add_file("d.ext".to_string(), 5626152).unwrap();
cursor.add_file("k".to_string(), 7214296).unwrap();
assert_eq!(part1(root), 95437);
}
}

44
days/day07/src/part2.rs Normal file
View file

@ -0,0 +1,44 @@
use crate::file_tree::*;
const TOTAL_SPACE: usize = 70000000;
const NEEDED_SPACE: usize = 30000000;
pub fn part2(input: NodeRef) -> usize {
let used_space = input.borrow().get_total_size();
let unused_space = TOTAL_SPACE - used_space;
let space_to_free = NEEDED_SPACE - unused_space;
let dirs = input.get_all_dirs();
dirs.iter()
.map(|d| d.borrow().get_total_size())
.filter(|s| *s >= space_to_free)
.min()
.unwrap()
}
#[cfg(test)]
mod tests {
use std::{ops::Deref, rc::Rc};
use super::*;
#[test]
fn test_part2() {
let mut root = NodeRef::new_dir("/".to_string());
let mut cursor = root.add_node(Node::new_dir("a".to_string())).unwrap();
cursor = cursor.add_dir("e".to_string()).unwrap();
cursor.add_file("i".to_string(), 584).unwrap();
cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
cursor.add_file("f".to_string(), 29116).unwrap();
cursor.add_file("g".to_string(), 2557).unwrap();
cursor.add_file("h.lst".to_string(), 62596).unwrap();
cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
cursor.add_file("b.txt".to_string(), 14848514).unwrap();
cursor.add_file("c.dat".to_string(), 8504156).unwrap();
cursor = cursor.add_dir("d".to_string()).unwrap();
cursor.add_file("j".to_string(), 4060174).unwrap();
cursor.add_file("d.log".to_string(), 8033020).unwrap();
cursor.add_file("d.ext".to_string(), 5626152).unwrap();
cursor.add_file("k".to_string(), 7214296).unwrap();
assert_eq!(part2(root), 24933642);
}
}

6
days/day08/Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "day08"
authors.workspace = true
description.workspace = true
version.workspace = true
edition.workspace = true

99
days/day08/src/input.txt Normal file
View file

@ -0,0 +1,99 @@
002100030222341303232115221524311502200403234452204125251345024423544443305142410110142101223120110
102030322341143330244233013052025453422005415304655426206452251310214055314024034341233110302320003
003012203404011430120134554314552441635001641050211406204621114102021543144514102510421243314102033
330313423002034140035001210441156554545625042262651356556544202500446121455112434243313013430141203
331203121131230002055113430244610062654034520106363462155201210355601153542301323442223310134324300
232201231021003254355411402310326206625011564114125202263504451451212600155351424154310240411213431
033033333301011523544023206136145505304224325606020360006206455564513553512054354124523232201230441
132201032234334044251334220345360402456541662253556375754662323265201641514121105025300453041111234
314322341322104402235020206565044225363527617767574524475421763504341061551154250344125514014234344
101323043023430543342440532324326413655657527215661116623455613664321005134300223542510253102211310
320404242514122111525043444530625417656773117247512712444315767422412130351505513231104322032421303
221204123205133142044056245654205231734371546616753217321556472223654044043612554152141554333102034
340310155225452152216635634352712541366312326272262143522347111166646736001360102010220214000133002
012404003515002416422500163244271366252711531615333437352461454777311142132000140205630042305222013
332434552302203445503543424523327464362526657251687634745536521746523154717531643250132300541053000
020130312425316362611130462217125425435545265467725256332777233137141524314631100051153314314343032
112115124512002346011342433146124542356845483862756322785545283652723747276776403131622540014001524
332354013101003031053022245431274627654677343638672643442563448782737464337546541546630431125021330
220315320142064161406534365262377268373743527784575246325564676238816733767331345114363612344051535
102041153526000601402325625766534543527882476653366727573448727775677146365732431425225562043130034
350054114310533002426654125166575285757827422257872378766383267543484865317252532765440216543555512
222440404353016144747347457368562668586285847553578732435887584463446862116134751240360645225435344
554234546163262630313431762248876668663352436888374587856263343842526635237314231451062036605442520
525531324662660356256614344438373575732699988366775989976447384338336827686445577222030363631240512
055541261042533424177375756738443482846986979788978997559377679255463858237757327464422026230510130
514123221240250442457744728347386637684953574546455344754548333793233865436751231314653541223102202
355454250661114645144551785724753237378345375493453967559796675839837444334776625552412552302431302
202445234333206767744653874724276586973668878949653473947686567565487325864733735677672241416513452
445415223211061633767433865252483574744685974593334963668983745643354885658423263536531213102544202
201405464251164654177385783224666473975674643767946648464678958969336335638578275154116223152222102
401423140356441654745572266848965593553995667644648964747884544439493545472454437715336645303346422
154440323240741427732867467564957336394985859766644495658985963583496399736552632162756445212536404
441663663062661372122867364584655388977474857585778686889578799644949733463423826715534215154065204
422036122016243651174663588693898583374968974778579585977478599643389537573534354622377452555411315
430412403362272513348763673566578945645997454758694486758844958569786758359475575577532661126532300
503653020441267422765353469867998339764449596776968996449777464644846938866332635583727771665263026
006252631541331635768754753357384754988659585857956567666645975599653466655333342485345762600032403
215205542775713732868842389885585646884858449858579777975997584997463698339932263363162431251615251
342224450731115175762626546538955447796468885776778879697695699945446388444478355347827635732006646
045011110226211633623658548365544498466468766878699597655897586488555435934935526883851537736604133
440352212243431376382869634434568447654566895897796875679759667598898849334873844583742271767024403
566632367121414762272448784755746799985759966559657989697977677955455754549393784586875275341562621
004131167135757426882464486773699786789959957795985595559587775554479945637849747667752242212324244
022411031432724262533554794664597446479869568767598899669969588984864457535986725263473577457413134
036415005331162527346577487593798458668976888776888766856699598847776567686579476836656723623111342
504001302331545267684439554776894957999788577876688969865558955547965687556849786463457244355044511
464266074264126575276833864784546697885788878967966988678696686685576789843676844576623242451411411
660130573642326366362654785549676574587876888769689696798799988678648554635745724364273772474666502
413511521313437652422664948645649566979966676679778669968777776786958464356797545247763267365643645
455033174473274564484285387995879595555686569997977698868769855686564847593489668858847744131410225
560316675532344635443349663994499869866598568889798868967976679655597494679336978524332246567265361
121053163342234352453837754569968465557968697766766888969966667796479457384444468264837376474515455
604062313527642634768255846899648545559665886668966887999959659769978495794795825775373713613231451
041031112622754332842439776736966994677888699898679988967779696758849589365579766676242256227420364
630161363126476778455475799658545955598576568877768698668579988799596866465635488284555252726211044
455563641427127283364758796475975894658677688789777769876667978747955677573575525588444241765111511
256420063532645225542863884958844496596759999769769687678888788875449888945958948378756476127155054
523256165217547362636325547686549767698957967985968987897777685866576744344388256886854362647342110
205224606764556763544234874676659474468968576879668558856675855668779847849738247387744421321145610
022651355615653552468486676459694744747575877656886776677858584988944678787576556747724125467333305
526313424324717126486746644643397589664468865599858886996669788566489473798387676766873216657521426
426530404522411762572567697375959747975669667958685679878659587764977658398697353283563215312244014
023510245741131775436864579684699874979976567776557765866775469587757498544476554753722641656303654
211341433442225414565332887899363678699495567888998675657659688744458493387343842346747477252626250
406543152154335614758277748595836896786654948759999978569588555764838686653647362854723163226456101
333640633617315535456525364849458558744656899855554897897568844446533866457545654847562377442214226
040003053246534354438748723933365934878485997458955574785966996653353969666867276761661111124104550
405602516206264365157378627495546935658594587869579958969686766986836687348285865231616336232000100
304131030254233641578272475868953446545577766644956989679964489688554398956223433417637732661500540
131164662225325441733366324345477954639475997658684766465487974699579665344326248136151472051130445
452312154206174654138684277376889449945746954689646875777596486949365968888456226732332263263420000
003010154551246223274282454345355673349967689986885795449989359633496728553885221437611730454554455
131435126460017635544785754344874379695379366384573934357795398633967475353836864461424146264354142
350154544045013352533173566257757787385448697484997454578735937499665628425542376452563635450224022
302420224365163651765264446875287359533637498445639443969586466433384346337722662774436566624454214
415242456321105173655733744886343826548944666338683876383973497998744488687446541256724244661531431
155303206134314124372553618623857237346567857564464797593393675563536467777317174625640132203003240
335521544652523624641575451785635352333587957647598535633948867838652636686573137515062356442045153
235314500244636615342325346277256685653838226755493858683465683736283367654226655456541546644313125
252520511531061305614364671212856473625642477732845278766573642425286572562373137446456005011330433
241525455120116046543737642325543677623243884242534423327827446383376441727657314343125403632434002
301045223551220356167117621755325772252845222546246588464784874685774676163655131632622146412415515
011150133311336614251435416453632383454327534367288242328746537673543714263674263262001132354544412
314104033000306256531666256433553535833538337463847277453476563227672715617272601302551120422305504
104211442013141664402363645617163435245556228235337864656673626354151416721375243323635625100210424
413422313502535362615054171511431775335574748526574728747453724472157632635263350024552502052340024
131225301023304456424150404525765416565572272321835377167235317312551645334432406536160545434122120
342131052232413325301451041516716541737346252413667115612642227312572433104525003114240240141232002
244421101354005430232434420344323273421374225635551363463245561271743411452116466311034334101231020
232404402304311415164151401553463731147111147752141732625152553615361046133341313265525232544143442
201321033520133414312301326330253041267251614477322566645472656414545035321106361434351501123314104
211232034442524242313453325046331353174352335422752364775746537513333534355120322320404054014303124
224032233240430510135541652065052415154147565656231651653327511443424113100543020223335130010141400
004110101133543440511523265424013341433043655022512172622140322434116104552043413352211021312421433
000304433232402410151205333526613043463556021413402141634154404530112303306244402221312522221004042
200204441020135232033032541516232550445221141520665016336536052063115335040344025054213324400312303
300211022440310123055510053251505226452265556365100101014044645236505213550201425252404100302413231
310312413210032422053242024243343060135340422313312403505631104430120233112324204414021331012401232
132020341330304022053503522313342026211133610000020554213662244142551253124302245242110111033101203

16
days/day08/src/main.rs Normal file
View file

@ -0,0 +1,16 @@
mod part1;
mod part2;
mod utilities;
type StructuredInput = Vec<Vec<u8>>;
fn main() {
let input = include_str!("./input.txt");
let structured_input = utilities::parse(input);
println!("Part One");
println!("Result: {}", part1::part1(&structured_input));
println!("Part Two");
println!("Result: {}", part2::part2(&structured_input));
}

85
days/day08/src/part1.rs Normal file
View file

@ -0,0 +1,85 @@
use crate::StructuredInput;
pub fn part1(input: &StructuredInput) -> usize {
let mut acc: usize = 0;
for y in 0..input.len(){
for x in 0..input[0].len(){
if is_visible(x, y, input){
acc+=1;
}
}
}
acc
}
fn is_visible(x: usize, y: usize, input: &StructuredInput) -> bool {
is_visible_north(x, y, input)
|| is_visible_east(x, y, input)
|| is_visible_south(x, y, input)
|| is_visible_west(x, y, input)
}
fn is_visible_north(x: usize, y: usize, input: &StructuredInput) -> bool {
if y == 0 {
return true;
};
let hight = input[y][x];
for y in 0..y {
if input[y][x] >= hight {
return false;
}
}
true
}
fn is_visible_east(x: usize, y: usize, input: &StructuredInput) -> bool {
if x == input[0].len() {
return true;
}
let hight = input[y][x];
for x in (x + 1)..input[0].len() {
if input[y][x] >= hight {
return false;
}
}
true
}
fn is_visible_south(x: usize, y: usize, input: &StructuredInput) -> bool {
if y == input.len() {
return true;
};
let hight = input[y][x];
for y in (y + 1)..input.len() {
if input[y][x] >= hight {
return false;
}
}
true
}
fn is_visible_west(x: usize, y: usize, input: &StructuredInput) -> bool {
if x == input[0].len() {
return true;
}
let hight = input[y][x];
for x in 0..x {
if input[y][x] >= hight {
return false;
}
}
true
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part1() {
let input = vec![
vec![3, 0, 3, 7, 3],
vec![2, 5, 5, 1, 2],
vec![6, 5, 3, 3, 2],
vec![3, 3, 5, 4, 9],
vec![3, 5, 3, 9, 0],
];
assert_eq!(part1(&input), 21);
}
}

109
days/day08/src/part2.rs Normal file
View file

@ -0,0 +1,109 @@
use crate::StructuredInput;
pub fn part2(input: &StructuredInput) -> usize {
let mut max: usize = 0;
for y in 0..input.len() {
for x in 0..input[0].len() {
let tree_score = tree_score(x, y, input);
if max < tree_score{
max = tree_score;
println!("found new max with score {} at {}, {}", tree_score, x, y)
}
}
}
max
}
fn tree_score(x: usize, y: usize, input: &StructuredInput) -> usize {
trees_visible_north(x, y, input)
* trees_visible_east(x, y, input)
* trees_visible_south(x, y, input)
* trees_visible_west(x, y, input)
}
fn trees_visible_north(x: usize, y: usize, input: &StructuredInput) -> usize {
if y == 0 {
return 0;
};
let hight = input[y][x];
let mut trees: usize = 0;
for y in (0..y).rev() {
trees += 1;
if input[y][x] >= hight {
break
}
}
trees
}
fn trees_visible_east(x: usize, y: usize, input: &StructuredInput) -> usize {
if x == input[0].len() {
return 0;
}
let hight = input[y][x];
let mut trees: usize = 0;
for x in (x + 1)..input[0].len() {
trees += 1;
if input[y][x] >= hight {
break
}
}
trees
}
fn trees_visible_south(x: usize, y: usize, input: &StructuredInput) -> usize {
if y == input.len() {
return 0;
};
let hight = input[y][x];
let mut trees: usize = 0;
for y in (y + 1)..input.len() {
trees += 1;
if input[y][x] >= hight {
break
}
}
trees
}
fn trees_visible_west(x: usize, y: usize, input: &StructuredInput) -> usize {
if x == input[0].len() {
return 0;
}
let hight = input[y][x];
let mut trees: usize = 0;
for x in (0..x).rev() {
trees += 1;
if input[y][x] >= hight {
break
}
}
trees
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part2() {
let input = vec![
vec![3, 0, 3, 7, 3],
vec![2, 5, 5, 1, 2],
vec![6, 5, 3, 3, 2],
vec![3, 3, 5, 4, 9],
vec![3, 5, 3, 9, 0],
];
assert_eq!(part2(&input), 8);
}
#[test]
fn test_trees_visible() {
let input = vec![
vec![3, 0, 3, 7, 3],
vec![2, 5, 5, 1, 2],
vec![6, 5, 3, 3, 2],
vec![3, 3, 5, 4, 9],
vec![3, 5, 3, 9, 0],
];
assert_eq!(trees_visible_north(2, 3, &input), 2);
assert_eq!(trees_visible_east(2, 3, &input), 2);
assert_eq!(trees_visible_south(2, 3, &input), 1);
assert_eq!(trees_visible_west(2, 3, &input), 2);
assert_eq!(tree_score(2, 3, &input), 8);
}
}

View file

@ -0,0 +1,26 @@
pub fn parse(input: &str) -> Vec<Vec<u8>> {
input
.lines()
.map(|l| l.chars().map(|c| c.to_digit(10).unwrap() as u8).collect())
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse() {
let input = concat!("30373\n", "25512\n", "65332\n", "33549\n", "35390\n",);
assert_eq!(
parse(input),
vec![
vec![3, 0, 3, 7, 3],
vec![2, 5, 5, 1, 2],
vec![6, 5, 3, 3, 2],
vec![3, 3, 5, 4, 9],
vec![3, 5, 3, 9, 0]
]
);
}
}