From f03573596dfa3d01b7d46126cbe157f2b2b3a1e7 Mon Sep 17 00:00:00 2001 From: Mattrixwv Date: Wed, 17 Jun 2020 10:45:57 -0400 Subject: [PATCH] Added solution to problem 18 --- src/Problems.rs | 1 + src/Problems/Problem18.rs | 178 ++++++++++++++++++++++++++++++++++++++ src/main.rs | 11 ++- 3 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 src/Problems/Problem18.rs diff --git a/src/Problems.rs b/src/Problems.rs index 5f1d867..b3024eb 100644 --- a/src/Problems.rs +++ b/src/Problems.rs @@ -40,3 +40,4 @@ pub mod Problem14; pub mod Problem15; pub mod Problem16; pub mod Problem17; +pub mod Problem18; diff --git a/src/Problems/Problem18.rs b/src/Problems/Problem18.rs new file mode 100644 index 0000000..c308690 --- /dev/null +++ b/src/Problems/Problem18.rs @@ -0,0 +1,178 @@ +//ProjectEulerRust/src/Problems/Problems18.rs +//Matthew Ellison +// Created: 06-17-20 +//Modified: 06-17-20 +//Find the maximum total from top to bottom +/* +75 +95 64 +17 47 82 +18 35 87 10 +20 04 82 47 65 +19 01 23 75 03 34 +88 02 77 73 07 63 67 +99 65 04 28 06 16 70 92 +41 41 26 56 83 40 80 70 33 +41 48 72 33 47 32 37 16 94 29 +53 71 44 65 25 43 91 52 97 51 14 +70 11 33 28 77 73 17 78 39 68 17 57 +91 71 52 38 17 14 91 43 58 50 27 29 48 +63 66 04 68 89 53 67 30 73 16 69 87 40 31 +04 62 98 27 23 09 70 98 73 93 38 53 60 04 23 +*/ +//This is done using a breadth first search +//Unless otherwise listed all non-standard includes are my own creation and available from https://bibucket.org/Mattrixwv/RustClasses +/* + Copyright (C) 2020 Matthew Ellison + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + + +extern crate myClasses; +use crate::Problems::Answer::Answer; + +pub fn getDescription() -> String{ + "Find the maximum total from top to bottom".to_string() +} + +#[derive(Copy, Clone, Debug)] +struct Location{ + pub xLocation: i32, + pub yLocation: i32, + pub total: i32, + pub fromRight: bool +} +impl Location{ + pub fn new(x: i32, y: i32, t: i32, r: bool) -> Location{ + let location = Location{xLocation: x, yLocation: y, total: t, fromRight: r}; + return location; + } +} +impl PartialEq for Location{ + fn eq(&self, other: &Self) -> bool{ + if((self.xLocation == other.xLocation) && (self.yLocation == other.yLocation)){ + return true; + } + else{ + return false; + } + } +} + +pub fn solve() -> Answer{ + let NUM_ROWS = 15; + //Start the timer + let mut timer = myClasses::Stopwatch::Stopwatch::new(); + timer.start(); + + //Setup the list you are trying to find a path through + let mut list = Vec::>::new(); + for _ in 0..15{ + list.push(Vec::::new()); + } + list[0].push(75); + list[1].extend_from_slice(&[95, 64]); + list[2].extend_from_slice(&[17, 47, 82]); + list[3].extend_from_slice(&[18, 35, 87, 10]); + list[4].extend_from_slice(&[20, 04, 82, 47, 65]); + list[5].extend_from_slice(&[19, 01, 23, 75, 03, 34]); + list[6].extend_from_slice(&[88, 02, 77, 73, 07, 63, 67]); + list[7].extend_from_slice(&[99, 65, 04, 28, 06, 16, 70, 92]); + list[8].extend_from_slice(&[41, 41, 26, 56, 83, 40, 80, 70, 33]); + list[9].extend_from_slice(&[41, 48, 72, 33, 47, 32, 37, 16, 94, 29]); + list[10].extend_from_slice(&[53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14]); + list[11].extend_from_slice(&[70, 11, 33, 28, 77, 73, 17, 78, 39, 68, 17, 57]); + list[12].extend_from_slice(&[91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27, 29, 48]); + list[13].extend_from_slice(&[63, 66, 04, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31]); + list[14].extend_from_slice(&[04, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 04, 23]); + + //Invert the list + invert(&mut list); + + let mut foundPoints = Vec::::new(); //For the points that I have already found the shortest distance to + foundPoints.push(Location::new(0, 0, list[0][0], false)); //Add the first row as a found point because you have to go through the tip + let mut possiblePoints = Vec::::new(); //For the locations you are checking this round + //Add the second row as possible points + possiblePoints.push(Location::new(0, 1, list[0][0] + list[1][0], true)); + possiblePoints.push(Location::new(1, 1, list[0][0] + list[1][1], false)); + let mut foundBottom = false; //Used when you find a point at the bottom of the list + + //Loop until you find the bottom of the list + while(!foundBottom){ + //Check which possible point gives us the lowest number. If more than one has the same number simply keep the first one + let mut minLoc = possiblePoints[0]; + for loc in 1..possiblePoints.len(){ + if(possiblePoints[loc].total < minLoc.total){ + minLoc = possiblePoints[loc]; + } + } + + //Remove it from the list of possible points + removeHelper(&mut possiblePoints, minLoc); + + //Add that point to the list of found points + foundPoints.push(minLoc); + + //Add to the list of possible points from the point we just found and + //If you are at the bottom raise the flag to end the program + let mut xLoc = minLoc.xLocation; + let yLoc = minLoc.yLocation + 1; + if(yLoc >= NUM_ROWS){ + foundBottom = true; + } + else{ + possiblePoints.push(Location::new(xLoc, yLoc, minLoc.total + list[yLoc as usize][xLoc as usize], true)); + xLoc += 1; //Advance the x location to simulate going right + //Check if x is out of bounds + if(xLoc < list[yLoc as usize].len() as i32){ + possiblePoints.push(Location::new(xLoc, yLoc, minLoc.total + list[yLoc as usize][xLoc as usize], false)); + } + } + } + + //Stop the timer + timer.stop(); + + //Get the correct total which will be the inversion of the current one + let actualTotal = ((100 * NUM_ROWS) - foundPoints[foundPoints.len() - 1].total); + + //Return the results + return Answer::new(format!("The value of the longest path is {}", actualTotal), timer.getString()); +} +//This function turns every number in the array into (100 - num) to allow you to find the largest numbers rather than the smallest +fn invert(list: &mut Vec::>){ + //Loop through every row in the list + for rowCnt in 0..list.len(){ + //Loop through every column in the list + for colCnt in 0..list[rowCnt].len(){ + //The current element gets the value of 100 - value + list[rowCnt][colCnt] = 100 - list[rowCnt][colCnt]; + } + } +} +//This function helps be removing th eelement that is the same as the minumum location +fn removeHelper(possiblePoints: &mut Vec, minLoc: Location){ + for loc in 0..possiblePoints.len(){ + if(possiblePoints[loc] == minLoc){ + possiblePoints.remove(loc); + break; + } + } +} + +/* Results: +The value of the longest path is 1074 +It took 195.800 microseconds to solve this problem +*/ diff --git a/src/main.rs b/src/main.rs index 3685fc9..b7044a0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,8 +33,8 @@ mod Problems; #[derive(PartialEq)] enum Selections{EMPTY, SOLVE, DESCRIPTION, LIST, EXIT, SIZE} -static problemNumbers: [u32; 18] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17]; +static problemNumbers: [u32; 19] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18]; fn main(){ let mut selection = Selections::EMPTY; @@ -199,6 +199,10 @@ fn solveProblem(problemNumber: u32){ println!("{}", Problems::Problem17::getDescription()); println!("{}", Problems::Problem17::solve()); } + else if(problemNumber == 18){ + println!("{}", Problems::Problem18::getDescription()); + println!("{}", Problems::Problem18::solve()); + } } fn descriptionMenu(){ //Give some extra space to print the description @@ -275,6 +279,9 @@ fn printDescription(problemNumber: u32){ else if(problemNumber == 17){ println!("{}", Problems::Problem17::getDescription()); } + else if(problemNumber == 18){ + println!("{}", Problems::Problem18::getDescription()); + } } fn getProblemNumber() -> u32{ println!("Enter a problem number: ");