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

@ -0,0 +1,101 @@
abstract class Cell(shared Character char) of emptyCell | head | tail | conductor {
shared Cell output({Cell*} neighbors) =>
switch (this)
case (emptyCell) emptyCell
case (head) tail
case (tail) conductor
case (conductor) (neighbors.count(head.equals) in 1..2 then head else conductor);
string => char.string;
}
object emptyCell extends Cell(' ') {}
object head extends Cell('H') {}
object tail extends Cell('t') {}
object conductor extends Cell('.') {}
Map<Character,Cell> cellsByChar = map { for (cell in `Cell`.caseValues) cell.char->cell };
class Wireworld(String data) {
value lines = data.lines;
value width = max(lines*.size);
value height = lines.size;
function toIndex(Integer x, Integer y) => x + y * width;
variable value currentState = Array.ofSize(width * height, emptyCell);
variable value nextState = Array.ofSize(width * height, emptyCell);
for (j->line in lines.indexed) {
for (i->char in line.indexed) {
currentState[toIndex(i, j)] = cellsByChar[char] else emptyCell;
}
}
value emptyGrid = Array.ofSize(width * height, emptyCell);
void clear(Array<Cell> cells) => emptyGrid.copyTo(cells);
shared void update() {
clear(nextState);
for(j in 0:height) {
for(i in 0:width) {
if(exists cell = currentState[toIndex(i, j)]) {
value nextCell = cell.output(neighborhood(currentState, i, j));
nextState[toIndex(i, j)] = nextCell;
}
}
}
value temp = currentState;
currentState = nextState;
nextState = temp;
}
shared void display() {
for (row in currentState.partition(width)) {
print("".join(row));
}
}
shared {Cell*} neighborhood(Array<Cell> grid, Integer x, Integer y) => {
for (j in y - 1..y + 1)
for (i in x - 1..x + 1)
if(i in 0:width && j in 0:height)
grid[toIndex(i, j)]
}.coalesced;
}
shared void run() {
value data = "tH.........
. .
...
. .
Ht.. ......";
value world = Wireworld(data);
variable value generation = 0;
void display() {
print("generation: ``generation``");
world.display();
}
display();
while (true) {
if (exists input = process.readLine(), input.lowercased == "q") {
return;
}
world.update();
generation++;
display();
}
}

View file

@ -0,0 +1,88 @@
var ctx, sizeW, sizeH, scl = 10, map, tmp;
function getNeighbour( i, j ) {
var ii, jj, c = 0;
for( var b = -1; b < 2; b++ ) {
for( var a = -1; a < 2; a++ ) {
ii = i + a; jj = j + b;
if( ii < 0 || ii >= sizeW || jj < 0 || jj >= sizeH ) continue;
if( map[ii][jj] == 1 ) c++;
}
}
return ( c == 1 || c == 2 );
}
function simulate() {
drawWorld();
for( var j = 0; j < sizeH; j++ ) {
for( var i = 0; i < sizeW; i++ ) {
switch( map[i][j] ) {
case 0: tmp[i][j] = 0; break;
case 1: tmp[i][j] = 2; break;
case 2: tmp[i][j] = 3; break;
case 3:
if( getNeighbour( i, j ) ) tmp[i][j] = 1;
else tmp[i][j] = 3;
break;
}
}
}
[tmp, map] = [map, tmp];
setTimeout( simulate, 200 );
}
function drawWorld() {
ctx.fillStyle = "#000"; ctx.fillRect( 0, 0, sizeW * scl, sizeH * scl );
for( var j = 0; j < sizeH; j++ ) {
for( var i = 0; i < sizeW; i++ ) {
switch( map[i][j] ) {
case 0: continue;
case 1: ctx.fillStyle = "#03f"; break;
case 2: ctx.fillStyle = "#f30"; break;
case 3: ctx.fillStyle = "#ff3"; break;
}
ctx.fillRect( i, j, 1, 1 );
}
}
}
function openFile( event ) {
var input = event.target;
var reader = new FileReader();
reader.onload = function() {
createWorld( reader.result );
};
reader.readAsText(input.files[0]);
}
function createWorld( txt ) {
var l = txt.split( "\n" );
sizeW = parseInt( l[0] );
sizeH = parseInt( l[1] );
map = new Array( sizeW );
tmp = new Array( sizeW );
for( var i = 0; i < sizeW; i++ ) {
map[i] = new Array( sizeH );
tmp[i] = new Array( sizeH );
for( var j = 0; j < sizeH; j++ ) {
map[i][j] = tmp[i][j] = 0;
}
}
var t;
for( var j = 0; j < sizeH; j++ ) {
for( var i = 0; i < sizeW; i++ ) {
switch( l[j + 2][i] ) {
case " ": t = 0; break;
case "H": t = 1; break;
case "t": t = 2; break;
case ".": t = 3; break;
}
map[i][j] = t;
}
}
init();
}
function init() {
var canvas = document.createElement( "canvas" );
canvas.width = sizeW * scl;
canvas.height = sizeH * scl;
ctx = canvas.getContext( "2d" );
ctx.scale( scl, scl );
document.body.appendChild( canvas );
simulate();
}

View file

@ -0,0 +1,69 @@
local map = {{'t', 'H', '.', '.', '.', '.', '.', '.', '.', '.', '.'},
{'.', ' ', ' ', ' ', '.'},
{' ', ' ', ' ', '.', '.', '.'},
{'.', ' ', ' ', ' ', '.'},
{'H', 't', '.', '.', ' ', '.', '.', '.', '.', '.', '.'}}
function step(map)
local next = {}
for i = 1, #map do
next[i] = {}
for j = 1, #map[i] do
next[i][j] = map[i][j]
if map[i][j] == "H" then
next[i][j] = "t"
elseif map[i][j] == "t" then
next[i][j] = "."
elseif map[i][j] == "." then
local count = ((map[i-1] or {})[j-1] == "H" and 1 or 0) +
((map[i-1] or {})[j] == "H" and 1 or 0) +
((map[i-1] or {})[j+1] == "H" and 1 or 0) +
((map[i] or {})[j-1] == "H" and 1 or 0) +
((map[i] or {})[j+1] == "H" and 1 or 0) +
((map[i+1] or {})[j-1] == "H" and 1 or 0) +
((map[i+1] or {})[j] == "H" and 1 or 0) +
((map[i+1] or {})[j+1] == "H" and 1 or 0)
if count == 1 or count == 2 then
next[i][j] = "H"
else
next[i][j] = "."
end
end
end
end
return next
end
if not not love then
local time, frameTime, size = 0, 0.25, 20
local colors = {["."] = {255, 200, 0},
["t"] = {255, 0, 0},
["H"] = {0, 0, 255}}
function love.update(dt)
time = time + dt
if time > frameTime then
time = time - frameTime
map = step(map)
end
end
function love.draw()
for i = 1, #map do
for j = 1, #map[i] do
love.graphics.setColor(colors[map[i][j]] or {0, 0, 0})
love.graphics.rectangle("fill", j*size, i*size, size, size)
end
end
end
else
for iter = 1, 10 do
print("\nstep "..iter.."\n")
for i = 1, #map do
for j = 1, #map[i] do
io.write(map[i][j])
end
io.write("\n")
end
map = step(map)
end
end

View file

@ -0,0 +1,167 @@
--
-- demo\rosetta\Wireworld.exw
-- ==========================
--
-- Invoke with file to read or let it read the one below (if compiled assumes source is in the same directory)
--
-- Note that tabs in description files are not supported - where necessary spaces can be replaced with _ chars.
-- (tab chars in text files should technically always represent (to-next) 8 spaces, but not many editors respect
-- that, and instead assume the file will only ever be read by the same program/with matching settings. </rant>)
-- (see also demo\edix\src\tabs.e\ExpandTabs() for what you'd need if you knew what tab chars really meant.)
--
/* -- default description:
tH.........
.___.
___...
.___.
Ht.. ......
*/
sequence lines, counts
integer longest
function valid_line(string line, integer l=0)
if length(line)=0 then return 0 end if
for i=1 to length(line) do
integer ch = line[i]
if not find(ch," _.tH") then
if l and ch='\t' then
-- as above
printf(1,"error: tab char on line %d\n",{l})
{} = wait_key()
abort(0)
end if
return 0
end if
end for
return 1
end function
procedure load_desc()
string filename = substitute(command_line()[$],".exe",".exw")
integer fn = open(filename,"r")
if fn=-1 then
printf(1,"error opening %s\n",{filename})
{} = wait_key()
abort(0)
end if
sequence text = get_text(fn,GT_LF_STRIPPED)
close(fn)
lines = {}
for i=1 to length(text) do
string line = text[i]
if valid_line(line) then
lines = {line}
longest = length(line)
for j=i+1 to length(text) do
line = text[j]
if not valid_line(line,j) then exit end if
lines = append(lines,line)
if longest<length(line) then
longest = length(line)
end if
end for
exit
end if
end for
counts = lines
end procedure
constant dxy = {{-1,-1}, {-1,+0}, {-1,+1},
{+0,-1}, {+0,+1},
{+1,-1}, {+1,+0}, {+1,+1}}
procedure set_counts()
for y=1 to length(lines) do
for x=1 to length(lines[y]) do
if lines[y][x]='.' then
integer count = 0
for k=1 to length(dxy) do
integer {cx,cy} = sq_add({x,y},dxy[k])
if cy>=1 and cy<=length(lines)
and cx>=1 and cx<=length(lines[cy])
and lines[cy][cx]='H' then
count += 1
end if
end for
counts[y][x] = (count=1 or count=2)
end if
end for
end for
end procedure
include pGUI.e
Ihandle dlg, canvas, timer
cdCanvas cddbuffer, cdcanvas
function redraw_cb(Ihandle /*ih*/, integer /*posx*/, integer /*posy*/)
integer {w, h} = IupGetIntInt(canvas, "DRAWSIZE")
integer dx = floor(w/(longest+2))
integer dy = floor(h/(length(lines)+2))
cdCanvasActivate(cddbuffer)
cdCanvasClear(cddbuffer)
set_counts()
for y=1 to length(lines) do
for x=1 to length(lines[y]) do
integer c = lines[y][x], colour
if find(c," _") then
colour = CD_BLACK
elsif c='.' then
colour = CD_YELLOW
if counts[y][x] then
lines[y][x] = 'H'
end if
elsif c='H' then
colour = CD_BLUE
lines[y][x] = 't'
elsif c='t' then
colour = CD_RED
lines[y][x] = '.'
end if
cdCanvasSetForeground(cddbuffer, colour)
cdCanvasBox(cddbuffer,x*dx,x*dx+dx,h-y*dy,h-(y*dy+dy))
end for
end for
cdCanvasFlush(cddbuffer)
return IUP_DEFAULT
end function
function timer_cb(Ihandle /*ih*/)
IupUpdate(canvas)
return IUP_IGNORE
end function
function map_cb(Ihandle ih)
cdcanvas = cdCreateCanvas(CD_IUP, ih)
cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
cdCanvasSetBackground(cddbuffer, CD_BLACK)
return IUP_DEFAULT
end function
function esc_close(Ihandle /*ih*/, atom c)
if c=K_ESC then return IUP_CLOSE end if
return IUP_CONTINUE
end function
procedure main()
load_desc()
IupOpen()
canvas = IupCanvas(NULL)
IupSetAttribute(canvas, "RASTERSIZE", "300x180")
IupSetCallback(canvas, "MAP_CB", Icallback("map_cb"))
IupSetCallback(canvas, "ACTION", Icallback("redraw_cb"))
timer = IupTimer(Icallback("timer_cb"), 500)
dlg = IupDialog(canvas)
IupSetAttribute(dlg, "TITLE", "Wireworld")
IupSetCallback(dlg, "K_ANY", Icallback("esc_close"))
IupShow(dlg)
IupSetAttribute(canvas, "RASTERSIZE", NULL)
IupMainLoop()
IupClose()
end procedure
main()

View file

@ -1,37 +1,36 @@
/*REXX program displays a wire world Cartesian grid of four─state cells. */
/*REXX program displays a wire world Cartesian grid of four─state cells. */
signal on halt /*handle any cell growth interruptus. */
parse arg iFID . '(' generations rows cols bare head tail wire clearScreen reps
if iFID=='' then iFID="WIREWORLD.TXT" /*should default input file be used? */
blank = 'BLANK' /*the "name" for a blank. */
if iFID=='' then iFID= "WIREWORLD.TXT" /*should default input file be used? */
bla = 'BLANK' /*the "name" for a blank. */
generations = p(generations 100 ) /*number generations that are allowed. */
rows = p(rows 3 ) /*the number of cell rows. */
cols = p(cols 3 ) /* " " " " columns. */
bare = pickChar(bare blank ) /*an empty cell character. */
bare = pickChar(bare bla ) /*an empty cell character. */
clearScreen = p(clearScreen 0 ) /*1 means to clear the screen. */
head = pickChar(head 'H' ) /*pick the character for the head. */
tail = pickChar(wire . ) /* " " " " " wire. */
tail = pickChar(tail 't' ) /* " " " " " tail. */
wire = pickChar(wire . ) /* " " " " " wire. */
reps = p(reps 2 ) /*stop program if there are 2 repeats.*/
fents=max(linesize()-1,cols) /*the fence width used after displaying*/
fents=max(cols, linesize() - 1) /*the fence width used after displaying*/
#reps=0; $.=bare /*at start, universe is new and barren.*/
gens=abs(generations) /*use for convenience (and short name).*/
/* [↓] read the input file. */
do r=1 while lines(iFID)\==0 /*keep reading until the End─Of─File. */
q=strip(linein(iFID), 'T') /*get single line from the input file. */
_=length(q) /*obtain the length of this (input) row*/
cols=max(cols, _) /*calculate the maximum number of cols.*/
do c=1 for _; $.r.c=substr(q, c, 1); end /*assign the row cells.*/
q=strip(linein(iFID),'T'); L=length(q) /*get a line from input file; get len.*/
cols=max(cols, L) /*calculate maximum number of columns. */
do c=1 for L; $.r.c=substr(q, c, 1); end /*c*/ /*assign the row cells.*/
end /*r*/
rows=r-1 /*adjust the row number (from DO loop).*/
life=0; !.=0; call showCells /*display initial state of the cells. */
life=0; !.=0; call showCells /*display initial state of the cells. */
/*watch cells evolve, 4 possible states*/
do life=1 for gens; @.=bare /*perform for the number of generations*/
do life=1 for gens; @.=bare /*perform for the number of generations*/
do r=1 for rows /*process each of the rows. */
do c=1 for cols; ?=$.r.c; ??=? /* " " " " columns. */
select /*determine the type of cell. */
when ?==head then ??=tail
when ?==tail then ??=wire
when ?==wire then do; n=hood(); if n==1 | n==2 then ??=head; end
when ?==wire then do; #=hood(); if #==1 | #==2 then ??=head; end
otherwise nop
end /*select*/
@.r.c=??
@ -44,21 +43,20 @@ life=0; !.=0; call showCells /*display initial state of the
/*stop watching the universe (or life).*/
halt: if life-1\==gens then say 'The ~~~Wireworld~~~ program was interrupted.'
done: exit /*stick a fork in it, we are all done.*/
/*───────────────────────────────────────────────────────────────────────────────────────────────────────────────────*/
$: parse arg _row,_col; return $._row._col==head
assign$: do r=1 for rows; do c=1 for cols; $.r.c=@.r.c; end; end; return
hood: return $(r-1,c-1) + $(r-1,c) + $(r-1,c+1) + $(r,c-1) + $(r,c+1) + $(r+1,c-1) + $(r+1,c) + $(r+1,c+1)
p: return word(arg(1), 1) /*pick the 1st word in list.*/
pickChar: _=p(arg(1));L=length(_);if translate(_)==bla then _=' ';if L==3 then _=d2c(_);if L==2 then _=x2c(_);return _
showRows: _=; do r=1 for rows; z=; do c=1 for cols; z=z||$.r.c; end; z=strip(z,'T'); say z; _=_||z; end; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
showCells: if clearScreen then 'CLS' /*◄──change this for the OS.*/
call showRows /*show rows in proper order.*/
say right(copies('',fents)life,fents) /*display a bunch of cells. */
if _=='' then signal done /*No life? Then stop run. */
if !._ then #reps=#reps+1 /*detected repeated pattern.*/
!._=1 /*it is now existence state.*/
say right( copies('', fents)life, fents) /*display a bunch of cells. */
if _=='' then signal done /*No life? Then stop run. */
if !._ then #reps=#reps+1 /*detected repeated pattern.*/
!._=1 /*it's now existence state. */
if reps\==0 & #reps<=reps then return /*so far, so good, no reps. */
say '"Wireworld" repeated itself' reps "times, program is stopping."
signal done /*exit program, we're done. */
/*─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────*/
$: parse arg _row,_col; return ($._row._col==head)
assign$: do r=1 for rows; do c=1 for cols; $.r.c=@.r.c; end; end; return
err: say; say center(' error! ',max(40,linesize()%2),"*"); say; do j=1 for arg(); say arg(j); say; end; say; exit 13
hood: return $(r-1,c-1) + $(r-1,c) + $(r-1,c+1) + $(r,c-1) + $(r,c+1) + $(r+1,c-1) + $(r+1,c) + $(r+1,c+1)
p: return word(arg(1), 1)
pickChar: _=p(arg(1));if translate(_)==blank then _=' ';if length(_)==3 then _=d2c(_);if length(_)==2 then _=x2c(_);return _
showRows: _=; do r=1 for rows; z=; do c=1 for cols; z=z || $.r.c; end; z=strip(z,'T'); say z; _=_ || z; end; return
say '"Wireworld" repeated itself' reps "times, program is stopping."
signal done /*jump to this pgm's "exit".*/