Post: Advent of code day 22

This commit is contained in:
Jez Cope 2017-12-24 19:32:13 +00:00
parent a3a96c1046
commit 8f9bd3027b
2 changed files with 150 additions and 1 deletions

View File

@ -13,7 +13,7 @@ series: aoc2017
[Today's challenge](http://adventofcode.com/2017/day/21) asks us to assist an artist building fractal patterns from a rulebook.
[→ Full code on GitHub](https://github.com/jezcope/aoc2017/blob/master/21-fractal-art.md)
[→ Full code on GitHub](https://github.com/jezcope/aoc2017/blob/master/21-fractal-art.py)
!!! commentary
Another fairly straightforward algorithm: the really tricky part was breaking the pattern up into chunks and rejoining it again. I could probably have done that more efficiently, and would have needed to if I had to go for a few more iterations and the grid grows with every iteration and gets big fast.

View File

@ -0,0 +1,149 @@
---
title: "Sporifica Virus — Rust — #adventofcode Day 22"
description: "In which I make more beautiful ASCII art and cause disease in the process."
slug: day-22
date: 2017-12-24T19:32:03+00:00
tags:
- Technology
- Learning
- Advent of Code
- Rust
series: aoc2017
---
[Today's challenge](http://adventofcode.com/2017/day/22) has us helping to clean up (or spread, I can't really tell) an infection of the "sporifica" virus.
[→ Full code on GitHub](https://github.com/jezcope/aoc2017/blob/master/22-sporifica-virus.rs)
!!! commentary
I thought I'd have another play with Rust, as its Haskell-like features resonate with me at the moment. I struggled quite a lot with the Rust concepts of ownership and borrowing, and this is a cleaned-up version of the code based on some [good advice from the folks on /r/rust](https://www.reddit.com/r/rust/comments/7lnmz4/code_review_fighting_the_borrow_checker_for/).
```rust
use std::io;
use std::env;
use std::io::BufRead;
use std::collections::HashMap;
#[derive(PartialEq, Clone, Copy, Debug)]
enum Direction {Up, Right, Down, Left}
#[derive(PartialEq, Clone, Copy, Debug)]
enum Infection {Clean, Weakened, Infected, Flagged}
use self::Direction::*;
use self::Infection::*;
type Grid = HashMap<(isize, isize), Infection>;
fn turn_left(d: Direction) -> Direction {
match d {Up => Left, Right => Up, Down => Right, Left => Down}
}
fn turn_right(d: Direction) -> Direction {
match d {Up => Right, Right => Down, Down => Left, Left => Up}
}
fn turn_around(d: Direction) -> Direction {
match d {Up => Down, Right => Left, Down => Up, Left => Right}
}
fn make_move(d: Direction, x: isize, y: isize) -> (isize, isize) {
match d {
Up => (x-1, y),
Right => (x, y+1),
Down => (x+1, y),
Left => (x, y-1),
}
}
fn basic_step(grid: &mut Grid, x: &mut isize, y: &mut isize, d: &mut Direction) -> usize {
let mut infect = 0;
let current = match grid.get(&(*x, *y)) {
Some(v) => *v,
None => Clean,
};
if current == Infected {
*d = turn_right(*d);
} else {
*d = turn_left(*d);
infect = 1;
};
grid.insert((*x, *y), match current {
Clean => Infected,
Infected => Clean,
x => panic!("Unexpected infection state {:?}", x),
});
let new_pos = make_move(*d, *x, *y);
*x = new_pos.0;
*y = new_pos.1;
infect
}
fn nasty_step(grid: &mut Grid, x: &mut isize, y: &mut isize, d: &mut Direction) -> usize {
let mut infect = 0;
let new_state: Infection;
let current = match grid.get(&(*x, *y)) {
Some(v) => *v,
None => Infection::Clean,
};
match current {
Clean => {
*d = turn_left(*d);
new_state = Weakened;
},
Weakened => {
new_state = Infected;
infect = 1;
},
Infected => {
*d = turn_right(*d);
new_state = Flagged;
},
Flagged => {
*d = turn_around(*d);
new_state = Clean;
}
};
grid.insert((*x, *y), new_state);
let new_pos = make_move(*d, *x, *y);
*x = new_pos.0;
*y = new_pos.1;
infect
}
fn virus_infect<F>(mut grid: Grid, mut step: F, mut x: isize, mut y: isize, mut d: Direction, n: usize) -> usize
where F: FnMut(&mut Grid, &mut isize, &mut isize, &mut Direction) -> usize,
{
(0..n).map(|_| step(&mut grid, &mut x, &mut y, &mut d))
.sum()
}
fn main() {
let args: Vec<String> = env::args().collect();
let n_basic: usize = args[1].parse().unwrap();
let n_nasty: usize = args[2].parse().unwrap();
let stdin = io::stdin();
let lines: Vec<String> = stdin.lock()
.lines()
.map(|x| x.unwrap())
.collect();
let mut grid: Grid = HashMap::new();
let x0 = (lines.len() / 2) as isize;
let y0 = (lines[0].len() / 2) as isize;
for (i, line) in lines.iter().enumerate() {
for (j, c) in line.chars().enumerate() {
grid.insert((i as isize, j as isize),
match c {'#' => Infected, _ => Clean});
}
}
let basic_steps = virus_infect(grid.clone(), basic_step, x0, y0, Up, n_basic);
println!("Basic: infected {} times", basic_steps);
let nasty_steps = virus_infect(grid, nasty_step, x0, y0, Up, n_nasty);
println!("Nasty: infected {} times", nasty_steps);
}
```