Skip to content

Instantly share code, notes, and snippets.

@iliakonnov
Last active November 14, 2021 17:12
Show Gist options
  • Save iliakonnov/6dc535f8d4227a7fc604aca1cc73a76b to your computer and use it in GitHub Desktop.
Save iliakonnov/6dc535f8d4227a7fc604aca1cc73a76b to your computer and use it in GitHub Desktop.
from dataclasses import dataclass, replace
from functools import wraps
from math import sin
SYMBOL_HEIGHT, SYMBOL_WIDTH, USE_COLORS = {
'1x1': (1, 1, True),
'2x2': (2, 2, True),
'braille': (4, 2, False),
}['2x2']
FONT_SCALE = 14 / 7
X_SCALE = (SYMBOL_WIDTH / SYMBOL_HEIGHT) * FONT_SCALE
def get_char(bits):
bits = [1 if int(i) else 0 for i in bits]
if len(bits) == 1:
return '█' if bits[0] else ' '
if len(bits) == 4:
'''
1 2
3 4
'''
char = bits[0] + 2*bits[1] + 4*bits[2] + 8*bits[3]
return [
' ', # 0000
'▘', # 0001
'▝', # 0010
'▀', # 0011
'▖', # 0100
'▌', # 0101
'▞', # 0110
'▛', # 0111
'▗', # 1000
'▚', # 1001
'▐', # 1010
'▜', # 1011
'▄', # 1100
'▙', # 1101
'▟', # 1110
'█', # 1111
][char]
if len(bits) == 8:
'''
1(0) 4(1)
2(2) 5(3)
3(4) 6(5)
7(6) 8(7)
'''
char = ( 1 * bits[0]
+ 2 * bits[2]
+ 4 * bits[4]
+ 8 * bits[1]
+ 16 * bits[3]
+ 32 * bits[5]
+ 64 * bits[6]
+ 128* bits[7])
return chr(10240 + char)
return '□'
def get_color(color):
colors = {
0b000: (0, (0, 0, 0 )), # black
0b100: (1, (255, 0, 0 )), # red
0b010: (2, (0, 255, 0 )), # green
0b110: (3, (255, 255, 0 )), # yellow
0b001: (4, (0, 0, 255)), # blue
0b101: (5, (255, 0, 255)), # magenta
0b011: (6, (0, 255, 255)), # cyan
0b111: (7, (255, 255, 255)), # white
}
code, *_ = colors[color]
return f'\x1b[3{code}m'
@dataclass
class Cell:
is_set: int = 0
color: int = 0
def __post_init__(self):
self.is_set = int(self.is_set)
def __int__(self):
return self.is_set
@property
def effective_color(self):
return self.color * self.is_set
def __or__(self, other):
return Cell(
is_set = self.is_set | other.is_set,
color = self.effective_color | other.effective_color
)
class Matrix:
@classmethod
def empty(cls, width, height):
data = [[Cell() for i in range(width)] for j in range(height)]
return Matrix(data)
def __init__(self, data):
if data and data[0] and not isinstance(data[0][0], Cell):
data = [[Cell(int(i)) for i in row] for row in data]
height = len(data)
width = max(len(row) for row in data) if height else 0
self._size = (width, height)
self._data = data
def size(self):
return self._size
def __setitem__(self, idx, cell):
x, y = idx
self._data[y][x] |= cell
def __getitem__(self, idx):
x, y = idx
return self._data[y][x]
def __call__(self, x, y):
if y >= len(self._data):
return Cell()
row = self._data[y]
if x >= len(row):
return Cell()
return row[x]
def plot_matrix(matrix):
width, height = matrix.size()
y = 0
while y <= height:
x = 0
while x <= width:
char = []
color = 0
for dy in range(SYMBOL_HEIGHT):
for dx in range(SYMBOL_WIDTH):
cell = matrix(x+dx, y+dy)
char.append(cell.is_set)
color |= cell.effective_color
char = get_char(char)
if USE_COLORS:
color = get_color(color)
print(f'{color}{char}\x1b[0m', end='')
else:
print(char, end='')
x += SYMBOL_WIDTH
print(flush=False)
y += SYMBOL_HEIGHT
def centered(matrix, func):
width, height = matrix.size()
result = lambda x, y: func((x - width // 2) / X_SCALE, (height // 2 - y))
return wraps(func)(result)
def plot_bool(matrix, func, **kwargs):
kwargs['color'] = kwargs.get('color', 0b111)
template = Cell(**kwargs)
func = centered(matrix, func)
width, height = matrix.size()
cnt = 0
print(f' - Rendering {func.__name__}...')
for y in range(height):
for x in range(width):
cell = replace(template, is_set=func(x, y))
matrix[x, y] = cell
if cnt == 0:
print(f'\x1b[F({x:03}, {y:03})')
cnt = 300
cnt -= 1
def plot_border(matrix, func, **kwargs):
@wraps(func)
def check_corners(x, y):
corners = [
func(x - 0.5, y - 0.5),
func(x - 0.5, y + 0.5),
func(x + 0.5, y - 0.5),
func(x + 0.5, y + 0.5),
]
return any(corners) and not all(corners)
return plot_bool(matrix, check_corners, **kwargs)
def function(code):
result = eval(f'lambda x, y: {code}')
result.__name__ = f'{{{code}}}'
return result
matrix = Matrix.empty(int(300 * X_SCALE), 300)
plot_border(matrix, function('y <= 0'))
plot_border(matrix, function('0 <= x'))
# circle:
plot_bool(matrix, function('(x+12)**2 + (y+12)**2 <= 15**2'), color=0b100)
# parabola:
#plot_border(matrix, lambda x, y: y <= x*x)
# sin:
plot_border(matrix, function('y <= 10*sin(x/5)'), color=0b001)
# hyperbola:
plot_border(matrix, function('y <= 270/x if x != 0 else False'), color=0b010)
plot_matrix(matrix)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment