Created
June 7, 2021 20:00
-
-
Save ericfode/ad9f5c2965ca60b6b46178bca0a7eec5 to your computer and use it in GitHub Desktop.
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
// 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