day6: problem 1 solution
This commit is contained in:
		
							
								
								
									
										7
									
								
								6/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								6/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -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"
 | 
				
			||||||
							
								
								
									
										8
									
								
								6/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								6/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@@ -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]
 | 
				
			||||||
							
								
								
									
										199
									
								
								6/src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								6/src/main.rs
									
									
									
									
									
										Normal file
									
								
							@@ -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<BufReader<File>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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<T: BufRead> From<Lines<T>> for Races {
 | 
				
			||||||
 | 
					    fn from(mut input: Lines<T>) -> 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<T: BufRead>(input: Lines<T>) -> 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<T: BufRead>(input: Lines<T>) -> 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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user