Project Euler #11"numbers in a grid" in Rust 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) -&gt; int {if a &gt; b {a} else {b}}
fn main() {
    let n = 20;
    let mut ar:Vec&lt;Vec&lt;int&gt;&gt; = vec![];
    for line in io::stdin().lines() {
        let s = line.unwrap();
        let ss = s.as_slice().trim().split(' ');
        let xs:Vec&lt;int&gt; = ss.map(|s|from_str::&lt;int&gt;(s).unwrap()).collect();
        ar.push(xs);
    }
    let mut best = 0;
    for i in range(0i,n) {
        for j in range(0i,n) {
            for &amp;(di, dj) in [(0,1),(1,1),(1,0),(1,-1i)].iter() {
                if i+di*3 &lt; n &amp;&amp; j+dj*3 &lt; n &amp;&amp; j+dj*3 &gt;= 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);
}
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&lt;T: Ord&gt;(v1: T, v2: T) -&gt; 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: &amp;str) -&gt; Vec&lt;Vec&lt;uint&gt;&gt; {
    let path = Path::new(path);
    let mut file = io::BufferedReader::new(io::File::open(&amp;path));
    let mut lines = file.lines().map(|x| x.unwrap());
    let mut grid: Vec&lt;Vec&lt;uint&gt;&gt; = vec![];

    for line in lines {
        let option = line.as_slice().split(' ').map(|x| -&gt; Option&lt;uint&gt; 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.