Rust solutions

This commit is contained in:
Sijmen 2020-12-06 18:07:08 +01:00
commit 59264dfa91
Signed by: vijfhoek
GPG key ID: DAF7821E067D9C48
3 changed files with 352 additions and 0 deletions

56
rust/Cargo.lock generated Normal file
View file

@ -0,0 +1,56 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
dependencies = [
"memchr",
]
[[package]]
name = "aoc"
version = "0.1.0"
dependencies = [
"regex",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "memchr"
version = "2.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
[[package]]
name = "regex"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"thread_local",
]
[[package]]
name = "regex-syntax"
version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
[[package]]
name = "thread_local"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
dependencies = [
"lazy_static",
]

10
rust/Cargo.toml Normal file
View file

@ -0,0 +1,10 @@
[package]
name = "aoc"
version = "0.1.0"
authors = ["Sijmen Schoon <me@sijmenschoon.nl>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
regex = "1.4.2"

286
rust/src/main.rs Normal file
View file

@ -0,0 +1,286 @@
use std::time::Duration;
mod day01 {
use std::{collections::HashMap, time::Duration, time::Instant};
pub fn run(print: bool) -> Duration {
let file_string = std::fs::read_to_string("inputs/day01").unwrap();
let instant = Instant::now();
let entries: Vec<usize> = file_string.lines().flat_map(|line| line.parse()).collect();
let mut sums = HashMap::new();
let mut part1 = None;
for i in &entries {
for j in &entries {
if i + j < 2020 {
sums.insert(i + j, i * j);
} else if i + j == 2020 {
part1 = Some(i * j);
}
}
}
let part1 = part1.unwrap();
let part2 = entries
.iter()
.find_map(|i| sums.get(&(2020 - i)).map(|mul| i * mul))
.unwrap();
let elapsed = instant.elapsed();
if print {
dbg!(elapsed, part1, part2);
}
elapsed
}
}
mod day02 {
use std::time::{Duration, Instant};
pub fn run(print: bool) -> Duration {
let file_string = std::fs::read_to_string("inputs/day02").unwrap();
let instant = Instant::now();
let rules: Vec<(usize, usize, char, &str)> = file_string
.lines()
.flat_map(|rule| {
let mut splitc = rule.splitn(2, ' ');
let mut split_range = splitc.next()?.split('-');
let min: usize = split_range.next()?.parse().ok()?;
let max: usize = split_range.next()?.parse().ok()?;
let rest = splitc.next()?;
let c = rest.chars().next()?;
let pw = &rest[3..];
Some((min, max, c, pw))
})
.collect();
let part1 = rules
.iter()
.filter(|(min, max, c, pw)| {
let c = &pw.chars().filter(|n| n == c).count();
min <= c && c <= max
})
.count();
let part2 = rules
.iter()
.filter(|(min, max, c, pw)| {
let mut chars = pw.chars();
let a = chars.nth(min - 1) == Some(*c);
let b = chars.nth(max - min - 1) == Some(*c);
a ^ b
})
.count();
let elapsed = instant.elapsed();
if print {
dbg!(elapsed, part1, part2);
}
elapsed
}
}
mod day03 {
use std::time::{Duration, Instant};
fn count(rows: &[Vec<char>], dx: usize, dy: usize) -> usize {
let mut x = 0;
let mut trees = 0;
for y in (0..rows.len()).step_by(dy) {
let row = &rows[y];
if row[x] == '#' {
trees += 1;
}
x = (x + dx) % row.len();
}
trees
}
pub fn run(print: bool) -> Duration {
let file_string = std::fs::read_to_string("inputs/day3").unwrap();
let instant = Instant::now();
let rows: Vec<Vec<char>> = file_string
.lines()
.map(|line| line.chars().collect())
.collect();
let part1 = count(&rows, 3, 1);
let part2 = part1
* [(1, 1), (5, 1), (7, 1), (1, 2)]
.iter()
.map(|(dx, dy)| count(&rows, *dx, *dy))
.fold(1, |acc, element| acc * element);
let elapsed = instant.elapsed();
if print {
dbg!(elapsed, part1, part2);
}
elapsed
}
}
mod day04 {
use std::time::{Duration, Instant};
fn between(field: &str, lower: i32, higher: i32) -> bool {
let n: i32 = field.parse().unwrap();
n >= lower && n <= higher
}
pub fn run(print: bool) -> Duration {
let input = std::fs::read_to_string("inputs/day04").unwrap();
let now = Instant::now();
let passports: Vec<_> = input
.split("\n\n")
.map(|p| p.replace('\n', " ").trim().to_string())
.collect();
let valid_passports = passports.iter().filter(|p| {
p.contains("byr")
&& p.contains("iyr")
&& p.contains("eyr")
&& p.contains("hgt")
&& p.contains("hcl")
&& p.contains("ecl")
&& p.contains("pid")
});
let mut part1 = 0;
let part2 = valid_passports
.filter(|p| {
part1 += 1;
let mut valid = true;
for field in p.split(' ') {
let mut parts = field.split(':');
let label = parts.next().unwrap();
let value = parts.next().unwrap();
valid = valid
&& match label {
"byr" => between(value, 1920, 2002),
"iyr" => between(value, 2010, 2020),
"eyr" => between(value, 2020, 2030),
"hgt" => {
let height = &value[..value.len() - 2];
(value.ends_with("in") && between(height, 59, 76))
|| (value.ends_with("cm") && between(height, 150, 193))
}
"hcl" => value.starts_with("#"),
"ecl" => {
value == "amb"
|| value == "blu"
|| value == "brn"
|| value == "gry"
|| value == "grn"
|| value == "hzl"
|| value == "oth"
}
"pid" => value.len() == 9,
"cid" => true,
_ => false,
}
}
valid
})
.count();
let elapsed = now.elapsed();
if print {
dbg!(elapsed, part1, part2);
}
elapsed
}
}
mod day05 {
use std::time::{Duration, Instant};
pub fn run(print: bool) -> Duration {
let input = std::fs::read_to_string("inputs/day05").unwrap();
let instant = Instant::now();
let passes: Vec<_> = input.lines().collect();
let mut ids: Vec<_> = passes
.iter()
.map(|pass| {
let mut row_min = 0;
let mut row_max = 128;
let mut column_min = 0;
let mut column_max = 8;
for c in pass.chars() {
match c {
'F' => row_max = (row_min + row_max) / 2,
'B' => row_min = (row_min + row_max) / 2,
'L' => column_max = (column_min + column_max) / 2,
'R' => column_min = (column_min + column_max) / 2,
_ => (),
};
}
row_min * 8 + column_min
})
.collect();
ids.sort();
let part1 = ids.iter().max().unwrap();
let part2 = ids
.windows(2)
.find_map(|window| {
if window[0] + 2 == window[1] {
Some(window[0] + 1)
} else {
None
}
})
.unwrap();
let elapsed = instant.elapsed();
if print {
dbg!(elapsed, part1, part2);
}
elapsed
}
}
fn main() {
let days = [day01::run, day02::run, day03::run, day04::run, day05::run];
if let Some(day) = std::env::args().nth(1) {
let day: usize = day.parse().expect("day not an integer");
if day > 0 {
days[day - 1](true);
}
} else {
let repetitions = 2000;
let mut total = Duration::new(0, 0);
for day in 0..days.len() {
for _ in 0..repetitions {
total += days[day](false) / repetitions;
}
}
dbg!(total);
}
}