initial commit, includes days 1 and 2 solutions
This commit is contained in:
11 files changed
+1401
No files matched your search
@@ -0,0 +1,41 @@
|
||||
// ==== day 1
|
||||
|
||||
use crate::utils;
|
||||
use anyhow::{anyhow, Result};
|
||||
|
||||
fn day01_part1(data: &[i64]) -> Result<i64> {
|
||||
for i in 0..data.len() - 2 {
|
||||
for j in i + 1..data.len() - 1 {
|
||||
if data[i] + data[j] == 2020 {
|
||||
return Ok(data[i] * data[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(anyhow!("no result found"))
|
||||
}
|
||||
|
||||
fn day01_part2(data: &[i64]) -> Result<i64> {
|
||||
for i in 0..data.len() - 3 {
|
||||
for j in i + 1..data.len() - 2 {
|
||||
for k in j + 1..data.len() - 1 {
|
||||
if data[i] + data[j] + data[k] == 2020 {
|
||||
return Ok(data[i] * data[j] * data[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(anyhow!("no result found"))
|
||||
}
|
||||
|
||||
pub fn run() -> Result<(i64, i64)> {
|
||||
let data = utils::read_i64s("data/input-01.txt")?;
|
||||
let answers = utils::read_i64s("data/output-01.txt")?;
|
||||
|
||||
let p1 = day01_part1(&data)?;
|
||||
assert_eq!(p1, answers[0]);
|
||||
|
||||
let p2 = day01_part2(&data)?;
|
||||
assert_eq!(p2, answers[1]);
|
||||
|
||||
Ok((p1, p2))
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// ==== day 2
|
||||
|
||||
use crate::utils;
|
||||
use anyhow::Result;
|
||||
use regex::Regex;
|
||||
|
||||
struct PasswordSpec {
|
||||
min: usize,
|
||||
max: usize,
|
||||
required: char,
|
||||
password: String,
|
||||
}
|
||||
|
||||
fn valid_password_1(p: &PasswordSpec) -> bool {
|
||||
let count = p.password.chars().filter(|c| c == &p.required).count();
|
||||
p.min <= count && count <= p.max
|
||||
}
|
||||
|
||||
fn valid_password_2(p: &PasswordSpec) -> bool {
|
||||
let char_a = p.password.chars().nth(p.min - 1).unwrap();
|
||||
let char_b = p.password.chars().nth(p.max - 1).unwrap();
|
||||
(char_a == p.required) ^ (char_b == p.required)
|
||||
}
|
||||
|
||||
pub fn run() -> Result<(usize, usize)> {
|
||||
let data = utils::read_file("data/input-02.txt")?;
|
||||
let answers = utils::read_i64s("data/output-02.txt")?;
|
||||
|
||||
// parse lines like "4-8 n: dnjjrtclnzdnghnbnn" into vector of PasswordSpec{}
|
||||
let re = Regex::new(r"(\d+)-(\d+) +([a-z]): +(\S*)")?;
|
||||
let pwspecs: Vec<PasswordSpec> = re
|
||||
.captures_iter(&data)
|
||||
.map(|cap| PasswordSpec {
|
||||
min: cap[1].parse().expect("parse error"),
|
||||
max: cap[2].parse().expect("parse error"),
|
||||
required: cap[3].chars().next().expect("string index error"),
|
||||
password: (&cap[4]).to_string(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let p1 = pwspecs.iter().filter(|p| valid_password_1(&p)).count();
|
||||
assert_eq!(p1, answers[0] as usize);
|
||||
|
||||
let p2 = pwspecs.iter().filter(|p| valid_password_2(&p)).count();
|
||||
assert_eq!(p2, answers[1] as usize);
|
||||
|
||||
Ok((p1, p2))
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
use anyhow::Result;
|
||||
|
||||
mod day01;
|
||||
mod day02;
|
||||
mod utils;
|
||||
|
||||
// TODO
|
||||
// ====
|
||||
// * move from i64 to something else that works with the data+problems, int, i32, usize?
|
||||
// * clean up error handling (move to `?` inside closures)
|
||||
|
||||
// ==== main()
|
||||
|
||||
fn main() -> Result<()> {
|
||||
println!("Day 01: {:?}", day01::run()?);
|
||||
println!("Day 02: {:?}", day02::run()?);
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// ==== utilities
|
||||
|
||||
use anyhow::Result;
|
||||
use std::fs;
|
||||
|
||||
pub fn read_i64s(filename: &str) -> Result<Vec<i64>> {
|
||||
Ok(read_file(filename)?
|
||||
.lines()
|
||||
.map(|s| s.parse::<i64>().expect("i64 parse error"))
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub fn read_file(filename: &str) -> Result<String> {
|
||||
Ok(fs::read_to_string(filename)?)
|
||||
}
|
||||
Reference in new issue
Block a user