[rust] Solve Day 2

main
Akshay Mankar 2023-12-02 13:51:15 +01:00
parent 0f431e9e3f
commit a2637587e9
Signed by: axeman
GPG Key ID: CA08F3AB62369B89
3 changed files with 175 additions and 0 deletions

View File

@ -6,6 +6,9 @@ case "$1" in
"day1")
"$SCRIPT_DIR/day1.sh"
;;
"day2")
"$SCRIPT_DIR/day2.sh"
;;
*)
echo "Invalid day"
exit 1

170
rust/src/day2.rs Normal file
View File

@ -0,0 +1,170 @@
use std::io;
use std::io::Read;
use std::str::FromStr;
pub fn run() {
let mut bytes: Vec<u8> = Vec::new();
let read_result = io::stdin().read_to_end(&mut bytes);
match read_result {
Err(e) => println!("Error while reading input: {}", e),
Ok(_) => {
let input = String::from_utf8(bytes).unwrap();
match parse_games(&input) {
Err(e) => println!("Parsing input failed: {}", e),
Ok(games) => {
println!("Part 1 Answer: {}", part1(games.clone()));
println!("Part 2 Answer: {}", part2(games));
}
}
}
}
}
fn part1(games: Vec<Game>) -> u32 {
games
.into_iter()
.filter(|g| is_game_possible(g))
.map(|g| g.id)
.sum()
}
fn is_game_possible(game: &Game) -> bool {
let revs: &Vec<Revelation> = game.revelations.as_ref();
revs.into_iter()
.all(|rev| rev.reds <= 12 && rev.greens <= 13 && rev.blues <= 14)
}
fn part2(games: Vec<Game>) -> u32 {
games.into_iter().map(|g| power(g)).sum()
}
fn power(game: Game) -> u32 {
let revs: &Vec<Revelation> = game.revelations.as_ref();
let max_reds = revs
.into_iter()
.max_by(|r1, r2| r1.reds.cmp(&r2.reds))
.unwrap()
.reds;
let max_greens = revs
.into_iter()
.max_by(|r1, r2| r1.greens.cmp(&r2.greens))
.unwrap()
.greens;
let max_blues = revs
.into_iter()
.max_by(|r1, r2| r1.blues.cmp(&r2.blues))
.unwrap()
.blues;
max_reds * max_greens * max_blues
}
#[derive(Clone)]
struct ColourRevelation {
count: u32,
colour: String,
}
impl FromStr for ColourRevelation {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let splits: Vec<&str> = s.split(' ').collect();
match splits.as_slice() {
[num, colour] => num
.parse()
.map_err(|e| format!("Invalid count: {}", e))
.and_then(|c| {
Ok(ColourRevelation {
count: c,
colour: String::from_str(colour).unwrap(),
})
}),
_ => Err(format!("Invalid revelation: {}", s)),
}
}
}
#[derive(Clone)]
struct Revelation {
reds: u32,
greens: u32,
blues: u32,
}
impl FromStr for Revelation {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let revelation_results: Vec<_> = s.split(", ").map(ColourRevelation::from_str).collect();
let revelations_result = traverse_results(revelation_results);
revelations_result.and_then(|revelations| {
let reds = extract_colour(revelations.clone(), String::from("red"));
let greens = extract_colour(revelations.clone(), String::from("green"));
let blues = extract_colour(revelations, String::from("blue"));
Ok(Revelation {
reds,
greens,
blues,
})
})
}
}
fn extract_colour(revelations: Vec<ColourRevelation>, colour: String) -> u32 {
revelations
.into_iter()
.find(|r| r.colour == colour)
.map(|r| r.count)
.unwrap_or(0)
}
#[derive(Clone)]
struct Game {
id: u32,
revelations: Vec<Revelation>,
}
impl FromStr for Game {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let splits: Vec<&str> = s.split(": ").collect();
match splits.as_slice() {
[game, revelations_str] => {
let game_id_result: Result<u32, _> = game
.replace("Game ", "")
.parse()
.map_err(|e| format!("Invalid game id: {}", e));
let revelations_results: Vec<Result<Revelation, _>> =
revelations_str.split("; ").map(|x| x.parse()).collect();
game_id_result.and_then(|id| {
traverse_results(revelations_results)
.and_then(|revelations| Ok(Game { id, revelations }))
})
}
_ => Err(format!("Invalid Game: {}", s)),
}
}
}
fn parse_games(s: &str) -> Result<Vec<Game>, String> {
traverse_results(s.split('\n').map(Game::from_str).collect())
}
// Me: Mom, can we have travese.
// Mom: We got traverse at home.
// Traverse at home:
fn traverse_results<A, B>(results: Vec<Result<A, B>>) -> Result<Vec<A>, B>
where
Vec<A>: Clone,
{
results.into_iter().fold(Ok(Vec::new()), |acc, res| {
acc.and_then(|vec| {
res.and_then(|r| {
let mut vectemp = vec.clone();
vectemp.push(r);
Ok(vectemp)
})
})
})
}

View File

@ -1,6 +1,7 @@
use std::env;
mod day1;
mod day2;
fn main() {
let mut args = env::args();
@ -9,6 +10,7 @@ fn main() {
match day {
Some(x) => match x.as_str() {
"day1" => day1::run(),
"day2" => day2::run(),
_ => todo!()
},
_ => println!("Please provide the day as day<n>"),