Day 2 complete
This commit is contained in:
50
.gitignore
vendored
Normal file
50
.gitignore
vendored
Normal 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
151
Cargo.lock
generated
Normal 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
13
day-2/Cargo.toml
Normal 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
4
day-2/src/lib.rs
Normal 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
12
day-2/src/main.rs
Normal 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
106
day-2/src/part1.rs
Normal 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
97
day-2/src/part2.rs
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user