Added solution to problem 18

This commit is contained in:
2020-06-17 10:45:57 -04:00
parent 81f05146a9
commit f03573596d
3 changed files with 188 additions and 2 deletions

View File

@@ -40,3 +40,4 @@ pub mod Problem14;
pub mod Problem15; pub mod Problem15;
pub mod Problem16; pub mod Problem16;
pub mod Problem17; pub mod Problem17;
pub mod Problem18;

178
src/Problems/Problem18.rs Normal file
View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
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::<Vec::<i32>>::new();
for _ in 0..15{
list.push(Vec::<i32>::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::<Location>::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::<Location>::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::<Vec::<i32>>){
//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<Location>, 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
*/

View File

@@ -33,8 +33,8 @@ mod Problems;
#[derive(PartialEq)] #[derive(PartialEq)]
enum Selections{EMPTY, SOLVE, DESCRIPTION, LIST, EXIT, SIZE} enum Selections{EMPTY, SOLVE, DESCRIPTION, LIST, EXIT, SIZE}
static problemNumbers: [u32; 18] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, static problemNumbers: [u32; 19] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17]; 10, 11, 12, 13, 14, 15, 16, 17, 18];
fn main(){ fn main(){
let mut selection = Selections::EMPTY; let mut selection = Selections::EMPTY;
@@ -199,6 +199,10 @@ fn solveProblem(problemNumber: u32){
println!("{}", Problems::Problem17::getDescription()); println!("{}", Problems::Problem17::getDescription());
println!("{}", Problems::Problem17::solve()); println!("{}", Problems::Problem17::solve());
} }
else if(problemNumber == 18){
println!("{}", Problems::Problem18::getDescription());
println!("{}", Problems::Problem18::solve());
}
} }
fn descriptionMenu(){ fn descriptionMenu(){
//Give some extra space to print the description //Give some extra space to print the description
@@ -275,6 +279,9 @@ fn printDescription(problemNumber: u32){
else if(problemNumber == 17){ else if(problemNumber == 17){
println!("{}", Problems::Problem17::getDescription()); println!("{}", Problems::Problem17::getDescription());
} }
else if(problemNumber == 18){
println!("{}", Problems::Problem18::getDescription());
}
} }
fn getProblemNumber() -> u32{ fn getProblemNumber() -> u32{
println!("Enter a problem number: "); println!("Enter a problem number: ");