Skip to content

Instantly share code, notes, and snippets.

@timo

timo/hilbert.p6 Secret

Created January 27, 2020 16:26
Show Gist options
  • Save timo/fe09badf375142c1a5d6b6d1ea950192 to your computer and use it in GitHub Desktop.
Save timo/fe09badf375142c1a5d6b6d1ea950192 to your computer and use it in GitHub Desktop.
Terminal::Print example for a hilbert curve
use Terminal::Print <T>;
use Terminal::Print::Pixelated;
my @colors =
(0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 0, 4), (0, 0, 5), # Dark to bright blue
(1, 1, 5), (2, 2, 5), (3, 3, 5), (4, 4, 5), (5, 5, 5), # Light blue to white
(5, 5, 4), (5, 5, 3), (5, 5, 2), (5, 5, 1), (5, 5, 0), # Pale to bright yellow
(5, 4, 0), (5, 3, 0), (5, 2, 0), (5, 1, 0), (5, 0, 0), # Yellow-orange to red
(4, 0, 0), (3, 0, 0), (2, 0, 0), (1, 0, 0), (0, 0, 0); # Brick red to black
my @ramp = @colors.map: { ~(16 + 36 * .[0] + 6 * .[1] + .[2]) }
sub d2xy(int $n, int $d, int $x is rw, int $y is rw) {
my int $rx;
my int $ry;
my int $t = $d;
$x = 0;
$y = 0;
my int $s = 1;
#for 1, 2, 4 ... * >= $n -> int $s {
while $s < $n {
$rx = 1 +& ($t div 2);
$ry = 1 +& ($t +^ $rx);
rot $s, $x, $y, $rx, $ry;
$x += $s * $rx;
$y += $s * $ry;
$t div= 4;
$s *= 2;
}
}
sub rot(int $n, int $x is rw, int $y is rw, int $rx, int $ry) {
if $ry == 0 {
if $rx == 1 {
$x = $n - 1 - $x;
$y = $n - 1 - $y;
}
my int $t = $x;
$x = $y;
$y = $t
}
}
class HilbertFrame is Terminal::Print::FrameInfo {
has $.pixels;
}
class HilbertCrawl is Terminal::Print::PixelAnimation {
has @!hilbertcoords;
has @!pixels;
has $.size;
has $.pixels-set-up = 0;
has $!depth;
method setup {
$!size = (($.h * 2) min $.w) div 2;
@!pixels = ['' xx $.w] xx ($.h * 2);
$!depth = 2 ** ($!size.msb);
}
method stepcount {
($.size * 2) ** 2;
}
method compute-pixels() {
for $!pixels-set-up .. $.cur.pixels {
my int $x;
my int $y;
d2xy $!depth, $_, $x, $y;
@!pixels[$y][$x] = @ramp[($_ div 3) % *];
#note $_;
}
$!pixels-set-up = $.cur.pixels;
@!pixels;
}
}
multi sub MAIN {
T.initialize-screen;
my $crawl = HilbertCrawl.new-from-grid(T.current-grid);
$crawl.setup;
for ^$crawl.stepcount {
$crawl.do-frame(HilbertFrame.new(:pixels($_)));
$crawl.composite;
}
sleep 1;
T.shutdown-screen;
}
multi sub MAIN("test") {
my @timings;
for ^10_000 {
my $t0 = now;
my int $x;
my int $y;
d2xy 64, $_, $x, $y;
@timings.push(now - $t0);
}
say @timings.fmt("%10f", "\n");
}
#convert d to (x,y)
#void d2xy(int n, int d, int *x, int *y) {
#int rx, ry, s, t=d;
#*x = *y = 0;
#for (s=1; s<n; s*=2) {
#rx = 1 & (t/2);
#ry = 1 & (t ^ rx);
#rot(s, x, y, rx, ry);
#*x += s * rx;
#*y += s * ry;
#t /= 4;
#}
#}
#rotate/flip a quadrant appropriately
#void rot(int n, int *x, int *y, int rx, int ry) {
#if (ry == 0) {
#if (rx == 1) {
#*x = n-1 - *x;
#*y = n-1 - *y;
#}
#//Swap x and y
#int t = *x;
#*x = *y;
#*y = t;
#}
#}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment