Baekjoon 5086번 배수와 약수
==============================================
Contents
1. Problem
2. Error & Fail
3. Solution
4. My Code
5. Other's Code
6. Shortest Code
7. 최종 제출 코드
==============================================
1. Problem
- 10,000이 넘지않는 두 자연수를 입력으로 주어지며 마지막 줄에는 0 0 2개가 주어진다.
- 테스트는 여러개로 이루어진다.(개수가 정해지지않음)
- 만약 첫 번째 숫자가 두 번째 숫자의 약수라면 factor를
배수라면 multiple을 둘 다 아니면 neither을 출력한다.
2. Error & Fail
이 문제는 쉬운 문제이기 때문에 어려운 점은 없었으나 출력에 관해 배울점이 있다.
3. Solution
Key 1
우선 집고넘어가야할 부분은 항상 테스트 케이스는 자연수로만 주어진다는 점이다.
이 말은 끝 부분으로 제공되는 0은 오로지 마지막일 때만 나타난다는 점이고 이를 통해 loop를 빠져나갈 수 잇다.
Key 2
당연하게도 앞 부분을 a 뒷 부분을 b라고 가정한다면 첫 번째 숫자가 두 번째 숫자의 약수라면 b%a = 0이어야 한다.
배수라면 a%b = 0이어야 하며 나머지는 둘을 제외한 경우를 뜻한다.
4. My Code 첫 코드 231B 56ms
a =[]
while len(a)==0 or a[-1][0] != 0 and a[-1][1] != 0:
a.append(list(map(int, input().split())))
for i in range(len(a)-1):
if a[i][1] % a[i][0] == 0:
print("factor")
elif a[i][0] % a[i][1] == 0:
print("multiple")
else:
print("neither")
개인적으로 list로 받는 것을 좋아한다. 때문에 둘을 list 형태롤 받는 것을 생각해서 a에 각각 넣는 것을 생각 그 다음 for문에서 Condition에 따른 조건들을 해결하였다.
물론 이 때는 while 문에서 조건 사항으로 처음을 진행하기 위해 len(a)==0이라는 부분을 썻고 그 다음은 입력받은 숫자가 0일 때 루프를 나오기 위해 처리했다.
그러나 나중에 보게되는 코드들은 이런 복잡한 조건을 필요로하지 않으며 더 간단해진다.
우선 딱 봐도 루프를 굳이 받아서 list에 입력받고 그것을 다시 루프를 돌아서 하는 것 보다 하나의 루프에서 도는 것이 효율적이라는 생각을 하게 된다.
그래서 나온 코드 - 231B 56ms
while True:
a = list(map(int, input().split()))
if a[0] == 0: #if a[0]+a[1] == 0:를 사용하면 56ms
break
if a[1] % a[0] == 0:
print("factor")
elif a[0] % a[1] == 0:
print("multiple")
else:
print("neither")
무한 루프를 돌되 break 포인트로 조건을 잡아주고 바로 조건문을 수행하는 것이다.
다만 실험 결과 a[0]+a[1] == 0를 통해 break 포인트를 잡는 것보다 a[0] == 0 하나로만 처리해도 된다는 것을 알아야한다. 왜냐하면 두 자연수로만 입력을 줄 뿐이고 0은 오로지 끝 부분에서만 처리되므로 Solution - Key 1
후에 다른 사람들의 코드를 보고 더 줄였다. 그것은 7번에서
5. Other's Code
(1)- changhw 131B 52ms or 56ms
while 1:
a,b=map(int,input().split())
if a<1 and b<1:break
if b%a==0:print("factor")
else:print(["multiple","neither"][a%b>0])
현재 1등의 코드로 52ms가 나오기도하고 56이 나오기도 한다.
그런데 신기한 코드이다 왜 그런지는 모르겠지만 마지막 줄이 5번째 줄인데 6번째 줄 시작부분까지 있으면 52ms가 나오고 5번째줄까지만 있으면 56ms가 나온다.
사실 52ms가 있는지도 처음알았는데 변덕이 심하다.
물론 이것은 핵심은 아니다
핵심은 elif로 처리하는 배수부분을 else 부분에서 print로 처리했다는 부분이다.
print()는 흔히들 출력을 하거나 delimiter를 이용해 사용하는 것을 본적은 있지만 조건문을 리스트안에서 따져서 사용하는 것은 처음 보았다.
사용법은 다음과 같다.
print([A,B][condition])이렇게 사용한다. 물론 []과 [] 사이에 ,(콤마)는 없다.
뜻은 condition이 틀리다면 A를 출력하고 맞다면 B를 출력한다는 뜻이다.
그럼 다시 이분의 코드를 보면 a%b>0가 틀리면(즉 a%b=0)이면 "multiple"을 출력하고 조건이 맞으면 "neither"를 출력하겠습니다라는 뜻이다.
조건문이기 때문에 당연히 시간복잡도는 상수이므로 크게 신경쓰지 않아도 된다.
참고로 indentation 즉 띄어쓰기 부분에 따라 용량을 줄일 수 있다.
파이썬은 2번의 띄어쓰기를 이용한 코드와 tab(4번의 띄어쓰기)을 이용한 코드가 같다. 때문에 Byte를 줄이고 싶다면 이를 통해 줄이는 것 또한 하나의 방법이다.
속도는 차이 없다.
(2) baehyunsol, 171B 52ms -> 56ms
이 코드는 내가 짠 코드와 매우 유사해보인다. 그런데 이 코드도 신기한 점은 이 분의 코드형식을 그대로 제출하면 171B인데 중간중간 보이는 공백을 줄여서 제출하면 208B가 나오는 신기한 코드이다. 왜 그런지는 모른다.
while True:
a, b = list(map(int, input().split()))
if a == 0:
break
if a % b == 0:
print('multiple')
elif b % a == 0:
print('factor')
else:
print('neither')
위와 같은 코드인데 208B가 나옴...
while True:
a, b = list(map(int, input().split()))
if a == 0:
break
if a % b == 0:
print('multiple')
elif b % a == 0:
print('factor')
else:
print('neither')
그래도 내가 추구하고자하는 방향대로 만들어진 코드이다
6. Shortest Code
(1) sait2000 99B 64ms
a=1
while a:a,b=map(int,input().split());a>0!=print('mn uefliattcihtpeolrre'[(a%b>0)+4*(b%a<1)::3])
음 글자 수를 줄여보겠다고 했던 것 같은데 읽기 어렵다.
3칸씩 뛰어 읽는 부분도 컴퓨터니까 가능하고 실제로 복잡도 또한 유용하지 않다.
그럼에도 배울점이 있는데 a를 통해 whlie문을 돌리는 점과 a>0!= 이 부분은 배울 점이다. 사실 무한루프를 도는 것은 뭐.... 알겠지만 a>0!=는 생소하다.
사용법은 아래와 같다
조건!=print()이라고 적으면 조건에 부합하면 print해주세요라는 의미이다.
!=를 우리는 같지 않다라고 이해하고 사용할 수 있다.
그럼에도 여기서는 반대의 뜻을 의미한다.
!에 헷갈리면 안된다.
비슷한 숏코딩이 있는데 이것은 우리가 5-(1)번에서 봤던 분의 코드이다.
(2) changhw 107B 56ms
a=1
while a:
a,b=map(int,input().split())
a>0!=print("factor"if b%a<1 else["multiple","neither"][a%b>0])
(1)에서 배웠던 조건문!=print()형식과 a를 이용한 무한루프를 사용했습니다. 시간상으로 (1)님의 코드를 배웠다라고 보는 것이 맞는 것 같다.
추가적으로 이 코드에서 배울점은 print()의 다른 활용법이다.
이것은 좀 유명할 수도 있지만
print(A if condition1 else B)
이렇게 쓰면 condition1이 맞다면 A를 틀리다면 B를 출력해주세요라는 의미이다.
다만 여기서는 아까배운 [A,B][condition]형식 또한 같이 넣어서 길이를 축약했다.
조건문은 상수 시간대이므로 속도에 큰 차이는 없다.
(3) lstar 120B 56ms
a,b=0,1
while a!=b:a,b=map(int,input().split());print(("neither"if a%b else"multiple")if b%a else"factor")if a!=b else 0
주어지는 입력이 자연수일 때 같을 수 없다는 조건에서 가능한 방법이다.7. 최종 제출 코드 - 108B 56ms
a=1
while a:a,b=map(int,input().split());a>0!=print(("neither" if b%a else "factor") if a%b else "multiple")
숏코딩(3) lstar, (2)changhw (1)sait2000 모든 분들의 정수를 담아 만들어봤습니다.
최종 제출 코드 업그레이드 103B 52ms
숏코딩 2등
a=1 while a:a,b=map(int,input().split());a>0!=print(["factor","neither"][b%a>0] if a%b else "multiple")
쉬운 문제도 이렇게 배울게 많다는 점을 깨달으며