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 = []
day19 = []
day20 = []
visualize = []

View File

@ -1,9 +1,10 @@
use crate::read;
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)]
pub struct Coord {
pub x: i32,
@ -89,23 +90,42 @@ pub fn run() {
})
.collect();
// Hide cursor
print!("\x1B[?25l");
#[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")]
{
let floor = rocks.iter().map(|r| r.y).max().unwrap() + 2;
for x in -1000..=1000 {
rocks.insert(Coord {
(-1000..=1000)
.map(|x| Coord {
x,
y: floor,
is_rock: true,
})
.for_each(|coord| {
rocks.insert(coord);
});
}
println!("Day 14, Part 02: {:?}", p2(&mut rocks.clone()));
// Clear screen
#[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 {
@ -121,8 +141,9 @@ fn p1(rocks: &mut HashSet<Coord>) -> usize {
let mut sand = sand_start.clone();
loop {
//print(rocks, &sand);
if sand.y > bottom {
#[cfg(feature = "visualize")]
print(rocks, &sand, 1, count_p1);
return count_p1;
}
let d = sand.down();
@ -134,6 +155,8 @@ fn p1(rocks: &mut HashSet<Coord>) -> usize {
if rocks.contains(&dr) {
count_p1 += 1;
rocks.insert(sand.clone());
#[cfg(feature = "visualize")]
print(rocks, &sand, 1, count_p1);
break;
}
sand = dr;
@ -158,6 +181,8 @@ fn p2(rocks: &mut HashSet<Coord>) -> usize {
loop {
let mut sand = sand_start.clone();
if rocks.contains(&sand) {
#[cfg(feature = "visualize")]
print(rocks, &sand, 2, count_p2);
return count_p2;
}
@ -171,6 +196,8 @@ fn p2(rocks: &mut HashSet<Coord>) -> usize {
if rocks.contains(&dr) {
count_p2 += 1;
rocks.insert(sand.clone());
#[cfg(feature = "visualize")]
print(rocks, &sand, 2, count_p2);
break;
}
sand = dr;
@ -184,14 +211,17 @@ fn p2(rocks: &mut HashSet<Coord>) -> usize {
}
}
fn print(rocks: &HashSet<Coord>, sand: &Coord) {
let min_y = 10;
let min_x = 452;
let max_y = 180;
let max_x = 514;
#[cfg(feature = "visualize")]
fn print(rocks: &HashSet<Coord>, sand: &Coord, part: i32, count: usize) {
let (min_y, min_x, max_y, max_x) = (10, 442, 182, 514);
let bounds = " ".repeat((max_y as usize) - (min_y as usize));
let mut out = format!("\n{}\n", bounds);
if sand.x < min_x || sand.x > max_x || sand.y < min_y || sand.y > max_y {
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 y in min_y..=max_y {
@ -201,17 +231,18 @@ fn print(rocks: &HashSet<Coord>, sand: &Coord) {
is_rock: false,
};
let c = match (sand == testing, rocks.get(testing)) {
(true, _) => 'o',
(_, None) => ' ',
(_, Some(coord)) if coord.is_rock => '#',
_ => 'o',
(true, _) => "\x1B[31mo\x1B[0m",
(_, None) => " ",
(_, Some(coord)) if coord.is_rock => "#",
_ => "\x1B[33mo\x1B[0m",
};
out += &format!("{}", c);
out += c;
}
out += "\n";
}
out += &bounds;
print!("{}", out);
std::io::stdout().flush().unwrap();
std::thread::sleep(std::time::Duration::from_millis(60));
// Clear terminal, position cursor at (1,1)
print!("\x1B[1;1H{}", out);
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));
}