Complete day 12.1

pull/10/head
Tristan Daniël Maat 2020-12-12 20:00:34 +00:00
parent 0355eeccb4
commit c0a6391e85
Signed by: tlater
GPG Key ID: 49670FD774E43268
4 changed files with 1020 additions and 0 deletions

78
day-12/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-12"
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-12/Cargo.toml Normal file
View File

@ -0,0 +1,10 @@
[package]
name = "day-12"
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"

771
day-12/input Normal file
View File

@ -0,0 +1,771 @@
F8
N2
F32
F17
E4
N4
R90
S2
R90
E3
L90
N5
E2
N2
W5
F78
L180
F19
R90
S1
E2
L180
E1
S5
E4
F62
R180
F16
S2
F8
R180
S1
L90
E4
R90
S3
E5
R180
F87
N2
E2
R90
N2
F2
R90
N5
W4
L90
F42
N1
F93
F87
E2
S4
F73
L270
S2
W3
F48
W5
L180
N1
F53
R90
S2
R90
N2
E2
S5
W3
R90
E2
R90
W1
L180
F29
W1
F56
R90
F34
F74
S1
R90
L90
W4
L90
W5
L90
W1
L90
N5
E2
S2
F58
N5
L90
S4
L90
R270
W4
S4
E3
R180
S4
W3
R90
F36
R90
W1
F73
S4
E1
L90
S4
W5
L90
F20
W3
L180
E3
S1
R90
S5
W3
L90
E5
W2
F21
N4
F83
W4
F48
W3
F4
L90
N5
R270
E1
S5
L180
F44
W5
R180
S3
F30
N5
F87
L90
F69
S5
E1
R90
E2
S3
F40
W4
F97
W5
F20
L180
N5
L90
E5
N3
L90
F13
N2
F38
S5
F27
E5
L180
F59
N3
F2
R90
N2
R90
F56
L90
N4
R90
F12
F34
N3
F93
L270
W3
F74
W4
R90
E2
L180
W3
F12
N5
W1
F98
E4
R180
S1
W5
R90
F96
N2
L90
F36
S1
F3
W3
F100
N5
R90
F33
W3
N5
E3
R90
F33
N5
E2
N1
L90
F84
L270
E1
F28
R180
W3
L90
S2
F88
L90
W2
N1
F3
R90
F56
N1
N4
L90
R90
F97
E5
N4
F38
N1
R90
W1
F60
W3
N1
F59
E1
N3
E3
L180
N1
F53
S1
E2
R90
E2
F6
R180
F36
R180
W2
F81
R90
E4
R90
F97
L90
W1
S1
E5
L180
F34
R180
F64
E2
R180
W3
S5
L90
E4
F12
F58
W3
N3
F77
N4
F32
R90
N2
E4
L90
S5
E1
N5
F44
R90
F5
E4
R90
N5
E4
R180
W3
L90
N1
F1
S3
E5
R180
S3
F86
S5
F61
W3
R270
W5
R90
F26
R180
F92
S5
L90
E5
N5
F82
R90
F22
R90
F23
S1
F42
N4
F76
E1
S1
W3
S2
L90
F19
E4
F41
E2
N2
L90
F34
S4
F20
W3
F18
S1
R90
N3
F38
W3
R90
W4
R90
E2
R90
F10
L90
N4
F94
S1
W3
R180
W5
F74
R90
S4
L180
S3
F74
N5
S4
L90
F34
S2
E5
N5
F28
L90
E1
F31
N1
L90
L90
W2
N5
R90
F1
N5
F48
W2
F50
N2
F62
S4
L90
W5
N1
F12
W3
R90
R90
F75
N5
F69
E3
F19
N2
F77
E1
N4
R180
E3
N2
L90
N1
W1
S4
F85
W1
R90
F74
E5
F73
E4
S3
W4
S5
L90
F49
S5
E5
F5
W2
F58
R90
W5
F53
S4
F86
N2
F88
E5
F59
E1
F56
W2
N4
W4
R180
F16
F25
R180
N3
F4
W4
S4
F98
E5
L90
W4
S1
E2
R90
F96
L270
E1
N1
F55
S1
F10
R90
W2
L90
N5
R90
N4
E4
L90
F52
S3
F43
E2
R90
S3
R90
N4
E1
N4
F15
E3
R270
L180
N2
F43
L90
W2
F19
L90
S5
F58
E4
S4
L90
W1
F9
N4
F38
S5
L90
W1
F39
W5
F83
L180
F99
L90
E3
S2
R90
N3
F35
N1
N3
L90
N4
W5
F26
R270
N2
F7
N1
F16
S4
L90
S5
L180
F5
W1
F32
S2
N3
F82
N4
R90
F27
R180
F20
S1
E3
L90
W3
F23
L180
N3
F34
W1
N3
S2
F80
E5
F65
L90
E5
N1
F80
R90
W3
L90
N1
L180
S1
F65
E3
S1
W3
F89
S1
F24
E5
F85
W1
F87
S1
R90
S4
F3
S3
F23
N4
L90
N5
R90
N2
R90
S2
W4
S2
F95
L90
F52
W1
N5
L90
N4
S3
E3
R90
N2
E1
R180
W4
F82
L180
E5
L90
E4
F65
W5
R90
W5
N5
L180
N4
F22
W3
S4
F60
R90
E5
N3
F32
S2
F80
R90
F18
S3
L90
F90
E3
L90
N3
E5
F79
N5
W4
S5
F100
N1
E3
S3
F49
R180
S3
E2
F1
W1
F5
R180
S5
W3
S3
F67
R270
N3
W3
N1
W3
F37
L90
N3
L90
F68
N3
W4
W2
F26
N3
L90
W3
S2
F7
W3
E3
L270
F64
R90
E4
R90
W3
N1
W1
F98
R270
W5
F45
R90
F49
E4
S2
F58
F56
W3
F57
E3
S5
R180
E3
F82
F57
S3
W2
R90
E2
R90
F95
W4
F85
E3
N3
R90
E5
F31
R90
F20
R90
N5
E3
S4
R180
W1
N5
F72
L90
E3
F46
R180
F18
E3
F48
S2
F84
W3
F88
F44
S2
E4
F77
L90
N4
L90
E2
F22
E5
L90
F79
W1
R90
F41
R180
F54

161
day-12/src/main.rs Normal file
View File

@ -0,0 +1,161 @@
use std::fs;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let input = fs::read_to_string("input")?;
let actions = parse_actions(&input)?;
// Part 1
let location = simulate_ship_movement(&actions);
println!("{}", location.0.abs() + location.1.abs());
Ok(())
}
#[derive(Copy, Clone, Debug)]
enum Action {
North(u32),
South(u32),
East(u32),
West(u32),
Left(u32),
Right(u32),
Forward(u32),
}
impl Action {
fn new(input: &str) -> Result<Self, String> {
if input.len() < 2 {
Err(format!("Invalud input line: {}", input))?;
}
let (action, value) = input.split_at(1);
let value = value
.parse()
.map_err(|e| format!("Could not parse value: {}", e))?;
Ok(match action {
"N" => Self::North(value),
"S" => Self::South(value),
"E" => Self::East(value),
"W" => Self::West(value),
"L" => Self::Left(value),
"R" => Self::Right(value),
"F" => Self::Forward(value),
_ => Err(format!("Could not parse action: {}", action))?,
})
}
fn opposite_direction(self) -> Self {
match self {
Action::North(x) => Action::South(x),
Action::South(x) => Action::North(x),
Action::East(x) => Action::West(x),
Action::West(x) => Action::East(x),
_ => panic!("Invalid direction"),
}
}
fn right_direction(self) -> Self {
match self {
Action::North(x) => Action::East(x),
Action::South(x) => Action::West(x),
Action::East(x) => Action::South(x),
Action::West(x) => Action::North(x),
_ => panic!("Invalid direction"),
}
}
fn left_direction(self) -> Self {
match self {
Action::North(x) => Action::West(x),
Action::South(x) => Action::East(x),
Action::East(x) => Action::North(x),
Action::West(x) => Action::South(x),
_ => panic!("Invalid direction"),
}
}
}
fn parse_actions(input: &str) -> Result<Vec<Action>, String> {
input.lines().map(Action::new).collect()
}
fn simulate_ship_movement(actions: &Vec<Action>) -> (i64, i64) {
let mut coords: (i64, i64) = (0, 0);
let mut direction = Action::East(0);
for action in actions {
// If the action is Action::Forward, we instead want to move
// in a direction determined by our current angle.
//
// So we convert Action::Forward to a concrete direction.
let converted_action = if let &Action::Forward(amount) = action {
match direction {
Action::North(_) => Action::North(amount),
Action::South(_) => Action::South(amount),
Action::East(_) => Action::East(amount),
Action::West(_) => Action::West(amount),
_ => unreachable!("Direction can only be NSEW."),
}
} else {
*action
};
match converted_action {
Action::North(amount) => {
coords.1 += amount as i64;
}
Action::South(amount) => {
coords.1 -= amount as i64;
}
Action::East(amount) => {
coords.0 += amount as i64;
}
Action::West(amount) => {
coords.0 -= amount as i64;
}
Action::Left(amount) => match amount % 360 {
0 => direction = direction,
90 => direction = direction.left_direction(),
180 => direction = direction.opposite_direction(),
270 => direction = direction.right_direction(),
_ => panic!("Only 90 degree turns allowed"),
},
Action::Right(amount) => match amount % 360 {
0 => direction = direction,
90 => direction = direction.right_direction(),
180 => direction = direction.opposite_direction(),
270 => direction = direction.left_direction(),
_ => panic!("Only 90 degree turns allowed"),
},
Action::Forward(_) => unreachable!("Converted previously"),
}
}
coords
}
#[cfg(test)]
mod tests {
use super::*;
use indoc::indoc;
#[test]
fn test_simple() -> Result<(), Box<dyn std::error::Error>> {
let input = indoc!(
"F10
N3
F7
R90
F11
"
);
let actions = parse_actions(&input)?;
let location = simulate_ship_movement(&actions);
assert_eq!(location.0.abs() + location.1.abs(), 25);
Ok(())
}
}