Improved solutions

This commit is contained in:
Dreaded_X 2022-12-04 19:44:00 +01:00
parent ec935fb2ef
commit 3be88c4f96
3 changed files with 27 additions and 40 deletions

View File

@ -95,14 +95,6 @@ impl From<&Hand> for u32 {
}
// -- Helper functions --
// Convert the round to a tuple containing the actions of both players
fn convert(round: &str) -> (&str, &str) {
match round.split_once(" ") {
Some((a, b)) => (a, b),
None => panic!("Invalid input: {round}"),
}
}
fn calc_score(sum: u32, (a, b): (Hand, Hand)) -> u32 {
sum + b.play(&a) + u32::from(&b)
}
@ -116,16 +108,14 @@ impl aoc::Solver for Day {
fn part1(input: &str) -> u32 {
input.lines()
.filter(|round| round.len() > 0)
.map(convert)
.filter_map(|round| round.split_once(" "))
.map(|(a, b)| (Hand::from(a), Hand::from(b)))
.fold(0, calc_score)
}
fn part2(input: &str) -> u32 {
input.lines()
.filter(|round| round.len() > 0)
.map(convert)
.filter_map(|round| round.split_once(" "))
.map(|(a, b)| {
let opponent = Hand::from(a);
(opponent, opponent.strategy(b))

View File

@ -29,13 +29,28 @@ mod tests {
}
// -- Helpers --
fn convert(c: &u8) -> u32 {
fn convert(c: char) -> u32 {
let result = match c {
b'a'..=b'z' => c - b'a' + 1,
b'A'..=b'Z' => c - b'A' + 27,
'a'..='z' => c as u32 - 'a' as u32 + 1,
'A'..='Z' => c as u32 - 'A' as u32 + 27,
_ => panic!("Invalid input"),
};
result as u32
result
}
// Very nice alternative way to find the overlap
// Based on something I say online
// Part 1 could also be adapted to use this, but for historical sake I will leave that as is
// Part 2 was originally done the same as part 1, just with an extra condition in the if
fn find_common(group: &[&str]) -> char {
let mut common = group[0].chars().collect::<Vec<_>>();
// Only keep characters that appear in all other strings
common.retain(|&c| {
group[1..].iter().all(|g| g.contains(c))
});
*common.first().expect("Should be one overlap")
}
// -- Solution --
@ -49,11 +64,9 @@ impl aoc::Solver for Day {
input.lines()
.map(|line| line.split_at(line.len()/2))
.map(|(a, b)| {
// @NOTE This is not really ok if the string contains multi byte characters, this
// is however not the case here
for c in a.as_bytes() {
for c in a.chars() {
// There is always one character in common between the two sides
if b.contains(*c as char) {
if b.contains(c) {
return c;
}
}
@ -67,24 +80,7 @@ impl aoc::Solver for Day {
input.lines()
.collect::<Vec<_>>()
.chunks(3)
.map(|group| {
if let [a, b, c] = group {
(a, b, c)
} else {
panic!("The total amount of lines should be a multiple of 3")
}
})
.map(|(a, b, c)| {
// @NOTE This is not really ok if the string contains multi byte characters, this
// is however not the case here
for l in a.as_bytes() {
// There is always one character in common between the three rucksacks
if b.contains(*l as char) && c.contains(*l as char) {
return l;
}
}
unreachable!("No characters in common, this should never happen")
})
.map(find_common)
.map(convert)
.sum()
}

View File

@ -54,8 +54,9 @@ fn overlaps((a, b): &(Elf, Elf)) -> bool {
// Transform from line to pair of Elfs
fn transform(s: &str) -> (Elf, Elf) {
let transformed = s.split(',')
.flat_map(|pair| pair.split('-'))
let transformed = s
.replace("-", ",")
.split(',')
.flat_map(|value| value.parse::<u32>())
.collect::<Vec<_>>();