From de6e826c3140050304dc19734badfc73a7bf5af7 Mon Sep 17 00:00:00 2001 From: Keenan Tims Date: Wed, 6 Dec 2023 18:07:15 -0800 Subject: [PATCH] day6: problem 1 solution --- 6/Cargo.lock | 7 ++ 6/Cargo.toml | 8 ++ 6/input | 2 + 6/src/main.rs | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 216 insertions(+) create mode 100644 6/Cargo.lock create mode 100644 6/Cargo.toml create mode 100644 6/input create mode 100644 6/src/main.rs diff --git a/6/Cargo.lock b/6/Cargo.lock new file mode 100644 index 0000000..a16c0bf --- /dev/null +++ b/6/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "day6" +version = "0.1.0" diff --git a/6/Cargo.toml b/6/Cargo.toml new file mode 100644 index 0000000..89d04ae --- /dev/null +++ b/6/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day6" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/6/input b/6/input new file mode 100644 index 0000000..38a3c3e --- /dev/null +++ b/6/input @@ -0,0 +1,2 @@ +Time: 53 89 76 98 +Distance: 313 1090 1214 1201 diff --git a/6/src/main.rs b/6/src/main.rs new file mode 100644 index 0000000..19e6737 --- /dev/null +++ b/6/src/main.rs @@ -0,0 +1,199 @@ +use std::fs::File; +use std::io::{BufRead, BufReader, Lines}; + +// --- Day 6: Wait For It --- + +// The ferry quickly brings you across Island Island. After asking around, you discover +// that there is indeed normally a large pile of sand somewhere near here, but you don't +// see anything besides lots of water and the small island where the ferry has docked. + +// As you try to figure out what to do next, you notice a poster on a wall near the +// ferry dock. "Boat races! Open to the public! Grand prize is an all-expenses-paid trip +// to Desert Island!" That must be where the sand comes from! Best of all, the boat +// races are starting in just a few minutes. + +// You manage to sign up as a competitor in the boat races just in time. The organizer +// explains that it's not really a traditional race - instead, you will get a fixed +// amount of time during which your boat has to travel as far as it can, and you win if +// your boat goes the farthest. + +// As part of signing up, you get a sheet of paper (your puzzle input) that lists the +// time allowed for each race and also the best distance ever recorded in that race. To +// guarantee you win the grand prize, you need to make sure you go farther in each race +// than the current record holder. + +// The organizer brings you over to the area where the boat races are held. The boats +// are much smaller than you expected - they're actually toy boats, each with a big +// button on top. Holding down the button charges the boat, and releasing the button +// allows the boat to move. Boats move faster if their button was held longer, but time +// spent holding the button counts against the total race time. You can only hold the +// button at the start of the race, and boats don't move until the button is released. + +// For example: + +// Time: 7 15 30 +// Distance: 9 40 200 + +// This document describes three races: + +// The first race lasts 7 milliseconds. The record distance in this race is 9 millimeters. +// The second race lasts 15 milliseconds. The record distance in this race is 40 millimeters. +// The third race lasts 30 milliseconds. The record distance in this race is 200 millimeters. + +// Your toy boat has a starting speed of zero millimeters per millisecond. For each +// whole millisecond you spend at the beginning of the race holding down the button, the +// boat's speed increases by one millimeter per millisecond. + +// So, because the first race lasts 7 milliseconds, you only have a few options: + +// Don't hold the button at all (that is, hold it for 0 milliseconds) at the start +// of the race. The boat won't move; it will have traveled 0 millimeters by the end +// of the race. + +// Hold the button for 1 millisecond at the start of the race. Then, the boat will +// travel at a speed of 1 millimeter per millisecond for 6 milliseconds, reaching a +// total distance traveled of 6 millimeters. + +// Hold the button for 2 milliseconds, giving the boat a speed of 2 millimeters per +// millisecond. It will then get 5 milliseconds to move, reaching a total distance +// of 10 millimeters. + +// Hold the button for 3 milliseconds. After its remaining 4 milliseconds of travel +// time, the boat will have gone 12 millimeters. + +// Hold the button for 4 milliseconds. After its remaining 3 milliseconds of travel +// time, the boat will have gone 12 millimeters. + +// Hold the button for 5 milliseconds, causing the boat to travel a total of 10 +// millimeters. + +// Hold the button for 6 milliseconds, causing the boat to travel a total of 6 +// millimeters. + +// Hold the button for 7 milliseconds. That's the entire duration of the race. You +// never let go of the button. The boat can't move until you let go of the button. +// Please make sure you let go of the button so the boat gets to move. 0 +// millimeters. + +// Since the current record for this race is 9 millimeters, there are actually 4 +// different ways you could win: you could hold the button for 2, 3, 4, or 5 +// milliseconds at the start of the race. + +// In the second race, you could hold the button for at least 4 milliseconds and at most +// 11 milliseconds and beat the record, a total of 8 different ways to win. + +// In the third race, you could hold the button for at least 11 milliseconds and no more +// than 19 milliseconds and still beat the record, a total of 9 ways you could win. + +// BOILERPLATE +type InputIter = Lines>; + +fn get_input() -> InputIter { + let f = File::open("input").unwrap(); + let br = BufReader::new(f); + br.lines() +} + +fn main() { + println!("Problem 1 solution: {}", problem1(get_input())); + println!("Problem 2 solution: {}", problem2(get_input())); +} + +// PARSER + +#[derive(Debug)] +struct Races(Vec<(u64, u64)>); + +impl From> for Races { + fn from(mut input: Lines) -> Self { + let timeline = input.next().unwrap().unwrap(); + let distline = input.next().unwrap().unwrap(); + + let times = timeline + .split_whitespace() + .skip(1) + .map(|s| s.parse().unwrap()); + let distances = distline + .split_whitespace() + .skip(1) + .map(|s| s.parse().unwrap()); + + Races(times.zip(distances).collect()) + } +} + +// PROBLEM 1 solution + +// To see how much margin of error you have, determine the number of ways you can beat +// the record in each race; in this example, if you multiply these values together, you +// get 288 (4 * 8 * 9). + +// Determine the number of ways you could beat the record in each race. What do you get +// if you multiply these numbers together? + +/// Calculate the 'score' of a race. Speed will equal button duration, and runtime +/// equals the remaining time +fn race_distance(button_duration: u64, race_duration: u64) -> u64 { + assert!(button_duration <= race_duration); + + let running_time = race_duration - button_duration; + + running_time * button_duration +} + +fn problem1_possible_wins(race: (u64, u64)) -> u64 { + let (duration, record) = race; + + (1..duration) + .map(|button_duration| race_distance(button_duration, duration)) + .filter(|achieved_distance| *achieved_distance > record) + .count() as u64 +} + +fn problem1(input: Lines) -> u64 { + let races = Races::from(input); + races.0.iter().map(|race| problem1_possible_wins(*race)).fold(1, |accum, elem| accum * elem) +} + +// PROBLEM 2 solution +fn problem2(input: Lines) -> u64 { + 0 +} + +#[cfg(test)] +mod tests { + use crate::*; + use std::io::Cursor; + + const EXAMPLE: &str = &"Time: 7 15 30 +Distance: 9 40 200"; + + #[test] + fn test_races_parser() { + let c = Cursor::new(EXAMPLE); + let races = Races::from(c.lines()); + assert_eq!(races.0, vec![(7, 9), (15, 40), (30, 200)]); + } + + #[test] + fn test_race_distance() { + assert_eq!(race_distance(0, 7), 0); + assert_eq!(race_distance(1, 7), 6); + assert_eq!(race_distance(2, 7), 10); + assert_eq!(race_distance(3, 7), 12); + assert_eq!(race_distance(7, 7), 0); + } + + #[test] + fn test_possible_wins() { + assert_eq!(problem1_possible_wins((7,9)), 4); + assert_eq!(problem1_possible_wins((15,40)), 8); + assert_eq!(problem1_possible_wins((30,200)), 9); + } + + #[test] + fn test_problem1_example() { + let c = Cursor::new(EXAMPLE); + assert_eq!(problem1(c.lines()), 288); + } +}