parent
5b22965ad3
commit
81decee6a9
|
@ -1,2 +1,4 @@
|
||||||
|
# Calorie Counting
|
||||||
|
|
||||||
Usage: `cargo run --release -- --input <Path to file with inputs`
|
## Usage
|
||||||
|
`cargo run --release -- --input <Path to file with inputs>`
|
||||||
|
|
|
@ -1,46 +1,18 @@
|
||||||
use calorie_counting_lib::*;
|
use calorie_counting_lib::{task_1a, task_1b};
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::collections::BinaryHeap;
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use tracing::{info, debug};
|
use tracing::{info, debug};
|
||||||
use crate::cli::Cli;
|
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
|
use crate::cli::Cli;
|
||||||
/// Finds the Elf carrying the most Calories.
|
|
||||||
/// Outputs how many total Calories that Elf is carrying.
|
|
||||||
fn task_1a(input: &PathBuf) {
|
|
||||||
debug!("Running task 1a");
|
|
||||||
let file_path = input;
|
|
||||||
let content = calorie_counting_lib::read_file(file_path).unwrap();
|
|
||||||
let splits = content.split("\n\n");
|
|
||||||
|
|
||||||
println!("{}", splits.map(|s| Elf::new(s).total_calories()).max().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Finds the top three Elves carrying the most Calories.
|
|
||||||
/// Outputs how many Calories those Elves are carrying in total.
|
|
||||||
fn task_1b(input: &PathBuf) {
|
|
||||||
debug!("Running task 1b");
|
|
||||||
let file_path = input;
|
|
||||||
let content = calorie_counting_lib::read_file(file_path).unwrap();
|
|
||||||
let splits = content.split("\n\n");
|
|
||||||
let mut heap = splits.map(|s| Elf::new(s).total_calories()).collect::<BinaryHeap<_>>();
|
|
||||||
|
|
||||||
let mut top_three = Vec::new();
|
|
||||||
for _ in 0..3 {
|
|
||||||
if let Some(c) = heap.pop() {
|
|
||||||
top_three.push(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("{}", top_three.iter().sum::<u64>());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
tracing_subscriber::fmt::init();
|
tracing_subscriber::fmt::init();
|
||||||
debug!("Running with debugging level logging");
|
debug!("Running with DEBUG logging");
|
||||||
|
info!("Running with INFO logging");
|
||||||
|
|
||||||
let args = Cli::parse();
|
let args = Cli::parse();
|
||||||
|
debug!("{:#?}", args);
|
||||||
|
|
||||||
task_1a(&args.input);
|
task_1a(&args.input);
|
||||||
task_1b(&args.input);
|
task_1b(&args.input);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Elf {
|
||||||
|
_input: String,
|
||||||
|
calories: Vec<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Elf {
|
||||||
|
pub fn new(input: &str) -> Self {
|
||||||
|
let cal: Vec<u64> = input
|
||||||
|
.split('\n')
|
||||||
|
.map(|i| i.parse::<u64>().unwrap())
|
||||||
|
.collect();
|
||||||
|
Self {
|
||||||
|
_input: input.to_string(),
|
||||||
|
calories: cal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn total_calories(self) -> u64 {
|
||||||
|
self.calories.iter().sum()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Elf {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "Elf: {:?}", self.calories)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,52 +1,64 @@
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Write, Read};
|
use std::io::{Read, Write};
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
use std::fmt;
|
use std::collections::BinaryHeap;
|
||||||
use tracing::{info, debug};
|
use tracing::{debug, info};
|
||||||
|
|
||||||
|
mod elf;
|
||||||
|
use crate::elf::Elf;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn create_file(path: &Path, content: String) {
|
||||||
|
info!("Creating file");
|
||||||
|
debug!("Writing file from: {:?}\nWith:\n{}", path, content);
|
||||||
|
|
||||||
pub fn create_file(path: &Path, content: String) {
|
|
||||||
debug!("Creating file");
|
|
||||||
let mut file = File::create(path).unwrap();
|
let mut file = File::create(path).unwrap();
|
||||||
let _ = file.write_all(content.as_bytes());
|
let _ = file.write_all(content.as_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_file(path: &Path) -> std::io::Result<String> {
|
#[allow(dead_code)]
|
||||||
debug!("Reading file");
|
fn read_file(path: &Path) -> std::io::Result<String> {
|
||||||
|
info!("Reading file");
|
||||||
|
debug!("Reading file from: {:?}", path);
|
||||||
|
|
||||||
let mut file = File::open(path)?;
|
let mut file = File::open(path)?;
|
||||||
let mut contents = String::new();
|
let mut contents = String::new();
|
||||||
let _ = file.read_to_string(&mut contents)?;
|
let _ = file.read_to_string(&mut contents)?;
|
||||||
Ok(contents.trim().to_string())
|
Ok(contents.trim().to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
/// Finds the Elf carrying the most Calories.
|
||||||
pub struct Elf {
|
/// Outputs how many total Calories that Elf is carrying.
|
||||||
_input: String,
|
#[allow(dead_code)]
|
||||||
calories: Vec<u64>,
|
pub fn task_1a(input: &PathBuf) {
|
||||||
|
debug!("Running task 1a");
|
||||||
|
info!("Running task 1a with {:?}", input);
|
||||||
|
|
||||||
|
let content = read_file(input).unwrap();
|
||||||
|
let splits = content.split("\n\n");
|
||||||
|
println!("Result (1a): {}", splits.map(|s| Elf::new(s).total_calories()).max().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Elf {
|
/// Finds the top three Elves carrying the most Calories.
|
||||||
pub fn new (input: &str) -> Self {
|
/// Outputs how many Calories those Elves are carrying in total.
|
||||||
let cal: Vec<u64> = input.split('\n')
|
#[allow(dead_code)]
|
||||||
.map(|i| i.parse::<u64>().unwrap())
|
pub fn task_1b(input: &PathBuf) {
|
||||||
.collect();
|
debug!("Running task 1b");
|
||||||
Self { _input: input.to_string(), calories: cal }
|
info!("Running task 1b with {:?}", input);
|
||||||
}
|
|
||||||
|
|
||||||
pub fn total_calories(self) -> u64 {
|
let content = read_file(input).unwrap();
|
||||||
self.calories.iter().sum()
|
let splits = content.split("\n\n");
|
||||||
|
let mut heap = splits.map(|s| Elf::new(s).total_calories()).collect::<BinaryHeap<_>>();
|
||||||
|
|
||||||
|
let mut sum = 0u64;
|
||||||
|
for _ in 0..3 {
|
||||||
|
if let Some(c) = heap.pop() {
|
||||||
|
sum += c;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
println!("Result (1b): {}", sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Elf{
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "Elf: {:?}", self.calories)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pub fn get_calories() -> std::io::Result<Vec<Elf>> {
|
|
||||||
// let content = read_file(Path::new("input.txt"))?;
|
|
||||||
// }
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -54,7 +66,8 @@ mod tests {
|
||||||
use std::str::from_utf8;
|
use std::str::from_utf8;
|
||||||
|
|
||||||
const PATH: &str = "input.txt";
|
const PATH: &str = "input.txt";
|
||||||
const CONTENT: &[u8; 55] = b"1000\n2000\n3000\n\n4000\n\n5000\n6000\n\n7000\n8000\n9000\n\n10000\n";
|
const CONTENT: &[u8; 55] =
|
||||||
|
b"1000\n2000\n3000\n\n4000\n\n5000\n6000\n\n7000\n8000\n9000\n\n10000\n";
|
||||||
|
|
||||||
fn create_test_setup() {
|
fn create_test_setup() {
|
||||||
let file_path = Path::new(PATH);
|
let file_path = Path::new(PATH);
|
||||||
|
@ -63,29 +76,14 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cleanup_test_setup() {
|
fn cleanup_test_setup() {
|
||||||
let _ = remove_file(&Path::new(PATH));
|
let _ = remove_file(Path::new(PATH));
|
||||||
}
|
}
|
||||||
/// Test if we corretly read file input.
|
/// Test if we corretly read file input.
|
||||||
#[test]
|
#[test]
|
||||||
fn file_io() {
|
fn file_io() {
|
||||||
create_test_setup();
|
create_test_setup();
|
||||||
let content = read_file(&Path::new(PATH));
|
let content = read_file(Path::new(PATH));
|
||||||
cleanup_test_setup();
|
|
||||||
assert_eq!(from_utf8(CONTENT).unwrap(), content.unwrap().to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Test if the calculation of calories each elf is carrying is correct.
|
|
||||||
#[test]
|
|
||||||
fn elf_calories() {
|
|
||||||
create_test_setup();
|
|
||||||
let content = read_file(&Path::new(PATH)).unwrap();
|
|
||||||
let file_path = Path::new("input.txt");
|
|
||||||
let content = calorie_counting_lib::read_file(file_path).unwrap();
|
|
||||||
let splits = content.split("\n\n");
|
|
||||||
let result_vec = Vec::<u64>::new();
|
|
||||||
for elf in splits.map(|s| Elf::new(s)) {
|
|
||||||
result_vec.push(elf.total_calories());
|
|
||||||
}
|
|
||||||
cleanup_test_setup();
|
cleanup_test_setup();
|
||||||
|
assert_eq!(from_utf8(CONTENT).unwrap(), content.unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue