Skip to content

Instantly share code, notes, and snippets.

@mykdavies
Last active December 14, 2022 17:46
Show Gist options
  • Save mykdavies/8f958eaf69bdda4138121d5b751e4bd4 to your computer and use it in GitHub Desktop.
Save mykdavies/8f958eaf69bdda4138121d5b751e4bd4 to your computer and use it in GitHub Desktop.
AOC 2022 Day 14 Visualisation
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="scaffolded-by" content="https://github.com/dart-lang/sdk">
<title>aoc2022_day12</title>
<link rel="stylesheet" href="styles.css">
<script defer src="main.dart.js"></script>
</head>
<body>
<div id="output">
</div>
<div id="wrapper">
<canvas id="canvas" width="400" height="600"/>
</div>
</body>
</html>
import 'dart:html';
import 'dart:async';
//import 'package:more/more.dart';
import 'package:collection/collection.dart';
late CanvasElement canvas;
late CanvasRenderingContext2D ctx;
int cellSize = 20;
void drawCell(Point coords, String color) {
ctx
..fillStyle = color
..strokeStyle = "white";
final num x = coords.x * cellSize;
final num y = coords.y * cellSize;
ctx
..fillRect(x, y, cellSize, cellSize)
..strokeRect(x, y, cellSize, cellSize);
}
void write(Point p, String text) {
final num x = p.x * cellSize;
final num y = p.y * cellSize;
ctx
..fillStyle = "black"
..strokeStyle = "black";
ctx.fillText(text, x, y);
}
void clear() {
ctx
..fillStyle = "white"
..fillRect(0, 0, canvas.width!, canvas.height!);
}
class Runner {
static const num speed = 1;
num _lastTimeStamp = 0;
Runner() {
init();
}
List<Point<int>> path = [];
int index = 0;
late Iterator<Record> gen;
var rocks = <Point>{};
var ps = <Point>[];
var offset = Point(0, 0);
void init() {
addLines(lines.split('\n'));
offset = Point([minX, 500 - maxY].max - 1, 0);
cellSize = [
600 ~/ (maxY + 2),
400 ~/ (maxX - minX + 3),
].min;
gen = part1().iterator..moveNext();
rocks = grid.toSet();
ps = [
for (var y in 1.to(maxY + 3))
for (var x in (500 - maxY).to(500 + maxY + 1)) Point(x, y)
];
}
bool ended = false;
void update(num delta) {
final num diff = delta - _lastTimeStamp;
if (diff > speed) {
_lastTimeStamp = delta;
clear();
var r = gen.current;
//draw everything else
for (var p in ps) {
if (rocks.contains(p)) {
drawCell(p - offset, 'black');
} else {
if (grid.contains(p)) {
drawCell(p - offset, 'darkOrange');
}
}
}
if (r.dropping) {
drawCell(r.pos - offset, 'orange');
} else if (r.ended) {
drawCell(r.pos - offset, 'red');
write(r.pos - offset, 'overflowed at grain number ${r.grainNo}');
ended = true;
}
if (!ended && !gen.moveNext()) {
return;
}
}
// keep looping
run();
}
Future run() async {
update(await window.animationFrame);
}
}
void main() {
querySelector('#output')?.text = 'AOC 2022 Day 14 - Regolith Reservoir';
canvas = document.querySelector('#canvas') as CanvasElement;
ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
Runner().run();
}
//import 'package:more/more.dart';
// Hack for missing `more` library
extension IntegerRangeExtension on int {
List<int> to(int end) => List.generate(end - this, (i) => i + this);
}
/// Build a passage, then flow sand through it
/// 1) until it is "filled" - any more flows out
/// 2) until the pile reaches the source
var grid = <Point<int>>{};
void drawLine(List<String> ps) {
var l1 = ps.first.split(',').map(int.parse);
var p1 = Point<int>(l1.first, l1.last);
var l2 = ps.last.split(',').map(int.parse);
var p2 = Point<int>(l2.first, l2.last);
var d = p2 - p1;
d = Point(d.x.sign, d.y.sign);
for (var i = p1; i != p2; i += d) {
grid.add(i);
}
grid.add(p2);
}
var drops = [Point(0, 1), Point(-1, 1), Point(1, 1)];
late int maxX, minX, maxY;
addLines(List<String> lines) {
grid = <Point<int>>{};
for (var line in lines) {
var ps = line.split(' -> ');
for (var i in 0.to(ps.length - 1)) {
drawLine([ps[i], ps[i + 1]]);
}
}
maxX = grid.map((e) => e.x).max;
minX = grid.map((e) => e.x).min;
maxY = grid.map((e) => e.y).max;
}
var sourcePoint = Point(500, 0);
class Record {
int grainNo;
Point pos;
bool dropping;
bool ended;
Record(this.grainNo, this.pos, this.dropping, this.ended);
}
Iterable<Record> part1() sync* {
var s = sourcePoint;
var grains = 0;
nextdrop:
while (true) {
var sn = s;
var canMove = false;
for (var d in drops) {
sn = s + d;
if (sn.x < minX || sn.x > maxX || sn.y > maxY) break nextdrop;
if (!grid.contains(sn)) {
canMove = true;
break;
}
}
if (canMove) {
s = sn;
//yield Record(grains, s, true, false);
} else {
yield Record(grains, s, false, false);
grid.add(s);
s = sourcePoint;
grains += 1;
}
}
yield Record(grains, s, false, true);
}
var lines = '''498,4 -> 498,6 -> 496,6
503,4 -> 502,4 -> 502,9 -> 494,9''';
@import url(https://fonts.googleapis.com/css?family=Roboto);
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
font-family: 'Roboto', sans-serif;
}
#output {
padding: 20px;
text-align: center;
}
#wrapper {
width: 400px;
height: 600px;
margin: auto;
border: solid thin black;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment