#![allow(dead_code)] use std::collections::HashMap; use std::fs::File; use std::io; use std::io::BufRead; use std::path::Path; use std::time::Instant; #[derive(Debug, Eq, Hash, PartialEq, Copy, Clone)] struct Coord(i32, i32); fn main() { let now = Instant::now(); part_one(); let part_one_duration = now.elapsed(); part_two(); let part_two_duration = now.elapsed(); println!( "p1: {}ms, p2: {}ms", part_one_duration.as_millis(), (part_two_duration - part_one_duration).as_millis() ); } fn read_lines

(filename: P) -> io::Result>> where P: AsRef, { // note that this discards a final newline let file = File::open(filename)?; Ok(io::BufReader::new(file).lines()) } fn part_one() { let mut grid = HashMap::::new(); let (mut head_x, mut head_y) = (0, 0); let (mut tail_x, mut tail_y) = (0, 0); grid.insert(Coord(0, 0), true); if let Ok(lines) = read_lines("./inputs/input") { for line in lines { if let Ok(m) = line { let mut i = m.split(" "); let dir = i.next().unwrap(); let steps = i.next().unwrap().parse::().unwrap(); match dir { "U" => { for _ in 0..steps { head_y += 1; (tail_x, tail_y) = update_tail(head_x, head_y, tail_x, tail_y); grid.insert(Coord(tail_x, tail_y), true); } } "D" => { for _ in 0..steps { head_y -= 1; (tail_x, tail_y) = update_tail(head_x, head_y, tail_x, tail_y); grid.insert(Coord(tail_x, tail_y), true); } } "L" => { for _ in 0..steps { head_x -= 1; (tail_x, tail_y) = update_tail(head_x, head_y, tail_x, tail_y); grid.insert(Coord(tail_x, tail_y), true); } } "R" => { for _ in 0..steps { head_x += 1; (tail_x, tail_y) = update_tail(head_x, head_y, tail_x, tail_y); grid.insert(Coord(tail_x, tail_y), true); } } _ => { println!("unknown instruction {:?}", m); } } } } } println!("{}", grid.len()); } fn part_two() { let mut grid = HashMap::::new(); let mut knots: Vec = vec![ Coord(0, 0), Coord(0, 0), Coord(0, 0), Coord(0, 0), Coord(0, 0), Coord(0, 0), Coord(0, 0), Coord(0, 0), Coord(0, 0), Coord(0, 0), ]; if let Ok(lines) = read_lines("./inputs/input") { for line in lines { if let Ok(m) = line { let mut i = m.split(" "); let dir = i.next().unwrap(); let steps = i.next().unwrap().parse::().unwrap(); match dir { "U" => { for _ in 0..steps { knots[0] = Coord(knots[0].0, knots[0].1 + 1); for j in 0..9 { let (tail_x, tail_y) = update_tail( knots[j].0, knots[j].1, knots[j + 1].0, knots[j + 1].1, ); knots[j + 1] = Coord(tail_x, tail_y); } grid.insert(knots[9], true); } } "D" => { for _ in 0..steps { knots[0] = Coord(knots[0].0, knots[0].1 - 1); for j in 0..9 { let (tail_x, tail_y) = update_tail( knots[j].0, knots[j].1, knots[j + 1].0, knots[j + 1].1, ); knots[j + 1] = Coord(tail_x, tail_y); } grid.insert(knots[9], true); } } "L" => { for _ in 0..steps { knots[0] = Coord(knots[0].0 - 1, knots[0].1); for j in 0..9 { let (tail_x, tail_y) = update_tail( knots[j].0, knots[j].1, knots[j + 1].0, knots[j + 1].1, ); knots[j + 1] = Coord(tail_x, tail_y); } grid.insert(knots[9], true); } } "R" => { for _ in 0..steps { knots[0] = Coord(knots[0].0 + 1, knots[0].1); for j in 0..9 { let (tail_x, tail_y) = update_tail( knots[j].0, knots[j].1, knots[j + 1].0, knots[j + 1].1, ); knots[j + 1] = Coord(tail_x, tail_y); } grid.insert(knots[9], true); } } _ => { println!("unknown instruction {:?}", m); } } } } } println!("{}", grid.len()); } fn update_tail(head_x: i32, head_y: i32, mut tail_x: i32, mut tail_y: i32) -> (i32, i32) { if head_y - tail_y == 2 { tail_y += 1; tail_x = head_x; } if tail_y - head_y == 2 { tail_y -= 1; tail_x = head_x; } if head_x - tail_x == 2 { tail_x += 1; tail_y = head_y; } if tail_x - head_x == 2 { tail_x -= 1; tail_y = head_y; } return (tail_x, tail_y); }