Skip to content

Instantly share code, notes, and snippets.

@int-e
Last active January 24, 2024 09:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save int-e/c1b40dbed8a39a20dfc1d94fc25226b2 to your computer and use it in GitHub Desktop.
Save int-e/c1b40dbed8a39a20dfc1d94fc25226b2 to your computer and use it in GitHub Desktop.
bitgrid playground
import System.Random
import Control.Monad
import Data.List
z = False
cell ' ' = \(a, b, c, d) -> (a, b, c, d)
cell '↓' = \(a, b, _, _) -> (a, b, a, b)
cell '↑' = \(_, _, c, d) -> (c, d, c, d)
cell '→' = \(a, _, c, _) -> (a, a, c, c)
cell '←' = \(_, b, _, d) -> (b, b, d, d)
cell '⇀' = \(a, _, c, d) -> (a, a, c, d)
cell '↼' = \(_, b, c, d) -> (b, b, c, d)
cell '⇁' = \(a, b, c, _) -> (a, b, c, c)
cell '↽' = \(a, b, _, d) -> (a, b, d, d)
cell '⇃' = \(a, b, _, d) -> (a, b, a, d)
cell '⇂' = \(a, b, c, _) -> (a, b, c, b)
cell '↿' = \(_, b, c, d) -> (c, b, c, d)
cell '↾' = \(a, _, c, d) -> (a, d, c, d)
cell 'X' = \(a, b, c, d) -> (d, c, b, a)
cell '↘' = \(a, b, c, _) -> (a, b, c, a)
cell '↙' = \(a, b, _, d) -> (a, b, b, d)
cell '↗' = \(a, _, c, d) -> (a, c, c, d)
cell '↖' = \(_, b, c, d) -> (d, b, c, d)
cell '↺' = \(a, b, c, d) -> (b, d, a, c)
cell '↻' = \(a, b, c, d) -> (c, a, d, b)
cell 'Z' = \(a, b, c, d) -> (d, a, b, c)
cell 'S' = \(a, b, c, d) -> (b, c, d, a)
cell 'N' = \(a, b, c, d) -> (c, d, b, a)
cell 'И' = \(a, b, c, d) -> (d, c, a, b)
cell '=' = \(a, _, c, _) -> (z, a && c, z, a || c)
cell '&' = \(a, _, c, _) -> (z, a && c, z, a && c)
cell '|' = \(a, _, c, _) -> (z, a || c, z, a || c)
cell '*' = \(a, _, c, _) -> (z, not a && c, z, not a && c)
cell 'z' = \(a, _, c, _) -> (z, False, z, False)
cell 'o' = \(a, _, c, _) -> (z, True, z, True)
cell '>' = \(_, b, _, d) -> (d, b, d, d)
display = putStrLn . unlines . map (("|"++).(++"|").map (\b -> if b then 'X' else ' '))
display' (a, b) = do print a; display b
main = main3
-- run a pulsar
main4 = do
p <- map (map cell) . lines <$> readFile "cell"
let (h, w) = (length p, length (head p))
let f xs = xs ++ concat (replicate 16 (tail xs))
p' = f (map f p)
cell x = replicate 15 (replicate 30 False) ++
[replicate 26 False ++ [x] ++ replicate 3 False] ++
[replicate 26 False ++ [x] ++ replicate 3 False] ++
replicate 9 (replicate 30 False)
pp = [(4,2),(5,2),(6,2),(7,4),(7,5),(7,6)]
check (x,y) = (x,y) `elem` pp || (16-x,y) `elem` pp || (x,16-y) `elem` pp || (16-x,16-y) `elem` pp
cells = [[cell (check (x,y) || check (y,x)) | x <- [0..16]] | y <- [0..16]]
i = concat (map (transpose . concat . map transpose) cells)
mapM_ display (map head . iterate (drop 64) $ evolve p' i)
-- run a blinker
main3 = do
p <- map (map cell) . lines <$> readFile "cell"
let (h, w) = (length p, length (head p))
let f xs = xs ++ concat (replicate 4 (tail xs))
p' = f (map f p)
cell x = replicate 15 (replicate 30 False) ++
[replicate 26 False ++ [x] ++ replicate 3 False] ++
[replicate 26 False ++ [x] ++ replicate 3 False] ++
replicate 9 (replicate 30 False)
cells = [[cell ((x,y) `elem` [(1,2),(2,2),(3,2)]) | x <- [0..4]] | y <- [0..4]]
i = concat (map (transpose . concat . map transpose) cells)
mapM_ display (map head . iterate (drop 64) $ evolve p' i)
main2 = do
p <- map (map cell) . lines <$> readFile "cell"
let (h, w) = (length p, length (head p))
b = replicate (w+1) True
m = [True] ++ replicate (w-1) False ++ [True]
i = [b] ++ replicate (h-1) m ++ [b]
display $ evolve p i !! 22
let i = [m] ++ replicate (h-1) (replicate (w+1) False) ++ [False : tail m]
mapM_ display' $ zip [0..] $ evolve p i
main' = do
p <- map (map cell) . lines <$> readFile "eval"
let (h, w) = (length p, length (head p))
i <- replicateM (h + 1) $ replicateM (w + 1) $ randomRIO (False, True)
mapM_ display $ take 16 $ evolve p i
putStrLn "...verifying eval function"
mapM_ (check_eval p) (replicateM 9 [False,True])
evolve p i = i : i' : evolve p i''
where
i' = step p i
p' = tail (map tail p)
i'' = head i' : zipWith ((:) . head) (tail i') (step p' (map tail (tail i')))
step (p:ps) (x:y:xs) = step' p x y ++ step (drop 1 ps) xs
step _ xs = xs
step' (p:ps) (a:b:xs) (c:d:ys)
| (a, b, c, d) <- p (a, b, c, d)
= zipWith (++) [[a, b], [c, d]] (step' (drop 1 ps) xs ys)
step' _ xs ys = [xs, ys]
check_eval p c
| i <- zipWith (:) c (replicate 9 (replicate 12 False))
, i <- [replicate 13 False] ++ i ++ [replicate 13 False]
, i <- evolve p i !! 12
, r <- i !! 5 !! 12
= when (r /= r' (reverse c)) $ do print c; display i
where
r' (c:xs) = case length (filter id xs) of
2 -> c
3 -> True
_ -> False
#! /usr/bin/env python3
import PIL.Image
import os
gates = {
' ': lambda a, b, c, d: (a, b, c, d),
'↓': lambda a, b, c, d: (a, b, a, b),
'↑': lambda a, b, c, d: (c, d, c, d),
'→': lambda a, b, c, d: (a, a, c, c),
'←': lambda a, b, c, d: (b, b, d, d),
'⇀': lambda a, b, c, d: (a, a, c, d),
'↼': lambda a, b, c, d: (b, b, c, d),
'⇁': lambda a, b, c, d: (a, b, c, c),
'↽': lambda a, b, c, d: (a, b, d, d),
'⇃': lambda a, b, c, d: (a, b, a, d),
'⇂': lambda a, b, c, d: (a, b, c, b),
'↿': lambda a, b, c, d: (c, b, c, d),
'↾': lambda a, b, c, d: (a, d, c, d),
'X': lambda a, b, c, d: (d, c, b, a),
'↘': lambda a, b, c, d: (a, b, c, a),
'↙': lambda a, b, c, d: (a, b, b, d),
'↗': lambda a, b, c, d: (a, c, c, d),
'↖': lambda a, b, c, d: (d, b, c, d),
'↺': lambda a, b, c, d: (b, d, a, c),
'↻': lambda a, b, c, d: (c, a, d, b),
'Z': lambda a, b, c, d: (d, a, b, c),
'S': lambda a, b, c, d: (b, c, d, a),
'N': lambda a, b, c, d: (c, d, b, a),
'И': lambda a, b, c, d: (d, c, a, b),
'=': lambda a, b, c, d: (a, a and c, c, a or c),
'&': lambda a, b, c, d: (a, a and c, c, a and c),
'|': lambda a, b, c, d: (a, a or c, c, a or c),
'*': lambda a, b, c, d: (a, not a and c, c, not a and c),
'z': lambda a, b, c, d: (a, False, c, False),
'o': lambda a, b, c, d: (a, True, c, True),
'>': lambda a, b, c, d: (d, b, d, d)
}
def load(file):
global gates
return [[gates[c] for c in l] for l in open(file,"r").read().splitlines()]
cell = load("cell")
h = len(cell) - 1
w = len(cell[0]) - 1
g = 0
world = [[False for _ in range(w*5+2)] for _ in range(h*5+2)]
def step():
global cell, h, w, g, world
for y in range(g % 2, len(world)-1, 2):
for x in range(g % 2, len(world[y])-1, 2):
(a, b) = (world[y][x], world[y][x+1])
(c, d) = (world[y+1][x], world[y+1][x+1])
(a, b, c, d) = cell[y % h][x % w](a, b, c, d)
(world[y][x], world[y][x+1]) = (a, b)
(world[y+1][x], world[y+1][x+1]) = (c, d)
g = g+1
# hack: blinker initial state
for (x, y) in [(1,2),(2,2),(3,2)]:
world[15 + y*h][26 + x*w] = True
world[16 + y*h][26 + x*w] = True
# one warmup cycle
while g < 64:
step()
frames = []
# animation: 2 cycles for the blinker
while g < 64 + 128:
frame = PIL.Image.new("L", (3*len(world[0]), 3*len(world)), 0)
for y in range(len(world)):
for x in range(len(world[0])):
if world[y][x]:
for yy in range(3*y, 3*y+3):
for xx in range(3*x, 3*x+3):
frame.putpixel((xx, yy), 1)
for y in range(len(world)):
for x in range(0, len(world[0]), w):
frame.putpixel((x*3+1, y*3+1), 2)
frame.putpixel((x*3+4, y*3+1), 2)
for y in range(0, len(world), h):
for x in range(len(world[0])):
frame.putpixel((x*3+1, y*3+1), 2)
frame.putpixel((x*3+1, y*3+4), 2)
frames.append(frame)
step()
frames[0].save(
"bitgrid_blinker.gif",
format = "GIF",
append_images=frames[1:],
palette = bytearray.fromhex('FFFFFF 000000 4466AA'),
save_all = True,
duration = 4,
loop = 0)
os.system("gifsicle --batch -O3 bitgrid_blinker.gif")
X ↾ ⇂ ↼ ↼ ↼ ↼ X
X ↺ ↽ ↽ S ↻ ↽ ↽ ↺ X
↺ ↼ N ↖ S ↺ ↙ ↼ ↼ ↺
Z ↖ S ⇃ ↙ ↺
↘ ↖ ↻ ⇂ ↙ Z
↘ ↼ ↖ ⇃ ↙ ⇁ Z
↘ X ↙ ↗ ↘ ↗
↘ ↙ ↖ ↙ ↾ ↻
↘ ↙ X ↽ ↽ ↿ S
↻ ⇁ ↘ ⇂ ↙ ↼ ↼ Z N ↻ N
⇀ N ↘ ↘ ↘ ⇂ ⇁ ⇁ ↖ Z ⇀ ⇀ ⇀
↘ ↘ ↘ = = = ↖ ↘ ⇁
↘ ↘ → = = = ↖ ↺ Z
↘ ⇁ ⇁ → = = = = ↖ Z
⇀ ⇀ → → = = = = ⇁ ↻ ↺
↗ → = = = = → * ↽ ↻
↽ ↽ ↽ ↗ ↗ → = = = = | X ↼ ↽
↼ ↼ ↖ ↗ ↗ ↗ = = = = & ↙ ⇃ ↙
↖ ↗ ↻ ↾ ↾ ⇀ ⇀ ⇀ ↾ ↙ ⇂ ↙
X ↺ ↖ ↖ ↽ ↽ ↽ ← ↺ X
↗ > ↗ ↖ ← ← ← ← ← ↼ ⇃
↗ ↙ X ↼ ↼ ↼ ↼ ↼ ↖ ↙
↗ ↙ ↾ ↖ X
N ↙ ↿ ↖ ↽ ↽ ↽ ↽ ↽ ↽ ↙ ↖
↻ ↙ ↾ ↼ ↼ ↼ ↼ ↼ ↼ ↺ ↻ Z
X ↼ ↿ ↽ ↽ ↺ ↺ S ↺ ⇀ X
X ↾ ⇂ ↼ ↼ ↼ ↼ X
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment