방금그곡 문서의 문제 1 풀이 코드다. if __name__ == "__main__": 아래가 자체 테스트다.

"""방금그곡 (프로그래머스 17683) 풀이와 검증."""
import random


def solution(m, musicinfos):
    def norm(s):
        for a, b in (("C#", "c"), ("D#", "d"), ("F#", "f"),
                     ("G#", "g"), ("A#", "a"), ("B#", "b")):
            s = s.replace(a, b)
        return s

    def minutes(t):
        h, mm = map(int, t.split(":"))
        return h * 60 + mm

    m = norm(m)
    best, best_len = "(None)", 0
    for info in musicinfos:
        start, end, title, sheet = info.split(",")
        dur = minutes(end) - minutes(start)
        sheet = norm(sheet)
        played = (sheet * (dur // len(sheet) + 1))[:dur]
        if m in played and dur > best_len:
            best, best_len = title, dur
    return best


def tokens(s):
    out = []
    for ch in s:
        if ch == "#":
            out[-1] += "#"
        else:
            out.append(ch)
    return out


def other(m, musicinfos):
    mel = tokens(m)
    cands = []
    for idx, info in enumerate(musicinfos):
        a, b, title, sheet = info.split(",")
        dur = (int(b[:2]) * 60 + int(b[3:])) - (int(a[:2]) * 60 + int(a[3:]))
        notes = tokens(sheet)
        played = [notes[i % len(notes)] for i in range(dur)]
        L = len(mel)
        if any(played[i:i + L] == mel for i in range(len(played) - L + 1)):
            cands.append((-dur, idx, title))
    return min(cands)[2] if cands else "(None)"


NOTES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]


def rand_case(rng):
    pool = rng.sample(NOTES, rng.randint(2, 4))
    infos = []
    for i in range(rng.randint(1, 5)):
        st = rng.randint(0, 1400)
        dur = rng.randint(1, 20)
        sheet = "".join(rng.choice(pool) for _ in range(rng.randint(1, 6)))
        infos.append(f"{st // 60:02d}:{st % 60:02d},{(st + dur) // 60:02d}:{(st + dur) % 60:02d},T{i},{sheet}")
    m = "".join(rng.choice(pool) for _ in range(rng.randint(1, 4)))
    return m, infos


if __name__ == "__main__":
    assert solution("ABCDEFG", ["12:00,12:14,HELLO,CDEFGAB", "13:00,13:05,WORLD,ABCDEF"]) == "HELLO"
    assert solution("CC#BCC#BCC#BCC#B", ["03:00,03:30,FOO,CC#B", "04:00,04:08,BAR,CC#BCC#BCC#B"]) == "FOO"
    assert solution("ABC", ["12:00,12:14,HELLO,C#DEFGAB", "13:00,13:05,WORLD,ABCDEF"]) == "WORLD"
    assert solution("CD", ["12:00,12:03,X,DC"]) == "X"
    assert solution("C", ["12:00,12:01,Y,C#"]) == "(None)"
    rng = random.Random(17683)
    for _ in range(3000):
        m, infos = rand_case(rng)
        assert solution(m, infos) == other(m, infos), (m, infos)
    print("ALL CHECKS PASSED")