HiveBrain v1.2.0
Get Started
← Back to all entries
patternrustMinor

Project Euler #11"numbers in a grid" in Rust

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
gridnumbersprojecteulerrust

Problem

To learn more about Rust, I implemented Project Euler #11 "Numbers in a grid". Contrary to some people, I prefer not having the actual data grid in my code, so I put it in a file, which I read in the beginning.

I'm wondering how 'Rustic' my code is. Specially I wonder about the following points:

  • How to most concisely read a table of integers into a data structure? Is it possible to create an array of a certain size? Do I need all this spliting and from_str mapping?



  • Have I handled the array indices in the right way? I'm not used to needing all this casting.



  • I my max function sufficiently generic?



use std::io;
fn max(a:int, b:int) -> int {if a > b {a} else {b}}
fn main() {
    let n = 20;
    let mut ar:Vec> = vec![];
    for line in io::stdin().lines() {
        let s = line.unwrap();
        let ss = s.as_slice().trim().split(' ');
        let xs:Vec = ss.map(|s|from_str::(s).unwrap()).collect();
        ar.push(xs);
    }
    let mut best = 0;
    for i in range(0i,n) {
        for j in range(0i,n) {
            for &(di, dj) in [(0,1),(1,1),(1,0),(1,-1i)].iter() {
                if i+di*3 = 0 {
                    let mut p = 1;
                    for k in range(0i,4) {
                        p *= ar[(i+di*k) as uint][(j+dj*k) as uint]
                    }
                    best = max(best, p);
                }
            }
        }
    }
    println!("{}", best);
}

Solution

Just like most people not actively involved in the language design, I'm still finding my feet with Rust as well, so take what I have to say with a large grain of salt.

You don't need to define your own max function: there is one already in the standard library, in std::cmp to be exact:

pub fn max(v1: T, v2: T) -> T


This will work for anything that has an impl Ord, which int certainly does.

You can avoid the casts if you simply read everything in as a uint in the first place. In fact, it's probably a good idea to split up the code reading and parsing the file from the code that does the calculation. I'd write it something like:

use std::io;

fn read_grid(path: &str) -> Vec> {
    let path = Path::new(path);
    let mut file = io::BufferedReader::new(io::File::open(&path));
    let mut lines = file.lines().map(|x| x.unwrap());
    let mut grid: Vec> = vec![];

    for line in lines {
        let option = line.as_slice().split(' ').map(|x| -> Option from_str(x.trim()));
        grid.push(option.filter(|x| x.is_some()).map(|x| x.unwrap()).collect());
    }
    grid
}


This will also skip over any non-convertible values (that is, anything that from_str(x.trim()) gives None from.

I don't doubt there are still much better ways of writing this, but that's about where I'm at for now.

Code Snippets

pub fn max<T: Ord>(v1: T, v2: T) -> T
use std::io;

fn read_grid(path: &str) -> Vec<Vec<uint>> {
    let path = Path::new(path);
    let mut file = io::BufferedReader::new(io::File::open(&path));
    let mut lines = file.lines().map(|x| x.unwrap());
    let mut grid: Vec<Vec<uint>> = vec![];

    for line in lines {
        let option = line.as_slice().split(' ').map(|x| -> Option<uint> from_str(x.trim()));
        grid.push(option.filter(|x| x.is_some()).map(|x| x.unwrap()).collect());
    }
    grid
}

Context

StackExchange Code Review Q#64084, answer score: 3

Revisions (0)

No revisions yet.