Guest User

Advent of Code: Day 2 in Rust

a guest
Dec 2nd, 2023
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 4.27 KB | Software | 0 0
  1. use std::cmp::max;
  2. use std::fmt::Error;
  3. use std::fs;
  4. use std::str::FromStr;
  5.  
  6. #[derive(Debug, PartialEq, Clone, Copy)]
  7. enum Ball {
  8.     Red(u32),
  9.     Blue(u32),
  10.     Green(u32),
  11. }
  12.  
  13. impl FromStr for Ball {
  14.     type Err = Error;
  15.  
  16.     fn from_str(s: &str) -> Result<Self, Self::Err> {
  17.         let mut components = s.split(" ");
  18.  
  19.         let count = components
  20.             .next()
  21.             .expect("Each component should have a count")
  22.             .parse::<u32>()
  23.             .expect("The count should be a number");
  24.  
  25.         Ok(
  26.             match components
  27.                 .next()
  28.                 .expect("Each component should have a type")
  29.             {
  30.                 "red" => Ball::Red(count),
  31.                 "blue" => Ball::Blue(count),
  32.                 "green" => Ball::Green(count),
  33.                 _ => panic!("Unknown ball type"),
  34.             },
  35.         )
  36.     }
  37. }
  38.  
  39. #[derive(Debug, PartialEq, Clone, Copy)]
  40. struct Draw {
  41.     red: u32,
  42.     blue: u32,
  43.     green: u32,
  44. }
  45.  
  46. impl Draw {
  47.     fn is_contained(&self, other: &Draw) -> bool {
  48.         self.red <= other.red && self.blue <= other.blue && self.green <= other.green
  49.     }
  50.  
  51.     fn power(&self) -> u32 {
  52.         self.red * self.blue * self.green
  53.     }
  54. }
  55.  
  56. impl FromStr for Draw {
  57.     type Err = Error;
  58.  
  59.     fn from_str(s: &str) -> Result<Self, Self::Err> {
  60.         let mut draw = Draw {
  61.             red: 0,
  62.             blue: 0,
  63.             green: 0,
  64.         };
  65.  
  66.         s.trim()
  67.             .split(",")
  68.             .map(|ball| ball.trim().parse::<Ball>().expect("Failed to parse ball"))
  69.             .for_each(|ball| match ball {
  70.                 Ball::Red(count) => draw.red += count,
  71.                 Ball::Blue(count) => draw.blue += count,
  72.                 Ball::Green(count) => draw.green += count,
  73.             });
  74.  
  75.         Ok(draw)
  76.     }
  77. }
  78.  
  79. #[derive(Debug, PartialEq, Clone)]
  80. struct Game {
  81.     id: u32,
  82.     draws: Vec<Draw>,
  83. }
  84.  
  85. impl Game {
  86.     fn minimum_draw(&self) -> Draw {
  87.         let mut draw = Draw {
  88.             red: 0,
  89.             blue: 0,
  90.             green: 0,
  91.         };
  92.  
  93.         self.draws.iter().for_each(|d| {
  94.             draw.red = max(d.red, draw.red);
  95.             draw.blue = max(d.blue, draw.blue);
  96.             draw.green = max(d.green, draw.green);
  97.         });
  98.  
  99.         draw
  100.     }
  101. }
  102.  
  103. impl FromStr for Game {
  104.     type Err = Error;
  105.  
  106.     fn from_str(s: &str) -> Result<Self, Self::Err> {
  107.         let mut components = s.split(":");
  108.  
  109.         let id = components
  110.             .next()
  111.             .expect("Each game should have an associated ID identifier")
  112.             .split(" ")
  113.             .skip(1)
  114.             .next()
  115.             .expect("Each game must have an id")
  116.             .parse::<u32>()
  117.             .expect("The game id should be a number");
  118.  
  119.         let draws = components
  120.             .next()
  121.             .expect("Each game should have atleast one draw")
  122.             .split(";")
  123.             .map(|draw| {
  124.                 draw.parse::<Draw>()
  125.                     .expect("Cannot be parsed into a valid Draw")
  126.             })
  127.             .collect::<Vec<Draw>>();
  128.  
  129.         Ok(Game { id, draws })
  130.     }
  131. }
  132.  
  133. pub fn part1(file_path: &str) -> u32 {
  134.     let encompassing_draw = Draw {
  135.         red: 12,
  136.         green: 13,
  137.         blue: 14,
  138.     };
  139.  
  140.     fs::read_to_string(file_path)
  141.         .expect("Unable to read the input file")
  142.         .lines()
  143.         .map(|line| {
  144.             line.parse::<Game>()
  145.                 .expect("Failed to parse a valid game from line")
  146.         })
  147.         .filter(|game| game.minimum_draw().is_contained(&encompassing_draw))
  148.         .map(|game| game.id)
  149.         .sum()
  150. }
  151.  
  152. pub fn part2(file_path: &str) -> u32 {
  153.     fs::read_to_string(file_path)
  154.         .expect("Unable to read the input file")
  155.         .lines()
  156.         .map(|line| {
  157.             line.parse::<Game>()
  158.                 .expect("Failed to parse a valid game from line")
  159.         })
  160.         .map(|game| game.minimum_draw().power())
  161.         .sum()
  162. }
  163.  
  164. #[cfg(test)]
  165. mod tests {
  166.     use super::*;
  167.  
  168.     #[test]
  169.     fn test_1() {
  170.         let result = part1("../data/2/test.txt");
  171.         assert_eq!(result, 8);
  172.     }
  173.  
  174.     #[test]
  175.     fn test_2() {
  176.         let result = part2("../data/2/test.txt");
  177.         assert_eq!(result, 2286);
  178.     }
  179. }
Tags: Day2 aoc
Advertisement
Add Comment
Please, Sign In to add comment