#!/usr/bin/perl
use 5.016;
use warnings;

package _Stream;

sub new {
	my $class = shift;
	return bless [ @_ ], $class;
}

sub value { $_[0]->[0] }
sub next { ref $_[0]->[1] eq 'CODE' ? $_[0]->[1] = $_[0]->[1]->() : $_[0]->[1] }

package main;

my @dir = ([1, 0], [0, 1], [-1, 0], [0, -1]);

sub f1 {
	my ($x, $y, $l, $c, $d) = @_;

	my ($dx, $dy) = @{$dir[$d]};

	return _Stream->new(
		[$x, $y],
		(($c < 1) ?
			sub{ f2($x + $dx, $y + $dy, $l + 1, $l + 1, ($d + 1) % 4) } :
			sub{ f1($x + $dx, $y + $dy, $l, $c - 1, $d) }
		)
	);
}

sub f2 {
	my ($x, $y, $l, $c, $d) = @_;

	my ($dx, $dy) = @{$dir[$d]};

	return _Stream->new(
		[$x, $y],
		(($c < 1) ?
			sub{ f1($x + $dx, $y + $dy, $l, $l, ($d + 1) % 4) } :
			sub{ f2($x + $dx, $y + $dy, $l, $c - 1, $d) }
		)
	);
}

sub f { f2(0, 0, 0, 0, 0) }

sub is_prime {
	my ($n) = @_;

	($n < 2) and return 0;
	($n == 2) and return 1;
	($n % 2 == 0) and return 0;

	for(my $i = 3; $i <= $n / $i; $i += 2){
		($n % $i == 0) and return 0;
	}

	return 1;
}

sub g {
	my $o = int(shift() / 2);
	my $n = ($o * 2 + 1) ** 2;

	my @d;
	my $f = f();
	foreach(1 .. $n){
		my ($x, $y) = @{$f->value};
		$f = $f->next;
		$d[$o - $y]->[$o + $x] = (is_prime($_) ? '*' : ' ');
	}

	return @d;
}

foreach(g(79)){
	say @{$_};
}
