Last active
December 14, 2022 17:46
-
-
Save mykdavies/8f958eaf69bdda4138121d5b751e4bd4 to your computer and use it in GitHub Desktop.
AOC 2022 Day 14 Visualisation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'''; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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