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

@ -3,7 +3,7 @@ on zigzagMatrix(n)
-- diagonals :: n -> [[n]]
script diagonals
on lambda(n)
on |λ|(n)
script mf
on diags(xs, iCol, iRow)
if (iCol < length of xs) then
@ -21,35 +21,25 @@ on zigzagMatrix(n)
end diags
end script
diags(range(0, n * n - 1), 1, 1) of mf
end lambda
diags(enumFromTo(0, n * n - 1), 1, 1) of mf
end |λ|
end script
-- oddReversed :: [a] -> Int -> [a]
script oddReversed
on lambda(lst, i)
on |λ|(lst, i)
if i mod 2 = 0 then
lst
else
reverse of lst
end if
end lambda
end |λ|
end script
rowsFromDiagonals(n, map(oddReversed, lambda(n) of diagonals))
rowsFromDiagonals(n, map(oddReversed, |λ|(n) of diagonals))
end zigzagMatrix
-- TEST
on run
zigzagMatrix(5)
end run
-- Rows of given length from list of diagonals
-- rowsFromDiagonals :: Int -> [[a]] -> [[a]]
on rowsFromDiagonals(n, lst)
@ -57,9 +47,9 @@ on rowsFromDiagonals(n, lst)
-- lengthOverOne :: [a] -> Bool
script lengthOverOne
on lambda(lst)
on |λ|(lst)
length of lst > 1
end lambda
end |λ|
end script
set {edge, residue} to splitAt(n, lst)
@ -69,14 +59,34 @@ on rowsFromDiagonals(n, lst)
map(my tail, ¬
filter(lengthOverOne, edge)) & residue)
else
[]
{}
end if
end rowsFromDiagonals
---------------------------------------------------------------------------
-- TEST -----------------------------------------------------------------------
on run
-- GENERIC FUNCTIONS
zigzagMatrix(5)
end run
-- GENERIC FUNCTIONS ----------------------------------------------------------
-- enumFromTo :: Int -> Int -> [Int]
on enumFromTo(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 enumFromTo
-- filter :: (a -> Bool) -> [a] -> [a]
on filter(f, xs)
@ -85,24 +95,45 @@ on filter(f, xs)
set lng to length of xs
repeat with i from 1 to lng
set v to item i of xs
if lambda(v, i, xs) then set end of lst to v
if |λ|(v, i, xs) then set end of lst to v
end repeat
return lst
end tell
end filter
-- head :: [a] -> a
on head(xs)
if length of xs > 0 then
item 1 of xs
else
missing value
end if
end head
-- 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)
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
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn
-- splitAt:: n -> list -> {n items from start of list, rest of list}
-- splitAt :: Int -> [a] -> ([a], [a])
on splitAt(n, xs)
@ -117,15 +148,6 @@ on splitAt(n, xs)
end if
end splitAt
-- head :: [a] -> a
on head(xs)
if length of xs > 0 then
item 1 of xs
else
missing value
end if
end head
-- tail :: [a] -> [a]
on tail(xs)
if length of xs > 1 then
@ -134,26 +156,3 @@ on tail(xs)
{}
end if
end tail
-- range :: Int -> Int -> [Int]
on range(m, n)
set d to 1
if n < m then set d to -1
set lst to {}
repeat with i from m to n by d
set end of lst to i
end repeat
return lst
end range
-- 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

@ -1,23 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
int main(int c, char **v)
{
int i, j, m, n, *s;
/* default size: 5 */
if (c < 2 || ((m = atoi(v[1]))) <= 0) m = 5;
/* alloc array*/
s = malloc(sizeof(int) * m * m);
for (i = n = 0; i < m * 2; i++)
for (j = (i < m) ? 0 : i-m+1; j <= i && j < m; j++)
s[(i&1)? j*(m-1)+i : (i-j)*m+j ] = n++;
for (i = 0; i < m * m; putchar((++i % m) ? ' ':'\n'))
printf("%3d", s[i]);
/* free(s) */
return 0;
}

View file

@ -1,8 +0,0 @@
% ./a.out 7
0 1 5 6 14 15 27
2 4 7 13 16 26 28
3 8 12 17 25 29 38
9 11 18 24 30 37 39
10 19 23 31 36 40 45
20 22 32 35 41 44 46
21 33 34 42 43 47 48

View file

@ -1,41 +0,0 @@
# Calculate a zig-zag pattern of numbers like so:
# 0 1 5
# 2 4 6
# 3 7 8
#
# There are many interesting ways to solve this; we
# try for an algebraic approach, calculating triangle
# areas, so that me minimize space requirements.
zig_zag_value = (x, y, n) ->
upper_triangle_zig_zag = (x, y) ->
# calculate the area of the triangle from the prior
# diagonals
diag = x + y
triangle_area = diag * (diag+1) / 2
# then add the offset along the diagonal
if diag % 2 == 0
triangle_area + y
else
triangle_area + x
if x + y < n
upper_triangle_zig_zag x, y
else
# For the bottom right part of the matrix, we essentially
# use reflection to count backward.
bottom_right_cell = n * n - 1
n -= 1
v = upper_triangle_zig_zag(n-x, n-y)
bottom_right_cell - v
zig_zag_matrix = (n) ->
row = (i) -> (zig_zag_value i, j, n for j in [0...n])
(row i for i in [0...n])
do ->
for n in [4..6]
console.log "---- n=#{n}"
console.log zig_zag_matrix(n)
console.log "\n"

View file

@ -1,23 +0,0 @@
> coffee zigzag.coffee
---- n=4
[ [ 0, 1, 5, 6 ],
[ 2, 4, 7, 12 ],
[ 3, 8, 11, 13 ],
[ 9, 10, 14, 15 ] ]
---- n=5
[ [ 0, 1, 5, 6, 14 ],
[ 2, 4, 7, 13, 15 ],
[ 3, 8, 12, 16, 21 ],
[ 9, 11, 17, 20, 22 ],
[ 10, 18, 19, 23, 24 ] ]
---- n=6
[ [ 0, 1, 5, 6, 14, 15 ],
[ 2, 4, 7, 13, 16, 25 ],
[ 3, 8, 12, 17, 24, 26 ],
[ 9, 11, 18, 23, 27, 32 ],
[ 10, 19, 22, 28, 31, 33 ],
[ 20, 21, 29, 30, 34, 35 ] ]

View file

@ -0,0 +1,46 @@
import extensions.
extension op
{
zigzagMatrix
[
intmatrix result := IntMatrix new int:self int:self.
int i := 0.
int j := 0.
int d := -1.
int start := 0.
int end := self*self - 1.
while (start < end)
[
result write int:i int:j int:start. start := start + 1.
result write int(self - i - 1) int(self - j - 1) int:end. end := end - 1.
i := i + d.
j := j - d.
if (i < 0)
[
i:=i+1. d := d negative
];
[
if (j < 0)
[
j := j + 1. d := d negative
]
]
].
if (start == end)
[
result write int:i int:j int:start.
].
^ result
]
}
program =
[
console printLine(5 zigzagMatrix); readChar.
].

View file

@ -0,0 +1,37 @@
import Data.List (mapAccumL)
import Data.Text (justifyRight, pack, unpack)
zigZag :: Int -> [[Int]]
zigZag n = horizontals n (diagonals n)
where
diagonals :: Int -> [[Int]]
diagonals n =
snd $
mapAccumL
(\xs h ->
let (grp, rst) = splitAt h xs
in ( rst
, (if mod h 2 /= 0
then reverse
else id)
grp))
[0 .. (n * n) - 1]
(slope ++ [n] ++ reverse slope)
where
slope = [1 .. n - 1]
horizontals :: Int -> [[Int]] -> [[Int]]
horizontals n xss =
if not (null xss)
then let (edge, rst) = splitAt n xss
in (head <$> edge) :
horizontals n (dropWhile null (tail <$> edge) ++ rst)
else []
main :: IO ()
main =
putStrLn $
unlines $
(concat . (unpack <$>)) . ((justifyRight 3 ' ' . pack . show) <$>) <$>
zigZag 5

View file

@ -0,0 +1,65 @@
#!/usr/bin/env jq -Mnrc -f
#
# solve zigzag matrix by constructing list of 2n+1 column "runs"
# and then shifting them into final form.
#
# e.g. for n=3 initial runs are [[0],[1,2],[3,4,5],[6,7],[8]]
# runs below are shown as columns:
#
# initial column runs 0 1 3 6 8
# 2 4 7
# 5
#
# reverse cols 0,2,4 0 1 5 6 8
# 2 4 7
# 3
#
# shift cols 3,4 down 0 1 5
# 2 4 6
# 3 7 8
#
# shift rows left 0 1 5
# to get final zigzag 2 4 6
# 3 7 8
def N: $n ; # size of matrix
def NR: 2*N - 1; # number of runs
def abs: if .<0 then -. else . end ; # absolute value
def runlen: N-(N-.|abs) ; # length of run
def makeruns: [
foreach range(1;NR+1) as $r ( # for each run
{c:0} # state counter
; .l = ($r|runlen) # length of this run
| .r = [range(.c;.c+.l)] # values in this run
| .c += .l # increment counter
; .r # produce run
) ] ; # collect into array
def even: .%2==0 ; # is input even?
def reverseruns: # reverse alternate runs
.[keys|map(select(even))[]] |= reverse ;
def zeros: [range(.|N-length)|0] ; # array of padding zeros
def shiftdown:
def pad($r): # pad run with zeros
if $r < N # determine where zeros go
then . = . + zeros # at back for left runs
else . = zeros + . # at front for right runs
end ;
reduce keys[] as $r (.;.[$r] |= pad($r)); # shift rows down with pad
def shiftleft: [
range(N) as $r
| [ range($r;$r+N) as $c
| .[$c][$r]
]
] ;
def width: [.[][]]|max|tostring|1+length; # width of largest value
def justify($w): (($w-length)*" ") + . ; # leading spaces
def format:
width as $w # compute width
| map(map(tostring | justify($w)))[] # justify values
| join(" ")
;
makeruns # create column runs
| reverseruns # reverse alternate runs
| shiftdown # shift right runs down
| shiftleft # shift rows left
| format # format final result

View file

@ -0,0 +1,37 @@
// version 1.1.3
typealias Vector = IntArray
typealias Matrix = Array<Vector>
fun zigzagMatrix(n: Int): Matrix {
val result = Matrix(n) { Vector(n) }
var down = false
var count = 0
for (col in 0 until n) {
if (down)
for (row in 0..col) result[row][col - row] = count++
else
for (row in col downTo 0) result[row][col - row] = count++
down = !down
}
for (row in 1 until n) {
if (down)
for (col in n - 1 downTo row) result[row + n - 1 - col][col] = count++
else
for (col in row until n) result[row + n - 1 - col][col] = count++
down = !down
}
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(zigzagMatrix(5))
printMatrix(zigzagMatrix(10))
}

View file

@ -1,64 +0,0 @@
function matrix = zigZag(n)
%This is very unintiutive. This algorithm parameterizes the
%zig-zagging movement along the matrix indicies. The easiest way to see
%what this algorithm does is to go through line-by-line and write out
%what the algorithm does on a peace of paper.
matrix = zeros(n);
counter = 1;
flipCol = true;
flipRow = false;
%This for loop does the top-diagonal of the matrix
for i = (2:n)
row = (1:i);
column = (1:i);
%Causes the zig-zagging. Without these conditionals, you would end
%up with a diagonal matrix. To see what happens comment these conditionals out.
if flipCol
column = fliplr(column);
flipRow = true;
flipCol = false;
elseif flipRow
row = fliplr(row);
flipRow = false;
flipCol = true;
end
%Selects a diagonal of the zig-zag matrix and places the correct
%integer value in each index along that diagonal
for j = (1:numel(row))
matrix(row(j),column(j)) = counter;
counter = counter + 1;
end
end
%This for loop does the bottom-diagonal of the matrix
for i = (2:n)
row = (i:n);
column = (i:n);
%Causes the zig-zagging. Without these conditionals, you would end
%up with a diagonal matrix. To see what happens comment these conditionals out.
if flipCol
column = fliplr(column);
flipRow = true;
flipCol = false;
elseif flipRow
row = fliplr(row);
flipRow = false;
flipCol = true;
end
%Selects a diagonal of the zig-zag matrix and places the correct
%integer value in each index along that diagonal
for j = (1:numel(row))
matrix(row(j),column(j)) = counter;
counter = counter + 1;
end
end
end

View file

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

View file

@ -0,0 +1,42 @@
call printArray zigzag(3)
say
call printArray zigzag(4)
say
call printArray zigzag(5)
::routine zigzag
use strict arg size
data = .array~new(size, size)
row = 1
col = 1
loop element = 0 to (size * size) - 1
data[row, col] = element
-- even stripes
if (row + col) // 2 = 0 then do
if col < size then col += 1
else row += 2
if row > 1 then row -= 1
end
-- odd rows
else do
if row < size then row += 1
else col += 2
if col > 1 then col -= 1
end
end
return data
::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,5 +1,5 @@
sub MAIN($size as Int) {
my $t = Turtle.new(dir => northeast);
my $t = Turtle.new(dir => 1);
my $counter = 0;
for 1 ..^ $size -> $run {
for ^$run {

View file

@ -0,0 +1 @@
zigzag 5 | Format-Wide {"{0,2}" -f $_} -Column 5 -Force

View file

@ -1,10 +1,19 @@
def zigzag(n:int) = {
var l = List[Tuple2[int,int]]()
(0 until n*n) foreach {i=>l = l + (i%n,i/n)}
l = l.sort{case ((x,y),(u,v)) => if (x+y == u+v)
if ((x+y) % 2 == 0) x<u else y<v
else (x+y) < (u+v) }
var a = new Array[Array[int]](n,n)
l.zipWithIndex foreach {case ((x,y),i) => a(y)(x) = i}
a
}
def zigzag(n: Int): Array[Array[Int]] = {
val l = for (i <- 0 until n*n) yield (i%n, i/n)
val lSorted = l.sortWith {
case ((x,y), (u,v)) =>
if (x+y == u+v)
if ((x+y) % 2 == 0) x<u else y<v
else x+y < u+v
}
val res = Array.ofDim[Int](n, n)
lSorted.zipWithIndex foreach {
case ((x,y), i) => res(y)(x) = i
}
res
}
zigzag(5).foreach{
ar => ar.foreach(x => print("%3d".format(x)))
println
}

View file

@ -1,10 +1,5 @@
def zigzag(n:int) = {
var indices = List[Tuple2[Int,Int]]()
var array = new Array[Array[Int]](n,n)
(0 until n*n).foldLeft(indices)((l,i) => l + (i%n,i/n)).
sort{case ((x,y),(u,v)) => if (x+y == u+v)
if ((x+y) % 2 == 0) x<u else y<v
else (x+y) < (u+v) }.
zipWithIndex.foldLeft(array) {case (a,((x,y),i)) => a(y)(x) = i; a}
}
0 1 5 6 14
2 4 7 13 15
3 8 12 16 21
9 11 17 20 22
10 18 19 23 24

View file

@ -1,24 +1,21 @@
func zig_zag(w, h) {
var r = [];
var n = 0;
var r = []
var n = 0
h.of { |e|
w.of { |f|
[e-1, f-1]
[e, f]
}
} \
-> reduce('+') \
-> sort { |a, b|
}.reduce('+').sort { |a, b|
(a[0]+a[1] <=> b[0]+b[1]) ||
(a[0]+a[1] -> is_even ? a[0]<=>b[0]
: a[1]<=>b[1])
} \
-> each { |a|
r[a[1]][a[0]] = n++;
}.each { |a|
r[a[1]][a[0]] = n++
}
return r;
return r
}
zig_zag(5, 5).each {say .join('', {|i| "%4i" % i})};
zig_zag(5, 5).each { say .join('', {|i| "%4i" % i}) }

View file

@ -0,0 +1,11 @@
fcn zz(n){
grid := (0).pump(n,List, (0).pump(n,List).copy).copy();
ri := Ref(0);
foreach d in ([1..n*2]){
x:=(0).max(d - n); y:=(n - 1).min(d - 1);
(0).pump(d.min(n*2 - d),Void,'wrap(it){
grid[if(d%2)y-it else x+it][if(d%2)x+it else y-it] = ri.inc();
});
}
grid.pump(String,'wrap(r){("%3s"*n+"\n").fmt(r.xplode())});
}

View file

@ -0,0 +1,7 @@
fcn ceg(m){
s := (0).pump(m*m,List).copy(); // copy to make writable
rn := Ref(0);
[[(i,j); [0..m*2-1]; '{[(0).max(i-m+1) .. i.min(m-1)]};
'{ s[ if(i.isOdd) j*(m-1)+i else (i-j)*m+j ] = rn.inc(); }]];
s.pump(String,T(Void.Read,m-1), ("%3s"*m+"\n").fmt);
}

View file

@ -0,0 +1,7 @@
fcn ceg2(m){
rn := Ref(0);
[[(i,j); [0..m*2-1]; '{[(0).max(i-m+1) .. i.min(m-1)]};
'{ T( if(i.isOdd) j*(m-1)+i else (i-j)*m+j;, rn.inc() ) }]]
.sort(fcn([(a,_)], [(b,_)]){ a<b }).apply("get",1)
.pump(String,T(Void.Read,m-1), ("%3s"*m+"\n").fmt);
}