Wednesday, 20 December 2017

Advent of Code

Over the past weeks, I've been working through Advent of Code. If you haven't seen it, it's basically a daily programming challenge - one a day for the 25 days running up to Christmas. Each challenge has two parts, and you get points for being in the first 100 people to submit a correct answer (usually a number, or a short string). There's nothing for coming 101st! The challenges open at 00:00 EST (so, 05:00 GMT) so if you want to have a crack at the leaderboard, it's a very early start. The best I've managed so far is about 162nd, but there's a few days left.

Most people tackle the problems in Python, and arguably that's a very good choice. It's a very expressive language, and as the winners produce short, dense code - it needs to be fast to type after all - the lack of static type checking isn't as much of a problem as it might be in a larger application.

I'm doing it in Rust, and it's been very educational.

I thought my Rust was OK going in to this challenge but it turns out I've spent an awful lot of time referring to the Standard Library documentation trying to find various methods on Vec or Iterator. This is getting better, slowly, and I guess only more practice will help here. I have found the Rust Enhanced plugin for Sublime Text to be very helpful - basically I can get a rough outline of the programme in, and then edit until all the red errors have gone away. This means I find the speed of the compiler is less of an issue than in C, as by the time I come to actually build the programme I know it is syntactically good and it's just down to run-time bugs.

To reduce the time it takes to put solutions together, I have a wrapper program which takes inputs files on the command line and calls out to the appropriate 'function' for each day's challenge. These functions take a &[Vec<String>] - that is, each input file is a Vec of Strings, and there's an arbitrary number of them in a slice. I also have a wrapper script which fetches that day's input file and adds it to git, and another which executes my main program with the correct arguments for that day. As the code increases in size, I'm starting to wonder if it's better to have some shared library boilerplate and to put each exercise in its own binary file, but it is what it is for now.

A typical input file might be some comma separated integers, as with 2017's Day 10. Parsing these is simple enough:

pub fn run(contents: &[Vec<String>]) {
    let lengths: Vec<u8> = contents[0][0].split(',').map(|x| x.parse().unwrap()).collect();
    ...
}

I started out doing splits with string literals (because Python), but Clippy told me I should use a char as my split pattern instead. Thanks Clippy! Sometimes the input isn't integers, but symbols of some sort (such as N, E, S, W movements on a map, or a maze layout, or some pseudo-assembler language that needs executing). The Python programmers often resort to some fairly grim looking string matching, but I generally prefer to define the appropriate enum and structs to hold the data, and then work in that. More typing, but less scope for silly mistakes that are impossible to see. Here's an example that's reading in an ASCII-art maze with letters that you need to collect as you walk the maze:

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
enum Piece {
    Cross,
    LeftRight,
    UpDown,
    Space,
    Letter(char),
}
 

pub fn run(contents: &[Vec<String>]) {
    let mut map: Vec<Vec<Piece>> = Vec::new();
    for line in &contents[0] {
        let mut line_vec = Vec::new();
        for square in line.chars() {
            match square {
                '|' => line_vec.push(Piece::UpDown),
                ' ' => line_vec.push(Piece::Space),
                '+' => line_vec.push(Piece::Cross),
                '-' => line_vec.push(Piece::LeftRight),
                'A'...'Z' => line_vec.push(Piece::Letter(square)),
                _ => panic!("Bad char {}", square),
            }
        }
        map.push(line_vec);
    }
    ...
}

Because I've got first class Iterators, Maps and Sets, I'm able to 'think' in a Python way, and with a syntax that I found an awful lot easier to work with that modern C++. Need to read some sentences and find those that contain duplicate words? No problem!

use std::collections::HashSet;

pub fn run(contents: &[Vec<String>]) {
    let mut count = 0;
    for line in &contents[0] {
        let mut dup = false;
        let mut set: HashSet<String> = HashSet::new();
        for word in line.split_whitespace() {
            if !set.insert(word.into()) {
                dup = true;
            }
        }
        if !dup {
            count += 1;
        }
    }
    println!("Count: {}", count);
}
While that's all positive, some things that have proved a little frustating include:
  • Google searches like "rust hashmap insert" don't always go to the canonical API docs. Sometimes you get Servo docs, or sometimes you get a link to an old version (say, 1.14). The documentation doesn't have a link to the latest canonical version ("These docs are out of date - try here!"), which would be useful.
  • I end up using too many unwraps because proper error handling takes more typing.
  • I have to get up at 5am.
Frankly, that's not a very long list considering it's a pretty new language with a famously steep learning curve. Onwards, to Christmas and the grand finale!





Friday, 14 April 2017

Results Analysis

Curious as to how each category did in PiWars (Professional, Intermediate and Beginner), I've annotated the official results with the category of the team and their overall leaderboard position in that category. For example, "2 wheels or not 2 wheels" is "Pro 1", as the winning Professional. You'll note that "Beginners" top four out of the seven categories!

Obstacle Course
1 2 wheels or not 2 wheels (Brian Corteil) Pro 1
2 Maxeos (Alex Daily) Inter 4
3 PiSquared (Leo White) Pro 6
4 Team Steve (Jonathan Pallant) Inter 1
5 Team 3.14 Musketeers / Robot Bâtagnan (Mark Edwards) Beginner 4
6 Hitchin Hackspace (David Booth) Pro 5
7 Slice of Pi Club (Martin Eyre) Inter 6
8 SmartPi (David Plaquin) Beginner 11
9 CNM Hackerspace / Not Today Skynet (Kerry Bruce) Beginner 2
10 Little TREV (Matt Teague) Pro 7
11 Metabot3 (John Palombo / Lance Robson) Pro 3
12 Ipswich Makerspace / Robot Tractorbot (Keith Ellis) Pro 2
13 PiTastrophy (James Cohen) Pro 9
14 KEITH 3 – “Mostly Harmless” (Harry Merckel) Pro 4
15 Sunny Mk2 (Stevie Wray) Inter 5
16 Xero Chatterbot (Robin Blackstone) Beginner 7
17 Maidstone Hackspace (Ian Wilkinson) Inter 2
18 Team Heroes (David Searle) Beginner 9
19 Project BODSSK (Kayleigh Churchill) Beginner 10
20 ICRS (Tom Hartley) Inter 7
21 ZeroHero (Femi Owolade-Coombes) Beginner 13
22 Viridia (Tom Oinn) Pro 8
23 Gnasher – Revenge of the Fallen (Grahame Collins) Inter 9
24 Frankenrobot (Dulcie Turner) Beginner 6
25 Glitterator (Emma Norling) Beginner 5
26 The PiONEERS (Spencer Cummings) Beginner 3
27 Ely Makers (Arvind Shah) Inter 8
28 Radioactive Funky Chickens (Rob Westwick) Beginner 8
29 Seaford (Andrew Seaford) Inter 10
30 Mr Bit (Tom Broughton) Beginner 1
31 Team Cybercondriac / Robot sHazBot 2 (David Pride) Inter 3
32 Snapdragon (Ben Rogers) Beginner 14
33 Awesome Tech (Martin Evans) Beginner 12
34 Java Driven (Wesley Coffin-Jones) Beginner 15


The Minimal Maze
1 Mr Bit (Tom Broughton) Beginner 1
2 Glitterator (Emma Norling) Beginner 5
3 Metabot3 (John Palombo / Lance Robson) Pro 3
4 The PiONEERS (Spencer Cummings) Beginner 3
5 Frankenrobot (Dulcie Turner) Beginner 6


Slightly Deranged Golf
1 CNM Hackerspace / Not Today Skynet (Kerry Bruce) Beginner 2
2 Ipswich Makerspace / Robot Tractorbot (Keith Ellis) Pro 2
3 Team Steve (Jonathan Pallant) Inter 1
4 KEITH 3 – “Mostly Harmless” (Harry Merckel) Pro 4
5 Team Cybercondriac / Robot sHazBot 2 (David Pride) Inter 3
6 Sunny Mk2 (Stevie Wray) Inter 5
7 2 wheels or not 2 wheels (Brian Corteil) Pro 1
8 Slice of Pi Club (Martin Eyre) Inter 6
9 Maxeos (Alex Daily) Inter 4
10 Maidstone Hackspace (Ian Wilkinson) Inter 2
11 Team 3.14 Musketeers / Robot Bâtagnan (Mark Edwards) Beginner 4
12 Team Heroes (David Searle) Beginner 9
13 ICRS (Tom Hartley) Inter 7
14 Metabot3 (John Palombo / Lance Robson) Pro 3
15 SmartPi (David Plaquin) Beginner 11
16 Hitchin Hackspace (David Booth) Pro 5
17 Little TREV (Matt Teague) Pro 7
18 PiSquared (Leo White) Pro 6
19 Seaford (Andrew Seaford) Inter 10
20 Glitterator (Emma Norling) Beginner 5
21 Xero Chatterbot (Robin Blackstone) Beginner 7
22 Awesome Tech (Martin Evans) Beginner 12
23 Project BODSSK (Kayleigh Churchill) Beginner 10
24 PiTastrophy (James Cohen) Pro 9
25 Ely Makers (Arvind Shah) Inter 8
26 ZeroHero (Femi Owolade-Coombes) Beginner 13
27 Radioactive Funky Chickens (Rob Westwick) Beginner 8
28 Gnasher – Revenge of the Fallen (Grahame Collins) Inter 9
29 Mr Bit (Tom Broughton) Beginner 1
30 Frankenrobot (Dulcie Turner) Beginner 6
31 The PiONEERS (Spencer Cummings) Beginner 3


Skittles
1 Ely Makers (Arvind Shah) Inter 8
2 The PiONEERS (Spencer Cummings) Beginner 3
3 Metabot3 (John Palombo / Lance Robson) Pro 3
4 Hitchin Hackspace (David Booth) Pro 5
5 2 wheels or not 2 wheels (Brian Corteil) Pro 1
6 Ipswich Makerspace / Robot Tractorbot (Keith Ellis) Pro 2
7 Mr Bit (Tom Broughton) Beginner 1
8 Project BODSSK (Kayleigh Churchill) Beginner 10
9 Team 3.14 Musketeers / Robot Bâtagnan (Mark Edwards) Beginner 4
10 Maidstone Hackspace (Ian Wilkinson) Inter 2
11 KEITH 3 – “Mostly Harmless” (Harry Merckel) Pro 4
12 Little TREV (Matt Teague) Pro 7
13 CNM Hackerspace / Not Today Skynet (Kerry Bruce) Beginner 2
14 Glitterator (Emma Norling) Beginner 5
15 ICRS (Tom Hartley) Inter 7
16 Slice of Pi Club (Martin Eyre) Inter 6
17 Frankenrobot (Dulcie Turner) Beginner 6
18 Sunny Mk2 (Stevie Wray) Inter 5
19 Team Heroes (David Searle) Beginner 9
20 Gnasher – Revenge of the Fallen (Grahame Collins) Inter 9
21 SmartPi (David Plaquin) Beginner 11
22 Xero Chatterbot (Robin Blackstone) Beginner 7
23 PiSquared (Leo White) Pro 6
24 PiTastrophy (James Cohen) Pro 9
25 Viridia (Tom Oinn) Pro 8
26 Radioactive Funky Chickens (Rob Westwick) Beginner 8
27 Maxeos (Alex Daily) Inter 4


Straight-Line Speed Test
1 Mr Bit (Tom Broughton) Beginner 1
2 Maidstone Hackspace (Ian Wilkinson) Inter 2
3 KEITH 3 – “Mostly Harmless” (Harry Merckel) Pro 4
4 Team Cybercondriac / Robot sHazBot 2 (David Pride) Inter 3
5 Gnasher – Revenge of the Fallen (Grahame Collins) Inter 9
6 CNM Hackerspace / Not Today Skynet (Kerry Bruce) Beginner 2
7 Radioactive Funky Chickens (Rob Westwick) Beginner 8
8 Ipswich Makerspace / Robot Tractorbot (Keith Ellis) Pro 2
9 The PiONEERS (Spencer Cummings) Beginner 3
10 Metabot3 (John Palombo / Lance Robson) Pro 3
11 ICRS (Tom Hartley) Inter 7
12 Sunny Mk2 (Stevie Wray) Inter 5
13 Glitterator (Emma Norling) Beginner 5
14 Team Steve (Jonathan Pallant) Inter 1
15 Xero Chatterbot (Robin Blackstone) Beginner 7
16 Ely Makers (Arvind Shah) Inter 8
17 Little TREV (Matt Teague) Pro 7
18 Team Heroes (David Searle) Beginner 9
19 Team 3.14 Musketeers / Robot Bâtagnan (Mark Edwards) Beginner 4
20 2 wheels or not 2 wheels (Brian Corteil) Pro 1
21 Slice of Pi Club (Martin Eyre) Inter 6
22 SmartPi (David Plaquin) Beginner 11
23 ZeroHero (Femi Owolade-Coombes) Beginner 13
24 Maxeos (Alex Daily) Inter 4
25 Pithon (Nick Young) Inter 11
26 Hitchin Hackspace (David Booth) Pro 5
27 PiTastrophy (James Cohen) Pro 9
28 Project BODSSK (Kayleigh Churchill) Beginner 10
29 Seaford (Andrew Seaford) Inter 10
30 Frankenrobot (Dulcie Turner) Beginner 6
31 PiSquared (Leo White) Pro 6


The Line Follower
1 Team 3.14 Musketeers / Robot Bâtagnan (Mark Edwards) Beginner 4
2 Ipswich Makerspace / Robot Tractorbot (Keith Ellis) Pro 2
3 Team Cybercondriac / Robot sHazBot 2 (David Pride) Inter 3
4 Radioactive Funky Chickens (Rob Westwick) Beginner 8
5 ICRS (Tom Hartley) Inter 7
6 The PiONEERS (Spencer Cummings) Beginner 3
7 KEITH 3 – “Mostly Harmless” (Harry Merckel) Pro 4
8 Metabot3 (John Palombo / Lance Robson) Pro 3
9 Frankenrobot (Dulcie Turner) Beginner 6
10 Viridia (Tom Oinn) Pro 8
11 Team Steve (Jonathan Pallant) Inter 1
12 Seaford (Andrew Seaford) Inter 10
13 PiTastrophy (James Cohen) Pro 9


PiNoon
1 2 wheels or not 2 wheels (Brian Corteil) Pro 1
2 Xero Chatterbot (Robin Blackstone) Beginner 7
3 Sunny Mk2 (Stevie Wray) Inter 5
3 Frankenrobot (Dulcie Turner) Beginner 6

Monday, 3 April 2017

It's a win for Steve!

What a weekend. I'm exhausted! At this time we're still waiting on the full results breakdown, but in the Intermediate category, Team Steve managed a 3rd place, a 2nd place and a 1st place (for the Slightly Deranged Golf)! The three placings (plus, I guess, points elsewhere - I don't know yet) were enough to put Steve, the dog/robot at the top of the rankings for the Intermediate category. I wouldn't have believed it was possible looking at the pile of scrap parts I had on my desk at the middle of last week, so the moral is - never give up!

Here are some photos from the day:

Steve waiting to see the judges.

The one and only, Dr Lucy!
And a couple of videos, starting with Steve playing golf:







The prize bundle I received was pretty epic. Thank you so much to all the sponsors - it really is incredible how generous they've all been. I found (in not particular order):

Not forgetting of course, the fabulous trophies:

Om nom nom nom ... tasty trophy ...

What a day.


Saturday, 25 March 2017

Yay, driving!

Haven't done this in a while. It feels good!

A few brief notes on Steve 2.0:

Raspberry Pi Zero W
Arduino Pro Mini (4x PWM output/quadrature input/current sensing)
Dagu Rover 5 four-motor chassis
Dagu speed controller
5V USB 'phone charger' power for the electronics
6xNiMH AA power for the motors
CSR Bluetooth USB dongle (the Pi Zero W bluetooth is not reliable for me)
PlayStation 3 SIXAXIS remote control
Nokia 5110 LCD with speed/current status display and on-board menu function

To add - 3x Ultrasonic sensors and 2x IR line sensors.

 

Motor test

Humm. Wired up the Arduino but something's not right...

Saturday, 18 March 2017

Flashing an AVR from a Raspberry Pi

It seems things have changed a bit since I last worked with an Arduino on a Raspberry Pi - plus I've forgotten a load of stuff. This is a note to myself, more than anything.

  1. You can install avrdude with sudo apt install avrdude.
  2. On a Raspberry Pi 3 or a Pi Zero W, the /dev/ttyAMA0 UART is used for Bluetooth. The GPIO pins are instead mapped to /dev/ttyS0.
  3. The Arduino Pro Mini (5V/16MHz) has an AtMega328P and the bootloader runs at 57,600 bps.
  4. You can find the built .hex file in /tmp/build*.
  5. The avrdude flash command line is:
avrdude -p m328p -c arduino -P /dev/ttyS0 -U ./path/to/file.hex