import unittest
def main():
lines = [
'1:>>2',
'2:>>1',
'3:>>1-3',
'4:>>1,3',
'5:>>1,2-4',
]
nodes = []
for line in lines:
line = line.strip()
no, content = line.split(':')
ancs = parse_anchor(content)
nodes.append({
'no': no,
'content': content,
'ancs': ancs,
'count': 0,
})
for n in nodes:
for a in n['ancs']:
if isinstance(a, tuple):
for i in range(a[0] - 1, a[1]):
nodes[i]['count'] += 1
else:
nodes[a - 1]['count'] += 1
for n in sorted(nodes, key=lambda n: n['count'], reverse=True):
print(f'{n["no"]}:{n["count"]}')
def parse_anchor(s):
m = 'first'
buf = ''
fd = 0
i = 0
ancs = []
s += ' '
while i < len(s):
c = s[i]
if m == 'first':
if c == '>':
m = 'found >'
elif m == 'found >':
if c == '>':
m = 'anchor'
else:
m = 'first'
elif m == 'anchor':
if c.isdigit():
buf += c
m = 'read digit'
elif c.isspace():
ancs.append(int(buf))
buf = ''
elif m == 'read digit':
if c.isdigit():
buf += c
elif c == ',':
ancs.append(int(buf))
buf = ''
elif c == '-':
fd = int(buf)
buf = ''
m = 'read second digit'
elif c.isspace():
ancs.append(int(buf))
buf = ''
else:
ancs.append(int(buf))
buf = ''
m = 'first'
elif m == 'read second digit':
if c.isdigit():
buf += c
elif c == ',':
ancs.append((fd, int(buf)))
buf = ''
m = 'anchor'
elif c.isspace():
ancs.append((fd, int(buf)))
buf = ''
else:
ancs.append((fd, int(buf)))
buf = ''
m = 'first'
i += 1
return ancs
main()
class ParseAnchorTest(unittest.TestCase):
def test_parse(self):
self.assertEqual(str(parse_anchor('>')), '[]')
self.assertEqual(str(parse_anchor('>,')), '[]')
self.assertEqual(str(parse_anchor('>>1')), '[1]')
self.assertEqual(str(parse_anchor('>>,1')), '[1]')
self.assertEqual(str(parse_anchor('>>1,2')), '[1, 2]')
self.assertEqual(str(parse_anchor('>>1,2,3')), '[1, 2, 3]')
self.assertEqual(str(parse_anchor('>>1-2')), '[(1, 2)]')
self.assertEqual(str(parse_anchor('>>1-2,3-4')), '[(1, 2), (3, 4)]')
self.assertEqual(
str(parse_anchor('text>>1-2,3-4text')), '[(1, 2), (3, 4)]')
self.assertEqual(str(parse_anchor('abc>>1,2def')), '[1, 2]')
aW1wb3J0IHVuaXR0ZXN0CgoKZGVmIG1haW4oKToKICAgIGxpbmVzID0gWwogICAgICAgICcxOj4+MicsCiAgICAgICAgJzI6Pj4xJywKICAgICAgICAnMzo+PjEtMycsCiAgICAgICAgJzQ6Pj4xLDMnLAogICAgICAgICc1Oj4+MSwyLTQnLAogICAgXQogICAgbm9kZXMgPSBbXQoKICAgIGZvciBsaW5lIGluIGxpbmVzOgogICAgICAgIGxpbmUgPSBsaW5lLnN0cmlwKCkKICAgICAgICBubywgY29udGVudCA9IGxpbmUuc3BsaXQoJzonKQogICAgICAgIGFuY3MgPSBwYXJzZV9hbmNob3IoY29udGVudCkKICAgICAgICBub2Rlcy5hcHBlbmQoewogICAgICAgICAgICAnbm8nOiBubywKICAgICAgICAgICAgJ2NvbnRlbnQnOiBjb250ZW50LAogICAgICAgICAgICAnYW5jcyc6IGFuY3MsCiAgICAgICAgICAgICdjb3VudCc6IDAsCiAgICAgICAgfSkKCiAgICBmb3IgbiBpbiBub2RlczoKICAgICAgICBmb3IgYSBpbiBuWydhbmNzJ106CiAgICAgICAgICAgIGlmIGlzaW5zdGFuY2UoYSwgdHVwbGUpOgogICAgICAgICAgICAgICAgZm9yIGkgaW4gcmFuZ2UoYVswXSAtIDEsIGFbMV0pOgogICAgICAgICAgICAgICAgICAgIG5vZGVzW2ldWydjb3VudCddICs9IDEKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIG5vZGVzW2EgLSAxXVsnY291bnQnXSArPSAxCgogICAgZm9yIG4gaW4gc29ydGVkKG5vZGVzLCBrZXk9bGFtYmRhIG46IG5bJ2NvdW50J10sIHJldmVyc2U9VHJ1ZSk6CiAgICAgICAgcHJpbnQoZid7blsibm8iXX06e25bImNvdW50Il19JykKCgpkZWYgcGFyc2VfYW5jaG9yKHMpOgogICAgbSA9ICdmaXJzdCcKICAgIGJ1ZiA9ICcnCiAgICBmZCA9IDAKICAgIGkgPSAwCiAgICBhbmNzID0gW10KICAgIHMgKz0gJyAnCgogICAgd2hpbGUgaSA8IGxlbihzKToKICAgICAgICBjID0gc1tpXQogICAgICAgIGlmIG0gPT0gJ2ZpcnN0JzoKICAgICAgICAgICAgaWYgYyA9PSAnPic6CiAgICAgICAgICAgICAgICBtID0gJ2ZvdW5kID4nCiAgICAgICAgZWxpZiBtID09ICdmb3VuZCA+JzoKICAgICAgICAgICAgaWYgYyA9PSAnPic6CiAgICAgICAgICAgICAgICBtID0gJ2FuY2hvcicKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIG0gPSAnZmlyc3QnCiAgICAgICAgZWxpZiBtID09ICdhbmNob3InOgogICAgICAgICAgICBpZiBjLmlzZGlnaXQoKToKICAgICAgICAgICAgICAgIGJ1ZiArPSBjCiAgICAgICAgICAgICAgICBtID0gJ3JlYWQgZGlnaXQnCiAgICAgICAgICAgIGVsaWYgYy5pc3NwYWNlKCk6CiAgICAgICAgICAgICAgICBhbmNzLmFwcGVuZChpbnQoYnVmKSkKICAgICAgICAgICAgICAgIGJ1ZiA9ICcnCiAgICAgICAgZWxpZiBtID09ICdyZWFkIGRpZ2l0JzoKICAgICAgICAgICAgaWYgYy5pc2RpZ2l0KCk6CiAgICAgICAgICAgICAgICBidWYgKz0gYwogICAgICAgICAgICBlbGlmIGMgPT0gJywnOgogICAgICAgICAgICAgICAgYW5jcy5hcHBlbmQoaW50KGJ1ZikpCiAgICAgICAgICAgICAgICBidWYgPSAnJwogICAgICAgICAgICBlbGlmIGMgPT0gJy0nOgogICAgICAgICAgICAgICAgZmQgPSBpbnQoYnVmKQogICAgICAgICAgICAgICAgYnVmID0gJycKICAgICAgICAgICAgICAgIG0gPSAncmVhZCBzZWNvbmQgZGlnaXQnCiAgICAgICAgICAgIGVsaWYgYy5pc3NwYWNlKCk6CiAgICAgICAgICAgICAgICBhbmNzLmFwcGVuZChpbnQoYnVmKSkKICAgICAgICAgICAgICAgIGJ1ZiA9ICcnCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBhbmNzLmFwcGVuZChpbnQoYnVmKSkKICAgICAgICAgICAgICAgIGJ1ZiA9ICcnCiAgICAgICAgICAgICAgICBtID0gJ2ZpcnN0JwogICAgICAgIGVsaWYgbSA9PSAncmVhZCBzZWNvbmQgZGlnaXQnOgogICAgICAgICAgICBpZiBjLmlzZGlnaXQoKToKICAgICAgICAgICAgICAgIGJ1ZiArPSBjCiAgICAgICAgICAgIGVsaWYgYyA9PSAnLCc6CiAgICAgICAgICAgICAgICBhbmNzLmFwcGVuZCgoZmQsIGludChidWYpKSkKICAgICAgICAgICAgICAgIGJ1ZiA9ICcnCiAgICAgICAgICAgICAgICBtID0gJ2FuY2hvcicKICAgICAgICAgICAgZWxpZiBjLmlzc3BhY2UoKToKICAgICAgICAgICAgICAgIGFuY3MuYXBwZW5kKChmZCwgaW50KGJ1ZikpKQogICAgICAgICAgICAgICAgYnVmID0gJycKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIGFuY3MuYXBwZW5kKChmZCwgaW50KGJ1ZikpKQogICAgICAgICAgICAgICAgYnVmID0gJycKICAgICAgICAgICAgICAgIG0gPSAnZmlyc3QnCgogICAgICAgIGkgKz0gMQoKICAgIHJldHVybiBhbmNzCgoKbWFpbigpCgoKY2xhc3MgUGFyc2VBbmNob3JUZXN0KHVuaXR0ZXN0LlRlc3RDYXNlKToKICAgIGRlZiB0ZXN0X3BhcnNlKHNlbGYpOgogICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoc3RyKHBhcnNlX2FuY2hvcignPicpKSwgJ1tdJykKICAgICAgICBzZWxmLmFzc2VydEVxdWFsKHN0cihwYXJzZV9hbmNob3IoJz4sJykpLCAnW10nKQogICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoc3RyKHBhcnNlX2FuY2hvcignPj4xJykpLCAnWzFdJykKICAgICAgICBzZWxmLmFzc2VydEVxdWFsKHN0cihwYXJzZV9hbmNob3IoJz4+LDEnKSksICdbMV0nKQogICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoc3RyKHBhcnNlX2FuY2hvcignPj4xLDInKSksICdbMSwgMl0nKQogICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoc3RyKHBhcnNlX2FuY2hvcignPj4xLDIsMycpKSwgJ1sxLCAyLCAzXScpCiAgICAgICAgc2VsZi5hc3NlcnRFcXVhbChzdHIocGFyc2VfYW5jaG9yKCc+PjEtMicpKSwgJ1soMSwgMildJykKICAgICAgICBzZWxmLmFzc2VydEVxdWFsKHN0cihwYXJzZV9hbmNob3IoJz4+MS0yLDMtNCcpKSwgJ1soMSwgMiksICgzLCA0KV0nKQogICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoCiAgICAgICAgICAgIHN0cihwYXJzZV9hbmNob3IoJ3RleHQ+PjEtMiwzLTR0ZXh0JykpLCAnWygxLCAyKSwgKDMsIDQpXScpCiAgICAgICAgc2VsZi5hc3NlcnRFcXVhbChzdHIocGFyc2VfYW5jaG9yKCdhYmM+PjEsMmRlZicpKSwgJ1sxLCAyXScpCg==