You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
3.4 KiB
Rust
104 lines
3.4 KiB
Rust
use std::collections::HashMap;
|
|
|
|
fn main() {
|
|
let contents = std::fs::read_to_string("data.txt").expect("Failed to read file");
|
|
let lines = contents.lines().collect::<Vec<&str>>();
|
|
|
|
let mut hash: HashMap<(i32, i32), bool> = HashMap::new();
|
|
run(&lines, &mut hash, 1);
|
|
let part_1 = hash.keys().len();
|
|
println!("Num visited, part 1: {:?}", part_1);
|
|
|
|
let mut hash2: HashMap<(i32, i32), bool> = HashMap::new();
|
|
run(&lines, &mut hash2, 9);
|
|
let part_2 = hash2.keys().len();
|
|
println!("Num visited, part 2: {:?}", part_2);
|
|
}
|
|
|
|
fn run(lines: &Vec<&str>, hash: &mut HashMap<(i32, i32), bool>, num_tails: usize) {
|
|
let mut head = (0i32, 0i32);
|
|
let mut tails: Vec<(i32, i32)> = vec![(0, 0); num_tails];
|
|
|
|
for line in lines {
|
|
let (dir, steps) = line.split_once(" ").unwrap();
|
|
|
|
for _ in 0..steps.parse().unwrap() {
|
|
match dir {
|
|
"L" => head = (head.0, head.1 - 1),
|
|
"R" => head = (head.0, head.1 + 1),
|
|
"U" => head = (head.0 - 1, head.1),
|
|
"D" => head = (head.0 + 1, head.1),
|
|
_ => (),
|
|
}
|
|
// println!("\nnew head location {:?}", head);
|
|
|
|
let mut parent = head;
|
|
|
|
for tail_i in 0..num_tails {
|
|
let mut tail = tails[tail_i];
|
|
|
|
// find the distance from parent to tail
|
|
let v_dist = parent.0 - tail.0;
|
|
let h_dist = parent.1 - tail.1;
|
|
let mut already_moved_diagonally = false;
|
|
|
|
// move vertically
|
|
if v_dist.abs() > 1 {
|
|
let v_diff = v_dist / v_dist.abs();
|
|
tail = (tail.0 + v_diff, tail.1);
|
|
|
|
// do we need to move horizontally?
|
|
if parent.1 != tail.1 {
|
|
let h_diff = h_dist / h_dist.abs();
|
|
tail = (tail.0, tail.1 + h_diff);
|
|
already_moved_diagonally = true;
|
|
}
|
|
}
|
|
|
|
// move horizontally
|
|
if h_dist.abs() > 1 && !already_moved_diagonally {
|
|
let h_diff = h_dist / h_dist.abs();
|
|
tail = (tail.0, tail.1 + h_diff);
|
|
|
|
// do we need to move horizontally?
|
|
if parent.0 != tail.0 {
|
|
let v_diff = v_dist / v_dist.abs();
|
|
tail = (tail.0 + v_diff, tail.1);
|
|
}
|
|
}
|
|
|
|
// println!("new tail ({:?}) location {:?}", tail_i + 1, tail);
|
|
if tail_i == num_tails - 1 {
|
|
// for the last tail, record where it has been
|
|
hash.insert(tail, true);
|
|
}
|
|
|
|
tails[tail_i] = tail;
|
|
parent = tail;
|
|
}
|
|
}
|
|
|
|
let mut temp = tails.to_owned();
|
|
temp.insert(0, head);
|
|
display(temp);
|
|
}
|
|
}
|
|
|
|
fn display(rope: Vec<(i32, i32)>) -> () {
|
|
let v_min = rope.iter().map(|x| x.0).min().unwrap();
|
|
let v_max = rope.iter().map(|x| x.0).max().unwrap();
|
|
let h_min = rope.iter().map(|x| x.1).min().unwrap();
|
|
let h_max = rope.iter().map(|x| x.1).max().unwrap();
|
|
|
|
for v in v_min..=v_max {
|
|
for h in h_min..=h_max {
|
|
match rope.iter().position(|&x| x == (v, h)) {
|
|
Some(i) => print!("{i}"),
|
|
None => print!("."),
|
|
}
|
|
}
|
|
println!("");
|
|
}
|
|
println!("");
|
|
}
|