Skip to content

Instantly share code, notes, and snippets.

@adrian17
Last active August 29, 2015 14:22
Show Gist options
  • Save adrian17/4a25ebd482f32330c187 to your computer and use it in GitHub Desktop.
Save adrian17/4a25ebd482f32330c187 to your computer and use it in GitHub Desktop.
TeXSCII (/r/dailyprogrammer #217)
# [2015-06-05] Challenge #217 [Practical Exercise] TeXSCII
# http://www.reddit.com/r/dailyprogrammer/comments/38nhgx/20150605_challenge_217_practical_exercise_texscii/
class Symbol:
def size(self):
raise Exception("should not be used")
def draw(self, canvas, x, y):
raise Exception("should not be used")
def __repr__(self):
if self.contents:
return '<{} {}>'.format(self.__class__.__name__, str(self.contents))
return '<{}>'.format(self.__class__.__name__)
class MainSymbol(Symbol):
def size(self):
return (1, 1)
def draw(self, canvas, x, y):
for e in self.contents:
e.draw(canvas, x, y)
w, h = e.size()
x += w
class FracSymbol(Symbol):
n_arguments = 2
def subsize(self):
top_sizes = [e.size() for e in self.contents[0]]
bot_sizes = [e.size() for e in self.contents[1]]
topW, topH = sum(xy[0] for xy in top_sizes), max(xy[1] for xy in top_sizes)
botW, botH = sum(xy[0] for xy in bot_sizes), max(xy[1] for xy in bot_sizes)
return topW, topH, botW, botH
def size(self):
topW, topH, botW, botH = self.subsize()
return (max(topW, botW), 1 + topH + botH)
def draw(self, canvas, x, y):
topW, topH, botW, botH = self.subsize()
W, H = self.size()
for dx in range(W):
canvas[(x+dx, y)] = '—'
orig_x, orig_y = x, y
y += botH
x += (W - botW) // 2
for e in self.contents[1]:
e.draw(canvas, x, y)
x += e.size()[0]
x, y = orig_x, orig_y - 1
x += (W - topW) // 2
for e in self.contents[0]:
e.draw(canvas, x, y)
x += e.size()[0]
class RootSymbol(Symbol):
n_arguments = 2
def size(self):
sizes = [e.size() for e in self.contents[1]]
subW, subH = sum(xy[0] for xy in sizes), max(xy[1] for xy in sizes)
return (subW + subH, subH + 1)
def draw(self, canvas, x, y):
W, H = self.size()
orig_x, orig_y = x, y
canvas[(x, y)] = 'v'
dx, dy = 1, 1
while dy < H - 1:
canvas[(x+dx, y-dy)] = '/'
dx, dy = dx+1, dy+1
self.contents[0][0].draw(canvas, x+dx-1, y-dy)
while dx < W:
canvas[(x+dx, y-dy)] = '_'
dx += 1
x += H - 1
for e in self.contents[1]:
e.draw(canvas, x, y)
x += e.size()[0]
class SqrtSymbol(Symbol):
n_arguments = 1
def size(self):
sizes = [e.size() for e in self.contents[0]]
subW, subH = sum(xy[0] for xy in sizes), max(xy[1] for xy in sizes)
return (subW + subH, subH + 1)
def draw(self, canvas, x, y):
W, H = self.size()
orig_x, orig_y = x, y
canvas[(x, y)] = 'v'
dx, dy = 1, 1
while dy < H - 1:
canvas[(x+dx, y-dy)] = '/'
dx, dy = dx+1, dy+1
while dx < W:
canvas[(x+dx, y-dy)] = '_'
dx += 1
x, y = orig_x, orig_y
x += H - 1
for e in self.contents[0]:
e.draw(canvas, x, y)
x += e.size()[0]
class SubSymbol(Symbol):
n_arguments = 1
def size(self):
sizes = [e.size() for e in self.contents[0]]
return (sum(xy[0] for xy in sizes), 1 + max(xy[1] for xy in sizes))
def draw(self, canvas, x, y):
ox, oy = x, y
y += self.size()[1] - 1
for e in self.contents[0]:
e.draw(canvas, x, y)
x += e.size()[0]
class SupSymbol(Symbol):
n_arguments = 1
def size(self):
sizes = [e.size() for e in self.contents[0]]
return (sum(xy[0] for xy in sizes), 1 + max(xy[1] for xy in sizes))
def draw(self, canvas, x, y):
ox, oy = x, y
y -= 1
for e in self.contents[0]:
e.draw(canvas, x, y)
x += e.size()[0]
class PiSymbol(Symbol):
n_arguments = 0
def size(self):
return (1, 1)
def draw(self, canvas, x, y):
canvas[(x, y)] = 'π'
class CharSymbol(Symbol):
n_arguments = 0
def size(self):
return (1, 1)
def draw(self, canvas, x, y):
canvas[(x, y)] = self.contents[0]
symbols = {
r'\frac': FracSymbol,
r'\root': RootSymbol,
r'\sqrt': SqrtSymbol,
r'\pi': PiSymbol,
r'_': SubSymbol,
r'^': SupSymbol
}
def parse(text, pos=0):
contents = []
while True:
for pattern, symClass in symbols.items():
if text[pos:].startswith(pattern):
symbol = symClass()
pos += len(pattern)
symContents = []
for i in range(symClass.n_arguments):
pos += 1
newContents, pos = parse(text, pos)
symContents.append(newContents)
symbol.contents = symContents
contents.append(symbol)
break
else:
char = CharSymbol()
char.contents = [text[pos]]
contents.append(char)
pos += 1
if pos == len(text):
break
if text[pos] == '}':
pos += 1
break
return contents, pos
output = open("output.txt", "w", encoding='utf-8')
lines = open("input.txt").read().splitlines()
for line in lines:
contents, _ = parse(line)
canvas = {}
root = MainSymbol()
root.contents = contents
root.draw(canvas, 0, 0)
maxX, minX = max(canvas, key=lambda xy: xy[0])[0], min(canvas, key=lambda xy: xy[0])[0]
maxY, minY = max(canvas, key=lambda xy: xy[1])[1], min(canvas, key=lambda xy: xy[1])[1]
for y in range(minY, maxY+1):
for x in range(minX, maxX+1):
output.write(canvas.get((x, y), ' '))
output.write('\n')
output.write('\n\n')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment