switched to workspaces.
This should let me make a cross-day library.
This commit is contained in:
parent
1469c3a32b
commit
242989bb95
57 changed files with 156 additions and 89 deletions
6
days/day01/Cargo.toml
Normal file
6
days/day01/Cargo.toml
Normal 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
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
14
days/day01/src/main.rs
Normal 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
48
days/day01/src/parse.rs
Normal 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
27
days/day01/src/part1.rs
Normal 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
27
days/day01/src/part2.rs
Normal 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
6
days/day02/Cargo.toml
Normal 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
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
13
days/day02/src/main.rs
Normal 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
62
days/day02/src/part1.rs
Normal 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
87
days/day02/src/part2.rs
Normal 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);
|
||||
}
|
||||
}
|
36
days/day02/src/utilities.rs
Normal file
36
days/day02/src/utilities.rs
Normal 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
6
days/day03/Cargo.toml
Normal 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
300
days/day03/src/input.txt
Normal 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
14
days/day03/src/main.rs
Normal 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
54
days/day03/src/part1.rs
Normal 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
78
days/day03/src/part2.rs
Normal 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);
|
||||
}
|
||||
}
|
93
days/day03/src/utilities.rs
Normal file
93
days/day03/src/utilities.rs
Normal 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
10
days/day04/Cargo.toml
Normal 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
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
14
days/day04/src/main.rs
Normal 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
27
days/day04/src/part1.rs
Normal 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
27
days/day04/src/part2.rs
Normal 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);
|
||||
}
|
||||
}
|
79
days/day04/src/utilities.rs
Normal file
79
days/day04/src/utilities.rs
Normal 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
10
days/day05/Cargo.toml
Normal 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
514
days/day05/src/input.txt
Normal 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
14
days/day05/src/main.rs
Normal 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
48
days/day05/src/part1.rs
Normal 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
48
days/day05/src/part2.rs
Normal 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
144
days/day05/src/utilities.rs
Normal 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
6
days/day06/Cargo.toml
Normal 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
1
days/day06/src/input.txt
Normal file
|
@ -0,0 +1 @@
|
|||
bhzhtzzsczszsjjjzddfzdfzfjfzfbbnntnzznwzzvfvrrqmrmmdzzfqfhqhsqqpwpgwpppbtbnnstthmhrrsmmvsmmhjmjfmfsfjfnfnjjvcjjszjszjsszbznzbnzndzzmlldsdgdcddmqmfqqlcllbvllztzctzczdzttlmtlthtmhtmhmmszsllvzvdzzzsqzqbqccvfvcffzsfslfsllcglclwlvwvzzdsslggtzzgzdzmzddjljvvztttsgscsstztjztjztzvzwwthtftppnmpmmcpmmjlmjjjsfjsjppgcgwcggzffzwzbbmbrbprpqqpccfncfnffvcffsqqtzqzqwzwvzwwwbjbfbcbfblltnlnhhcthtvvzzfcfgfddlggbbshsggplglqqbrbggsvvzdvvlfvlvpvhhmggbrrnppjfjhffttfpffbdfbfvfqvvtcvvbvnnhbhhglgjgzzghhwrrtntrtwwfdfdmmcmtctftpptllzqllzflfrrgqgvgdvdfdbddprrrgccqvqnnmtmvmffpzzqggfbfnfwwqdqldqqlnqnttnbttrffnmmzwzjjtrjtrtmmqsmqmffqmfqfhhbthbhdhvdhvdvmvdmdhdshsqslldzztvvmzzdcccmbbhfhshrrrpsrrqqmdmmgdmmwdmdjdqqmcmttpgtgwgpwpprbrprhrsrllhsllprlplhppfzpffbhbccwdwbbrpbpvpqqmsspjssmbbmfmrmnrnwwgbwwbpwpjwwhqqgcqcvqccgffzpfftcffqlqjjznnlflhhlcczhzvhzhmzhmhfhnnqznntstwtggqjgjhggsvslltjlttfjjgffjzjwzzqzrrhlhzhbhphmhlmlzmzsmzmccvllgrrpbrbfbjfjttqjttdrdhhggqgddppqgpqgpgtptjptpllwccmwcmcpmcppdrrtstqqczqzvvlsltlddnvdvggcqqblqqsjqjttzhtzzszllqsqfqddqdbqddwqddfzzlczcscfsfpfdpdrpddsggcqchcfcpcssstwstwtggghvhqhzzqssjddwjwbjjsnjnfnwwglwwfnfhnnscsggzgjzzhzmmqfqsqwqrwqqqdtdcttzvvnbngbbcdbdggddnmddgzghhzgghwwbjbttlwlcctlccwwdhhrqrvrjjlglssgttpllwclwwtptwptwtvthtbhbzhbzhhrsrwwwnrwrfwfnwnhhnqqdjqjpqqwdwttzhttcdttvztzltzlzmzddrsdsfdsfftdfffmwffrjrffqrfqfsfqqqgqjggwzzrnnqfnqffdbfbtbbrpbrpbptpwttjmjjzrrhhqppdzdtdjttqwwtddjdzzmgzzhwwwdsdgssprsrgsgbbphhdpdwppnfppdqqwzzpbzzqwqpqsqhqdhqqtwwjnnmvmwvmmwwgjgzjjvcjcvcjcnjcncmmphmmvmwmwpwbbtbffhnhshgssgvgvrrbwbtbddqmqfqvvfqvqdvvdbvdbdcdfdlflmffrwwgmmttrztrrfrqrpqrrzjrjpjdpjprrnhhbhcbbcwwqlwwcssbddfrfjrfjfrjfjvvdmdtdzzlvzlzhzmhmhphchnnfqnffvccfpfbfpfqpprrmttzrzzjzmjmzjmmfvmmrzrqqdllgjlglcchssgllsbllrbrlrjlrrhhfwwsqwsstpssznzcznzqzssvtvtrrqwqvvtssgfsfhssljjnwjnjddjdggclcrrfsfhsstgtdtctfttvvsbvvbtbttcgcssjlslhlpljpppwzwnwdnngmgjjbzznwwdllrrfppshhvdhhldhdbbdbjbdjjrnjjzhzfhhsqqbqgmsbvnjsptlrsszlqfmgprvscphmqztbgtlrqvcgdzcptcqjncrdtfqnghnbmwwmcjgtjlbvqqzslgbbntrdfnvfjvfgcgngndjcspgwmpnsrqzzvzljbzlzzrwflrqqqmhsvqwbmdftnhwwzgqrlhddbbtwvbphljmstcjzvpjqwcnhlvpqvqdgvntgqzqwrlwbwvngwtqgrhznlzcvbwqmwncccjctrdzrmzjsvrmcfpjjcczhbvdfwhqvczggfmrspvprvvthvtqnsphpcsdmbrtbdqljvssdrhwjsrrlzprstpgqcbpmnpdgzgjttwcfrgjnsghmszlclgvmlsjrqfvflbnhwwphtvrnrbhdvdglcvgpzfsjpwwhtlvvdzthsrldfzhnlrblzsjjnwclqsqzgdbflhvpwcrtfbfbjcjttbjpvfgvfcswnqqwshbmqlscdzzwshfqwsvwnwzltbnrmzzhzvtwpzqcgwshpvzgtcmwrtrwctnpzbznnwqphnrgwljtrcwlqmvlndwrdrctztnmswslqmbjcmtlrmcpjvzccqszrnflqnqzttbhqlrhbmqdpscqvfgtdbnwjdcljwcbgbgjfzgrgpwqzqgbnrtpntfthhdbqmswvhnmwmszpghgjjzrbnbbfjblpstdfslmmmqfdcrhblqjqfphnldrvvfpnfrcvprjnqbzbspfpjtgqhnjbhnrwzcjvdbshhqpgrmzqpmjfmqwqvvdbddbsldwzzsrhnhsjjnvljrbwcnjrnjpmrrvfthftgptgtlpbgqffthflgftwcrqcqwqwrmrcmfrcqgmrnqjbscdcgrqlhjzthvzdgjbvpswflqcgsnlmgmvcsttsgmnqdtvwdvrndvfdcvrcwmqlmlhtrvthsndsrmnsfmdmfnpfmfhzjqmtcjzcrnsjdztztvgdtlrmbdmmstbfgpmmzthcslpvgrpgfljfgqlqhldfwvvvdvbzjtdtppbtrnqwsqztjrsjhtfrgmvsdngvsdzjgpwrldqpzdpvhljzpjvttwltdwcrhcbrgrvdrmpwvdwjchqsjfprbgtjtzggvgrgmlvvwqrjfprbbgjjqrtdfnrdffwbswbvqtqtfsrhsgrjhftqldhmcnmsnfflmdrzqdjmbqqgqsttdmtrrvfsjnccnhcpcvqtrzdjzrpwswmjvvgsgwvnmdgqwlctrlhqnsmczbwsjhmtgvdcgsndzlstcwchcztqqbtdwfvlljdvdlzljslgnzpmqvzfcvqhdzvgchffqgfwrnmwqzwgbzblpmvddlvnhglrhdnwzqwztzgjczjpwcjwmpnrnrhncfjfggrbphrjztwtfqmfjlwfhnqfftfghbnvtwgtmdzzrdrtmfrwhrrbhzmcllsgqzwzzqtgdggvzptvtdcpzmtmsfcfbjtzlbdrwhdbtdhhrgggmddnzsvjwgcdcqfppqwphfvlhmgqsznlhmgpnjvcvrwwppnphchgsrhjwjcpjggsrcwrvnllfgrmjltfzwhmbqwpwwzmrtlqcprrqztcgnghcbvzrbfptjmhtdcfhhffdbrswqpnpppnpqwtflrrmqgjzctmmvvvwzllbsfdvpqjtmvpjcpmjztscsgbdznfgcmtjzdqzwqrsvstnnvddcstzqjtnbsnlptpmbmfqmhppgnjrffqrtchgptbmwlwbwbcqqfngpbwtwdmlmdstmqwcwjtbwbbbhghgptmvhfmvqfvpwqzwnbjdhpwlgjgvprdjbnlzhnllssbpvzfzspwsscfpqtpdvtzvqncfrfrgddsdglqvpblmpcczlqfdmwzmgvrljhqtcglcvfhbdwhbttqqrjbqwhsrhrbjwmtqwqddvdggdwfsmnpbpvvgsqnvvrqntwmbzdnqpmmqtbnlsbmslpfmqjtgvbddhwvlvjtlrhqdpfnjwtbhwjwdrpgctbbrdqvbbnvgqwngrhqfvwzmlqtmhfqphnmczlbdpnbmpvwrsjbcnjnvcfgnsvlhpzdgdzgvfbgwdcrswznrggnghzssdwqvvlwftqhbnwdvghhvjlqqmcnqmvbwhrrnsswlwmwbsmpcpdzzgmcmqnzpvjpzqbwcsgdhqtqhcpbtqftvscmntsbdcbrndvlfhprpblzbjcpqhfljtvnvtgvrcgqbsgl
|
14
days/day06/src/main.rs
Normal file
14
days/day06/src/main.rs
Normal 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
23
days/day06/src/part1.rs
Normal 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
23
days/day06/src/part2.rs
Normal 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);
|
||||
}
|
||||
}
|
19
days/day06/src/utilities.rs
Normal file
19
days/day06/src/utilities.rs
Normal 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
11
days/day07/Cargo.toml
Normal 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
305
days/day07/src/file_tree.rs
Normal 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
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
19
days/day07/src/main.rs
Normal 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
262
days/day07/src/parser.rs
Normal 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
37
days/day07/src/part1.rs
Normal 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
44
days/day07/src/part2.rs
Normal 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
6
days/day08/Cargo.toml
Normal 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
99
days/day08/src/input.txt
Normal 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
16
days/day08/src/main.rs
Normal 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
85
days/day08/src/part1.rs
Normal 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
109
days/day08/src/part2.rs
Normal 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);
|
||||
}
|
||||
}
|
26
days/day08/src/utilities.rs
Normal file
26
days/day08/src/utilities.rs
Normal 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]
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue