Skip to content

Commit 05e22da

Browse files
committed
feat: completed day 13
1 parent 6e01b40 commit 05e22da

File tree

8 files changed

+196
-1
lines changed

8 files changed

+196
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
- [Day 10](https://github.com/ankjevel/adventofcode/tree/2020/day_10) 🌟 🌟
1515
- [Day 11](https://github.com/ankjevel/adventofcode/tree/2020/day_11) 🌟 🌟
1616
- [Day 12](https://github.com/ankjevel/adventofcode/tree/2020/day_12) 🌟 🌟
17-
- [Day 13](#)
17+
- [Day 13](https://github.com/ankjevel/adventofcode/tree/2020/day_13) 🌟 🌟
1818
- [Day 14](#)
1919
- [Day 15](#)
2020
- [Day 16](#)

day_13/Cargo.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[package]
2+
name = "day_13"
3+
version = "0.1.0"
4+
edition = "2018"
5+
authors = ["Dennis Pettersson <mail@dennispettersson.se>"]
6+
7+
[lib]
8+
doctest = false
9+
10+
[[bin]]
11+
name = "day_13"
12+
13+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
14+
15+
[dependencies]

day_13/src/chinese_remainder.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// https://rosettacode.org/wiki/Chinese_remainder_theorem#Rust
2+
3+
fn egcd(a: i64, b: i64) -> (i64, i64, i64) {
4+
if a == 0 {
5+
(b, 0, 1)
6+
} else {
7+
let (g, x, y) = egcd(b % a, a);
8+
(g, y - (b / a) * x, x)
9+
}
10+
}
11+
12+
fn mod_inv(x: i64, n: i64) -> Option<i64> {
13+
let (g, x, _) = egcd(x, n);
14+
if g == 1 {
15+
Some((x % n + n) % n)
16+
} else {
17+
None
18+
}
19+
}
20+
21+
pub fn chinese_remainder(residues: &[i64], modulii: &[i64]) -> Option<i64> {
22+
let prod = modulii.iter().product::<i64>();
23+
let mut sum = 0;
24+
for (&residue, &modulus) in residues.iter().zip(modulii) {
25+
let p = prod / modulus;
26+
sum += residue * mod_inv(p, modulus)? * p
27+
}
28+
Some(sum % prod)
29+
}

day_13/src/lib.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
pub mod chinese_remainder;
2+
pub mod part_01;
3+
pub mod part_02;
4+
5+
pub type Input = (u64, Vec<Option<u64>>);
6+
7+
pub fn parse_input(input: &str) -> Input {
8+
let mut input = input
9+
.lines()
10+
.map(str::trim)
11+
.filter(|string| !string.is_empty())
12+
.map(str::to_owned)
13+
.into_iter();
14+
15+
let earliest = input
16+
.next()
17+
.unwrap_or("".to_string())
18+
.parse::<_>()
19+
.unwrap_or(0);
20+
21+
let busses = input.next().unwrap_or("".to_string());
22+
let busses = busses
23+
.split(",")
24+
.into_iter()
25+
.map(|string| {
26+
if string == "x" {
27+
None
28+
} else {
29+
Some(string.parse::<_>().unwrap_or(0))
30+
}
31+
})
32+
.collect::<Vec<_>>();
33+
34+
(earliest, busses)
35+
}
36+
37+
#[cfg(test)]
38+
mod tests {
39+
use super::*;
40+
41+
const EXAMPLE_DATA: &'static str = "
42+
939
43+
7,13,x,x,59,x,31,19
44+
";
45+
46+
#[test]
47+
fn it_parses_example() {
48+
assert_eq!(
49+
parse_input(&EXAMPLE_DATA),
50+
(
51+
939,
52+
vec![
53+
Some(7),
54+
Some(13),
55+
None,
56+
None,
57+
Some(59),
58+
None,
59+
Some(31),
60+
Some(19)
61+
]
62+
)
63+
);
64+
}
65+
}

day_13/src/main.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use std::io::Result;
2+
3+
use day_13::{parse_input, part_01::main as part_01, part_02::main as part_02};
4+
5+
fn main() -> Result<()> {
6+
let input = parse_input(include_str!("../../input/day_13"));
7+
8+
println!("part_01: {:?}", part_01(&input)?);
9+
println!("part_02: {:?}", part_02(&input)?);
10+
11+
Ok(())
12+
}

day_13/src/part_01.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use std::io::Result;
2+
3+
use crate::Input;
4+
5+
pub fn main((earliest, busses): &Input) -> Result<u64> {
6+
let earliest = *earliest;
7+
let busses = busses
8+
.iter()
9+
.filter(|bus| bus.is_some())
10+
.map(|bus| bus.unwrap())
11+
.collect::<Vec<_>>();
12+
13+
let mut result = 0;
14+
for timestamp in earliest.. {
15+
if let Some(bus_id) = busses.iter().find(|bus_id| timestamp % **bus_id == 0) {
16+
result = *bus_id * (timestamp - earliest);
17+
break;
18+
}
19+
}
20+
Ok(result)
21+
}
22+
23+
#[cfg(test)]
24+
mod tests {
25+
use crate::parse_input;
26+
27+
use super::*;
28+
29+
const EXAMPLE_DATA: &'static str = "
30+
939
31+
7,13,x,x,59,x,31,19
32+
";
33+
34+
#[test]
35+
fn it_gets_the_example_correct() -> Result<()> {
36+
assert_eq!(main(&parse_input(&EXAMPLE_DATA))?, 295);
37+
Ok(())
38+
}
39+
}

day_13/src/part_02.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use std::io::Result;
2+
3+
use crate::{chinese_remainder::chinese_remainder, Input};
4+
5+
pub fn main((_, busses): &Input) -> Result<i64> {
6+
let busses = busses
7+
.iter()
8+
.enumerate()
9+
.filter(|(_, bus)| bus.is_some())
10+
.map(|(i, bus)| (i as i64, bus.unwrap_or(0) as i64))
11+
.collect::<Vec<_>>();
12+
let mods = busses.iter().map(|&(_, b)| b).collect::<Vec<_>>();
13+
let res = busses.iter().map(|&(i, b)| b - i).collect::<Vec<_>>();
14+
Ok(chinese_remainder(&res, &mods).unwrap())
15+
}
16+
17+
#[cfg(test)]
18+
mod tests {
19+
use crate::parse_input;
20+
21+
use super::*;
22+
23+
#[test]
24+
fn it_gets_the_example_correct() -> Result<()> {
25+
assert_eq!(main(&parse_input("0\n7,13,x,x,59,x,31,19"))?, 1068781);
26+
assert_eq!(main(&parse_input("0\n17,x,13,19"))?, 3417);
27+
assert_eq!(main(&parse_input("0\n67,7,59,61"))?, 754018);
28+
assert_eq!(main(&parse_input("0\n67,x,7,59,61"))?, 779210);
29+
assert_eq!(main(&parse_input("0\n67,7,x,59,61"))?, 1261476);
30+
assert_eq!(main(&parse_input("0\n1789,37,47,1889"))?, 1202161486);
31+
Ok(())
32+
}
33+
}

input/day_13

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
1001287
2+
13,x,x,x,x,x,x,37,x,x,x,x,x,461,x,x,x,x,x,x,x,x,x,x,x,x,x,17,x,x,x,x,19,x,x,x,x,x,x,x,x,x,29,x,739,x,x,x,x,x,x,x,x,x,41,x,x,x,x,x,x,x,x,x,x,x,x,23

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy