Jump to content

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,333

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.