2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,10 +1,12 @@
Produce a spiral array. <br>
A spiral array is a square arrangement of the
first <tt>N<sup>2</sup></tt> natural numbers,
where the numbers increase sequentially
as you go around the edges of the array spiralling inwards.
;Task:
Produce a spiral array.
For example, given 5, produce this array:
A &nbsp; ''spiral array'' &nbsp; is a square arrangement of the first &nbsp; <big> N<sup>2</sup></big> &nbsp; natural numbers, &nbsp; where the
<br>numbers increase sequentially as you go around the edges of the array spiraling inwards.
For example, given &nbsp; '''5''', &nbsp; produce this array:
<pre>
0 1 2 3 4
15 16 17 18 5
@ -13,4 +15,9 @@ For example, given 5, produce this array:
12 11 10 9 8
</pre>
;See also [[Zig-zag matrix]] and [[Ulam_spiral_(for_primes)]]
;Related tasks:
* &nbsp; [[Zig-zag matrix]]
* &nbsp; [[Identity_matrix]]
* &nbsp; [[Ulam_spiral_(for_primes)]]
<br><br>

View file

@ -0,0 +1,128 @@
-- Int -> Int -> Int -> [[Int]]
on spiral(lngRows, lngCols, nStart)
if lngRows > 0 then
{range(nStart, (nStart + lngCols) - 1)} & ¬
map(my _reverse, ¬
transpose(spiral(lngCols, lngRows - 1, nStart + lngCols)))
else
{{}}
end if
end spiral
-- TEST
on run
set n to 5
set lstSpiral to spiral(n, n, 0)
-- {{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}}
wikiTable(lstSpiral, ¬
false, ¬
"text-align:center;width:12em;height:12em;table-layout:fixed;")
end run
-- WIKI TABLE FORMAT
-- wikiTable :: [Text] -> Bool -> Text -> Text
on wikiTable(lstRows, blnHdr, strStyle)
script fWikiRows
on lambda(lstRow, iRow)
set strDelim to cond(blnHdr and (iRow = 0), "!", "|")
set strDbl to strDelim & strDelim
linefeed & "|-" & linefeed & strDelim & space & ¬
intercalate(space & strDbl & space, lstRow)
end lambda
end script
linefeed & "{| class=\"wikitable\" " & ¬
cond(strStyle "", "style=\"" & strStyle & "\"", "") & ¬
intercalate("", ¬
map(fWikiRows, lstRows)) & linefeed & "|}" & linefeed
end wikiTable
-- GENERIC LIBRARY FUNCTIONS
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to lambda(item i of xs, i, xs)
end repeat
return lst
end tell
end map
-- transpose :: [[a]] -> [[a]]
on transpose(xss)
script column
on lambda(_, iCol)
script row
on lambda(xs)
item iCol of xs
end lambda
end script
map(row, xss)
end lambda
end script
map(column, item 1 of xss)
end transpose
-- _reverse :: [a] -> [a]
on _reverse(xs)
if class of xs is text then
(reverse of characters of xs) as text
else
reverse of xs
end if
end _reverse
-- Text -> [Text] -> Text
on intercalate(strText, lstText)
set {dlm, my text item delimiters} to {my text item delimiters, strText}
set strJoined to lstText as text
set my text item delimiters to dlm
return strJoined
end intercalate
-- range :: Int -> Int -> [Int]
on range(m, n)
if n < m then
set d to -1
else
set d to 1
end if
set lst to {}
repeat with i from m to n by d
set end of lst to i
end repeat
return lst
end range
-- cond :: Bool -> (a -> b) -> (a -> b) -> (a -> b)
on cond(bool, f, g)
if bool then
f
else
g
end if
end cond
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
f
else
script
property lambda : f
end script
end if
end mReturn

View file

@ -0,0 +1,19 @@
defmodule RC do
def spiral_matrix(n) do
wide = length(to_char_list(n*n-1))
fmt = String.duplicate("~#{wide}w ", n) <> "~n"
runs = Enum.flat_map(n..1, &[&1,&1]) |> tl
delta = Stream.cycle([{0,1},{1,0},{0,-1},{-1,0}])
running(Enum.zip(runs,delta),0,-1,[])
|> Enum.with_index |> Enum.sort |> Enum.chunk(n)
|> Enum.each(fn row -> :io.format fmt, (for {_,i} <- row, do: i) end)
end
defp running([{run,{dx,dy}}|rest], x, y, track) do
new_track = Enum.reduce(1..run, track, fn i,acc -> [{x+i*dx, y+i*dy} | acc] end)
running(rest, x+run*dx, y+run*dy, new_track)
end
defp running([],_,_,track), do: track |> Enum.reverse
end
RC.spiral_matrix(5)

View file

@ -0,0 +1,30 @@
defmodule RC do
def spiral_matrix(n) do
wide = String.length(to_string(n*n-1))
fmt = String.duplicate("~#{wide}w ", n) <> "~n"
right(n,n-1,0,[]) |> Enum.reverse |> Enum.with_index |> Enum.sort |> Enum.chunk(n) |>
Enum.each(fn row ->
:io.format fmt, (for {_,i} <- row, do: i)
end)
end
def right(n, side, i, coordinates) do
down(n, side, i, Enum.reduce(0..side, coordinates, fn j,acc -> [{i, i+j} | acc] end))
end
def down(_, 0, _, coordinates), do: coordinates
def down(n, side, i, coordinates) do
left(n, side-1, i, Enum.reduce(1..side, coordinates, fn j,acc -> [{i+j, n-1-i} | acc] end))
end
def left(n, side, i, coordinates) do
up(n, side, i, Enum.reduce(side..0, coordinates, fn j,acc -> [{n-1-i, i+j} | acc] end))
end
def up(_, 0, _, coordinates), do: coordinates
def up(n, side, i, coordinates) do
right(n, side-1, i+1, Enum.reduce(side..1, coordinates, fn j,acc -> [{i+j, i} | acc] end))
end
end
RC.spiral_matrix(5)

View file

@ -0,0 +1,19 @@
defmodule RC do
def spiral_matrix(n) do
fmt = String.duplicate("~#{length(to_char_list(n*n-1))}w ", n) <> "~n"
Enum.flat_map(n..1, &[&1, &1])
|> tl
|> Enum.reduce({{0,-1},{0,1},[]}, fn run,{{x,y},{dx,dy},acc} ->
side = for i <- 1..run, do: {x+i*dx, y+i*dy}
{{x+run*dx, y+run*dy}, {dy, -dx}, acc++side}
end)
|> elem(2)
|> Enum.with_index
|> Enum.sort
|> Enum.map(fn {_,i} -> i end)
|> Enum.chunk(n)
|> Enum.each(fn row -> :io.format fmt, row end)
end
end
RC.spiral_matrix(5)

View file

@ -1,33 +0,0 @@
defmodule RC do
def spiral_matrix(n) do
right(n,n-1,0,[]) |> Enum.with_index |> Enum.sort |> Enum.with_index |>
Enum.each(fn {{_,x},i} ->
:io.format("~2w ", [x])
if( rem(i+1,n)==0, do: IO.puts "")
end)
end
def right(n,side,i,coordinates) do
coord = for j <- 0..side, do: {i, i+j}
down(n,side,i,coordinates++coord)
end
def down(_,0,_,coordinates), do: coordinates
def down(n,side,i,coordinates) do
coord = for j <- 1..side, do: {i+j, n-1-i}
left(n,side-1,i,coordinates++coord)
end
def left(n,side,i,coordinates) do
coord = for j <- 0..side, do: {n-1-i, i+side-j}
up(n,side,i,coordinates++coord)
end
def up(_,0,_,coordinates), do: coordinates
def up(n,side,i,coordinates) do
coord = for j <- 1..side, do: {i+side-j+1, i}
right(n,side-1,i+1,coordinates++coord)
end
end
RC.spiral_matrix(5)

View file

@ -3,7 +3,7 @@ import Text.Printf (printf)
-- spiral is the first row plus a smaller spiral rotated 90 deg
spiral 0 _ _ = [[]]
spiral h w s = [[s .. s+w-1]] ++ rot90 (spiral w (h-1) (s+w))
spiral h w s = [s .. s+w-1] : rot90 (spiral w (h-1) (s+w))
where rot90 = (map reverse).transpose
-- this is sort of hideous, someone may want to fix it

View file

@ -0,0 +1,67 @@
(n => {
// spiral :: the first row plus a smaller spiral rotated 90 degrees clockwise
// spiral :: Int -> Int -> Int -> [[Int]]
function spiral(lngRows, lngCols, nStart) {
return lngRows ? [range(nStart, (nStart + lngCols) - 1)]
.concat(
transpose(
spiral(lngCols, lngRows - 1, nStart + lngCols)
)
.map(reverse)
) : [[]];
}
// transpose :: [[a]] -> [[a]]
function transpose(xs) {
return xs[0]
.map((_, iCol) => xs
.map((row) => row[iCol]));
}
// reverse :: [a] -> [a]
function reverse(xs) {
return xs.slice(0)
.reverse();
}
// range(intFrom, intTo, optional intStep)
// Int -> Int -> Maybe Int -> [Int]
function range(m, n, step) {
let d = (step || 1) * (n >= m ? 1 : -1);
return Array.from({
length: Math.floor((n - m) / d) + 1
}, (_, i) => m + (i * d));
}
// TESTING
// replicate :: Int -> String -> String
function replicate(n, a) {
var v = [a],
o = '';
if (n < 1) return o;
while (n > 1) {
if (n & 1) o = o + v;
n >>= 1;
v = v + v;
}
return o + v;
}
return spiral(n, n, 0)
.map(
xs => xs.map(x => {
let s = `${x}`;
return replicate(4 - s.length, ' ') + s;
})
.join('')
)
.join('\n');
})(5);

View file

@ -0,0 +1,9 @@
spiral(dim) = {
my (M = matrix(dim, dim), p = s = 1, q = i = 0);
for (n=1, dim,
for (b=1, dim-n+1, M[p,q+=s] = i; i++);
for (b=1, dim-n, M[p+=s,q] = i; i++);
s = -s;
);
M
}

View file

@ -0,0 +1,36 @@
function Spiral-Matrix ( [int]$N )
{
# Initialize variables
$X = 0
$Y = -1
$i = 0
$Sign = 1
# Intialize array
$A = New-Object 'int[,]' $N, $N
# Set top row
1..$N | ForEach { $Y += $Sign; $A[$X,$Y] = ++$i }
# For each remaining half spiral...
ForEach ( $M in ($N-1)..1 )
{
# Set the vertical quarter spiral
1..$M | ForEach { $X += $Sign; $A[$X,$Y] = ++$i }
# Curve the spiral
$Sign = -$Sign
# Set the horizontal quarter spiral
1..$M | ForEach { $Y += $Sign; $A[$X,$Y] = ++$i }
}
# Convert the array to text output
$Spiral = ForEach ( $X in 1..$N ) { ( 1..$N | ForEach { $A[($X-1),($_-1)] } ) -join "`t" }
return $Spiral
}
Spiral-Matrix 5
""
Spiral-Matrix 7

View file

@ -1,11 +1,12 @@
n = 5
dx, dy = [0, 1, 0, -1], [1, 0, -1, 0]
x, y, c = 0, -1, 1
m = [[0 for i in range(n)] for j in range(n)]
for i in range(n + n - 1):
for j in range((n + n - i) // 2):
x += dx[i % 4]
y += dy[i % 4]
m[x][y] = c
c += 1
print('\n'.join([' '.join([str(v) for v in r]) for r in m]))
def spiral_matrix(n):
m = [[0] * n for i in range(n)]
dx, dy = [0, 1, 0, -1], [1, 0, -1, 0]
x, y, c = 0, -1, 1
for i in range(n + n - 1):
for j in range((n + n - i) // 2):
x += dx[i % 4]
y += dy[i % 4]
m[x][y] = c
c += 1
return m
for i in spiral_matrix(5): print(*i)

View file

@ -0,0 +1,5 @@
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

View file

@ -1,32 +1,11 @@
runsum <- function(v) {
rs <- c()
for(i in 1:length(v)) {
rs <- c(rs, sum(v[1:i]))
}
rs
spiral_matrix <- function(n) {
stopifnot(is.numeric(n))
stopifnot(n > 0)
steps <- c(1, n, -1, -n)
reps <- n - seq_len(n * 2 - 1L) %/% 2
indicies <- rep(rep_len(steps, length(reps)), reps)
indicies <- cumsum(indicies)
values <- integer(length(indicies))
values[indicies] <- seq_along(indicies)
matrix(values, n, n, byrow = TRUE)
}
grade <- function(v) {
g <- vector("numeric", length(v))
for(i in 1:length(v)) {
g[v[i]] <- i-1
}
g
}
makespiral <- function(spirald) {
series <- vector("numeric", spirald^2)
series[] <- 1
l <- spirald-1; p <- spirald+1
s <- 1
while(l > 0) {
series[p:(p+l-1)] <- series[p:(p+l-1)] * spirald*s
series[(p+l):(p+l*2-1)] <- -s*series[(p+l):(p+l*2-1)]
p <- p + l*2
l <- l - 1; s <- -s
}
matrix(grade(runsum(series)), spirald, spirald, byrow=TRUE)
}
print(makespiral(5))

View file

@ -1,13 +1,15 @@
#more general function, v is assumed to be a vector
spiralv<-function(v){
n<-sqrt(length(v))
if(n!=floor(n)) stop(simpleError("length of v should be a square of an integer"))
if(n==0) stop(simpleError("v should be of positive length"))
if(n==1) M<-matrix(v,1,1)
else M<-rbind(v[1:n],cbind(spiralv(v[(2*n):(n^2)])[(n-1):1,(n-1):1],v[(n+1):(2*n-1)]))
M
}
#wrapper
spiral<-function(n){spiralv(0:(n^2-1))}
#check:
spiral(5)
> spiral_matrix(5)
[,1] [,2] [,3] [,4] [,5]
[1,] 1 2 3 4 5
[2,] 16 17 18 19 6
[3,] 15 24 25 20 7
[4,] 14 23 22 21 8
[5,] 13 12 11 10 9
> t(spiral_matrix(5))
[,1] [,2] [,3] [,4] [,5]
[1,] 1 16 15 14 13
[2,] 2 17 24 23 12
[3,] 3 18 25 22 11
[4,] 4 19 20 21 10
[5,] 5 6 7 8 9

View file

@ -0,0 +1,15 @@
spiral_matrix <- function(n) {
spiralv <- function(v) {
n <- sqrt(length(v))
if (n != floor(n))
stop("length of v should be a square of an integer")
if (n == 0)
stop("v should be of positive length")
if (n == 1)
m <- matrix(v, 1, 1)
else
m <- rbind(v[1:n], cbind(spiralv(v[(2 * n):(n^2)])[(n - 1):1, (n - 1):1], v[(n + 1):(2 * n - 1)]))
m
}
spiralv(1:(n^2))
}

View file

@ -1,22 +1,21 @@
/*REXX program displays a spiral in a square array (of any size). */
parse arg size . /*get the array size from the CL.*/
if size=='' then size=5 /*No argument? Then use default.*/
tot=size**2 /*total # of elements in spiral.*/
k=size /*K is the counter for the spiral*/
row=1; col=0; start=0 /*start at row 1, col 0, with 0.*/
/*──────────────────────────────────────────────construct the spiral #s.*/
do n=start for k; col=col+1; @.col.row=n; end; if k==0 then exit
/* [↑] build first row of spiral*/
do until n>=tot /*spiral matrix.*/
do one=1 to -1 by -2 until n>=tot; k=k-1 /*perform twice.*/
do n=n for k; row=row+one; @.col.row=n; end /*for the row···*/
do n=n for k; col=col-one; @.col.row=n; end /* " " col···*/
end /*one*/ /* ↑↓ direction.*/
end /*until n≥tot*/ /* [↑] done with matrix spiral.*/
/*──────────────────────────────────────────────display spiral to screen*/
do row=1 for size; _= /*construct display row by row.*/
do col=1 for size /*construct a line col by col.*/
_=_ right(@.col.row, length(tot)) /*construct a line for display. */
end /*col*/ /* [↑] line has an extra blank.*/
say substr(_,2) /*SUBSTR ignores the first blank.*/
end /*row*/ /*stick a fork in it, we're done.*/
/*REXX program displays a spiral in a square array (of any size) from a start number.*/
parse arg size . /*obtain optional arguments from the CL*/
if size=='' | size=="," then size=5 /*Not specified? Then use the default.*/
tot=size**2; L=length(tot) /*total number of elements in spiral. */
k=size /*K: is the counter for the spiral. */
row=1; col=0; start=0 /*start spiral at row 1, column 0. */
/* [↓] construct the numbered spiral. */
do n=start for k; col=col+1; @.col.row=n; end; if k==0 then exit
/* [↑] build the first row of spiral. */
do until n>=tot /*spiral matrix.*/
do one=1 to -1 by -2 until n>=tot; k=k-1 /*perform twice.*/
do n=n for k; row=row+one; @.col.row=n; end /*for the row···*/
do n=n for k; col=col-one; @.col.row=n; end /* " " col···*/
end /*one*/ /* ↑↓ direction.*/
end /*until n≥tot*/ /* [↑] done with the matrix spiral. */
/* [↓] display spiral to the screen. */
do r=1 for size; _= right(@.1.r, L) /*construct display row by row. */
do c=2 for size-1; _=_ right(@.c.r, L) /*construct a line for the display. */
end /*col*/ /* [↑] line has an extra leading blank*/
say _ /*display a line (row) of the sprial. */
end /*row*/ /*stick a fork in it, we're all done. */

View file

@ -1,25 +1,25 @@
/*REXX program displays a spiral in a square array (of any size). */
parse arg size . /*get the array size from the CL.*/
if size=='' then size=5 /*No argument? Then use default.*/
tot=size**2 /*total # of elements in spiral.*/
k=size /*K is the counter for the spiral*/
row=1; col=0; start=0 /*start at row 1, col 0, with 0.*/
/*──────────────────────────────────────────────construct the spiral #s.*/
do n=start for k; col=col+1; @.col.row=n; end; if k==0 then exit
/* [↑] build first row of spiral*/
do until n>=tot /*spiral matrix.*/
do one=1 to -1 by -2 until n>=tot; k=k-1 /*perform twice.*/
do n=n for k; row=row+one; @.col.row=n; end /*for the row···*/
do n=n for k; col=col-one; @.col.row=n; end /* " " col···*/
end /*one*/ /* ↑↓ direction.*/
end /*until n≥tot*/ /* [↑] done with matrix spiral.*/
/*──────────────────────────────────────────────display spiral to screen*/
do twice=0 for 2; if \twice then !.=0 /*1st time? Find max col width.*/
do row=1 for size; _= /*construct display row by row. */
do col=1 for size; x=@.col.row /*construct a line col by col. */
if twice then _=_ right(x,!.col) /*construct a line for display.*/
else !.col=max(!.col,length(x)) /*find width of column*/
end /*col*/ /* [↓] line has an extra blank.*/
if twice then say substr(_,2) /*SUBSTR ignores the 1st blank. */
end /*row*/ /*stick a fork in it, we're done*/
end /*twice*/
/*REXX program displays a spiral in a square array (of any size) from a start number.*/
parse arg size . /*obtain optional arguments from the CL*/
if size=='' | size=="," then size=5 /*Not specified? Then use the default.*/
tot=size**2; L=length(tot) /*total number of elements in spiral. */
k=size /*K: is the counter for the spiral. */
row=1; col=0; start=0 /*start spiral at row 1, column 0. */
/* [↓] construct the numbered spiral. */
do n=start for k; col=col+1; @.col.row=n; end; if k==0 then exit
/* [↑] build the first row of spiral. */
do until n>=tot /*spiral matrix.*/
do one=1 to -1 by -2 until n>=tot; k=k-1 /*perform twice.*/
do n=n for k; row=row+one; @.col.row=n; end /*for the row···*/
do n=n for k; col=col-one; @.col.row=n; end /* " " col···*/
end /*one*/ /* ↑↓ direction.*/
end /*until n≥tot*/ /* [↑] done with the matrix spiral. */
!.=0 /* [↓] display spiral to the screen. */
do two=0 for 2 /*1st time? Find max column and width.*/
do r=1 for size; _= /*construct display row by row. */
do c=1 for size; x=@.c.r /*construct a line column by column. */
if two then _=_ right(x, !.c) /*construct a line for the display. */
else !.c=max(!.c, length(x)) /*find the maximum width of the column.*/
end /*c*/ /* [↓] line has an extra leading blank*/
if two then say substr(_,2) /*this SUBSTR ignores the first blank. */
end /*r*/
end /*two*/ /*stick a fork in it, we're all done. */