Spiral matrix: Difference between revisions

Rename Perl 6 -> Raku, alphabetize, minor clean-up
(Realize in MiniZinc)
(Rename Perl 6 -> Raku, alphabetize, minor clean-up)
Line 305:
13 12 11 10 9
</pre>
 
 
=={{header|AppleScript}}==
Line 735 ⟶ 734:
}
return 0;
}</lang>
 
=={{header|C++}}==
<lang cpp>#include <vector>
#include <memory> // for auto_ptr
#include <cmath> // for the ceil and log10 and floor functions
#include <iostream>
#include <iomanip> // for the setw function
 
using namespace std;
 
typedef vector< int > IntRow;
typedef vector< IntRow > IntTable;
 
auto_ptr< IntTable > getSpiralArray( int dimension )
{
auto_ptr< IntTable > spiralArrayPtr( new IntTable(
dimension, IntRow( dimension ) ) );
 
int numConcentricSquares = static_cast< int >( ceil(
static_cast< double >( dimension ) / 2.0 ) );
 
int j;
int sideLen = dimension;
int currNum = 0;
 
for ( int i = 0; i < numConcentricSquares; i++ )
{
// do top side
for ( j = 0; j < sideLen; j++ )
( *spiralArrayPtr )[ i ][ i + j ] = currNum++;
 
// do right side
for ( j = 1; j < sideLen; j++ )
( *spiralArrayPtr )[ i + j ][ dimension - 1 - i ] = currNum++;
 
// do bottom side
for ( j = sideLen - 2; j > -1; j-- )
( *spiralArrayPtr )[ dimension - 1 - i ][ i + j ] = currNum++;
 
// do left side
for ( j = sideLen - 2; j > 0; j-- )
( *spiralArrayPtr )[ i + j ][ i ] = currNum++;
 
sideLen -= 2;
}
 
return spiralArrayPtr;
}
 
void printSpiralArray( const auto_ptr< IntTable >& spiralArrayPtr )
{
size_t dimension = spiralArrayPtr->size();
 
int fieldWidth = static_cast< int >( floor( log10(
static_cast< double >( dimension * dimension - 1 ) ) ) ) + 2;
 
size_t col;
for ( size_t row = 0; row < dimension; row++ )
{
for ( col = 0; col < dimension; col++ )
cout << setw( fieldWidth ) << ( *spiralArrayPtr )[ row ][ col ];
cout << endl;
}
}
 
int main()
{
printSpiralArray( getSpiralArray( 5 ) );
}</lang>
 
C++ solution done properly:
<lang cpp>#include <vector>
#include <iostream>
using namespace std;
int main() {
const int n = 5;
const int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
int x = 0, y = -1, c = 0;
vector<vector<int>> m(n, vector<int>(n));
for (int i = 0, im = 0; i < n + n - 1; ++i, im = i % 4)
for (int j = 0, jlen = (n + n - i) / 2; j < jlen; ++j)
m[x += dx[im]][y += dy[im]] = ++c;
for (auto & r : m) {
for (auto & v : r)
cout << v << ' ';
cout << endl;
}
}</lang>
 
Line 998 ⟶ 909:
16 15 14 13 12 11
</lang>
 
=={{header|C++}}==
<lang cpp>#include <vector>
#include <memory> // for auto_ptr
#include <cmath> // for the ceil and log10 and floor functions
#include <iostream>
#include <iomanip> // for the setw function
 
using namespace std;
 
typedef vector< int > IntRow;
typedef vector< IntRow > IntTable;
 
auto_ptr< IntTable > getSpiralArray( int dimension )
{
auto_ptr< IntTable > spiralArrayPtr( new IntTable(
dimension, IntRow( dimension ) ) );
 
int numConcentricSquares = static_cast< int >( ceil(
static_cast< double >( dimension ) / 2.0 ) );
 
int j;
int sideLen = dimension;
int currNum = 0;
 
for ( int i = 0; i < numConcentricSquares; i++ )
{
// do top side
for ( j = 0; j < sideLen; j++ )
( *spiralArrayPtr )[ i ][ i + j ] = currNum++;
 
// do right side
for ( j = 1; j < sideLen; j++ )
( *spiralArrayPtr )[ i + j ][ dimension - 1 - i ] = currNum++;
 
// do bottom side
for ( j = sideLen - 2; j > -1; j-- )
( *spiralArrayPtr )[ dimension - 1 - i ][ i + j ] = currNum++;
 
// do left side
for ( j = sideLen - 2; j > 0; j-- )
( *spiralArrayPtr )[ i + j ][ i ] = currNum++;
 
sideLen -= 2;
}
 
return spiralArrayPtr;
}
 
void printSpiralArray( const auto_ptr< IntTable >& spiralArrayPtr )
{
size_t dimension = spiralArrayPtr->size();
 
int fieldWidth = static_cast< int >( floor( log10(
static_cast< double >( dimension * dimension - 1 ) ) ) ) + 2;
 
size_t col;
for ( size_t row = 0; row < dimension; row++ )
{
for ( col = 0; col < dimension; col++ )
cout << setw( fieldWidth ) << ( *spiralArrayPtr )[ row ][ col ];
cout << endl;
}
}
 
int main()
{
printSpiralArray( getSpiralArray( 5 ) );
}</lang>
 
C++ solution done properly:
<lang cpp>#include <vector>
#include <iostream>
using namespace std;
int main() {
const int n = 5;
const int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
int x = 0, y = -1, c = 0;
vector<vector<int>> m(n, vector<int>(n));
for (int i = 0, im = 0; i < n + n - 1; ++i, im = i % 4)
for (int j = 0, jlen = (n + n - i) / 2; j < jlen; ++j)
m[x += dx[im]][y += dy[im]] = ++c;
for (auto & r : m) {
for (auto & v : r)
cout << v << ' ';
cout << endl;
}
}</lang>
 
=={{header|Clojure}}==
Line 1,100 ⟶ 1,099:
[ 18, 17, 16, 15, 14, 13, 12 ] ]
</lang>
 
 
=={{header|Common Lisp}}==
Line 1,236 ⟶ 1,234:
20 35 34 33 32 31 30 29 10
19 18 17 16 15 14 13 12 11</pre>
 
=={{header|DCL}}==
<lang DCL>$ p1 = f$integer( p1 )
Line 1,467 ⟶ 1,466:
{12,11,10,9,8}
}
 
=={{header|F_Sharp|F#}}==
No fancy schmancy elegance here, just putting the numbers in the right place (though I commend the elegance)...
<lang fsharp>let Spiral n =
let sq = Array2D.create n n 0 // Set up an output array
let nCur = ref -1 // Current value being inserted
let NextN() = nCur := (!nCur+1) ; !nCur // Inc current value and return new value
let Frame inset = // Create the "frame" at an offset from the outside
let rangeF = [inset..(n - inset - 2)] // Range we use going forward
let rangeR = [(n - inset - 1)..(-1)..(inset + 1)] // Range we use going backward
rangeF |> Seq.iter (fun i -> sq.[inset,i] <- NextN()) // Top of frame
rangeF |> Seq.iter (fun i -> sq.[i,n-inset-1] <- NextN()) // Right side of frame
rangeR |> Seq.iter (fun i -> sq.[n-inset-1,i] <- NextN()) // Bottom of frame
rangeR |> Seq.iter (fun i -> sq.[i,inset] <- NextN()) // Left side of frame
[0..(n/2 - 1)] |> Seq.iter (fun i -> Frame i) // Fill in all frames
if n &&& 1 = 1 then sq.[n/2,n/2] <- n*n - 1 // If n is odd, fill in the last single value
sq // Return our output array</lang>
 
=={{header|Factor}}==
Line 1,648 ⟶ 1,664:
12 11 10 9 8
</pre>
 
=={{header|F_Sharp|F#}}==
No fancy schmancy elegance here, just putting the numbers in the right place (though I commend the elegance)...
<lang fsharp>let Spiral n =
let sq = Array2D.create n n 0 // Set up an output array
let nCur = ref -1 // Current value being inserted
let NextN() = nCur := (!nCur+1) ; !nCur // Inc current value and return new value
let Frame inset = // Create the "frame" at an offset from the outside
let rangeF = [inset..(n - inset - 2)] // Range we use going forward
let rangeR = [(n - inset - 1)..(-1)..(inset + 1)] // Range we use going backward
rangeF |> Seq.iter (fun i -> sq.[inset,i] <- NextN()) // Top of frame
rangeF |> Seq.iter (fun i -> sq.[i,n-inset-1] <- NextN()) // Right side of frame
rangeR |> Seq.iter (fun i -> sq.[n-inset-1,i] <- NextN()) // Bottom of frame
rangeR |> Seq.iter (fun i -> sq.[i,inset] <- NextN()) // Left side of frame
[0..(n/2 - 1)] |> Seq.iter (fun i -> Frame i) // Fill in all frames
if n &&& 1 = 1 then sq.[n/2,n/2] <- n*n - 1 // If n is odd, fill in the last single value
sq // Return our output array</lang>
 
=={{header|GAP}}==
Line 2,950 ⟶ 2,949:
----------
</pre>
 
=={{header|NetRexx}}==
{{Trans|ooRexx}}
Line 3,274:
| 12 11 10 9 8 |
</pre>
 
 
=={{header|Oz}}==
Line 3,456 ⟶ 3,455:
{printf "%3d", $_ foreach @$_;
print "\n";}</lang>
 
=={{header|Perl 6}}==
===Object-oriented Solution===
Suppose we set up a Turtle class like this:
<lang perl6>class Turtle {
my @dv = [0,-1], [1,-1], [1,0], [1,1], [0,1], [-1,1], [-1,0], [-1,-1];
my $points = 8; # 'compass' points of neighbors on grid: north=0, northeast=1, east=2, etc.
 
has @.loc = 0,0;
has $.dir = 0;
has %.world;
has $.maxegg;
has $.range-x;
has $.range-y;
 
method turn-left ($angle = 90) { $!dir -= $angle / 45; $!dir %= $points; }
method turn-right($angle = 90) { $!dir += $angle / 45; $!dir %= $points; }
 
method lay-egg($egg) {
%!world{~@!loc} = $egg;
$!maxegg max= $egg;
$!range-x minmax= @!loc[0];
$!range-y minmax= @!loc[1];
}
 
method look($ahead = 1) {
my $there = @!loc »+« @dv[$!dir] »*» $ahead;
%!world{~$there};
}
 
method forward($ahead = 1) {
my $there = @!loc »+« @dv[$!dir] »*» $ahead;
@!loc = @($there);
}
 
method showmap() {
my $form = "%{$!maxegg.chars}s";
my $endx = $!range-x.max;
for $!range-y.list X $!range-x.list -> ($y, $x) {
print (%!world{"$x $y"} // '').fmt($form);
print $x == $endx ?? "\n" !! ' ';
}
}
}
 
# Now we can build the spiral in the normal way from outside-in like this:
 
sub MAIN(Int $size = 5) {
my $t = Turtle.new(dir => 2);
my $counter = 0;
$t.forward(-1);
for 0..^ $size -> $ {
$t.forward;
$t.lay-egg($counter++);
}
for $size-1 ... 1 -> $run {
$t.turn-right;
$t.forward, $t.lay-egg($counter++) for 0..^$run;
$t.turn-right;
$t.forward, $t.lay-egg($counter++) for 0..^$run;
}
$t.showmap;
}</lang>
 
Or we can build the spiral from inside-out like this:
 
<lang perl6>sub MAIN(Int $size = 5) {
my $t = Turtle.new(dir => ($size %% 2 ?? 4 !! 0));
my $counter = $size * $size;
while $counter {
$t.lay-egg(--$counter);
$t.turn-left;
$t.turn-right if $t.look;
$t.forward;
}
$t.showmap;
}</lang>
Note that with these "turtle graphics" we don't actually have to care about the coordinate system, since the <code>showmap</code> method can show whatever rectangle was modified by the turtle. So unlike the standard inside-out algorithm, we don't have to find the center of the matrix first.
 
===Procedural Solution===
<lang perl6>sub spiral_matrix ( $n ) {
my @sm;
my $len = $n;
my $pos = 0;
 
for ^($n/2).ceiling -> $i {
my $j = $i + 1;
my $e = $n - $j;
 
@sm[$i ][$i + $_] = $pos++ for ^( $len); # Top
@sm[$j + $_][$e ] = $pos++ for ^(--$len); # Right
@sm[$e ][$i + $_] = $pos++ for reverse ^( $len); # Bottom
@sm[$j + $_][$i ] = $pos++ for reverse ^(--$len); # Left
}
 
return @sm;
}
 
say .fmt('%3d') for spiral_matrix(5);</lang>
{{out}}
<pre> 0 1 2 3 4
15 16 17 18 5
14 23 24 19 6
13 22 21 20 7
12 11 10 9 8</pre>
 
=={{header|Phix}}==
Line 4,144 ⟶ 4,038:
(mutable-array #[#[0 1 2 3] #[11 12 13 4] #[10 15 14 5] #[9 8 7 6]])
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)
===Object-oriented Solution===
Suppose we set up a Turtle class like this:
<lang perl6>class Turtle {
my @dv = [0,-1], [1,-1], [1,0], [1,1], [0,1], [-1,1], [-1,0], [-1,-1];
my $points = 8; # 'compass' points of neighbors on grid: north=0, northeast=1, east=2, etc.
 
has @.loc = 0,0;
has $.dir = 0;
has %.world;
has $.maxegg;
has $.range-x;
has $.range-y;
 
method turn-left ($angle = 90) { $!dir -= $angle / 45; $!dir %= $points; }
method turn-right($angle = 90) { $!dir += $angle / 45; $!dir %= $points; }
 
method lay-egg($egg) {
%!world{~@!loc} = $egg;
$!maxegg max= $egg;
$!range-x minmax= @!loc[0];
$!range-y minmax= @!loc[1];
}
 
method look($ahead = 1) {
my $there = @!loc »+« @dv[$!dir] »*» $ahead;
%!world{~$there};
}
 
method forward($ahead = 1) {
my $there = @!loc »+« @dv[$!dir] »*» $ahead;
@!loc = @($there);
}
 
method showmap() {
my $form = "%{$!maxegg.chars}s";
my $endx = $!range-x.max;
for $!range-y.list X $!range-x.list -> ($y, $x) {
print (%!world{"$x $y"} // '').fmt($form);
print $x == $endx ?? "\n" !! ' ';
}
}
}
 
# Now we can build the spiral in the normal way from outside-in like this:
 
sub MAIN(Int $size = 5) {
my $t = Turtle.new(dir => 2);
my $counter = 0;
$t.forward(-1);
for 0..^ $size -> $ {
$t.forward;
$t.lay-egg($counter++);
}
for $size-1 ... 1 -> $run {
$t.turn-right;
$t.forward, $t.lay-egg($counter++) for 0..^$run;
$t.turn-right;
$t.forward, $t.lay-egg($counter++) for 0..^$run;
}
$t.showmap;
}</lang>
 
Or we can build the spiral from inside-out like this:
 
<lang perl6>sub MAIN(Int $size = 5) {
my $t = Turtle.new(dir => ($size %% 2 ?? 4 !! 0));
my $counter = $size * $size;
while $counter {
$t.lay-egg(--$counter);
$t.turn-left;
$t.turn-right if $t.look;
$t.forward;
}
$t.showmap;
}</lang>
Note that with these "turtle graphics" we don't actually have to care about the coordinate system, since the <code>showmap</code> method can show whatever rectangle was modified by the turtle. So unlike the standard inside-out algorithm, we don't have to find the center of the matrix first.
 
===Procedural Solution===
<lang perl6>sub spiral_matrix ( $n ) {
my @sm;
my $len = $n;
my $pos = 0;
 
for ^($n/2).ceiling -> $i {
my $j = $i + 1;
my $e = $n - $j;
 
@sm[$i ][$i + $_] = $pos++ for ^( $len); # Top
@sm[$j + $_][$e ] = $pos++ for ^(--$len); # Right
@sm[$e ][$i + $_] = $pos++ for reverse ^( $len); # Bottom
@sm[$j + $_][$i ] = $pos++ for reverse ^(--$len); # Left
}
 
return @sm;
}
 
say .fmt('%3d') for spiral_matrix(5);</lang>
{{out}}
<pre> 0 1 2 3 4
15 16 17 18 5
14 23 24 19 6
13 22 21 20 7
12 11 10 9 8</pre>
 
=={{header|REXX}}==
Line 4,844:
Return (c@)
EndIf</lang>
 
=={{header|Ursala}}==
Helpful hints from the [[#J|J]] example are gratefully acknowledged. The spiral function works for any n, and results are shown for n equal to 5, 6, and 7. The results are represented as lists of lists rather than arrays.
10,327

edits