Skip to content

Instantly share code, notes, and snippets.

@ericfode
Created June 7, 2021 20:00
Show Gist options
  • Save ericfode/ad9f5c2965ca60b6b46178bca0a7eec5 to your computer and use it in GitHub Desktop.
Save ericfode/ad9f5c2965ca60b6b46178bca0a7eec5 to your computer and use it in GitHub Desktop.
// jsonnet -S -V depth=5 hanoi.jsonnet >/tmp/hanoi.html && open /tmp/hanoi.html
local depth = std.parseInt(std.extVar('depth'));
local rect(width, height, column) = [
'rect',
{
width: width * 40,
height: 40,
x: (column + 1) * 300 - width * 20,
y: 550 - height * 50,
stroke: 'black',
'stroke-width': 3,
fill: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'][width - 1]
},
];
local animate(index, from, to, from_height, to_height) = [
local delay = 0.5;
[ 'animateTransform',
{
attributeName: 'transform',
type: 'translate',
from: '%d %d' % [0, 0],
to: '%d %d' % [(to - from) * 300, (from_height - to_height - 1) * 50],
begin: '%fs' % [index * delay],
dur: '%fs' % delay,
additive: 'sum',
repaetCount: 1,
fill: 'freeze',
}
]
];
local moveTower(from, to, using, depth) =
if depth == 1 then
[{ width: depth, from: from, to: to, }]
else
std.flattenArrays([moveTower(from, using, to, depth - 1),
[{ width: depth, from: from, to: to, }],
moveTower(using, to, from, depth - 1)]);
local hanoi = [ rect(disk, depth - disk + 1, 0) for disk in std.range(1, depth) ];
// return array with new value at index
local update(array, index, value) =
std.mapWithIndex(function(i, v) if i == index then value else v, array);
std.manifestXmlJsonml(
[ 'svg', { height: 600, width: 1200 } ] +
[[ 'polyline', { points: '150,570 1050,570 1050,550 910,550 910,100 890,100 890,550 610,550 610,100 590,100 590,550 310,550 310,100 290,100 290,550 150,550 150,570' } ]] +
std.foldl(function(accum, move) [
update(accum[0], move.width - 1, accum[0][move.width - 1] +
animate(move.index, move.from, move.to, accum[1][move.from-1], accum[1][move.to-1])),
update(update(accum[1], move.from-1, accum[1][move.from-1] - 1), move.to-1, accum[1][move.to-1] + 1)
],
// this adds the key index to each move (1 based)
std.mapWithIndex(function(index, value) value + {index:: index}, moveTower(1, 3, 2, depth)),
// [rects, column-heights]
[hanoi, [depth, 0, 0]])[0]
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment