use std::str::FromStr;
use round::Round;
use std::cmp;
+use std::fmt;
#[derive(Debug, PartialEq, Eq)]
pub struct Game {
}
return res.red * res.green * res.blue;
}
+
+ pub fn valid(&self, limits: &Round) -> bool {
+ return self.rounds.iter().all(|r| r <= limits)
+ }
+}
+
+impl fmt::Display for Game {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "Game {}", self.id)?;
+ let mut joiner = ':';
+ for round in &self.rounds {
+ write!(f, "{} {}", joiner, round)?;
+ joiner = ';'
+ }
+ Ok(())
+ }
}
impl FromStr for Game {
let game = Game::from_str("Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green").unwrap();
assert_eq!(game.power(), 48);
}
+
+ #[test]
+ fn test_game_fmt() {
+ let input = "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green";
+ let expected = "Game 1: 4 red, 3 blue; 1 red, 2 green, 6 blue; 2 green";
+ let game = Game::from_str(input).unwrap();
+ assert_eq!(expected, format!("{}", game));
+ }
}
use std::error::Error;
use std::str::FromStr;
use std::fs::File;
-use std::io::{BufReader, BufRead}; //, Error};
-
-fn valid_round(round: &Round, limits: &Round) -> bool {
- return round.red <= limits.red
- && round.green <= limits.green
- && round.blue <= limits.blue;
-}
-
-fn valid_game(game: &Game, limits: &Round) -> bool {
- return game.rounds.iter().all(|x| valid_round(x, limits))
-}
-
-#[allow(dead_code)]
-fn print_game(game: &Game) {
- print!("Game {}: ", game.id);
- for round in game.rounds.iter() {
- print!("{} red, {} green, {} blue;", round.red, round.green, round.blue);
- }
- println!("");
-}
+use std::io::{BufReader, BufRead};
fn main() -> Result<(), Box<dyn Error>> {
let args: Vec<String> = env::args().collect();
let limits = Round { red: 12, green: 13, blue: 14 };
let sum_ids: u32 = games.iter()
- .filter(|g| valid_game(g, &limits))
- // .inspect(|g| print_game(g))
+ .filter(|g| g.valid(&limits))
+ // .inspect(|g| println!("{}", g))
.map(|g| g.id)
.sum();
println!("part 1: {}", sum_ids);
use std::str::FromStr;
+use std::fmt;
-#[derive(Debug, PartialEq, Eq)]
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Round {
pub red: u32,
pub green: u32,
#[derive(Debug, PartialEq, Eq)]
pub struct ParseRoundError;
+impl fmt::Display for Round {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let mut vec = Vec::<String>::new();
+ if self.red > 0 { vec.push(format!("{} red", self.red)); }
+ if self.green > 0 { vec.push(format!("{} green", self.green)); }
+ if self.blue > 0 { vec.push(format!("{} blue", self.blue)); }
+ write!(f, "{}", vec.join(", "))
+ }
+}
+
impl FromStr for Round {
type Err = ParseRoundError;
fn test_parse_invalid_line() {
assert!(Round::from_str("").is_err());
}
+
+ #[test]
+ fn test_format_round() {
+ let r = Round { red: 20, green: 2, blue: 5 };
+ assert_eq!("20 red, 2 green, 5 blue",
+ format!("{}", r));
+ }
+
+ #[test]
+ fn test_format_round_zeros() {
+ let r = Round { red: 0, green: 2, blue: 0 };
+ assert_eq!("2 green", format!("{}", r));
+ }
+
+ #[test]
+ fn test_round_eq() {
+ let a = Round { red: 1, green: 2, blue: 3 };
+ let b = Round { red: 1, green: 2, blue: 3 };
+ assert!(a == b);
+ }
+
+ #[test]
+ fn test_round_lt() {
+ let a = Round { red: 1, green: 2, blue: 3 };
+ let b = Round { red: 1, green: 2, blue: 3 };
+ let c = Round { red: 0, green: 1, blue: 1 };
+ assert!(b <= a);
+ assert!(c <= a);
+ assert!(c < a);
+ assert!(a > c);
+ assert!(a != c);
+ assert_ne!(a, c);
+ }
}