# -*- coding: utf-8 -*-
"""묶인절점 합계가 2,647 → 2,212 로 435개 줄어든 것이 '어디서' 줄었는지 가른다.
추측하지 않는다 — 두 실행의 접합면별 묶인절점을 쌍 단위로 빼서 적는다.

공통 쌍(두 실행 모두에 있는 접합면)과 한쪽에만 있는 쌍을 분리해 합계를 맞춘다.
합이 실제 차이와 같아야 이 분해가 옳다(검산을 출력한다).
"""
import json, sys
from collections import defaultdict

a = json.load(open(sys.argv[1], encoding='utf-8'))   # 적은 쪽(134부품)
b = json.load(open(sys.argv[2], encoding='utf-8'))   # 많은 쪽(141부품)


def key(p):
    c = p['center'] or [9e9, 9e9, 9e9]
    return (p['a'], p['b'], tuple(c), p['kind'])


A = {key(p): p for p in a['pairs']}
B = {key(p): p for p in b['pairs']}
newp = set(b['parts_nos']) - set(a['parts_nos'])
print('부품: %d → %d (새로 들어온 번호 %s)'
      % (a['parts_meshed'], b['parts_meshed'], sorted(newp)))
print('묶인절점 합계: %d → %d (차이 %+d)'
      % (a['welds_tied_total'], b['welds_tied_total'],
         b['welds_tied_total'] - a['welds_tied_total']))
print('  그중 다리 방정식: %d → %d' % (a['bridge_eqs'], b['bridge_eqs']))

common = sorted(set(A) & set(B))
onlyA = sorted(set(A) - set(B))
onlyB = sorted(set(B) - set(A))
d_common = sum(B[k]['tied'] - A[k]['tied'] for k in common)
d_onlyA = -sum(A[k]['tied'] for k in onlyA)
d_onlyB = sum(B[k]['tied'] for k in onlyB)
print()
print('| 묶음 | 쌍 수 | 묶인절점 변화 |')
print('|---|---|---|')
print('| 두 실행에 공통인 접합면 (재배분) | %d | %+d |' % (len(common), d_common))
print('| 134쪽에만 있던 접합면 (사라짐) | %d | %+d |' % (len(onlyA), d_onlyA))
print('| 141쪽에만 있는 접합면 (새로 생김) | %d | %+d |' % (len(onlyB), d_onlyB))
print('| **합** | | **%+d** |' % (d_common + d_onlyA + d_onlyB))
print('검산: 합계 차이 %+d / 분해 합 %+d → %s'
      % (b['welds_tied_total'] - a['welds_tied_total'], d_common + d_onlyA + d_onlyB,
         'OK' if (b['welds_tied_total'] - a['welds_tied_total']
                  == d_common + d_onlyA + d_onlyB) else '안 맞음'))

# 새 부품이 끼어든 쌍만 따로
def touches_new(k):
    return k[0] in newp or k[1] in newp


d_new_side = sum((B[k]['tied'] if k in B else 0) - (A[k]['tied'] if k in A else 0)
                 for k in sorted(set(A) | set(B)) if touches_new(k))
d_old_side = (d_common + d_onlyA + d_onlyB) - d_new_side
print()
print('| 구분 | 묶인절점 변화 | 몫 |')
print('|---|---|---|')
tot = d_common + d_onlyA + d_onlyB
for lab, v in (('새 부품이 한쪽인 쌍', d_new_side), ('기존 부품끼리의 쌍', d_old_side)):
    print('| %s | %+d | %.1f%% |' % (lab, v, 100.0 * v / tot if tot else 0.0))

print()
print('재배분이 가장 큰 공통 접합면 12개 (기존 부품끼리):')
rows = sorted(((B[k]['tied'] - A[k]['tied'], k) for k in common if not touches_new(k)),
              key=lambda t: t[0])
for v, k in rows[:12]:
    print('  %4d번↔%4d번 %s : %d → %d (%+d)'
          % (k[0], k[1], k[2], A[k]['tied'], B[k]['tied'], v))
