Skip to content

Instantly share code, notes, and snippets.

@pgtwitter
Created March 25, 2025 06:20
Show Gist options
  • Save pgtwitter/742a1b852e9148a3ced10efa2ad0b484 to your computer and use it in GitHub Desktop.
Save pgtwitter/742a1b852e9148a3ced10efa2ad0b484 to your computer and use it in GitHub Desktop.
幅80に収めて可読性を多少考えた版 https://gist.github.com/pgtwitter/2e0e0037928680dd6b10d531c591595e
# %%
def morse2Dot(in_filename, out_filename):
ROOT_LABEL = '(start)'
ROOT_CODE = 'START'
DUMMY = 'dummy'
DOT_SHAPE = 'shape=circle'
BAR_SHAPE = 'shape=rectangle'
ROOT_SHAPE = 'shape=diamond'
PROP_LINES = '\n\trankdir=TB;\n\tnodesep=0.5;\n\tpad=0.2;'
DUMMY_NODE_ATTR = ', label="(N/A)", margin=0'
DOT_EDGE_ATTR = 'penwidth=2, weight=1000, style=dashed'
BAR_EDGE_ATTR = 'penwidth=2'
class m:
def __init__(self, l, c):
self.code = c
self.n = c.count('.')
self.children = []
self.p = ROOT_CODE if len(c) == 1 else c[0:-1]
self.shape = DOT_SHAPE if c[-1] == '.' else BAR_SHAPE
self.l = f'{DUMMY}{self.code}' if l == DUMMY else l
self.node_attr = DUMMY_NODE_ATTR if l == DUMMY else ''
self.edge_attr = DOT_EDGE_ATTR if c[-1] == '.' else BAR_EDGE_ATTR
self.node_line = f'\n\t"{self.l}" [{self.shape}{self.node_attr}];'
def node_lines(n):
ret = [n.node_line] if n.code != ROOT_CODE else []
ret.extend([l for c in n.children for l in node_lines(c)])
return ret
def edge_lines(n):
ret = [f'\n\t"{n.l}" -> "{c.l}" [{c.edge_attr}];' for c in n.children]
ret.extend([l for c in n.children for l in edge_lines(c)])
return ret
def read(in_filename):
ms = {ROOT_CODE: m(ROOT_LABEL, ROOT_CODE)}
with open(in_filename, 'r', encoding='utf-8') as f:
kv = {(k, m(v, k)) for v, k in [l.strip().split('\t') for l in f]}
ms.update(kv)
return ms
def build(ms):
while (flag := True):
for n in [v for v in ms.values() if v.code != ROOT_CODE]:
ms[n.p] = m(DUMMY, n.p) if n.p not in ms else ms[n.p]
if n not in ms[n.p].children and ms[n.p] != n:
ms[n.p].children.append(n)
flag = False
if flag:
break
return ms
def generate(ms):
lines = f'\n\n\t"{ROOT_LABEL}" [{ROOT_SHAPE}];'
lines += ''.join(sorted(node_lines(ms[ROOT_CODE])))
lines += '\n' + ''.join(sorted(edge_lines(ms[ROOT_CODE]))) + '\n'
for i in range(max([n.n for n in ms.values()]) + 1):
nodes = sorted([f'"{n.l}"' for n in ms.values() if n.n == i])
lines += '\n\t{rank=same; ' + ' '.join(nodes) + '}'
return 'digraph MorseTree {' + PROP_LINES + lines + '\n}'
with open(out_filename, 'w', encoding='utf-8') as f:
f.write(generate(build(read(in_filename))))
morse2Dot('morse.txt', 'own_tree.dot')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment