Complete day 10

This commit is contained in:
Tristan Daniël Maat 2020-12-10 23:41:34 +00:00
parent af685599f5
commit cd519c3bd1
Signed by: tlater
GPG key ID: 49670FD774E43268
5 changed files with 412 additions and 0 deletions

1
day-10/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target/

78
day-10/Cargo.lock generated Normal file
View file

@ -0,0 +1,78 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "day-10"
version = "0.1.0"
dependencies = [
"indoc",
]
[[package]]
name = "indoc"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8"
dependencies = [
"indoc-impl",
"proc-macro-hack",
]
[[package]]
name = "indoc-impl"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0"
dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote",
"syn",
"unindent",
]
[[package]]
name = "proc-macro-hack"
version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro2"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [
"proc-macro2",
]
[[package]]
name = "syn"
version = "1.0.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "unindent"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7"

10
day-10/Cargo.toml Normal file
View file

@ -0,0 +1,10 @@
[package]
name = "day-10"
version = "0.1.0"
authors = ["Tristan Daniël Maat <tm@tlater.net>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
indoc = "0.3"

95
day-10/input Normal file
View file

@ -0,0 +1,95 @@
76
12
97
28
132
107
145
121
84
34
115
127
22
23
11
135
113
82
140
119
69
77
83
36
13
37
92
133
122
99
147
112
42
62
65
40
123
139
33
129
149
68
41
16
48
109
5
27
142
81
90
9
78
103
26
100
141
59
55
120
126
1
35
2
20
114
58
54
10
51
116
93
6
134
108
47
70
91
138
63
19
64
148
106
21
98
43
30
146
46
128
73
94
87
29

228
day-10/src/main.rs Normal file
View file

@ -0,0 +1,228 @@
use std::convert::TryInto;
use std::fs;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let input = fs::read_to_string("input")?;
let jolts = parse_jolts(&input)?;
// Part 1
let result = chain_all(&jolts);
println!("{}", result.0 * result.2);
// Part 2
let result = count_possible_chains(&jolts)?;
println!("{}", result);
Ok(())
}
fn count_possible_chains(jolts: &Vec<u64>) -> Result<u64, std::num::TryFromIntError> {
let mut jolts = jolts.to_vec();
jolts.push(0);
jolts.sort();
jolts.push(jolts.last().expect("Need some jolts") + 3);
let window_lengths: Vec<usize> = jolts
.windows(2)
.scan(0, |length, window| {
if let [previous, current, _empty @ ..] = window {
if *current - *previous < 3 {
*length += 1;
Some(None)
} else {
let full_length = *length;
*length = 0;
Some(Some(full_length))
}
} else {
unreachable!("Window size is 2");
}
})
.filter_map(|option| option)
.collect();
fn permutations(length: u32) -> u64 {
if length == 0 {
1
} else {
2u64.pow(length - 1) - if length > 3 { 2u64.pow(length - 4) } else { 0 }
}
}
window_lengths
.iter()
.map(|length| Ok(permutations((*length).try_into()?)))
.product::<Result<u64, _>>()
}
fn chain_all(jolts: &Vec<u64>) -> (usize, usize, usize) {
let mut jolts = jolts.to_vec();
// Add input jolts
jolts.push(0);
// Add output jolts
jolts.sort();
jolts.push(jolts.last().expect("Need some jolts") + 3);
let jolt_jumps: Vec<u64> = jolts
.windows(2)
.map(|window| {
if let [first, second, _empty @ ..] = window {
second - first
} else {
unreachable!("Window size is 2");
}
})
.collect();
let jump_1s = jolt_jumps.iter().filter(|e| **e == 1).count();
let jump_2s = jolt_jumps.iter().filter(|e| **e == 2).count();
let jump_3s = jolt_jumps.iter().filter(|e| **e == 3).count();
(jump_1s, jump_2s, jump_3s)
}
fn parse_jolts(input: &str) -> Result<Vec<u64>, std::num::ParseIntError> {
input.lines().map(|line| line.parse()).collect()
}
#[cfg(test)]
mod tests {
use super::*;
use indoc::indoc;
#[test]
fn test_simple() -> Result<(), Box<dyn std::error::Error>> {
let input = indoc!(
"16
10
15
5
1
11
7
19
6
12
4
"
);
let jolts = parse_jolts(input)?;
let result = chain_all(&jolts);
assert_eq!(result.0 * result.2, 7 * 5);
Ok(())
}
#[test]
fn test_simple2() -> Result<(), Box<dyn std::error::Error>> {
let input = indoc!(
"28
33
18
42
31
14
46
20
48
47
24
23
49
45
19
38
39
11
1
32
25
35
8
17
7
9
4
2
34
10
3
"
);
let jolts = parse_jolts(input)?;
let result = chain_all(&jolts);
assert_eq!(result.0 * result.2, 22 * 10);
Ok(())
}
#[test]
fn test_simple3() -> Result<(), Box<dyn std::error::Error>> {
let input = indoc!(
"16
10
15
5
1
11
7
19
6
12
4
"
);
let jolts = parse_jolts(input)?;
let result = count_possible_chains(&jolts)?;
assert_eq!(result, 8);
Ok(())
}
#[test]
fn test_simple4() -> Result<(), Box<dyn std::error::Error>> {
let input = indoc!(
"28
33
18
42
31
14
46
20
48
47
24
23
49
45
19
38
39
11
1
32
25
35
8
17
7
9
4
2
34
10
3
"
);
let jolts = parse_jolts(input)?;
let result = count_possible_chains(&jolts)?;
assert_eq!(result, 19208);
Ok(())
}
}