주간 챌린지: 최대 충돌
Source: Dev.to
매주 Mohammad S. Anwar는 The Weekly Challenge 를 보내며, 우리 모두가 주간 과제 두 개에 대한 해결책을 제시할 기회를 제공합니다.
제 해결책은 먼저 Python으로 작성한 뒤 Perl로 변환합니다. 별도 언급이 없는 한, Copilot(및 기타 AI 도구)는 사용되지 않았음을 알려드립니다. 이는 우리 모두가 코딩을 연습하기에 좋은 방법입니다.
- 챌린지: https://theweeklychallenge.org/blog/perl-weekly-challenge-367/
- 내 솔루션: https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-367/sgreen
작업 1 – 최대 홀수 이진수
작업
이진 문자열이 주어지며, 최소 하나의 1이 포함되어 있습니다.
비트를 재배열하여 결과 이진수가 최대 홀수 이진수가 되도록 스크립트를 작성하고, 결과 이진 문자열을 반환하십시오. 결과 문자열은 앞에 0이 있을 수 있습니다.
내 솔루션 (Python)
아이디어는 간단합니다:
- 숫자는 홀수여야 하므로 마지막 비트가
1이어야 합니다. - 값을 최대화하려면, 남은 모든
1을 가능한 한 왼쪽(가장 높은 자리)으로 배치해야 합니다.
import re
def max_odd_binary(input_string: str) -> str:
"""Return the maximum odd binary string that can be built from the bits
of *input_string*.
The input must contain at least one '1' and consist only of '0' and '1'.
"""
if not re.search(r'^[01]*1[01]*$', input_string):
raise ValueError("Input not in expected format")
zeros = input_string.count('0')
ones = input_string.count('1')
# (ones‑1) leading 1s, all zeros, final 1 to make it odd
return '1' * (ones - 1) + '0' * zeros + '1'
Perl 대응 버전
Perl 버전도 동일한 논리를 따르며, 비트를 세기 위해 tr///를 사용하고 반복을 위해 x 연산자를 사용합니다.
예시
$ ./ch-1.py 1011
1101
$ ./ch-1.py 100
001
$ ./ch-1.py 111000
110001
$ ./ch-1.py 0101
1001
$ ./ch-1.py 1111
1111
Source: …
작업 2 – 충돌 이벤트
작업
두 개(또는 그 이상)의 이벤트가 주어집니다. 각 이벤트는 HH:MM 형식의 시작 시각과 종료 시각으로 정의됩니다.
스크립트를 작성하여 두 이벤트가 충돌하는지, 즉 공통 구간이 존재하는지를 판단하십시오.
나의 해결책 (Python)
HH:MM을 자정 이후 분(hm2m)으로 변환합니다.- 자정을 넘는 이벤트를 처리하기 위해 각 이벤트에 대한 분 범위 리스트를 만듭니다.
- 분을 순회하면서 집합을 이용해 겹치는 부분을 탐지합니다.
import re
def hm2m(t: str) -> int:
"""Convert HH:MM to minutes after midnight."""
if not re.search(r'^([01][0-9]|2[0-3]):[0-5][0-9]$', t):
raise ValueError("Input is not in the expected format (HH:MM)")
return int(t[:2]) * 60 + int(t[3:])
def conflict_events(events) -> bool:
"""Return True if any two (or more) events overlap.
*events* is a list of (start, end) tuples, each in HH:MM format.
"""
event_minutes = []
for start, end in events:
start_min = hm2m(start)
end_min = hm2m(end)
# Zero‑length events are ignored
if start_min == end_min:
continue
# Event crosses midnight → split into two ranges
if end_min < start_min:
event_minutes.extend([
range(start_min, 1440), # up to midnight
range(0, end_min) # after midnight
])
else:
event_minutes.append(range(start_min, end_min))
minutes_seen = set()
for r in event_minutes:
for minute in r:
if minute in minutes_seen:
return True
minutes_seen.add(minute)
return False
Perl 대응 버전
Perl 버전은 동일한 알고리즘을 구현합니다. Perl에는 내장 range 객체가 없으므로 시작·종료 분을 배열에 저장합니다.
예시
$ ./ch-2.py 10:00 12:00 11:00 13:00
True
$ ./ch-2.py 09:30 10:30 10:30 12:00
False
$ ./ch-2.py 14:00 15:30 14:30 16:00
True
$ ./ch-2.py 08:00 09:00 09:01 10:00
False
$ ./ch-2.py 23:00 00:30 00:00 01:00
True
즐거운 코딩 되세요!
