Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

80 lines
2.3KB

  1. import math
  2. def send(parent, sender, signal):
  3. match kinds[sender], signal:
  4. case 'rx' | 'output', _:
  5. signal = None
  6. case 'button' | 'broadcaster', _:
  7. pass
  8. case '%', 0:
  9. signal = state[sender] = int(not state[sender])
  10. case '%', 1:
  11. signal = None
  12. case '&', _:
  13. state[sender][parent] = signal
  14. seen = set(state[sender].values())
  15. signal = 0 if seen == {1} else 1
  16. case default:
  17. raise RuntimeError(default)
  18. if signal is not None:
  19. for target in targets[sender]:
  20. # print(sender, signal, target)
  21. output.append(signal)
  22. yield (sender, target, signal)
  23. def deps(p):
  24. seen = set()
  25. state = {p}
  26. while state:
  27. seen |= state
  28. state = {k for p in state for k, vs in targets.items() if p in vs and k not in seen}
  29. return tuple(sorted(seen))
  30. text = open(0).read()
  31. targets = {'button': ['broadcaster']}
  32. kinds = {'button': 'button', 'rx': 'rx', 'output': 'output'}
  33. for line in text.splitlines():
  34. src, dst = line.split(' -> ')
  35. dst = dst.split(', ')
  36. if src == 'broadcaster':
  37. label = kind = 'broadcaster'
  38. else:
  39. label, kind = src[1:], src[0]
  40. targets[label] = dst
  41. kinds[label] = kind
  42. state = {}
  43. state |= {l: 0 for l, k in kinds.items() if k == '%'}
  44. state |= {l: {i: 0 for i, ts in targets.items() if l in ts} for l, k in kinds.items() if k == '&'}
  45. families = {}
  46. for k in kinds:
  47. families.setdefault(hash(deps(k)), []).append(k)
  48. families = {tuple(vs): set() for vs in families.values() if len(vs) > 1}
  49. seq = []
  50. seen = set()
  51. while True:
  52. output = []
  53. active = [(None, 'button', 0)]
  54. while active:
  55. active = [new for old in active for new in send(*old)]
  56. seq.append(output)
  57. before = [len(vs) for vs in families.values()]
  58. for ks in families:
  59. families[ks].add(hash(str([state[k] for k in ks])))
  60. after = [len(vs) for vs in families.values()]
  61. if before == after:
  62. break
  63. if len(seq) == 1000:
  64. # pt 1
  65. los = [sum(v == 0 for v in vs) for vs in seq]
  66. his = [sum(v == 1 for v in vs) for vs in seq]
  67. print(sum(los[i % len(los)] for i in range(1000)) * sum(his[i % len(his)] for i in range(1000)))
  68. print(math.prod(after))