Adds Day1
This commit is contained in:
parent
a2d898e66b
commit
d3bd96f14f
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
/target
|
||||
.vscode
|
||||
|
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -1,7 +1,25 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aoc-2024"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
@ -4,3 +4,4 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
itertools = "0.13"
|
||||
|
1000
resources/input1.txt
Normal file
1000
resources/input1.txt
Normal file
File diff suppressed because it is too large
Load Diff
71
src/days/day1.rs
Normal file
71
src/days/day1.rs
Normal file
@ -0,0 +1,71 @@
|
||||
use std::{collections::HashMap, iter::zip, path::Path};
|
||||
|
||||
use crate::{days::AdventDay, error::AdventError, input::get_lines};
|
||||
|
||||
pub struct Day1 {
|
||||
list1: Vec<i32>,
|
||||
list2: Vec<i32>,
|
||||
count1: HashMap<i32, u64>,
|
||||
count2: HashMap<i32, u64>
|
||||
}
|
||||
|
||||
|
||||
impl AdventDay for Day1 {
|
||||
fn new() -> Self {
|
||||
Day1 {
|
||||
list1: vec![],
|
||||
list2: vec![],
|
||||
count1: HashMap::new(),
|
||||
count2: HashMap::new()
|
||||
}
|
||||
}
|
||||
|
||||
fn read_input(&mut self) -> Result<(),AdventError> {
|
||||
for line in get_lines(Path::new("resources/input1.txt")) {
|
||||
let line = line?;
|
||||
let mut s = line.split(" ");
|
||||
let l = s.next().unwrap().parse::<i32>()?;
|
||||
self.list1.push(l);
|
||||
if self.count1.contains_key(&l) {
|
||||
*self.count1.get_mut(&l).unwrap() += 1;
|
||||
}
|
||||
else {
|
||||
self.count1.insert(l, 1);
|
||||
}
|
||||
let r = s.next().unwrap().parse::<i32>()?;
|
||||
self.list2.push(r);
|
||||
if self.count2.contains_key(&r) {
|
||||
*self.count2.get_mut(&r).unwrap() += 1;
|
||||
}
|
||||
else {
|
||||
self.count2.insert(r, 1);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn puzzle1(&mut self) -> Result<u64, AdventError> {
|
||||
|
||||
self.list1.sort();
|
||||
self.list2.sort();
|
||||
|
||||
Ok(zip(self.list1.clone(), self.list2.clone())
|
||||
.map(|(l, r)| {
|
||||
(l - r).abs() as u64
|
||||
})
|
||||
.sum::<u64>())
|
||||
}
|
||||
|
||||
fn puzzle2(&mut self) -> Result<u64, AdventError> {
|
||||
Ok(self.count1.keys().into_iter().map(
|
||||
|k| {
|
||||
let s = *k as u64;
|
||||
if self.count2.contains_key(k) {
|
||||
s * self.count1[k] * self.count2[k]
|
||||
}
|
||||
else {
|
||||
0
|
||||
}
|
||||
}).sum())
|
||||
}
|
||||
}
|
11
src/days/mod.rs
Normal file
11
src/days/mod.rs
Normal file
@ -0,0 +1,11 @@
|
||||
use crate::error::AdventError;
|
||||
|
||||
pub trait AdventDay {
|
||||
fn new() -> Self;
|
||||
|
||||
fn read_input(&mut self) -> Result<(),AdventError>;
|
||||
fn puzzle1(&mut self) -> Result<u64, AdventError>;
|
||||
fn puzzle2(&mut self) -> Result<u64, AdventError>;
|
||||
}
|
||||
|
||||
pub mod day1;
|
28
src/error/mod.rs
Normal file
28
src/error/mod.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use std::{num::{ParseIntError, TryFromIntError}, convert::Infallible, io};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AdventError(pub String);
|
||||
|
||||
impl From<ParseIntError> for AdventError {
|
||||
fn from(e: ParseIntError) -> Self {
|
||||
AdventError(e.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for AdventError {
|
||||
fn from(e: io::Error) -> Self {
|
||||
AdventError(e.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Infallible> for AdventError {
|
||||
fn from(_: Infallible) -> Self {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TryFromIntError> for AdventError {
|
||||
fn from(e: TryFromIntError) -> Self {
|
||||
AdventError(e.to_string())
|
||||
}
|
||||
}
|
29
src/input/mod.rs
Normal file
29
src/input/mod.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use std::{fs::File, io::{BufRead, BufReader, Lines, Read}, path::{Path, PathBuf}, str::FromStr};
|
||||
|
||||
use crate::error::AdventError;
|
||||
|
||||
pub fn _read_into_vec<T:FromStr>(file_path : &Path) -> Result<Vec<T>, AdventError> where AdventError: From<<T as FromStr>::Err> {
|
||||
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
path.push(file_path);
|
||||
let file = File::open(path).expect("no such file");
|
||||
let buf = BufReader::new(file);
|
||||
buf.lines().map(|line| T::from_str(line?.as_str()).map_err(Into::into)).collect::<Result<Vec<T>, AdventError>>()
|
||||
}
|
||||
|
||||
pub fn _read_into<T:FromStr>(file_path: &Path) -> Result<T, AdventError> where AdventError: From<<T as FromStr>::Err> {
|
||||
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
path.push(file_path);
|
||||
let mut file = File::open(path).expect("no such file");
|
||||
let mut str: String = "".to_string();
|
||||
file.read_to_string(&mut str)?;
|
||||
Ok(T::from_str(str.as_str())?)
|
||||
}
|
||||
|
||||
pub fn get_lines(file_path: &Path) -> Lines<BufReader<File>> {
|
||||
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
path.push(file_path);
|
||||
let file = File::open(path).expect("no such file");
|
||||
let buf = BufReader::new(file);
|
||||
let lines = buf.lines();
|
||||
lines
|
||||
}
|
48
src/main.rs
48
src/main.rs
@ -1,3 +1,45 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
|
||||
pub mod error;
|
||||
pub mod days;
|
||||
mod input;
|
||||
|
||||
use std::env;
|
||||
|
||||
use day1::Day1;
|
||||
|
||||
use crate::error::AdventError;
|
||||
use crate::days::*;
|
||||
|
||||
fn main() -> Result<(), AdventError> {
|
||||
|
||||
let mut advent_days = vec!(
|
||||
Day1::new()
|
||||
);
|
||||
|
||||
if env::args().len() == 1 {
|
||||
Ok(advent_days.into_iter().map(|mut day| {
|
||||
day.read_input()?;
|
||||
let one_result = day.puzzle1()?;
|
||||
let two_result = day.puzzle2()?;
|
||||
Ok((one_result, two_result))
|
||||
}).enumerate().map(|(index, r): (usize, Result<(u64, u64), AdventError>)| {
|
||||
match r {
|
||||
Ok((res1, res2)) => println!("{}: ({}, {})", index + 1, res1, res2),
|
||||
Err(e) => println!("Error: {}", e.0)
|
||||
};
|
||||
}).fold((), |acc, _| { acc }))
|
||||
} else {
|
||||
let day_index = env::args().nth(1).ok_or(AdventError("Failed to parse day".into()))?.parse::<usize>()? - 1;
|
||||
let day = &mut advent_days[day_index];
|
||||
day.read_input()?;
|
||||
if env::args().len() == 3 {
|
||||
match env::args().nth(2).unwrap().parse::<usize>()? {
|
||||
1 => Ok(println!("1: {}", &day.puzzle1()?)),
|
||||
2 => Ok(println!("2: {}", &day.puzzle2()?)),
|
||||
_ => return Err(AdventError("part must be either 1 or 2".into()))
|
||||
}
|
||||
} else {
|
||||
Ok(println!("{}: ({}, {})", day_index + 1, day.puzzle1()?, day.puzzle2()?))
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user