September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -1,8 +1,10 @@
-- Int -> Int -> Int -> [[Int]]
-- SPIRAL MATRIX -------------------------------------------------------------
-- spiral :: Int -> Int -> Int -> [[Int]]
on spiral(lngRows, lngCols, nStart)
if lngRows > 0 then
{range(nStart, (nStart + lngCols) - 1)} & ¬
map(my _reverse, ¬
{enumFromTo(nStart, (nStart + lngCols) - 1)} & ¬
map(my |reverse|, ¬
transpose(spiral(lngCols, lngRows - 1, nStart + lngCols)))
else
{{}}
@ -10,7 +12,7 @@ on spiral(lngRows, lngCols, nStart)
end spiral
-- TEST
-- TEST ----------------------------------------------------------------------
on run
set n to 5
set lstSpiral to spiral(n, n, 0)
@ -24,17 +26,17 @@ on run
end run
-- WIKI TABLE FORMAT
-- WIKI TABLE FORMAT ---------------------------------------------------------
-- wikiTable :: [Text] -> Bool -> Text -> Text
on wikiTable(lstRows, blnHdr, strStyle)
script fWikiRows
on lambda(lstRow, iRow)
on |λ|(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 |λ|
end script
linefeed & "{| class=\"wikitable\" " & ¬
@ -44,57 +46,20 @@ on wikiTable(lstRows, blnHdr, strStyle)
end wikiTable
-- GENERIC LIBRARY FUNCTIONS
-- GENERIC 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
-- cond :: Bool -> a -> a -> a
on cond(bool, x, y)
if bool then
x
else
reverse of xs
y
end if
end _reverse
end cond
-- 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
-- enumFromTo :: Int -> Int -> [Int]
on enumFromTo(m, n)
if m > n then
set d to -1
else
set d to 1
@ -104,16 +69,27 @@ on range(m, n)
set end of lst to i
end repeat
return lst
end range
end enumFromTo
-- cond :: Bool -> (a -> b) -> (a -> b) -> (a -> b)
on cond(bool, f, g)
if bool then
f
else
g
end if
end cond
-- 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
-- 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 |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
@ -122,7 +98,33 @@ on mReturn(f)
f
else
script
property lambda : f
property |λ| : f
end script
end if
end mReturn
-- 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|
-- transpose :: [[a]] -> [[a]]
on transpose(xss)
script column
on |λ|(_, iCol)
script row
on |λ|(xs)
item iCol of xs
end |λ|
end script
map(row, xss)
end |λ|
end script
map(column, item 1 of xss)
end transpose

View file

@ -3,7 +3,7 @@
(->> (range (dec n) 0 -1)
(mapcat #(repeat 2 %))
(cons n)
#(mapcat repeat % cyc)
(mapcat #(repeat %2 %) cyc)
(reductions +)
(map vector (range 0 (* n n)))
(sort-by second)

View file

@ -0,0 +1,8 @@
(defn spiral-matrix [m n & [start]]
(let [row (list (map #(+ start %) (range m)))]
(if (= 1 n) row
(concat row (map reverse
(apply map list
(spiral-matrix (dec n) m (+ start m))))))))
(defn spiral [n m] (spiral-matrix n m 1))

View file

@ -0,0 +1,11 @@
import Data.List (transpose)
spiral :: Int -> Int -> Int -> [[Int]]
spiral rows cols start =
if rows > 0
then [start .. start + cols - 1] :
(reverse <$> transpose (spiral cols (rows - 1) (start + cols)))
else [[]]
main :: IO ()
main = mapM_ print $ spiral 5 5 0

View file

@ -0,0 +1,40 @@
// version 1.1.3
typealias Vector = IntArray
typealias Matrix = Array<Vector>
fun spiralMatrix(n: Int): Matrix {
val result = Matrix(n) { Vector(n) }
var pos = 0
var count = n
var value = -n
var sum = -1
do {
value = -value / n
for (i in 0 until count) {
sum += value
result[sum / n][sum % n] = pos++
}
value *= n
count--
for (i in 0 until count) {
sum += value
result[sum / n][sum % n] = pos++
}
}
while (count > 0)
return result
}
fun printMatrix(m: Matrix) {
for (i in 0 until m.size) {
for (j in 0 until m.size) print("%2d ".format(m[i][j]))
println()
}
println()
}
fun main(args: Array<String>) {
printMatrix(spiralMatrix(5))
printMatrix(spiralMatrix(10))
}

View file

@ -0,0 +1,55 @@
call printArray generateArray(3)
say
call printArray generateArray(4)
say
call printArray generateArray(5)
::routine generateArray
use arg dimension
-- the output array
array = .array~new(dimension, dimension)
-- get the number of squares, including the center one if
-- the dimension is odd
squares = dimension % 2 + dimension // 2
-- length of a side for the current square
sidelength = dimension
current = 0
loop i = 1 to squares
-- do each side of the current square
-- top side
loop j = 0 to sidelength - 1
array[i, i + j] = current
current += 1
end
-- down the right side
loop j = 1 to sidelength - 1
array[i + j, dimension - i + 1] = current
current += 1
end
-- across the bottom
loop j = sidelength - 2 to 0 by -1
array[dimension - i + 1, i + j] = current
current += 1
end
-- and up the left side
loop j = sidelength - 2 to 1 by -1
array[i + j, i] = current
current += 1
end
-- reduce the length of the side by two rows
sidelength -= 2
end
return array
::routine printArray
use arg array
dimension = array~dimension(1)
loop i = 1 to dimension
line = "|"
loop j = 1 to dimension
line = line array[i, j]~right(2)
end
line = line "|"
say line
end

View file

@ -1,47 +1,40 @@
enum Dir < north northeast east southeast south southwest west northwest >;
my $debug = 0;
class Turtle {
has @.loc = 0,0;
has Dir $.dir = north;
my @dv = [0,-1], [1,-1], [1,0], [1,1], [0,1], [-1,1], [-1,0], [-1,-1];
my @num-to-dir = Dir.invert.sort».value;
my $points = +Dir;
my $points = 8; # 'compass' points of neighbors on grid: north=0, northeast=1, east=2, etc.
my %world;
my $maxegg;
my $range-x;
my $range-y;
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];
%!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] X* $ahead);
say "looking @num-to-dir[$!dir] to $there" if $debug;
%world{~$there};
my $there = @!loc »+« @dv[$!dir] »*» $ahead;
%!world{~$there};
}
method forward($ahead = 1) {
my $there = @!loc »+« (@dv[$!dir] X* $ahead);
@!loc = @($there);
say " moving @num-to-dir[$!dir] to @!loc[]" if $debug;
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" !! ' ';
}
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" !! ' ';
}
}
}

View file

@ -1,16 +1,16 @@
sub MAIN($size as Int) {
my $t = Turtle.new(dir => east);
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;
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;
}

View file

@ -1,11 +1,11 @@
sub MAIN($size as Int) {
my $t = Turtle.new(dir => ($size %% 2 ?? south !! north));
my $counter = $size * $size;
while $counter {
$t.lay-egg(--$counter);
$t.turn-left;
$t.turn-right if $t.look;
$t.forward;
}
$t.showmap;
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;
}

View file

@ -1,21 +1,22 @@
/*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. */
/*REXX program displays a spiral in a square array (of any size) starting at START. */
parse arg size start . /*obtain optional arguments from the CL*/
if size =='' | size =="," then size =5 /*Not specified? Then use the default.*/
if start=='' | start=="," then start=0 /*Not specified? Then use the default.*/
tot=size**2; L=length(tot + start) /*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. */
row=1; col=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
do n=0 for k; col=col + 1; @.col.row=n + start; 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···*/
do n=n for k; row=row + one; @.col.row=n + start; end /*for the row···*/
do n=n for k; col=col - one; @.col.row=n + start; 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. */
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. */
say _ /*display a line (row) of the spiral. */
end /*row*/ /*stick a fork in it, we're all done. */

View file

@ -1,16 +1,17 @@
/*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. */
/*REXX program displays a spiral in a square array (of any size) starting at START. */
parse arg size start . /*obtain optional arguments from the CL*/
if size =='' | size =="," then size =5 /*Not specified? Then use the default.*/
if start=='' | start=="," then start=0 /*Not specified? Then use the default.*/
tot=size**2; L=length(tot + start) /*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. */
row=1; col=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
do n=0 for k; col=col + 1; @.col.row=n + start; 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···*/
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 + start; end /*for the row···*/
do n=n for k; col=col - one; @.col.row=n + start; end /* " " col···*/
end /*one*/ /* ↑↓ direction.*/
end /*until n≥tot*/ /* [↑] done with the matrix spiral. */
!.=0 /* [↓] display spiral to the screen. */
@ -20,6 +21,6 @@ row=1; col=0; start=0 /*start spiral at row 1, co
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. */
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. */

View file

@ -1,20 +1,20 @@
func spiral(n) {
var (x, y, dx, dy, a) = (0, 0, 1, 0, []);
var (x, y, dx, dy, a) = (0, 0, 1, 0, [])
{ |i|
a[y][x] = i;
var (nx, ny) = (x+dx, y+dy);
a[y][x] = i
var (nx, ny) = (x+dx, y+dy)
( if (dx == 1 && (nx == n || a[ny][nx]!=nil)) { [ 0, 1] }
elsif (dy == 1 && (ny == n || a[ny][nx]!=nil)) { [-1, 0] }
elsif (dx == -1 && (nx < 0 || a[ny][nx]!=nil)) { [ 0, -1] }
elsif (dy == -1 && (ny < 0 || a[ny][nx]!=nil)) { [ 1, 0] }
else { [dx, dy] }
) » (\dx, \dy);
x = x+dx;
y = y+dy;
} * n**2;
return a;
) » (\dx, \dy)
x = x+dx
y = y+dy
} << (1 .. n**2)
return a
}
 
spiral(5).each { |row|
row.map {"%3d" % _}.join(' ').say;
row.map {"%3d" % _}.join(' ').say
}

View file

@ -0,0 +1,9 @@
fcn spiralMatrix(n){
sm:=(0).pump(n,List,(0).pump(n,List,False).copy); //L(L(False,False..), L(F,F,..) ...)
drc:=Walker.cycle(T(0,1,0), T(1,0,1), T(0,-1,0), T(-1,0,1)); // deltas
len:=n; r:=0; c:=-1; z:=-1; while(len>0){ //or do(2*n-1){
dr,dc,dl:=drc.next();
do(len-=dl){ sm[r+=dr][c+=dc]=(z+=1); }
}
sm
}

View file

@ -0,0 +1,4 @@
foreach n in (T(5,-1,0,1,2)){
spiralMatrix(n).pump(Console.println,fcn(r){ r.apply("%4d".fmt).concat() });
println("---");
}