Skip to content

Instantly share code, notes, and snippets.

@williame
Created September 15, 2014 12:29
Show Gist options
  • Save williame/263bf661f0d0ba173c44 to your computer and use it in GitHub Desktop.
Save williame/263bf661f0d0ba173c44 to your computer and use it in GitHub Desktop.
versions = [version.strip() for version in (
"""
def t(b):
L=len;w,n=L(b[0])+3,-1;b=list("@"*w+"@@".join(b)+"@"*w);w+=n;I=b.index
for i in range(L(b)):
c=b[i];d={"^":-w,"<":n,">":1,"v":w}.get(c)
if d:
while c!='@':
i+=d;c=b[i]
if c=='*':b[i]='.'
elif c in "123456789":i+=I(c)-i or I(c,i+1)-i
elif c in '/\\':d={-w:n,w:1,1:w,n:-w}[d]*(-1 if c=='/' else 1)
return "*" not in b
""",
"""
def t(b):
L=len;w=L(b[0])+3;b=list("@"*w+"@@".join(b)+"@"*w);w-=1;I=b.index
for i in range(L(b)):
c=b[i];d={"^":-w,"<":-1,">":1,"v":w}.get(c)
if d:
while c!='@':
i+=d;c=b[i]
if c=='*':b[i]='.'
elif c in "123456789":i+=I(c)-i or I(c,i+1)-i
elif c in '/\\':d={-w:-1,w:1,1:w,-1:-w}[d]*(-1 if c=='/' else 1)
return "*" not in b
""",
"""
def t(b):
L=len;w=L(b[0])+3;b=list("@"*w+"@@".join(b)+"@"*w);w-=1;I=b.index
for i in range(L(b)):
c=b[i];d={"^":-w,"<":-1,">":1,"v":w}.get(c)
if d:
while c!='@':
i+=d;c=b[i]
if c=='*':b[i]='.'
elif c in '/\\':d={-w:-1,w:1,1:w,-1:-w}[d]*(-1 if c=='/' else 1)
elif c>'0':i+=I(c)-i or I(c,i+1)-i
return "*" not in b
""",
"""
def t(b):
w=len(b[0])+2;B=list('@'*w+'@@'.join(b)+'@'*w);l=len(B);C="<>v^";D=[-1,1,w,-w];i=0
while i<l:
d=C.find(B[i])
if-1<d:
j=i;n=l*4
while('@'!=B[j])*n:
c=B[j]
if'+'>c:B[j]=''
if'/'==c:d=(d+2)%4
if'\\'==c:d=3-d
if c.isdigit():j=(B*2).index(c,j+1)%l
j+=D[d];n-=1
i+=1
return'*'not in B
""",
"""
def t(b):
w=len(b[0])+2;B=list('@'*w+'@@'.join(b)+'@'*w);l=len(B);i=0
while i<l:
d="<>v^".find(B[i])
if-1<d:
j=i;n=l*4
while(B[j]!='@')*n:
c=B[j]
if'+'>c:B[j]=''
if'/'==c:d=(d+2)%4
if'\\'==c:d=3-d
if c.isdigit():j=(B*2).index(c,j+1)%l
j+=[-1,1,w,-w][d];n-=1
i+=1
return'*'not in B
""",
"""
def t(b):
w=len(b[0])+2;B=list('@'*w+'@@'.join(b)+'@'*w);l=len(B);i=0
while i<l:
d="<>v^".find(B[i])
if-1<d:
j=i;c='.'
while c not in"@<>v^":
if'+'>c:B[j]=''
if'/'==c:d^=2
if'\\'==c:d^=3
elif'0'<c:j=(B*2).index(c,j+1)%l
j+=[-1,1,w,-w][d];c=B[j]
i+=1
return'*'not in B
""",
"""
def t(b):
w=len(b[0])+2;B=list('@'*w+'@@'.join(b)+'@'*w);l=len(B);i=0
while i<l:
d="<>v^".find(B[i]);j=i;c='.'
while c not in"@<>v^":
if'+'>c:B[j]=''
if'/'==c:d^=2
if'\\'==c:d^=3
elif'0'<c:j=(B*2).index(c,j+1)%l
j+=[-1,1,w,-w,-i][d];c=B[j]
i+=1
return'*'not in B
""",
"""
def t(b):
w=len(b[0])+1;B=list('@'*w+'@'.join(b)+'@'*w);l=len(B);i=0
while i<l:
d="<>v^".find(B[i]);j=i;c='.'
while c not in"@<>v^":
if'+'>c:B[j]=''
if'/'==c:d^=2
if'\\'==c:d^=3
elif'0'<c:j=(B*2).index(c,j+1)%l
j+=[-1,1,w,-w,-j][d];c=B[j]
i+=1
return'*'not in B
""",
"""
def t(b):
w=len(b[0])+1;B=list('@'*w+'@'.join(b));i=l=len(B);C="<>^v@"
while i:
j=l-i;i-=1;d=C.find(B[j]);c='.'
while c not in C:
if'+'>c:B[j]='.'
if'0'<c<C:j=(B*2).index(c,j+1)%l
elif'.'<c:d^=2+(c<C)
j-=[1,-1,w,-w,j][d];c=B[j%l]
return'*'not in B
""",
"""
def t(b):
w=len(b[0])+1;B=list('@'*w+'@'.join(b));i=l=len(B);C="<>^v@"
while i:
i-=1;d,j,c=C.find(B[i]),i,'.'
while(c in C)-1:
if'+'>c:B[j]='.'
if'0'<c<C:j=(B*2).index(c,j+1)%l
elif'.'<c:d^=2+(c<C)
j-=[1,-1,w,-w,j][d];c=B[j%l]
return('*'in B)-1
""")]
width = max(len(line) for version in versions for line in version.split("\n"))
height = max(len(version.split("\n")) for version in versions)
import difflib
from PIL import Image, ImageFont, ImageDraw, ImageChops, GifImagePlugin
font = ImageFont.truetype("/Library/Fonts/Courier New.ttf", 15)
em, lineheight = 9, 14
anim_frames = 1
def render(text, ofs, diff, diff_ch, frames):
for frame in range(anim_frames if ofs is not None else 1):
image = Image.new("RGB", (width * em + int(em * 1.5), height * lineheight + int(lineheight/2)), "white")
frames.append(image)
draw = ImageDraw.Draw(image)
x, y = 0, 0
for i, ch in enumerate(text):
if ch == '\n':
x = 0
y += lineheight
else:
if i == ofs:
draw.rectangle((x, y, x + em, y + lineheight),
fill='red' if diff=='+' else 'blue')
scale = 1.0 / 3 * frame
if diff == '-':
scale = 1.0 - scale
draw.text((x, y), ch, font=font,
fill='yellow')
draw.rectangle((x + em, y, x + em + em, y + lineheight),
fill='white')
x += int(round(float(em) * scale))
draw.text((x, y), ch, font=font, fill=0)
x += em
del draw
frames = []
render(versions[0], None, None, None, frames)
prev = versions[0]
for i in range(3, len(versions)):
curr = versions[i]
print "==== %d (%d %d) ====" % (i, len(curr), len(prev)-len(curr))
adjust = 0
for ofs, diff in enumerate(difflib.ndiff(prev, curr)):
diff, ch = diff[0], diff[-1]
if diff in "+-":
render(prev, ofs-adjust, diff, ch, frames)
if diff == "+":
prev = prev[:ofs-adjust] + ch + prev[ofs-adjust:]
else:
assert prev[ofs-adjust] == ch, (ofs, prev[:ofs+1], ch)
prev = prev[:ofs-adjust] + prev[ofs-adjust+1:]
adjust += 1
assert prev == curr
render(versions[-1], None, None, None, frames)
with open("anim.gif", "wb") as f:
prev = None
for frame in frames:
frame = frame.convert('P', palette=Image.WEB)
if not prev:
for s in GifImagePlugin.getheader(frame)[0]:
f.write(s)
prev = frame.copy()
frame = GifImagePlugin.getdata(frame)
else:
delta = ImageChops.subtract_modulo(frame, prev)
prev = frame.copy()
bbox = delta.getbbox()
if bbox:
frame = GifImagePlugin.getdata(frame.crop(bbox), offset = bbox[:2])
else:
continue
for s in frame:
f.write(s)
f.write(";")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment