#!/usr/bin/python3
import random
import sys

WIDTH = None
SHAPE_CHARS = list('#$%&*+/=?')
COL_DEPTH = 15

def dec(n):
    return n - 1

def inc(n):
    return n + 1

def gx(x):
    return x[0] if isinstance(x, tuple) else [gx(k) for k in x]

def gy(x):
    return x[1] if isinstance(x, tuple) else [gy(k) for k in x]

def in_bounds(x, y, w, h):
    return x >= 0 and y >= 0 and (x < w) and (y < h)

def rotate(shape, qta):
    return {(-1 ** (qta // 2) * (inc(qta) % 2) * x + -1 * -1 ** (qta // 2) * (qta % 2) * y, -1 ** (qta // 2) * (inc(qta) % 2) * y + -1 ** (qta // 2) * (qta % 2) * x) for x, y in shape}

def translate(shape, dx, dy):
    return {(x + dx, y + dy) for x, y in shape}

def normalise(shape):
    return translate(shape, -min(gx(shape), default=0), -min(gy(shape), default=0))

def init_grid(w, h):
    return {(x1, y1): {(x2, y2) for x2, y2 in [(dec(x1), y1), (x1, dec(y1)), (inc(x1), y1), (x1, inc(y1))] if in_bounds(x2, y2, w, h)} for x1 in range(w) for y1 in range(h)}

def draw(scr, shape, ch, bg=' ', w=0, h=0):
    if shape:
        _hy_let_cg_2 = scr or [[bg for _ in range(w or inc(max(gx(shape))))] for _ in range(h or inc(max(gy(shape))))]
        for x, y in shape:
            _hy_let_cg_2[y][x] = ch
        _hy_anon_var_3 = _hy_let_cg_2
    else:
        _hy_anon_var_3 = scr
    return _hy_anon_var_3

def to_pbm(shapes):
    w = 2 + max([max(gx(s)) - min(gx(s)) - -1 for s in shapes])
    h = inc(sum([inc(max(gy(s)) - min(gy(s)) - -1) for s in shapes]))
    header = f'P1\n{w} {h}\n'
    return header + '\n'.join(['\n'.join([''.join(r) for r in draw('', translate(normalise(s), 1, 1), '1', '0', w)]) for s in shapes]) + '\n' + '0' * w + '\n'

def colour(t):

    def ud(x):
        _hy_let_y_5 = min(x % 0.5 * 6, 1)
        return round(COL_DEPTH * (1 - _hy_let_y_5 if x % 1 >= 0.5 else _hy_let_y_5))
    _hy_let_r_6 = ud(t + 1 / 3)
    _hy_let_g_7 = ud(t)
    _hy_let_b_8 = ud(t + 2 / 3)
    return f'{_hy_let_r_6} {_hy_let_g_7} {_hy_let_b_8}'

def to_ppm(shapes):
    w = 3 + max([max(gx(s)) for s in shapes])
    h = 3 + max([max(gy(s)) for s in shapes])
    header = f'P3\n{w} {h}\n{COL_DEPTH}\n'
    grid = draw('', {(0, 0)}, '0 0 0', '0 0 0', w, h)
    for i, s in enumerate(shapes):
        grid = draw(grid, translate(s, 1, 1), colour(i / len(shapes)))
    return header + '\n'.join([' '.join(r) for r in grid]) + '\n'

def nbhd(xy):
    return [(gx(xy) + gx(d), gy(xy) + gy(d)) for d in [(1, 0), (0, 1), (-1, 0), (0, -1)]]

def hop_shape(xy, src, dst):
    dst[xy] = {*()}
    del src[xy]
    for sc in nbhd(xy):
        if sc in dst:
            dst[xy].add(sc)
            _hy_anon_var_9 = dst[sc].add(xy)
        else:
            _hy_anon_var_9 = None
        src[sc].discard(xy) if sc in src else None

def components(shape):
    pl = set(shape.keys())
    comps = []
    comp = []
    fi = 0
    while pl:
        if fi >= len(comp):
            comps.append(set(comp)) if comp else None
            comp = [pl.pop()]
            fi = 0
            _hy_anon_var_11 = None
        else:
            for ap in nbhd(comp[fi]):
                if ap in pl:
                    comp.append(ap)
                    _hy_anon_var_10 = pl.remove(ap)
                else:
                    _hy_anon_var_10 = None
            fi += 1
            _hy_anon_var_11 = None
    return comps

def equiv(s1, s2):
    _hy_let_ns2_12 = normalise(s2)
    return any([not normalise(rotate(s1, r)).symmetric_difference(_hy_let_ns2_12) for r in range(4)])

def load_shapes(fname):
    _hy_anon_var_34 = None
    with open(fname, 'r') as fh:
        _hy_anon_var_34 = [l.strip() for l in fh.readlines() if not l.startswith('#')]
    fl = _hy_anon_var_34
    WIDTH = len(fl[0])
    shapes = [init_grid(WIDTH, WIDTH)]
    for y, r in enumerate(fl):
        for x, c in enumerate(r):
            if c.isdigit():
                _hy_let_i_35 = int(c)
                shapes.extend([{} for _ in range(inc(_hy_let_i_35) - len(shapes))]) if len(shapes) <= _hy_let_i_35 else None
                hop_shape((x, y), shapes[0], shapes[_hy_let_i_35])
    return shapes
try:
    mode = sys.argv[1]
    fname = sys.argv[2]
    if mode.isdigit():
        WIDTH = int(mode)
        shapes = [init_grid(WIDTH, WIDTH)]
        print(f"{sys.argv[0]}: can't build new shape (no curses, etc)")
        og = draw('', {(0, 0)}, '_', '_', WIDTH, WIDTH)
        for i, s in enumerate(shapes):
            og = draw(og, s, str(i), '_')
        _hy_anon_var_36 = None
        with open(fname, 'w') as fh:
            _hy_anon_var_36 = fh.write('\n'.join([''.join(r) for r in og]) + '\n')
        _hy_anon_var_37 = _hy_anon_var_36
    else:
        _hy_anon_var_37 = print(to_pbm([rotate(s, random.randrange(4)) for s in load_shapes(fname) if s])) if mode == 'q' else print(to_ppm([s for s in load_shapes(fname) if s])) if mode == 'a' else None
    _hy_anon_var_38 = _hy_anon_var_37
except FileNotFoundError:
    _hy_anon_var_38 = print(f"{sys.argv[0]}: can't load from {fname}: No such file or directory")
