Day 9 WIP working on test example

Still need to handle a special case for the full example.
This commit is contained in:
Tyler Hallada 2019-02-16 02:27:38 -05:00
parent af6709d2a8
commit dc5e1c6427
4 changed files with 172 additions and 2 deletions

1
inputs/9.txt Normal file
View File

@ -0,0 +1 @@
471 players; last marble is worth 72026 points

1
inputs/9_test.txt Normal file
View File

@ -0,0 +1 @@
9 players; last marble is worth 25 points

165
src/day9.rs Normal file
View File

@ -0,0 +1,165 @@
extern crate regex;
use std::error::Error;
use std::fmt;
use std::fs;
use std::result;
use std::str::FromStr;
use regex::Regex;
type Result<T> = result::Result<T, Box<Error>>;
const INPUT: &str = "inputs/9_test.txt";
#[derive(Clone, Copy, Debug, PartialEq)]
struct GameParameters {
players: usize,
last_marble: usize,
}
impl FromStr for GameParameters {
type Err = Box<Error>;
fn from_str(s: &str) -> Result<GameParameters> {
lazy_static! {
static ref RE: Regex = Regex::new(
r"(?P<players>\d+) players; last marble is worth (?P<last_marble>\d+) points"
)
.unwrap();
}
let captures = match RE.captures(s) {
None => {
return Err(From::from(
"Malformed game parameters, no fields could be found",
));
}
Some(captures) => captures,
};
Ok(GameParameters {
players: captures["players"].parse()?,
last_marble: captures["last_marble"].parse()?,
})
}
}
#[derive(Debug, PartialEq)]
struct GameState {
turn: Option<usize>,
circle: Vec<usize>,
current_marble_index: usize,
current_marble: usize,
player_scores: Vec<usize>,
}
impl GameState {
fn new(parameters: GameParameters) -> GameState {
GameState {
turn: None,
circle: vec![0],
current_marble_index: 0,
current_marble: 0,
player_scores: vec![0; parameters.players as usize],
}
}
fn play_until_marble(&mut self, last_marble: usize) {
println!("{}", &self);
for _ in 0..last_marble {
self.turn = match self.turn {
None => Some(0),
Some(turn) => Some((turn + 1) % self.player_scores.len()),
};
if (self.current_marble + 1) % 23 == 0 {
self.place_23rd_marble();
} else {
self.place_next_marble();
}
println!("{}", &self);
}
dbg!(&self.player_scores);
}
fn place_next_marble(&mut self) {
self.current_marble += 1;
if self.current_marble_index == self.circle.len() - 1 {
self.current_marble_index = 1;
self.circle.insert(self.current_marble_index, self.current_marble);
} else {
self.current_marble_index += 2;
self.circle.insert(self.current_marble_index, self.current_marble);
}
}
fn place_23rd_marble(&mut self) {
println!("23rd marble placed");
self.current_marble += 1;
// TODO: handle case where this over-extends over the beginning of the vec
let removed_marble = self.circle.remove(self.current_marble_index - 7);
self.player_scores[self.turn.unwrap()] += removed_marble + self.current_marble;
self.current_marble_index -= 7;
}
fn highest_score(&mut self) -> usize {
*self.player_scores.iter().max().unwrap_or(&0)
}
}
impl fmt::Display for GameState {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.turn {
None => write!(f, "[-] ")?,
Some(turn) => write!(f, "[{}] ", turn + 1)?,
}
for (index, marble) in self.circle.iter().enumerate() {
if index == self.current_marble_index {
write!(f, "({}) ", marble)?;
} else {
write!(f, "{} ", marble)?;
}
}
Ok(())
}
}
pub fn solve_part1() -> Result<usize> {
let game_params = read_game_parameters(INPUT)?;
Ok(get_highest_score_for_game(game_params))
}
fn read_game_parameters(filename: &str) -> Result<GameParameters> {
let game_params = fs::read_to_string(filename)?;
Ok(game_params.parse()?)
}
fn get_highest_score_for_game(game_params: GameParameters) -> usize {
let mut game_state = GameState::new(game_params);
game_state.play_until_marble(game_params.last_marble);
game_state.highest_score()
}
#[cfg(test)]
mod tests {
use super::*;
const TEST_INPUT: &str = "inputs/9_test.txt";
const TEST_GAME_PARAMS: GameParameters = GameParameters {
players: 9,
last_marble: 25,
};
#[test]
fn reads_game_parameters_file() {
assert_eq!(read_game_parameters(TEST_INPUT).unwrap(), TEST_GAME_PARAMS);
}
#[test]
fn gets_highest_score_for_game() {
assert_eq!(get_highest_score_for_game(TEST_GAME_PARAMS), 32);
}
}

View File

@ -11,6 +11,7 @@ mod day5;
mod day6; mod day6;
mod day7; mod day7;
mod day8; mod day8;
mod day9;
fn main() { fn main() {
// println!("Day 1:"); // println!("Day 1:");
@ -34,7 +35,9 @@ fn main() {
// println!("Day 7:"); // println!("Day 7:");
// println!("{}", day7::solve_part1().unwrap()); // println!("{}", day7::solve_part1().unwrap());
// println!("{}", day7::solve_part2().unwrap()); // println!("{}", day7::solve_part2().unwrap());
println!("Day 8:"); // println!("Day 8:");
// println!("{}", day8::solve_part1().unwrap()); // println!("{}", day8::solve_part1().unwrap());
println!("{}", day8::solve_part2().unwrap()); // println!("{}", day8::solve_part2().unwrap());
println!("Day 9:");
println!("{}", day9::solve_part1().unwrap());
} }