Day 2 complete

This commit is contained in:
Dylan Thies
2023-12-02 14:40:22 -05:00
parent ac6662445d
commit 5f9d9af50c
7 changed files with 433 additions and 0 deletions

50
.gitignore vendored Normal file
View File

@@ -0,0 +1,50 @@
# Generated by Cargo
# will have compiled files and executables
debug/
target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
#Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix
# Swap
[._]*.s[a-v][a-z]
!*.svg # comment out if you don't need vector files
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]
# Session
Session.vim
Sessionx.vim
# Temporary
.netrwhist
*~
# Auto-generated tag files
tags
# Persistent undo
[._]*.un~
.vscode/settings.json
input.txt

151
Cargo.lock generated Normal file
View File

@@ -0,0 +1,151 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anyhow"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]]
name = "day-1"
version = "2023.0.0"
dependencies = [
"derive-getters",
"error-stack",
"itertools",
"log",
"nom",
]
[[package]]
name = "day-2"
version = "2023.0.0"
dependencies = [
"itertools",
"log",
"nom",
]
[[package]]
name = "day-n"
version = "2023.0.0"
dependencies = [
"itertools",
"nom",
]
[[package]]
name = "derive-getters"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2c35ab6e03642397cdda1dd58abbc05d418aef8e36297f336d5aba060fe8df"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "either"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "error-stack"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27a72baa257b5e0e2de241967bc5ee8f855d6072351042688621081d66b2a76b"
dependencies = [
"anyhow",
"rustc_version",
]
[[package]]
name = "itertools"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
dependencies = [
"either",
]
[[package]]
name = "log"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "memchr"
version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "proc-macro2"
version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"semver",
]
[[package]]
name = "semver"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"

13
day-2/Cargo.toml Normal file
View File

@@ -0,0 +1,13 @@
[package]
name = "day-2"
version.workspace = true
edition.workspace = true
authors.workspace = true
repository.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nom.workspace = true
itertools.workspace = true
log.workspace = true

4
day-2/src/lib.rs Normal file
View File

@@ -0,0 +1,4 @@
pub mod part1;
pub use crate::part1::part1;
pub mod part2;
pub use crate::part2::part2;

12
day-2/src/main.rs Normal file
View File

@@ -0,0 +1,12 @@
#![warn(clippy::all, clippy::pedantic)]
use day_2::part1;
use day_2::part2;
fn main() {
let input = include_str!("./input.txt");
let part1_result = part1(input);
println!("part 1: {part1_result}");
let part2_result = part2(input);
println!("part 2: {part2_result}");
}

106
day-2/src/part1.rs Normal file
View File

@@ -0,0 +1,106 @@
use log::debug;
use nom::{
bytes::complete::tag,
character::complete::{self, newline},
multi::separated_list1,
sequence::{preceded, separated_pair},
};
#[derive(Debug)]
struct Round {
pub red_n: u32,
pub green_n: u32,
pub blue_n: u32,
}
#[derive(Debug)]
struct Game {
pub id: u32,
pub rounds: Vec<Round>,
}
impl Game {
fn to_part1(&self) -> Option<u32> {
if self
.rounds
.iter()
.find_map(|r| {
//TODO if inverted use find_map
if r.red_n > 12 || r.green_n > 13 || r.blue_n > 14 {
Some(self.id)
} else {
None
}
})
.is_some()
{
None
} else {
Some(self.id)
}
}
}
pub fn part1(input: &str) -> String {
let (_, games) = process_input(input).expect("there should be input");
debug!("{games:?}");
games
.iter()
.filter_map(Game::to_part1)
.sum::<u32>()
.to_string()
}
fn process_block(input: &str) -> nom::IResult<&str, (u32, String)> {
let (i, (cnt, color)) =
separated_pair(complete::u32, complete::space1, complete::alpha1)(input)?;
Ok((i, (cnt, color.to_owned())))
}
fn process_round(input: &str) -> nom::IResult<&str, Round> {
let (i, blocks) = separated_list1(tag(", "), process_block)(input)?;
let mut round = Round {
red_n: 0,
green_n: 0,
blue_n: 0,
};
for (cnt, color) in blocks {
match color.as_str() {
"red" => round.red_n = cnt,
"green" => round.green_n = cnt,
"blue" => round.blue_n = cnt,
_ => panic!("this should be a color name"),
};
}
Ok((i, round))
}
fn process_game(input: &str) -> nom::IResult<&str, Game> {
let (i, (id, rounds)) = separated_pair(
preceded(tag("Game "), complete::u32),
tag(": "),
separated_list1(tag("; "), process_round),
)(input)?;
Ok((i, Game { id, rounds }))
}
fn process_input(input: &str) -> nom::IResult<&str, Vec<Game>> {
separated_list1(newline, process_game)(input)
}
#[cfg(test)]
mod test {
use super::*;
const INPUT: &str = "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green";
#[test]
fn part1_works() {
let result = part1(INPUT);
assert_eq!(result, "8".to_string());
}
}

97
day-2/src/part2.rs Normal file
View File

@@ -0,0 +1,97 @@
use nom::{
bytes::complete::tag,
character::complete::{self, newline},
multi::separated_list1,
sequence::{preceded, separated_pair},
};
#[derive(Debug)]
struct Round {
pub red_n: u32,
pub green_n: u32,
pub blue_n: u32,
}
#[derive(Debug)]
struct Game {
pub _id: u32,
pub rounds: Vec<Round>,
}
impl Game {
fn to_power(&self) -> u64 {
let (r, g, b) = self.rounds.iter().fold((0_u64, 0_u64, 0_u64), |acc, x| {
let (mut val_r, mut val_g, mut val_b) = acc;
if u64::from(x.red_n) > acc.0 {
val_r = x.red_n.into();
}
if u64::from(x.green_n) > acc.1 {
val_g = x.green_n.into();
}
if u64::from(x.blue_n) > acc.2 {
val_b = x.blue_n.into();
}
(val_r, val_g, val_b)
});
r * g * b
}
}
pub fn part2(input: &str) -> String {
let (_, games) = process_input(input).expect("there should be input");
games.iter().map(Game::to_power).sum::<u64>().to_string()
}
fn process_block(input: &str) -> nom::IResult<&str, (u32, String)> {
let (i, (cnt, color)) =
separated_pair(complete::u32, complete::space1, complete::alpha1)(input)?;
Ok((i, (cnt, color.to_owned())))
}
fn process_round(input: &str) -> nom::IResult<&str, Round> {
let (i, blocks) = separated_list1(tag(", "), process_block)(input)?;
let mut round = Round {
red_n: 0,
green_n: 0,
blue_n: 0,
};
for (cnt, color) in blocks {
match color.as_str() {
"red" => round.red_n = cnt,
"green" => round.green_n = cnt,
"blue" => round.blue_n = cnt,
_ => panic!("this should be a color name"),
};
}
Ok((i, round))
}
fn process_game(input: &str) -> nom::IResult<&str, Game> {
let (i, (id, rounds)) = separated_pair(
preceded(tag("Game "), complete::u32),
tag(": "),
separated_list1(tag("; "), process_round),
)(input)?;
Ok((i, Game { _id: id, rounds }))
}
fn process_input(input: &str) -> nom::IResult<&str, Vec<Game>> {
separated_list1(newline, process_game)(input)
}
#[cfg(test)]
mod test {
use super::*;
const INPUT: &str = "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green";
#[test]
fn part2_works() {
let result = part2(INPUT);
assert_eq!(result, "2286".to_string());
}
}