노란불 신호등 문서의 문제 1 풀이 코드다. if __name__ == "__main__": 아래가 자체 테스트다.
"""노란불 신호등 (프로그래머스 468371) 풀이와 검증."""
import random
from itertools import combinations_with_replacement
from math import lcm
def solution(signals):
period = 1
for g, y, r in signals:
period = lcm(period, g + y + r)
for t in range(1, period + 1):
if all(g <= (t - 1) % (g + y + r) < g + y for g, y, r in signals):
return t
return -1
def slow(signals):
"""색을 한 칸씩 바꿔 가며 따라간다. 멈추는 곳은 주기들의 곱."""
state = [[0, s[0]] for s in signals] # [색 번호(0초록 1노랑 2빨강), 그 색의 남은 초]
limit = 1
for g, y, r in signals:
limit *= g + y + r
for t in range(1, limit + 1):
if all(c == 1 for c, _ in state):
return t
for i, (g, y, r) in enumerate(signals):
state[i][1] -= 1
if state[i][1] == 0:
state[i][0] = (state[i][0] + 1) % 3
state[i][1] = (g, y, r)[state[i][0]]
return -1
if __name__ == "__main__":
assert solution([[2, 1, 2], [5, 1, 1]]) == 13
assert solution([[2, 3, 2], [3, 1, 3], [2, 1, 1]]) == 11
assert solution([[3, 3, 3], [5, 4, 2], [2, 1, 2]]) == 193
assert solution([[1, 1, 4], [2, 1, 3], [3, 1, 2], [4, 1, 1]]) == -1
assert solution([[1, 1, 1], [2, 1, 1]]) == 11
rng = random.Random(468371)
for _ in range(2000):
n = rng.randint(2, 3)
sig = []
for _ in range(n):
g, y = rng.randint(1, 5), rng.randint(1, 4)
r = rng.randint(1, 5)
sig.append([g, y, r])
assert solution(sig) == slow(sig), sig
best = max(lcm(*c) for c in combinations_with_replacement(range(3, 21), 5))
assert best == 1007760, best
import time
t0 = time.perf_counter()
assert solution([[14, 1, 1], [13, 1, 1], [11, 1, 1], [15, 1, 1], [17, 1, 1]]) == 1007759
assert time.perf_counter() - t0 < 2.0
print("ALL CHECKS PASSED")