Improved solutions
This commit is contained in:
parent
ec935fb2ef
commit
3be88c4f96
|
@ -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))
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<_>>();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user