Last active
October 14, 2024 13:03
-
-
Save jul/c164cf6e3e6cb2376afeb17aa822f9c1 to your computer and use it in GitHub Desktop.
evaluating if an hexagonal patterned game of life can be used as a PRNG (spoiler : NO)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from time import time, sleep | |
import select | |
from subprocess import Popen, PIPE | |
from random import randint | |
import random | |
from os import system | |
import os | |
ORD=0 | |
SZ=12 | |
DIMX=64 | |
DIMY=64 | |
SSP=50 | |
old_alivep=set() | |
new_alivep=set() | |
old_alive=set() | |
new_alive=set() | |
dead_alive_percent=50 | |
pause=False | |
print_board=True | |
set_alive={ 3, 4, 5} | |
set_dead={ 3, 4, 5} | |
old_old_samplep=0 | |
old_samplep=0 | |
samplep = 0 | |
old_old_sample=0 | |
old_sample=0 | |
sample = 0 | |
sample_mask=set([]) | |
plt_pause = False | |
system("rm *ps output2.mp4 ev*.jpg") | |
seed=int(time()) | |
print("seed %d" % seed) | |
random.seed(seed) | |
save_canvas = True | |
ORD=1 | |
# let's talk to tk/tcl directly | |
p = Popen(['wish'], stdin=PIPE, stdout=PIPE, stderr=PIPE) | |
os.set_blocking(p.stdout.fileno(), False) | |
os.set_blocking(p.stdin.fileno(), False) | |
os.set_blocking(p.stderr.fileno(), False) | |
n=0 | |
def puts(s): | |
global n | |
n+=1 | |
for l in s.split("\n"): | |
select.select([], [p.stdin],[]) | |
p.stdin.write((l + "\n").encode()) | |
if back := p.stderr.read(): | |
print("TCL>" + back.decode()) | |
def gets(): | |
ret=p.stdout.read() | |
if ret: | |
print(ret) | |
exec(ret, globals(), ) | |
puts(f""" | |
package require Tk | |
set code [ catch {{ | |
source /usr/share/tcltk/ttkthemes/themes/plastik/plastik.tcl | |
ttk::style theme use plastik | |
}} pass ] | |
set status 0 | |
proc SaveAsC {{}} {{ | |
set out [tk_getSaveFile] | |
set code [ catch {{.c postscript -file $out }} result ] | |
if {{$result != ""}} {{ | |
error $result | |
}} | |
}} | |
proc SaveAsC2 {{}} {{ | |
set out [tk_getSaveFile] | |
set code [ catch {{.c2 postscript -file $out }} result ] | |
if {{$result != ""}} {{ | |
error $result | |
}} | |
}} | |
proc SaveAsC3 {{}} {{ | |
set out [tk_getSaveFile] | |
set code [ catch {{.c3 postscript -file $out }} result ] | |
if {{$result != ""}} {{ | |
error $result | |
}} | |
}} | |
proc SaveAsC4 {{}} {{ | |
set out [tk_getSaveFile] | |
set code [ catch {{.c4 postscript -file $out }} result ] | |
if {{$result != ""}} {{ | |
error $result | |
}} | |
}} | |
if {{$code}} {{ | |
puts "print('theme not found, fallback to ugly tcl/tk look')" | |
puts "print('on debian : apt install tcl-ttkthemes to have ttkthemes installed')" | |
}} | |
pack [ ttk::frame .t ] | |
pack [ ttk::frame .tt1 ] -in .t -anchor s -side left | |
pack [ ttk::frame .tt2 ] -in .t -anchor s -side left | |
pack [ ttk::frame .tt3 ] -in .t -anchor s -side left | |
pack [ ttk::label .ll2 -text "board of the game of life" ] -in .tt1 | |
pack [ canvas .c -width {DIMX*SZ*1.01} -height { DIMY*SZ*.87 } -bg white ] -in .tt1 -anchor s | |
pack [ttk::button .bc -text "Save as postscript" -command SaveAsC ] -in .tt1 -anchor s | |
pack [ ttk::label .ll1 -text "x,y = u(n-1),u(n) aka Takens Serie " ] -in .tt2 -anchor s | |
pack [ canvas .c2 -width {DIMX*SZ*1.01//2} -height { DIMY*SZ*.87//2 } -bg white ] -in .tt2 -anchor s | |
.c configure -bg white | |
pack [ttk::button .bc2 -text "Save as postscript" -command SaveAsC2 ] -in .tt2 -anchor s | |
pack [ ttk::label .ll3 -text "Takens Serie for perturbed serie" ] -in .tt2 -anchor s | |
pack [ canvas .c3 -width {DIMX*SZ//2*1.01} -height { DIMY*SZ*.87//2 } -bg white ] -in .tt2 -anchor s | |
pack [ttk::button .bc3 -text "Save as postscript" -command SaveAsC3 ] -in .tt2 -anchor s | |
pack [ ttk::label .ll4 -text "Takens Serie for random" ] -in .tt3 -anchor s | |
pack [ canvas .c4 -width {DIMX*SZ//2*1.01} -height { DIMY*SZ*.87//2 } -bg white ] -in .tt3 -anchor s | |
pack [ttk::button .bc4 -text "Save as postscript" -command SaveAsC4 ] -in .tt3 -anchor s | |
pack [ ttk::frame .first ] -expand true -fill both -anchor s | |
pack [ ttk::label .s -textvariable status ] -anchor s -in .first | |
pack [ ttk::frame .f ] -anchor s -expand true -fill both | |
pack [ ttk::frame .center ] -anchor s -in .f | |
ttk::button .r -text Reset -command {{ puts seed() }} | |
ttk::button .b -text Pause -command {{ puts pause^=True }} | |
ttk::button .quit -text Quit -command {{ destroy . }} | |
pack .r .b .quit -in .center -anchor se -side left | |
pack [ ttk::labelframe .rules -text "rules change" ] -in .f -expand true -fill both -padx 5 -pady 5 | |
pack [ ttk::frame .g ] -anchor s -expand true -fill both -in .rules -padx 5 | |
pack [ ttk::checkbutton .v1 -text 1 -command {{ puts "seed();set_alive^=set({1,})" }}] -in .g -anchor w -side left | |
pack [ ttk::label .s1 -text " " ] -in .g -anchor w -side left | |
pack [ ttk::checkbutton .v2 -text 2 -command {{ puts "seed();set_alive^=set({2,})" }}] -in .g -anchor w -side left | |
pack [ ttk::label .s2 -text " " ] -in .g -anchor w -side left | |
pack [ ttk::checkbutton .v3 -text 3 -onvalue 1 -variable a -command {{ puts "seed();set_alive^=set({3,})" }}] -in .g -anchor w -side left | |
set a 1 | |
set b 1 | |
set c 1 | |
set d 1 | |
set e 1 | |
set f 1 | |
pack [ ttk::label .s3 -text " " ] -in .g -anchor w -side left | |
pack [ ttk::checkbutton .v4 -text 4 -onvalue 1 -variable b -command {{ puts "seed();set_alive^=set({4,})" }}] -in .g -anchor w -side left | |
pack [ ttk::label .s4 -text " " ] -in .g -anchor w -side left | |
pack [ ttk::checkbutton .v5 -text 5 -onvalue 1 -variable c -command {{ puts "seed();set_alive^=set({5,})" }}] -in .g -anchor w -side left | |
pack [ ttk::label .s5 -text " " ] -in .g -anchor w -side left | |
pack [ ttk::checkbutton .v6 -text 6 -command {{ puts "seed();set_alive^=set({6,})" }}] -in .g -anchor w -side left | |
pack [ ttk::label .s6 -text " " ] -in .g -anchor w -side left | |
pack [ ttk::label .v -text "neighbour alive to give life" ] -in .g -anchor w -side left | |
pack [ ttk::frame .h ] -anchor s -expand true -fill both -in .rules -padx 5 | |
pack [ ttk::checkbutton .d1 -text 1 -command {{ puts "seed();set_dead^=set({1,})" }}] -in .h -anchor w -side left | |
pack [ ttk::label .t1 -text " " ] -in .h -anchor w -side left | |
pack [ ttk::checkbutton .d2 -text 2 -command {{ puts "seed();set_dead^=set({2,})" }}] -in .h -anchor w -side left | |
pack [ ttk::label .t2 -text " " ] -in .h -anchor w -side left | |
pack [ ttk::checkbutton .d3 -text 3 -onvalue 1 -variable d -command {{ puts "seed();set_dead^=set({3,})" }}] -in .h -anchor w -side left | |
pack [ ttk::label .t3 -text " " ] -in .h -anchor w -side left | |
pack [ ttk::checkbutton .d4 -text 4 -onvalue 1 -variable e -command {{ puts "seed();set_dead^=set({4,})" }}] -in .h -anchor w -side left | |
pack [ ttk::label .t4 -text " " ] -in .h -anchor w -side left | |
pack [ ttk::checkbutton .d5 -text 5 -onvalue 1 -variable f -command {{ puts "seed();set_dead^=set({5,})" }}] -in .h -anchor w -side left | |
pack [ ttk::label .t5 -text " " ] -in .h -anchor w -side left | |
pack [ ttk::checkbutton .d6 -text 6 -command {{ puts "seed();set_dead^=set({6,})" }}] -in .h -anchor w -side left | |
pack [ ttk::label .t6 -text " " ] -in .h -anchor w -side left | |
pack [ ttk::label .d -text "neighbour dead to give life" ] -in .h -anchor w -side left | |
pack [ ttk::frame .l ] -expand true -fill both -in .rules -padx 5 -pady 5 | |
set seed 50 | |
pack [ ttk::spinbox .sc -width 4 -from 0 -to 100 -textvariable seed -command {{ | |
puts "dead_alive_percent=$seed;seed()" | |
}} | |
] -in .l -anchor w -side left | |
pack [ ttk::label .scl -text " re seed session with a different percentage of dead/alive ratio" ] -in .l -anchor w -side left | |
pack [ ttk::frame .k ] -expand true -fill both | |
pack [ ttk::checkbutton .tb -text "disable printing of board" -command "puts {{print_board^=True}}" ] -in .k -anchor w -side left -padx 5 -pady 5 | |
#.tb invoke | |
pack [ ttk::frame .kk ] -expand true -fill both | |
pack [ ttk::checkbutton .tcv -text "disable saving of canvas" -command "puts {{save_canvas^=True}}" ] -in .kk -anchor w -side left -padx 5 -pady 5 | |
.tcv invoke | |
""") | |
def save(name="save"): | |
global ORD, save_canvas | |
ORD+=1 | |
puts(f"set status {ORD}") | |
puts(f""".c postscript -file {name}-{"%04d"% ORD}.ps""") | |
puts(f""".c2 postscript -file t{name}-{"%04d"% ORD}.ps""") | |
def cell(x,y, **kw): | |
hs=0.866 # heigth of an equilateral triangle | |
px,py=x/2-1/2*(y%2),y-2/3 | |
#px,py=x-(y%2),y-2/3 | |
xr,yr=px*SZ+SZ,py*hs*SZ+SZ | |
# triangle compliqué à dessiner | |
r=SZ/2 | |
#from pdb import set_trace; set_trace() | |
puts(f""" | |
.c create oval {xr-r} {yr-r} {xr+r} {yr+r} -width 0 -outline "" {["","-fill black "][kw.get("state","dead")=="alive"]} -tags [ list "p:{x//2},{y}" ]\n""") | |
def get_neighbour(x,y): | |
ye = [(-1, -1), (1, 0), (0, -1), (-1, 1), (-1,0), (0, 1)] | |
yo= [(1, 1), (-1, 0), (0, -1), (1, 0), (0, 1), (1, -1) ] | |
return set( ((dxdy[0]+x)%DIMX,(y+dxdy[1])%DIMY) for dxdy in [yo,ye][y%2]) | |
def clear(): | |
global ORD | |
ORD=0 | |
system("rm *ps output2.mp4 ev*.jpg") | |
puts(".c delete all") | |
puts(".c2 delete all") | |
puts(".c3 delete all") | |
puts(".c4 delete all") | |
pick_sample() | |
def pick_entropy(board, _from, _to,w=0): | |
entropy=0 | |
for o,i in enumerate(range(_from, _from+_to*2,2)): | |
if (w,i) in board: | |
entropy |= 1<<o | |
return entropy | |
def flipbit(board,w): | |
for i in range(0,10): | |
board ^= {(pick_entropy(board,i*6,6,w), pick_entropy(board,(i+1)*6,6,w))} | |
def seed(): | |
global old_alive, dead_alive_percent, old_alivep | |
clear() | |
for x in range(0,DIMX*2,2): | |
for y in range(DIMY): | |
state = randint(0, 100) >= dead_alive_percent and "alive" or "dead" | |
if state=="alive": | |
old_alive|= {(x/2,y),} | |
cell( | |
x, | |
y, | |
state=state, | |
outline="black") | |
old_alivep = old_alive.copy() | |
for i in range(64): | |
flipbit(old_alivep,i) | |
def live_neighbour(x,y,board): | |
return sum(map(lambda x : x in board,get_neighbour(x,y))) | |
def pick_sample(): | |
global sample_mask | |
sample_mask=set([]) | |
for i in range(SSP): | |
x, y=(randint(0, DIMX),randint(0, DIMY)) | |
sample_mask |= set([( x, y, )]) | |
def plot_sample(): | |
global old_sample, old_old_sample, old_old_samplep, sample_mask, new_alive, ORD, SZ, sample, sample_array, plt_pause, samplep, old_samplep, new_alivep, old_alivep | |
old_old_sample=old_sample | |
old_sample = sample | |
sample = 0 | |
old_old_samplep=old_samplep | |
old_samplep = samplep | |
samplep = 0 | |
for i, coord in enumerate(sample_mask): | |
if coord in new_alive: | |
sample |= 1<<i | |
if coord in new_alivep: | |
samplep |= 1<<i | |
_max = ((1<<(len(sample_mask)))) | |
r=_max//512 | |
if ORD > 1: | |
_max = ((1<<(len(sample_mask))) // SZ*2) | |
cr=.8 | |
x = old_sample | |
y = sample | |
puts(f""".c2 create oval {(x -r)*DIMX*cr//_max} {(y -r )*DIMY*cr//_max} {(x+r)*DIMX*cr//_max} {(y+r)*DIMY*cr//_max}""") | |
x = old_samplep | |
y = samplep | |
puts(f""".c3 create oval {(x -r)*DIMX*cr//_max} {(y -r )*DIMY*cr//_max} {(x+r)*DIMX*cr//_max} {(y+r)*DIMY*cr//_max} """) | |
random.seed(ORD) | |
x=randint(0,_max*6) | |
y=randint(0,_max*6) | |
random.seed(time()) | |
puts(f""".c4 create oval {(x -r)*DIMX*cr//_max} {(y -r )*DIMY*cr//_max} {(x+r)*DIMX*cr//_max} {(y+r)*DIMY*cr//_max} """) | |
def will_live(x,y, old_board, new_board): | |
global set_dead, set_alive | |
ostate = (x,y) not in old_board and 'dead' or "alive" | |
lively = live_neighbour(x,y, old_board) | |
#print("%d-%d:%s:%d" % (x,y,ostate,lively)) | |
state = ( ostate == "alive" and lively in set_alive ) or ( | |
ostate == "dead" and lively in set_dead ) | |
if(state): | |
new_board |= {(x,y),} | |
return state | |
seed() | |
save("ev") | |
while True: | |
gets() | |
sleep(0.0001) | |
while pause: | |
sleep(.1) | |
gets() | |
for x in range(DIMX): | |
for y in range(DIMY): | |
will_live(x,y, old_alivep, new_alivep) | |
will_live(x,y, old_alive, new_alive) | |
print_board and puts(f""".c itemconfigure "p:{x},{y}" -fill {["white","lightgray", "darkgray", "black"][((x,y) in new_alive) + 2* ((x,y) in new_alivep)]}""") | |
flipbit(new_alivep,0) | |
flipbit(new_alivep,1) | |
plot_sample() | |
puts("update") | |
old_alive=new_alive | |
old_alivep=new_alivep | |
new_alive=set() | |
new_alivep=set() | |
save("ev") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment