#!/usr/bin/perl
use 5.016;
use warnings;
sub new {
}
sub value { $_[0]->[0] }
sub next { ref $_[0]->[1] eq 'CODE' ? $_[0]->[1] = $_[0]->[1]->() : $_[0]->[1] }
sub take {
my ($f, $n) = @_;
my @list;
$f = $f->next;
}
}
my @dir = ([1, 0], [0, 1], [-1, 0], [0, -1]);
sub f_next {
my ($x, $y, $length, $c, $s, $d) = @_;
if ($c < 1){
if (--$s < 1){
$length++;
$s = 2;
}
$c = $length;
$d = ($d + 1) % 4;
}
my ($dx, $dy) = @{$dir[$d]};
[$x, $y],
sub{ f_next($x + $dx, $y + $dy, $length, $c - 1, $s, $d) }
);
}
sub f { f_next(0, 0, 1, 1, 2, 0) }
sub g_next {
my ($n, $f, $filter) = @_;
while(($n > 0) and not $filter->(@{$f->value})){
$f = $f->next;
--$n;
}
$f->value,
sub{ g_next($n - 1, $f->next, $filter) },
);
}
sub g {
my ($r) = @_;
my $n = (2 * $r + 1) ** 2;
my $filter = sub{ $_[0] ** 2 + $_[1] ** 2 <= $r ** 2 };
return g_next
($n, f
(), $filter); }
use Data::Dumper;
local $Data::Dumper::Terse = 1; local $Data::Dumper::Indent = 0;
say Dumper(f()->take(15));
say Dumper(g(2)->take);
IyEvdXNyL2Jpbi9wZXJsCnVzZSA1LjAxNjsKdXNlIHdhcm5pbmdzOwoKcGFja2FnZSBfU3RyZWFtOwoKc3ViIG5ldyB7CglteSAkY2xhc3MgPSBzaGlmdDsKCXJldHVybiBibGVzcyBbIEBfIF0sICRjbGFzczsKfQoKc3ViIHZhbHVlIHsgJF9bMF0tPlswXSB9CnN1YiBuZXh0IHsgcmVmICRfWzBdLT5bMV0gZXEgJ0NPREUnID8gJF9bMF0tPlsxXSA9ICRfWzBdLT5bMV0tPigpIDogJF9bMF0tPlsxXSB9CgpzdWIgdGFrZSB7CglteSAoJGYsICRuKSA9IEBfOwoKCW15IEBsaXN0OwoJd2hpbGUoZGVmaW5lZCAkbiA/ICgtLSRuID49IDApIDogZGVmaW5lZCAkZi0+dmFsdWUpewoJCXB1c2ggQGxpc3QsICRmLT52YWx1ZTsKCQkkZiA9ICRmLT5uZXh0OwoJfQoKCXJldHVybiBcQGxpc3Q7Cn0KCnBhY2thZ2UgbWFpbjsKCm15IEBkaXIgPSAoWzEsIDBdLCBbMCwgMV0sIFstMSwgMF0sIFswLCAtMV0pOwoKc3ViIGZfbmV4dCB7CglteSAoJHgsICR5LCAkbGVuZ3RoLCAkYywgJHMsICRkKSA9IEBfOwoKCWlmICgkYyA8IDEpewoJCWlmICgtLSRzIDwgMSl7CgkJCSRsZW5ndGgrKzsKCQkJJHMgPSAyOwoJCX0KCQkkYyA9ICRsZW5ndGg7CgkJJGQgPSAoJGQgKyAxKSAlIDQ7Cgl9CgoJbXkgKCRkeCwgJGR5KSA9IEB7JGRpclskZF19OwoKCXJldHVybiBfU3RyZWFtLT5uZXcoCgkJWyR4LCAkeV0sCgkJc3VieyBmX25leHQoJHggKyAkZHgsICR5ICsgJGR5LCAkbGVuZ3RoLCAkYyAtIDEsICRzLCAkZCkgfQoJKTsKfQoKc3ViIGYgeyBmX25leHQoMCwgMCwgMSwgMSwgMiwgMCkgfQoKc3ViIGdfbmV4dCB7CglteSAoJG4sICRmLCAkZmlsdGVyKSA9IEBfOwoKCXdoaWxlKCgkbiA+IDApIGFuZCBub3QgJGZpbHRlci0+KEB7JGYtPnZhbHVlfSkpewoJCSRmID0gJGYtPm5leHQ7CgkJLS0kbjsKCX0KCSgkbiA+IDApIG9yIHJldHVybiBfU3RyZWFtLT5uZXcodW5kZWYsIHN1Ynt9KTsKCglyZXR1cm4gX1N0cmVhbS0+bmV3KAoJCSRmLT52YWx1ZSwKCQlzdWJ7IGdfbmV4dCgkbiAtIDEsICRmLT5uZXh0LCAkZmlsdGVyKSB9LAoJKTsKfQoKc3ViIGcgewoJbXkgKCRyKSA9IEBfOwoKCW15ICRuID0gKDIgKiAkciArIDEpICoqIDI7CglteSAkZmlsdGVyID0gc3VieyAkX1swXSAqKiAyICsgJF9bMV0gKiogMiA8PSAkciAqKiAyIH07CglyZXR1cm4gZ19uZXh0KCRuLCBmKCksICRmaWx0ZXIpOwp9Cgp1c2UgRGF0YTo6RHVtcGVyOwpsb2NhbCAkRGF0YTo6RHVtcGVyOjpUZXJzZSA9IDE7CmxvY2FsICREYXRhOjpEdW1wZXI6OkluZGVudCA9IDA7CgpzYXkgRHVtcGVyKGYoKS0+dGFrZSgxNSkpOwpzYXkgRHVtcGVyKGcoMiktPnRha2UpOwo=
[[0,0],[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1],[0,-1],[1,-1],[2,-1],[2,0],[2,1],[2,2],[1,2],[0,2]]
[[0,0],[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1],[0,-1],[1,-1],[2,0],[0,2],[-2,0],[0,-2]]