// Problem 81:
|
|
//
|
|
// In the 5 by 5 matrix below, the minimal path sum from the top left to the
|
|
// bottom right, by only moving to the right and down, is indicated in brackets
|
|
// and is equal to 2427.
|
|
//
|
|
// [131] 673 234 103 018
|
|
// [201] [096] [342] 965 150
|
|
// 630 803 [746] [422] 111
|
|
// 537 699 497 [121] 956
|
|
// 805 732 524 [037] [331]
|
|
//
|
|
// Find the minimal path sum from the top left to the bottom right by only
|
|
// moving right and down in matrix.txt, a 31K text file containing an 80x80
|
|
// matrix.
|
|
// https://projecteuler.net/project/resources/p081_matrix.txt
|
|
|
|
use std::collections::HashMap;
|
|
use std::io;
|
|
use std::io::prelude::*;
|
|
use std::io::BufReader;
|
|
|
|
fn parse<T: Read>(reader: T) -> io::Result<Vec<Vec<i32>>> {
|
|
let mut mat = Vec::new();
|
|
|
|
for line in BufReader::new(reader).lines() {
|
|
let row = line?
|
|
.trim()
|
|
.split(',')
|
|
.filter_map(|s| s.parse::<i32>().ok())
|
|
.collect();
|
|
mat.push(row);
|
|
}
|
|
|
|
Ok(mat)
|
|
}
|
|
|
|
fn compute(matrix: &[Vec<i32>], mut memo: &mut HashMap<(usize, usize), i32>, x: usize, y: usize) -> i32 {
|
|
let (w, h) = (matrix[0].len(), matrix.len());
|
|
|
|
// memoize
|
|
if let Some(ret) = memo.get(&(x, y)) {
|
|
return *ret;
|
|
}
|
|
|
|
// base cases
|
|
if (x, y) == (w - 1, h - 1) {
|
|
return matrix[y][x];
|
|
} else if x == w - 1 {
|
|
return matrix[y][x] + compute(matrix, &mut memo, x, y + 1);
|
|
} else if y == h - 1 {
|
|
return matrix[y][x] + compute(matrix, &mut memo, x + 1, y);
|
|
}
|
|
|
|
let ret = matrix[y][x] + {
|
|
let bottom = compute(matrix, &mut memo, x, y + 1);
|
|
let right = compute(matrix, &mut memo, x + 1, y);
|
|
|
|
if bottom < right {
|
|
bottom
|
|
} else {
|
|
right
|
|
}
|
|
};
|
|
memo.insert((x, y), ret);
|
|
ret
|
|
}
|
|
|
|
fn main() {
|
|
let mat = parse(io::stdin());
|
|
if let Ok(data) = mat {
|
|
println!(
|
|
"the minimal path sum is: {}",
|
|
compute(&data, &mut HashMap::new(), 0, 0)
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn five_by_five() {
|
|
let mat = vec![
|
|
vec![131, 673, 234, 103, 18],
|
|
vec![201, 96, 342, 965, 150],
|
|
vec![630, 803, 746, 422, 111],
|
|
vec![537, 699, 497, 121, 956],
|
|
vec![805, 732, 524, 37, 331],
|
|
];
|
|
assert_eq!(2427, compute(&mat, &mut HashMap::new(), 0, 0));
|
|
}
|