제로베이스 20220404 코테 연습
1. 로마 숫자 만들기
-
로마 숫자에서는 수를 나타내기 위해서 I, V, X, L을 사용한다. 각 문자는 1, 5, 10, 50을 의미하고, 이 문제에서 다른 문자는 사용하지 않는다.
-
하나 또는 그 이상의 문자를 이용해서 수를 나타낼 수 있다. 문자열이 나타내는 값은, 각 문자가 의미하는 수를 모두 합한 값이다. 예를 들어, XXXV는 35, IXI는 12를 의미한다.
-
실제 로마 숫자에서는 문자의 순서가 중요하지만, 이 문제에서는 순서는 신경쓰지 않는다. 예를 들어, 실제 로마 숫자에서 IX는 9를 의미하지만, 이 문제에서는 11을 의미한다.
-
로마 숫자를 N개 사용해서 만들 수 있는 서로 다른 수의 개수를 구해보자.
입력
- 첫째 줄에 사용할 수 있는 문자의 개수 N (1 ≤ N ≤ 20)이 주어진다.
출력
- 첫째 줄에 로마 숫자 N개를 사용해서 만들 수 있는 서로 다른 수의 개수를 출력한다.
풀이
import sys
from itertools import combinations_with_replacement
from collections import Counter
N = int(sys.stdin.readline())
rom = {'I': 1,
'V': 5,
'X': 10,
'L': 50}
c = list(combinations_with_replacement(rom,N))
nums = []
for s in list(c):
tmp = 0
for r in s:
tmp += rom[r]
nums.append(tmp)
nums = len(list(Counter(nums).keys()))
print(nums)
채점 결과
- 정답
리뷰
-
4개의 문자를 N번 뽑아 만들수 있는 조합
을 살짝 변형하면 답이 나온다.- 조합으로 나오는 경우를 모두 출력하고, 각 경우에 나오는 수를 합한후, 중복되는 수를 제거하는 방식으로 진행했다.
-
itertools의
combinations_with_replacement
메서드를 활용해 편안하게 구현할수 있었다.- 이번 문제에서 나오는 문자의 최대 개수는 20개. 무리없이 조합을 사용할수 있었다.
-
중복 제거는 Counter를 활용해주었다.
-
Do not reinvent wheel
이라는 격언이 있긴 하지만, 메서드 하나로 문제를 날로 먹을때마다 가끔은 죄책감이 들 때가 있다..
2. 동전
-
여러분은 양팔 저울 하나와 동전 12개(1, 2, …, 12 의 번호)를 가지고 있는데, 그 중 하나는 모조품입니다. 모조품은 다른 동전보다 가볍거나 무겁습니다.
-
양팔 저울로 세 번 측정하여 모조품을 찾고, 그것이 무거운지 가벼운지 밝히는 프로그램을 작성하세요.
입력
- 무게를 측정한 결과 데이터가 아래와 같은 형식의 표준 입력으로 주어지게 됩니다.
A B C D x E F G H
-
A, B, C, D, E, F, G, H 는 서로 다른 8 개의 동전들의 숫자이고, x 는 <, >, = 중에 하나입니다. 다음과 같은 의미를 지닙니다.
- < : A, B, C, D 의 총합은 E, F, G, H 의 총합보다 작다
- > : A, B, C, D 의 총합은 E, F, G, H 의 총합보다 크다
- = : A, B, C, D 의 총합은 E, F, G, H 의 총합과 같다
출력
- 프로그램은 표준출력에 모조품의 번호를 출력하고, 다른 동전보다 무거운 경우에는 + 를, 가벼운 경우에는 - 를 이어서 출력합니다.
세 번의 측정 데이터가 모순되는 경우에는 “impossible” 을 출력해야 합니다.
데이터가 모순되지는 않지만 모조품의 번호를 알아내기에 불충분하거나, 무거운지 가벼운지 알 수 없는 경우에는 “indefinite” 를 출력해야 합니다.
풀이
import sys
nums = [x for x in range(1,13)]
suspect = {'heavy':[], 'light':[], 'innocent':[]}
for _ in range(0, 3):
line = list(sys.stdin.readline().split())
left = list(map(int, line[0:4]))
sep = line[4]
right = list(map(int, line[5:9]))
if sep == '>':
suspect['heavy'] += left
suspect['light'] += right
suspect['innocent'] += [x for x in nums if x not in left and x not in right]
elif sep == '<':
suspect['heavy'] += right
suspect['light'] += left
suspect['innocent'] += [x for x in nums if x not in left and x not in right]
elif sep == '=':
suspect['innocent'] += right + left
if suspect['heavy']:
for s in suspect['heavy'][:]:
if s in suspect['innocent']:
suspect['heavy'].remove(s)
elif s in suspect['light']:
suspect['heavy'].remove(s)
suspect['innocent'].append(s)
if suspect['light']:
for s in suspect['light'][:]:
if s in suspect['innocent']:
suspect['light'].remove(s)
elif s in suspect['heavy']:
suspect['light'].remove(s)
suspect['innocent'].append(s)
suspect['heavy'] = list(set(suspect['heavy']))
suspect['light'] = list(set(suspect['light']))
suspect['innocent'] = list(set(suspect['innocent']))
if sorted(suspect['heavy'] + suspect['light'] + suspect['innocent']) != nums:
print('indefinite')
elif not suspect['heavy'] and not suspect['light']:
print('impossible')
elif len(suspect['innocent']) < 11:
print('indefinite')
elif suspect['heavy'] and not suspect['light']:
print(str(suspect['heavy'][0]) + '+')
elif suspect['light'] and not suspect['heavy']:
print(str(suspect['light'][0]) + '-')
채점 결과
- 오답(Index Error)
리뷰
-
양팔 저울을 사용해 동전을 분류하는 문제이다.
-
이 문제에서는 모조 동전이 단 한 개인것에 주의한다.
-
양팔 저울이라 헷갈릴수 있는 부분인데, 이 문제에서 한번 비교할때
세개의 부류가 나오게 된다.
- 저울 왼팔에 있는 동전들(left)
- 저울 오른팔에 있는 동전들(right)
- 저울에 올라가지 않은 동전들
- 세개로 나뉘는 이유는 다음과 같다.
- 어느 한쪽이 더 무거울때,
저울에 올라가지 않은 나머지 동전은 모두 무게가 같다.
- 저울이 평행할때,
저울에 올라가지 않은 동전중에 모조품이 존재한다
- 어느 한쪽이 더 무거울때,
-
단순하게 접근하여 식이 입력될때, 식의 결과에 따라 ‘무거운 동전 의심군’, ‘가벼운 동전 의심군’, ‘무고한 동전군’ 세가지로 분류하여 나누어주었다.
-
무거운 동전 의심군과 가벼운 동전 의심군에서 동시에 발견된다면, 무고한 동전군으로 변경한다.
-
저울이 평행하지 않을때, 남은 동전들은 결백하다.
-
-
세번의 비교가 끝났을때, 무고한 동전이 11개보다 적다면, 둘중 하나의 상황이다.
-
비교가 충분히 진행되지 못해 가벼운 동전과 무거운 동전이 각각 하나 이상씩 의심군에 남아있을때.
- 등호식이 세번 등장하였고, 한번도 분류되지 못한 동전이 있을 경우.
- 즉, 무거운 동전 + 가벼운 동전 + 무고한 동전의 합이 1~12번 동전 모두를 나타내지 못할때.
- 어느쪽이던지 비교가 더 필요하다는 의미의 indefinite를 출력.
-
-
무거운 동전 의심군과 가벼운 동전 의심군 모두 비어있을때, 어느쪽 데이터가 오류가 발생한것으로 간주. impossible을 출력한다.
-
나머지 경우 해당 데이터를 출력하면 되는데..
-
해결을 위한 논리에는 빈틈이 없어보이는데, 정작 채점을 돌려보면 20%즈음에서 IndexError로 실패한다.
-
적어도 오답이 아닌 IndexError이므로, 배열을 다루는 어딘가에서 나올 반례가 있다는 것이라고 생각할수 있다.
-