Implementation day 22.

This commit is contained in:
2020-12-22 09:11:27 +01:00
parent e06e77dbad
commit 5a055b3fb1
4 changed files with 179 additions and 3 deletions

View File

@@ -7,7 +7,7 @@ use criterion::criterion_main;
use criterion::BenchmarkId; use criterion::BenchmarkId;
use criterion::Criterion; use criterion::Criterion;
const DAYS_IMPLEMENTED: usize = 20; const DAYS_IMPLEMENTED: usize = 22;
fn read_input(day: usize) -> Vec<u8> { fn read_input(day: usize) -> Vec<u8> {
let input_path = format!("inputs/{:02}.txt", day); let input_path = format!("inputs/{:02}.txt", day);

53
2020/inputs/22.txt Normal file
View File

@@ -0,0 +1,53 @@
Player 1:
26
14
6
34
37
9
17
39
4
5
1
8
49
16
18
47
20
31
23
19
35
41
28
15
44
Player 2:
7
2
10
25
29
46
40
45
11
50
42
24
38
13
36
22
33
3
43
21
48
30
32
12
27

13
2020/samples/22.txt Normal file
View File

@@ -0,0 +1,13 @@
Player 1:
9
2
6
3
1
Player 2:
5
8
4
7
10

View File

@@ -1,12 +1,122 @@
use std::collections::HashSet;
use std::collections::VecDeque;
use std::io::Read; use std::io::Read;
use crate::common::Lines;
use crate::Solution; use crate::Solution;
type Deck = VecDeque<u32>;
fn read_input(input: &mut dyn Read) -> (Deck, Deck) {
let mut lines = Lines::new(input).skip(1);
let mut player1 = VecDeque::new();
while let Some(line) = lines.next() {
if line.is_empty() {
break;
}
player1.push_back(line.parse().unwrap());
}
let player2 = lines.skip(1).map(|l| l.parse().unwrap()).collect();
(player1, player2)
}
fn play_recursive_game(mut p1: Deck, mut p2: Deck) -> (bool, Deck) {
let mut seen = HashSet::new();
while !p1.is_empty() && !p2.is_empty() {
if !seen.insert((p1.clone(), p2.clone())) {
return (true, p1);
}
let v1 = p1.pop_front().unwrap();
let v2 = p2.pop_front().unwrap();
let p1_wins = if v1 as usize <= p1.len() && v2 as usize <= p2.len() {
let p1_copy = p1.iter().take(v1 as usize).copied().collect();
let p2_copy = p2.iter().take(v2 as usize).copied().collect();
play_recursive_game(p1_copy, p2_copy).0
} else {
v1 > v2
};
if p1_wins {
p1.push_back(v1);
p1.push_back(v2);
} else {
p2.push_back(v2);
p2.push_back(v1);
}
}
if p1.is_empty() {
(false, p2)
} else {
(true, p1)
}
}
fn score(winner: Deck) -> u32 {
winner
.into_iter()
.rev()
.enumerate()
.map(|(pos, val)| (pos as u32 + 1) * (val as u32))
.sum()
}
#[derive(Default)] #[derive(Default)]
pub struct Day22; pub struct Day22;
impl Solution for Day22 { impl Solution for Day22 {
fn part1(&mut self, _input: &mut dyn Read) -> String { fn part1(&mut self, input: &mut dyn Read) -> String {
todo!() let (mut p1, mut p2) = read_input(input);
while !p1.is_empty() && !p2.is_empty() {
let v1 = p1.pop_front().unwrap();
let v2 = p2.pop_front().unwrap();
if v1 > v2 {
p1.push_back(v1);
p1.push_back(v2);
} else {
p2.push_back(v2);
p2.push_back(v1);
}
}
let winner = if p1.is_empty() { p2 } else { p1 };
score(winner).to_string()
}
fn part2(&mut self, input: &mut dyn Read) -> String {
let (p1, p2) = read_input(input);
score(play_recursive_game(p1, p2).1).to_string()
}
}
#[cfg(test)]
mod tests {
use crate::test_implementation;
use super::*;
const SAMPLE: &[u8] = include_bytes!("../samples/22.txt");
#[test]
fn sample_part1() {
test_implementation!(Day22, 1, SAMPLE, 306);
}
#[test]
fn sample_part2() {
test_implementation!(Day22, 2, SAMPLE, 291);
} }
} }