Skip to content

Commit

Permalink
Day 2
Browse files Browse the repository at this point in the history
  • Loading branch information
kcaffrey committed Dec 2, 2023
1 parent 3506927 commit d149df9
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 2 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.

| Day | Part 1 | Part 2 |
| :---: | :---: | :---: |
| [Day 1](./src/bin/01.rs) | `40.4µs` | `80.7µs` |
| [Day 1](./src/bin/01.rs) | `32.9µs` | `81.1µs` |
| [Day 2](./src/bin/02.rs) | `43.6µs` | `42.6µs` |

**Total: 0.12ms**
**Total: 0.20ms**
<!--- benchmarking table --->

---
Expand Down
5 changes: 5 additions & 0 deletions data/examples/02.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
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
135 changes: 135 additions & 0 deletions src/bin/02.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
use std::str::FromStr;

advent_of_code::solution!(2);

pub fn part_one(input: &str) -> Option<u32> {
Some(
input
.lines()
.filter_map(|line| line.parse::<Game>().ok())
.filter(|game| {
game.possible(Colors {
red: 12,
green: 13,
blue: 14,
})
})
.map(|game| game.id)
.sum(),
)
}

pub fn part_two(input: &str) -> Option<u32> {
Some(
input
.lines()
.filter_map(|line| line.parse::<Game>().ok())
.filter_map(|game| {
game.reveals
.iter()
.copied()
.reduce(|acc, reveal| acc.maximum(reveal))
})
.map(Colors::power)
.sum(),
)
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd)]
struct Colors {
red: u32,
green: u32,
blue: u32,
}

#[derive(Clone, Debug, Eq, PartialEq)]
struct Game {
id: u32,
reveals: Vec<Colors>,
}

impl Game {
pub fn possible(&self, bag: Colors) -> bool {
self.reveals
.iter()
.all(|reveal| reveal.possible_reveal(bag))
}
}

impl Colors {
pub fn possible_reveal(self, bag: Colors) -> bool {
self.red <= bag.red && self.green <= bag.green && self.blue <= bag.blue
}

pub fn maximum(self, other: Self) -> Self {
Self {
red: self.red.max(other.red),
green: self.green.max(other.green),
blue: self.blue.max(other.blue),
}
}

pub fn power(self) -> u32 {
self.red * self.green * self.blue
}
}

struct ParseGameErr;

impl FromStr for Game {
type Err = ParseGameErr;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let (game_id, reveal_str) = s.split_once(':').ok_or(ParseGameErr)?;
if game_id.len() < 6 {
return Err(ParseGameErr);
}
let id = game_id[5..].parse::<u32>().map_err(|_| ParseGameErr)?;
let reveals = reveal_str
.trim()
.split(';')
.map(|reveal| reveal.parse::<Colors>())
.collect::<Result<Vec<Colors>, ParseGameErr>>()?;
Ok(Self { id, reveals })
}
}

impl FromStr for Colors {
type Err = ParseGameErr;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut ret = Colors {
red: 0,
green: 0,
blue: 0,
};
for part in s.split(',') {
let (num_str, color) = part.trim().split_once(' ').ok_or(ParseGameErr)?;
let num = num_str.parse::<u32>().map_err(|_| ParseGameErr)?;
match color {
"red" => ret.red += num,
"green" => ret.green += num,
"blue" => ret.blue += num,
_ => return Err(ParseGameErr),
};
}
Ok(ret)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_part_one() {
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, Some(8));
}

#[test]
fn test_part_two() {
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, Some(2286));
}
}

0 comments on commit d149df9

Please sign in to comment.