Skip to content

Instantly share code, notes, and snippets.

@tinaun
Created Dec 22, 2017
Embed
What would you like to do?
day22 p2
extern crate gif;
use std::collections::HashMap;
use gif::{Frame, Encoder, Repeat, SetParameter};
use std::fs::File;
use std::io::prelude::*;
static COLOR_MAP: [u8; 15] = [
20, 12, 28, // CLEAN
218, 212, 94, // WEAKENED
208, 70, 72, // INFECTED
89, 125, 206, // FLAGGED
222, 238, 214 // ANT
];
static SIZE_X: u16 = 501;
static SIZE_Y: u16 = 501;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum State {
Weakened,
Infected,
Flagged,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum Facing {
North,
East,
South,
West,
}
impl Facing {
fn rot_r(&mut self) {
*self = match *self {
Facing::North => Facing::East,
Facing::East => Facing::South,
Facing::South => Facing::West,
Facing::West => Facing::North,
}
}
fn rot_l(&mut self) {
*self = match *self {
Facing::North => Facing::West,
Facing::East => Facing::North,
Facing::South => Facing::East,
Facing::West => Facing::South,
}
}
fn delta(&self) -> (isize, isize) {
match *self {
Facing::North => (0, 1),
Facing::East => (1, 0),
Facing::South => (0, -1),
Facing::West => (-1, 0),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
struct Ant {
pos: (isize, isize),
dir: Facing,
}
impl Ant {
fn new() -> Self {
Ant {
pos: (0, 0),
dir: Facing::North,
}
}
fn step(&mut self) {
let delta = self.dir.delta();
self.pos.0 += delta.0;
self.pos.1 += delta.1;
}
}
fn gen_frame<W: Write>(e: &mut Encoder<W>, buf: &[u8], delay: u16) {
// write frame
let mut frame = Frame::default();
frame.delay = delay;
frame.width = SIZE_X;
frame.height = SIZE_Y;
frame.buffer = buf.into();
e.write_frame(&frame).unwrap();
}
fn main() {
let input = include_str!("../input.txt");
let mut image = File::create("path.gif").unwrap();
let mut encoder = Encoder::new(&mut image, SIZE_X, SIZE_Y, &COLOR_MAP).unwrap();
encoder.set(Repeat::Infinite).unwrap();
let sx = SIZE_X as usize;
let sy = SIZE_Y as usize;
let mut buf = vec![0; sx * sy];
let mut field = HashMap::<(isize, isize), State>::new();
for (y, l) in input.lines().enumerate() {
let m = (l.len() / 2) as isize;
let px = (sx - l.len()) / 2;
let py = (sy - l.len()) / 2;
for (x, c) in l.chars().enumerate() {
if c == '#' {
field.insert((x as isize - m, m - y as isize), State::Infected);
buf[(py + y) * sx + (px + x)] = 2;
}
}
}
buf[(sy/2) * sx + (sx/2)] = 4;
let mut ant = Ant::new();
let mut infects = 0;
for f in 0..10_000_000 {
if f % 5_000 == 0 {
gen_frame(&mut encoder, &buf, 2);
}
// turn
let (px, py) = (sx/2, sy/2);
let (nx, ny) = (px as isize + ant.pos.0, py as isize + ant.pos.1);
if field.contains_key(&ant.pos) {
match *field.get(&ant.pos).unwrap() {
State::Flagged => {
ant.dir.rot_l();
ant.dir.rot_l();
field.remove(&ant.pos);
if nx > -1 && nx < sx as isize && ny > -1 && ny < sy as isize {
buf[ny as usize * sx + nx as usize] = 0;
}
},
State::Infected => {
ant.dir.rot_r();
field.insert(ant.pos, State::Flagged);
if nx > -1 && nx < sx as isize && ny > -1 && ny < sy as isize {
buf[ny as usize * sx + nx as usize] = 3;
}
},
State::Weakened => {
// don't turn
field.insert(ant.pos, State::Infected);
infects += 1;
if nx > -1 && nx < sx as isize && ny > -1 && ny < sy as isize {
buf[ny as usize * sx + nx as usize] = 2;
}
},
}
} else {
ant.dir.rot_l();
field.insert(ant.pos, State::Weakened);
if nx > -1 && nx < sx as isize && ny > -1 && ny < sy as isize {
buf[ny as usize * sx + nx as usize] = 1;
}
}
// move
ant.step();
let (nx, ny) = (px as isize + ant.pos.0, py as isize + ant.pos.1);
if nx > -1 && nx < sx as isize && ny > -1 && ny < sy as isize {
buf[ny as usize * sx + nx as usize] = 4;
}
}
gen_frame(&mut encoder, &buf, 100);
println!("p2: {}", infects);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment