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 -- // -- 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 { fn calc_score(sum: u32, (a, b): (Hand, Hand)) -> u32 {
sum + b.play(&a) + u32::from(&b) sum + b.play(&a) + u32::from(&b)
} }
@ -116,16 +108,14 @@ impl aoc::Solver for Day {
fn part1(input: &str) -> u32 { fn part1(input: &str) -> u32 {
input.lines() input.lines()
.filter(|round| round.len() > 0) .filter_map(|round| round.split_once(" "))
.map(convert)
.map(|(a, b)| (Hand::from(a), Hand::from(b))) .map(|(a, b)| (Hand::from(a), Hand::from(b)))
.fold(0, calc_score) .fold(0, calc_score)
} }
fn part2(input: &str) -> u32 { fn part2(input: &str) -> u32 {
input.lines() input.lines()
.filter(|round| round.len() > 0) .filter_map(|round| round.split_once(" "))
.map(convert)
.map(|(a, b)| { .map(|(a, b)| {
let opponent = Hand::from(a); let opponent = Hand::from(a);
(opponent, opponent.strategy(b)) (opponent, opponent.strategy(b))

View File

@ -29,13 +29,28 @@ mod tests {
} }
// -- Helpers -- // -- Helpers --
fn convert(c: &u8) -> u32 { fn convert(c: char) -> u32 {
let result = match c { let result = match c {
b'a'..=b'z' => c - b'a' + 1, 'a'..='z' => c as u32 - 'a' as u32 + 1,
b'A'..=b'Z' => c - b'A' + 27, 'A'..='Z' => c as u32 - 'A' as u32 + 27,
_ => panic!("Invalid input"), _ => 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 -- // -- Solution --
@ -49,11 +64,9 @@ impl aoc::Solver for Day {
input.lines() input.lines()
.map(|line| line.split_at(line.len()/2)) .map(|line| line.split_at(line.len()/2))
.map(|(a, b)| { .map(|(a, b)| {
// @NOTE This is not really ok if the string contains multi byte characters, this for c in a.chars() {
// is however not the case here
for c in a.as_bytes() {
// There is always one character in common between the two sides // There is always one character in common between the two sides
if b.contains(*c as char) { if b.contains(c) {
return c; return c;
} }
} }
@ -67,24 +80,7 @@ impl aoc::Solver for Day {
input.lines() input.lines()
.collect::<Vec<_>>() .collect::<Vec<_>>()
.chunks(3) .chunks(3)
.map(|group| { .map(find_common)
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(convert) .map(convert)
.sum() .sum()
} }

View File

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