06 Dec 2017
This is a series where I’ll be discussing interesting Rust tidbits that I encounter when solving
Advent of Code 2017 .
You can find the complete (spoiler) solution here: udoprog/rust-advent-of-code-2017
On day 6 we need to iterate over a vector, by starting at an index in the middle of the vector and
wrap around.
A neat way to accomplish this, is to use range expressions (like 0..10
) as an iterator, and split
it into two parts.
let mut v = vec! [ 0 , 0 , 0 , 0 ];
let idx = 2 ;
for ( i , idx ) in ( idx .. v .len ()) .chain ( 0usize .. idx ) .enumerate () {
v [ idx ] += i ;
}
println! ( "out = {:?}" , v );
This would print:
05 Dec 2017
This is a series where I’ll be discussing interesting Rust tidbits that I encounter when solving
Advent of Code 2017 .
You can find the complete (spoiler) solution here: udoprog/rust-advent-of-code-2017
Attempting to access data that is out of bounds in a collections could potentially ruin your day.
To combat this, rust provides ‘safe’ alternatives for slice indexing in the form of get
and
get_mut
.
Note : these are available on Vec
because it implements Deref<Target = [T]>
, which causes rust
to look for methods there as well.
These return an Option<&T>
and Option<&mut T>
, requiring you to check that the provided index
was present, before attempting to deal with the data.
So this:
let mut v = vec! [ 1 , 2 , 2 ];
println! ( "data = {}" , v [ 2 ]);
Becomes this:
let mut v = vec! [ 1 , 2 , 2 ];
match v .get ( 2 ) {
Some ( value ) => println! ( "data = {}" , value ),
None => println! ( "no value present :(" ),
}
04 Dec 2017
This is a series where I’ll be discussing interesting Rust tidbits that I encounter when solving
Advent of Code 2017 .
You can find the complete (spoiler) solution here: udoprog/rust-advent-of-code-2017
If you want to test a function that reads stuff, you can do the following:
use std :: io :: Read ;
fn my_fun < R : Read > ( reader : R ) {
/* */
}
This allows you to write tests like these:
#[test]
fn test_with_cursor () {
use std :: io :: Cursor ;
my_fun ( Cursor :: new ( "hello \n world" ));
}
If you don’t like monomorphization (large binaries?), use a trait object instead:
use std :: io :: Read ;
fn my_fun ( reader : & mut Read ) {
/* */
}
But pay the price of dynamic dispatch.
03 Dec 2017
This is a series where I’ll be discussing interesting Rust tidbits that I encounter when solving
Advent of Code 2017 .
You can find the complete (spoiler) solution here: udoprog/rust-advent-of-code-2017
Option can be used as an Iterator:
fn cell_value ( storage : & HashMap < ( i64 , i64 ), u64 > , x : i64 , y : i64 ) -> u64 {
[
& ( x - 1 , y - 1 ), & ( x , y - 1 ), & ( x + 1 , y - 1 ),
& ( x - 1 , y ), /* (x, y) */ & ( x + 1 , y ),
& ( x - 1 , y + 1 ), & ( x , y + 1 ), & ( x + 1 , y + 1 ),
] .into_iter () .flat_map (| k | storage .get ( k )) .map (| v | * v ) .sum ()
}
Note that storage.get(k)
returns an Option
, And the flat_map
closure returns U:
IntoIterator
.
Option
implements IntoIterator
, which for None
is an empty iterator, and Some(T)
is an
iterator with a single item. You can see that in action for the Item
struct which is used to
implement this behavior: https://doc.rust-lang.org/src/core/option.rs.html#912
01 Dec 2017
This is a series where I’ll be discussing interesting Rust tidbits that I encounter when solving
Advent of Code 2017 .
You can find the complete (spoiler) solution here: udoprog/rust-advent-of-code-2017
I decided the use the following compact expression to open and read the entire contents of a file:
let mut data = String :: new ();
File :: open ( path ) ? .read_to_string ( & mut data ) ? ;
Desugared, it would read as something like this:
let mut data = String :: new ();
{
let mut _f = File :: open ( path ) ? ;
_f .read_to_string ( & mut data ) ? ;
}
This means that the file is closed immediately after its contents has been read, and is not
accessible anywhere else in the scope.