advent-of-code/2022/rust/day02.rs

160 lines
3.7 KiB
Rust

use std::collections::HashMap;
use std::{
fs::File,
io::{prelude::*, BufReader},
path::Path,
};
fn lines_from_file(filename: impl AsRef<Path>) -> Vec<String> {
let file = File::open(filename).expect("no such file");
let buf = BufReader::new(file);
buf.lines()
.map(|l| l.expect("Could not parse line"))
.collect()
}
// ---
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
enum Move {
Rock,
Paper,
Scissors,
INVALID,
Win,
Lose,
Tie,
}
fn main() {
let lines = lines_from_file("../full/day02.txt");
part1(&lines);
part2(&lines);
}
fn to_enum(s: &str, part: i32) -> Move {
if s == "A" {
return Move::Rock;
} else if s == "B" {
return Move::Paper;
} else if s == "C" {
return Move::Scissors;
} else if s == "X" {
if part == 1 {
return Move::Rock;
} else {
return Move::Lose;
}
} else if s == "Y" {
if part == 1 {
return Move::Paper;
} else {
return Move::Tie;
}
} else if s == "Z" {
if part == 1 {
return Move::Scissors;
} else {
return Move::Win;
}
}
return Move::INVALID;
}
fn parse(lines: &Vec<String>, part: i32) -> (Vec<Move>, Vec<Move>) {
let mut oppt: Vec<Move> = Vec::new();
let mut mine: Vec<Move> = Vec::new();
for line in lines {
let split = line.split_whitespace().collect::<Vec<_>>();
oppt.push(to_enum(split[0], part));
mine.push(to_enum(split[1], part));
}
return (oppt, mine);
}
fn score_1(o: &Move, m: Move) -> i32 {
let mut score: i32 = 0;
let scores: HashMap<Move, i32> = HashMap::from([
(Move::Rock, 1),
(Move::Paper, 2),
(Move::Scissors, 3),
(Move::Win, 6),
(Move::Tie, 3),
(Move::Lose, 0),
]);
// For my choice
score += scores[&m];
// for which outcome
if o == &m {
//println!("Tie");
score += scores[&Move::Tie];
} else if (m == Move::Paper && o == &Move::Rock)
|| (m == Move::Rock && o == &Move::Scissors)
|| (m == Move::Scissors && o == &Move::Paper)
{
//println!("Win");
score += scores[&Move::Win];
} else {
//println!("Lose");
score += scores[&Move::Lose];
}
return score;
}
fn part1(lines: &Vec<String>) {
let (oppt, mine) = parse(lines, 1);
let mut score: i32 = 0;
for (idx, el) in oppt.iter().enumerate() {
score += score_1(el, mine[idx]);
}
println!("{}", score);
}
fn score_2(o: &Move, m: Move) -> i32 {
let mut new_move: &Move = &Move::INVALID;
let mut score: i32 = 0;
let scores: HashMap<Move, i32> = HashMap::from([
(Move::Rock, 1),
(Move::Paper, 2),
(Move::Scissors, 3),
(Move::Win, 6),
(Move::Tie, 3),
(Move::Lose, 0),
]);
// For my choice
if m == Move::Tie {
new_move = o;
} else if m == Move::Lose {
if o == &Move::Rock {
new_move = &Move::Scissors;
} else if o == &Move::Paper {
new_move = &Move::Rock;
} else {
new_move = &Move::Paper;
}
} else if m == Move::Win {
if o == &Move::Rock {
new_move = &Move::Paper;
} else if o == &Move::Paper {
new_move = &Move::Scissors;
} else {
new_move = &Move::Rock;
}
}
score += scores[new_move];
score += scores[&m];
return score;
}
fn part2(lines: &Vec<String>) {
let (oppt, mine) = parse(lines, 2);
let mut score: i32 = 0;
for (idx, el) in oppt.iter().enumerate() {
score += score_2(el, mine[idx]);
}
println!("{}", score);
}