[백준/2839]설탕배달
◯문제 링크◯
◯코드 미리보기◯
⫷처음에 짠 코드⫸
from sys import exit as kill
N = int(input())
HowMany = list()
BreakCode = True
BreakAllCode = True
Smallest = 3333
for x in range(3334):
for y in range(1001):
if N == (3*x + 5*y):
HowMany.append(x+y)
if N < 3*x :
BreakCode = False
break
if N < (3*x + 5*y):
break
if BreakCode == False:
break
if len(HowMany) == 0 :
print("%d"%(-1))
kill()
for x in range(len(HowMany)):
if Smallest > HowMany[x] :
Smallest = HowMany[x]
print(Smallest)
⫷시간단축 코드⫸
from sys import exit as kill
N = int(input())
HowMany = 0
BreakCode = True
BreakAllCode = True
Smallest = 3333
for x in range(3334):
for y in range(1001):
if N == (3*x + 5*y):
HowMany= (x + y)
BreakCode = False
break
if N < (3*x + 5*y):
break
if BreakCode == False:
break
if BreakCode == False:
break
if HowMany == 0 :
print("%d"%(-1))
kill()
print(HowMany)
◯설명◯
이 문제를 보자마자 든 생각은 이중for문을 시도해봐야겠다는 것이었다. 그렇게 코드를 짜보기 전에 머릿속으로 예외를 어떻게 처리할지 고민을 하고 있었다.
생각한 방법은 if와 else를 이용해서 n이 나눠 떨어지지 않을 때 -1을 출력하게 하는 것이었는데, 한번에 맞아 떨어지는 조건이 도저히 보이지 않아 고민이었다.
그래서 일단 생각이 난 부분부터 코드를 짜기 시작했는데, 그렇게 하다보니까 문제가 해결되었다.
코드에 들어가기에 앞서 핵심이 되는 수식을 소개하겠다. 바로 [N= 3X + 5Y]이다.
N = int(input())
HowMany = list()
BreakCode = True
BreakAllCode = True
Smallest = 3333
이번 코드에서 사용하는 변수들이다. N은 배달해야될 총 킬로그램, HowMany는 수식에 해당되는 X+Y값들이 저장될 list, BreakCode와 BreakAllCode는 각각 반복의 탈출을 위한 변수이다. Smallest는 최솟값을 구하기 위한 변수이다. 자세한건 이따가 최소값을 구하는 코드에서 설명하겠다.
for x in range(3334):
for y in range(1001):
if N == (3*x + 5*y):
HowMany.append(x+y)
if N < 3*x :
BreakCode = False
break
if N < (3*x + 5*y):
break
if BreakCode == False:
break
앞서 말한 수식(N = 3X + 5Y)을 기억하면 for문이 의미하는 것이 무엇인지 알 수 있다. 주의할 점은 바로 범위인데, for문의 범위에서 시작지점을 정하지 않으면 0부터 시작하기 때문에 그냥 3333을 하면 3332까지밖에 들어가지 않는다. 그래서 범위를 3334까지 해주어야한다. 두번째 for문 역시 같은 맥락에서 1001로 범위를 잡았다.
(3333과 1000은 5000을 각각 3과 5로 나누어서 나온 숫자이다.)
두번째 for문 안에는 if 문이 총 3개 있다.
첫번째는 수식에 일치하는 x와 y값을 찾아서 HowMany에 저장하는 코드이다.
두번째는 x값 만으로 N보다 값이 커지기 시작했을 때(최대값을 지났을 때) 이중 for문 전체의 반복을 멈추기 위해 BreakCode를 False로 바꾸고 두번째 for문을 멈추는 코드이다.
세번째는 y값 만으로 N보다 값이 커지기 시작했을 때 두번째 for문의 반복을 멈추는 코드이다.
두번째가 세번째보다 위에 있는 이유는 세번째코드가 먼저 작동할 경우 두번째 if문에 있는 BreakCode변수의 값을 바꾸는 코드가 작동하지 않기 때문이다.
맨 밑에 있는 if문은 첫번째 for문에 속한 if문으로, BreakCode가 False값으로 바뀌었을 때 첫번째 for문을 멈추는 코드이다. 이렇게 되면 이중for문 자체가 멈추게 된다.
위의 모든 코드들이 종료되고 나면 HowMany리스트 속에는 가능한 x+y의 값들이 저장되어 있다.
이때 저장된 값들이 하나도 없는 경우는 어떤 경우일까?
바로 문제에서 말하는 '정확하게 N킬로그램을 만들수 없는 경우'이다.
그래서 나오게 된 것이 바로 다음의 코드이다.
from sys import exit as kill
/
.
.
.
/
if len(HowMany) == 0 :
print("%d"%(-1))
kill()
먼저 맨 윗줄에 있는 코드부터 살펴보자. 이 코드는 sys모듈에서 exit라는 함수를 kill이라는 이름으로 꺼내온다는 말이다.
보통 이렇게 python내장함수가 아닌 다른 모듈에 있는 함수를 꺼내오는 경우에는 코드의 맨 윗줄에 적는데, 이는 코드를 보게될 다른 인원이 보기 편하게 하기 위해서이다.
그 다음 if문을 살펴보자. 조건은 HowMany리스트의 길이가 0일 때를 가리키고 있다. 만약 이중for문에서 해당되는 x+y값이 없을 경우에는 선언된 상태 그대로이기 때문에 길이가 0이되서 조건이 성립된다.
if문 안을 살펴보면, 먼저 문제에서 제시된데로 -1을 출력한다. 그 다음 아까 불러온 kill함수를 사용해서 프로그램 자체를 종료시킨다.
for x in range(len(HowMany)):
if Smallest > HowMany[x] :
Smallest = HowMany[x]
print(Smallest)
위의 for문은 최솟값을 구하는 for문이다. 코드 처음에 Smallest의 값을 최대로 잡아뒀기 때문에 if문의 조건에 일치하게 되고, 이후부터는 더 작은 값이 나올때마다 작동하게 되서 최솟값이 나오는 구조이다.
이후 구해진 최솟값을 출력하게되면 문제가 해결된다.
이렇게 코드를 다 작성하고 제출을 하고 보니, 한가지 재미있는 사실을 알게되었다.
바로 맨 처음 구해진 x+y의 값이(HowMany리스트의 첫번째 인자가) 제일 최솟값이라는 사실이다.
이것을 이용해서 시간을 단축시킨 코드가 바로 코드미리보기에 나와있는 시간단축코드이다.
처음에 작성했던 코드와의 차이점은 3가지이다.
HowMany = 0
HowMany를 리스트에서 그냥 변수로 변경,
if N == (3*x + 5*y):
HowMany= (x + y)
BreakCode = False
break
이중 for문에서 x+y의 값을 처음 찾게되면 for문의 반복을 멈춤,
if HowMany == 0 :
print("%d"%(-1))
kill()
그리고 예외의 경우를 for문이 아닌 if 문으로 출력한다는 점이다.
◯배운 것◯
⩥break는 해당 루프 하나만을 멈추는 것, 다중루프문에서 전체 루프를 부수려면 위의 방식을 사용해야한다.
ㄴ다른 함수가 있는지 더 찾아볼 것
⩥sys 모듈에는 프로그램 전체를 멈추는 exit함수가 존재한다. 사용하려면 exit()의 방식으로 사용해야한다.
⩥from import구문을 사용할 때 as를 추가하면 원하는 이름으로 함수를 사용할 수 있다.