Skip to content

Instantly share code, notes, and snippets.

@paniq
Created April 29, 2020 17:07
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 paniq/e53513800a53deaaaf8ec50607b0939c to your computer and use it in GitHub Desktop.
Save paniq/e53513800a53deaaaf8ec50607b0939c to your computer and use it in GitHub Desktop.
using import itertools
using import Set
let TILEX = 4
let TILEY = 3
let NUMTILES = (TILEX * TILEY)
let TILEBITS = 4
let TILEBITMASK = 0xf:u64
fn tiledata (i)
# NEWS flipx flipy
switch i
case 0 (_ " " 0b0000 0 0)
case 1 (_ "┐" 0b0011 2 6)
case 2 (_ "┌" 0b0101 1 8)
case 3 (_ "─" 0b0110 3 3)
case 4 (_ "┬" 0b0111 4 10)
case 5 (_ "│" 0b1001 5 5)
case 6 (_ "┘" 0b1010 8 1)
case 7 (_ "┤" 0b1011 9 7)
case 8 (_ "└" 0b1100 6 2)
case 9 (_ "├" 0b1101 7 9)
case 10 (_ "┴" 0b1110 10 4)
case 11 (_ "┼" 0b1111 11 11)
default (_ "?" 0b0000 -1 -1)
fn tilechar (i)
let c = (tiledata i)
c
fn tilebits (i)
let c b = (tiledata i)
b
fn tileflipx (i)
let c b fx = (tiledata i)
fx
fn tileflipy (i)
let c b fx fy = (tiledata i)
fy
fn tile@ (T x y)
let x =
(? (x < 0) (x + TILEX) x) % TILEX
let y =
(? (y < 0) (y + TILEY) y) % TILEY
let ofs = ((y * TILEX + x) * TILEBITS)
(T >> ofs) & TILEBITMASK
fn settile (T x y v)
let x =
(? (x < 0) (x + TILEX) x) % TILEX
let y =
(? (y < 0) (y + TILEY) y) % TILEY
let ofs = ((y * TILEX + x) * TILEBITS)
let mask = (~ (TILEBITMASK << ofs))
(T & mask) | (((v as u64) & TILEBITMASK) << ofs)
fn flipx (T)
local R = 0:u64
for x y in (dim TILEX TILEY)
R = (settile R (TILEX - x) y (tileflipx (tile@ T x y)))
R
fn flipy (T)
local R = 0:u64
for x y in (dim TILEX TILEY)
R = (settile R x (TILEY - y) (tileflipy (tile@ T x y)))
R
fn canonical (T)
let TX = (flipx T)
let TY = (flipy T)
let TXY = (flipy TX)
min T TX TY TXY
fn valid? (T)
for x y in (dim TILEX TILEY)
let center = (tilebits (tile@ T x y))
let right = (tilebits (tile@ T (x + 1) y))
let down = (tilebits (tile@ T x (y + 1)))
# center-east must match right-west
if (((center >> 2) & 1) != ((right >> 1) & 1))
return false
# center-south must match down-north
if (((center >> 0) & 1) != ((down >> 3) & 1))
return false
return true
fn patternstr (T)
local s = ""
for x y in (dim TILEX TILEY)
let c = (tile@ T x y)
if ((x == 0) & (y > 0))
s = s .. "\n"
s = s .. (tilechar c)
s = s .. "\n"
s
let numpatterns =
* 11:u64 10 9 8 7 6 5 4 3 2
local valid-count = 0
local patterns : (Set u64)
for v in (permutate-range 11)
let v... = (unpack v)
let pattern =
va-lifold
11:u64
inline (i key value result)
result | (value as u64 << ((i + 1) * TILEBITS))
v...
if (valid? pattern)
let pattern = (canonical pattern)
assert (valid? pattern) # transformation should still be ok
if (not ('in? patterns pattern))
'insert patterns pattern
print (patternstr pattern)
valid-count += 1
print valid-count "patterns valid"
┼─┤┌
├┬┴┘
│└┐
┼─┐└
┤┌┴┬
├┘ │
┼─┐├
└┬┴┤
┌┘ │
┼┴─┬
┤┌┐└
│├┘
┼┘└┬
┤┌─┴
│├┐
┼┬┘┌
┤├─┴
│└┐
┼┘ └
┤┌┬─
│├┴┐
┼┤ ┌
┘├┬┴
┐│└─
┼─┴┬
├┐┌┘
│└┤
┼─┴┬
┤┌┐└
├┘│
┼┤└┬
├┴─┘
│┌┐
┼┐├┬
┴┘│└
┌─┤
┼┘├┬
┴─┤└
┌┐│
┼┬┤┌
│└┴┘
├─┐
14 patterns valid
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment