Add visualization

main
Max Nuding 2022-12-14 16:14:21 +00:00
parent 3de6c685b3
commit 0d4c2a7b4e
2 changed files with 56 additions and 24 deletions

View File

@ -39,6 +39,7 @@ day17 = []
day18 = [] day18 = []
day19 = [] day19 = []
day20 = [] day20 = []
visualize = []

View File

@ -1,9 +1,10 @@
use crate::read; use crate::read;
use itertools::Itertools; use itertools::Itertools;
use std::collections::*;
use std::hash::{Hash, Hasher};
use std::io::Write;
use std::{
collections::*,
hash::{Hash, Hasher},
};
#[derive(Debug, Clone, Eq)] #[derive(Debug, Clone, Eq)]
pub struct Coord { pub struct Coord {
pub x: i32, pub x: i32,
@ -89,23 +90,42 @@ pub fn run() {
}) })
.collect(); .collect();
// Hide cursor
print!("\x1B[?25l");
#[cfg(feature = "part1")] #[cfg(feature = "part1")]
{ {
println!("Day 14, Part 01: {:?}", p1(&mut rocks.clone())); #[cfg(feature = "visualize")]
print!("\x1B[2J\x1B[1;1H");
let _count = p1(&mut rocks.clone());
#[cfg(not(feature = "visualize"))]
println!("Day 14, Part 01: {:?}", _count);
} }
#[cfg(feature = "part2")] #[cfg(feature = "part2")]
{ {
let floor = rocks.iter().map(|r| r.y).max().unwrap() + 2; let floor = rocks.iter().map(|r| r.y).max().unwrap() + 2;
for x in -1000..=1000 { (-1000..=1000)
rocks.insert(Coord { .map(|x| Coord {
x, x,
y: floor, y: floor,
is_rock: true, is_rock: true,
})
.for_each(|coord| {
rocks.insert(coord);
}); });
} // Clear screen
println!("Day 14, Part 02: {:?}", p2(&mut rocks.clone())); #[cfg(feature = "visualize")]
print!("\x1B[2J\x1B[1;1H");
let _count = p2(&mut rocks);
#[cfg(not(feature = "visualize"))]
println!("Day 14, Part 02: {:?}", _count);
} }
// Restore cursor
print!("\x1B[?25h");
} }
fn p1(rocks: &mut HashSet<Coord>) -> usize { fn p1(rocks: &mut HashSet<Coord>) -> usize {
@ -121,8 +141,9 @@ fn p1(rocks: &mut HashSet<Coord>) -> usize {
let mut sand = sand_start.clone(); let mut sand = sand_start.clone();
loop { loop {
//print(rocks, &sand);
if sand.y > bottom { if sand.y > bottom {
#[cfg(feature = "visualize")]
print(rocks, &sand, 1, count_p1);
return count_p1; return count_p1;
} }
let d = sand.down(); let d = sand.down();
@ -134,6 +155,8 @@ fn p1(rocks: &mut HashSet<Coord>) -> usize {
if rocks.contains(&dr) { if rocks.contains(&dr) {
count_p1 += 1; count_p1 += 1;
rocks.insert(sand.clone()); rocks.insert(sand.clone());
#[cfg(feature = "visualize")]
print(rocks, &sand, 1, count_p1);
break; break;
} }
sand = dr; sand = dr;
@ -158,6 +181,8 @@ fn p2(rocks: &mut HashSet<Coord>) -> usize {
loop { loop {
let mut sand = sand_start.clone(); let mut sand = sand_start.clone();
if rocks.contains(&sand) { if rocks.contains(&sand) {
#[cfg(feature = "visualize")]
print(rocks, &sand, 2, count_p2);
return count_p2; return count_p2;
} }
@ -171,6 +196,8 @@ fn p2(rocks: &mut HashSet<Coord>) -> usize {
if rocks.contains(&dr) { if rocks.contains(&dr) {
count_p2 += 1; count_p2 += 1;
rocks.insert(sand.clone()); rocks.insert(sand.clone());
#[cfg(feature = "visualize")]
print(rocks, &sand, 2, count_p2);
break; break;
} }
sand = dr; sand = dr;
@ -184,14 +211,17 @@ fn p2(rocks: &mut HashSet<Coord>) -> usize {
} }
} }
fn print(rocks: &HashSet<Coord>, sand: &Coord) { #[cfg(feature = "visualize")]
let min_y = 10; fn print(rocks: &HashSet<Coord>, sand: &Coord, part: i32, count: usize) {
let min_x = 452; let (min_y, min_x, max_y, max_x) = (10, 442, 182, 514);
let max_y = 180;
let max_x = 514;
let bounds = " ".repeat((max_y as usize) - (min_y as usize)); if sand.x < min_x || sand.x > max_x || sand.y < min_y || sand.y > max_y {
let mut out = format!("\n{}\n", bounds); return; // Don't render if not displayed
}
let status = format!("Part: {}, Count: {}", part, count);
let bounds = " ".repeat((max_y as usize) - (min_y as usize) - status.len());
let mut out = format!("{}{}\n", status, bounds);
for x in (min_x..=max_x).rev() { for x in (min_x..=max_x).rev() {
for y in min_y..=max_y { for y in min_y..=max_y {
@ -201,17 +231,18 @@ fn print(rocks: &HashSet<Coord>, sand: &Coord) {
is_rock: false, is_rock: false,
}; };
let c = match (sand == testing, rocks.get(testing)) { let c = match (sand == testing, rocks.get(testing)) {
(true, _) => 'o', (true, _) => "\x1B[31mo\x1B[0m",
(_, None) => ' ', (_, None) => " ",
(_, Some(coord)) if coord.is_rock => '#', (_, Some(coord)) if coord.is_rock => "#",
_ => 'o', _ => "\x1B[33mo\x1B[0m",
}; };
out += &format!("{}", c); out += c;
} }
out += "\n"; out += "\n";
} }
out += &bounds; out += &bounds;
print!("{}", out); // Clear terminal, position cursor at (1,1)
std::io::stdout().flush().unwrap(); print!("\x1B[1;1H{}", out);
std::thread::sleep(std::time::Duration::from_millis(60)); let ms = if part == 1 { 34 } else { 8 }; // Go faster in part 2, takes too long otherwise
std::thread::sleep(std::time::Duration::from_millis(ms));
} }