백준 1107번 파이썬 풀이
문제 원본 링크 : 백준 1107번 문제
원래 계획은 다양한 알고리즘 분류 문제를 풀어보며 알고리즘의 유형들을 탐색해볼 생각이었지만, 브루트포스 알고리즘 문제를 푸는 것에 연달아 실패한 이후 먼저 브루트포스 알고리즘부터 정복해야겠다는 오기(?)가 생겼다.
그래서 이번에도 알고리즘 분류의 브루트포스 알고리즘 탭으로 들어가 문제를 하나 골랐다.
첫 시도, 잘못된 코드
#백준 1107번 문제
# 1. 사용 가능한 숫자로 주어진 채널과 가장 가까운 숫자를 만든다.
# 2. 그렇게 만든 숫자에서 + 또는 -를 눌러 주어진 채널로 이동한다.
# 3. 이 방식에서 버튼을 누른 횟수와, 채널 100에서 오로지 + 또는 -를 눌러 주어진 채널로 이동할 때 버튼을 누르는 횟수를 비교하여 횟수가 더 적은 방법을 찾는다.
# 4. 만약 주어진 채널이 100일 경우 횟수 0을 출력한다.
# 5. 만약 0에서 9까지의 모든 버튼이 다 고장났을 경우 주어진 채널과 100의 차를 출력한다.
# 6. 만약 아무 버튼도 고장나지 않았을 경우 주어진 채널의 자릿수를 출력한다.
goal = int(input())
err_count = int(input())
if err_count == 0:
pass
else:
err_buttons = list(map(int, input().split()))
#사용 가능한 숫자로 주어진 채널과 가장 가까운 숫자 만들기
def closest_ch(target_ch, err_buttons):
closest = []
if target_ch < 10:
upside_range = list(range(target_ch, 10))
else:
upside_range = list(range(target_ch, target_ch*2+1))
downside_range = list(reversed(range(0, target_ch)))
for n in upside_range:
check = True
for i in err_buttons:
if str(i) in str(n):
check = False
break
if check == False:
continue
closest.append(n)
break
for n in downside_range:
check = True
for i in err_buttons:
if str(i) in str(n):
check = False
break
if check == False:
continue
closest.append(n)
break
if len(closest) == 1:
return closest[0]
else:
if abs(closest[0]-target_ch) < abs(closest[1]-target_ch):
return closest[0]
else:
return closest[1]
def solve():
if goal == 100:
print('0')
elif err_count == 10:
print(abs(goal - 100))
elif err_count == 0:
print(len(str(goal)))
else:
closest_num = closest_ch(goal, err_buttons)
route_1 = abs(closest_num - goal) + len(str(closest_num))
route_2 = abs(goal - 100)
if route_1 < route_2:
print(route_1)
else:
print(route_2)
solve()
#백준 1107번 문제
# 1. 사용 가능한 숫자로 주어진 채널과 가장 가까운 숫자를 만든다.
# 2. 그렇게 만든 숫자에서 + 또는 -를 눌러 주어진 채널로 이동한다.
# 3. 이 방식에서 버튼을 누른 횟수와, 채널 100에서 오로지 + 또는 -를 눌러 주어진 채널로 이동할 때 버튼을 누르는 횟수를 비교하여 횟수가 더 적은 방법을 찾는다.
# 4. 만약 주어진 채널이 100일 경우 횟수 0을 출력한다.
# 5. 만약 0에서 9까지의 모든 버튼이 다 고장났을 경우 주어진 채널과 100의 차를 출력한다.
# 6. 만약 아무 버튼도 고장나지 않았을 경우 주어진 채널의 자릿수를 출력한다.
goal = int(input())
err_count = int(input())
if err_count == 0:
pass
else:
err_buttons = list(map(int, input().split()))
#사용 가능한 숫자로 주어진 채널과 가장 가까운 숫자 만들기
def closest_ch(target_ch, err_buttons):
closest = []
if target_ch < 10:
upside_range = list(range(target_ch, 10))
else:
upside_range = list(range(target_ch, target_ch*2+1))
downside_range = list(reversed(range(0, target_ch)))
for n in upside_range:
check = True
for i in err_buttons:
if str(i) in str(n):
check = False
break
if check == False:
continue
closest.append(n)
break
for n in downside_range:
check = True
for i in err_buttons:
if str(i) in str(n):
check = False
break
if check == False:
continue
closest.append(n)
break
if len(closest) == 1:
return closest[0]
else:
if abs(closest[0]-target_ch) < abs(closest[1]-target_ch):
return closest[0]
else:
return closest[1]
def solve():
if goal == 100:
print('0')
elif err_count == 10:
print(abs(goal - 100))
elif err_count == 0:
print(len(str(goal)))
else:
closest_num = closest_ch(goal, err_buttons)
route_1 = abs(closest_num - goal) + len(str(closest_num))
route_2 = abs(goal - 100)
if route_1 < route_2:
print(route_1)
else:
print(route_2)
solve()
문제 해결 접근 방식은 다음과 같다.
- 1. 사용 가능한 숫자로 주어진 채널과 가장 가까운 숫자를 만든다.
- 2. 그렇게 만든 숫자에서 + 또는 -를 눌러 주어진 채널로 이동한다.
- 3. 이 방식에서 버튼을 누른 횟수와, 채널 100에서 오로지 + 또는 -를 눌러 주어진 채널로 이동할 때 버튼을 누르는 횟수를 비교하여 횟수가 더 적은 방법을 찾는다.
- 4. 만약 주어진 채널이 100일 경우 횟수 0을 출력한다.
- 5. 만약 0에서 9까지의 모든 버튼이 다 고장났을 경우 주어진 채널과 100의 차를 출력한다.
- 6. 만약 아무 버튼도 고장나지 않았을 경우 주어진 채널의 자릿수를 출력한다.
여느 때와 같이 코드를 전부 작성한 후에는 '이번에는 진짜 틀릴 리가 없어!' 하는 근거없는 자신감과 함께 채점을 시작했으나...
도저히 혼자만의 힘으로는 역부족이라 생각해 숨고에서 코딩 과외 선생님을 구해 피드백을 받았다.
수정한 코드
#백준 1107번
#문제 해결 논리
#목표채널 : 100 -> 이동할 필요 없음. 버튼 누르는 횟수 0
#목표채널 : 100 이외의 숫자 -> 루트1과 루트2 비교 후 적은 횟수 채택
#루트1 : 현재채널 100에서 목표채널로 +/-로만 이동하는 경우
#루트2 : 사용가능한 숫자버튼을 활용해 목표채널과 가장 가까운 채널로 이동 후 목표채널까지 +/-를 활용해 이동하는 경우
#고장난 버튼 0개 : 숫자버튼만 눌러 목표채널로 바로 이동
#고장난 버튼 10개 : +/- 버튼만 눌러 목표채널로 이동
#고장난 버튼 9개(숫자 0 버튼만 사용 가능) : 숫자 0으로 이동, 목표채널까지 +/-
def route_1(target_ch:int) -> int:
return abs(target_ch - 100)
def closest_num(target_ch:int, err_buttons:list) -> int:
closest_number = 1000000
err_buttons_set = set(map(str, err_buttons))
for num in range(1000001):
num_set = set(str(num))
if err_buttons_set.isdisjoint(num_set):
if abs(closest_number - target_ch) > abs(num - target_ch):
closest_number = num
return closest_number
def route_2(target_ch:int, err_buttons_num:int, err_buttons:list) -> int:
ans = 0
if err_buttons_num == 0:
ans = len(str(target_ch))
elif err_buttons_num == 10:
ans = abs(target_ch - 100)
elif err_buttons_num == 9 and 0 not in err_buttons:
ans = target_ch + 1
else:
closest_ch = closest_num(target_ch, err_buttons)
ans = len(str(closest_ch)) + abs(closest_ch - target_ch)
return ans
def solve(target_ch:int, err_buttons_num:int, err_buttons:list) -> None:
if target_ch == 100:
print(0)
return
else:
print(min(route_1(target_ch), route_2(target_ch, err_buttons_num, err_buttons)))
return
target_ch = int(input())
err_buttons_num = int(input())
if err_buttons_num:
err_buttons = list(map(int, input().split()))
else:
err_buttons = []
solve(target_ch, err_buttons_num, err_buttons)
#백준 1107번
#문제 해결 논리
#목표채널 : 100 -> 이동할 필요 없음. 버튼 누르는 횟수 0
#목표채널 : 100 이외의 숫자 -> 루트1과 루트2 비교 후 적은 횟수 채택
#루트1 : 현재채널 100에서 목표채널로 +/-로만 이동하는 경우
#루트2 : 사용가능한 숫자버튼을 활용해 목표채널과 가장 가까운 채널로 이동 후 목표채널까지 +/-를 활용해 이동하는 경우
#고장난 버튼 0개 : 숫자버튼만 눌러 목표채널로 바로 이동
#고장난 버튼 10개 : +/- 버튼만 눌러 목표채널로 이동
#고장난 버튼 9개(숫자 0 버튼만 사용 가능) : 숫자 0으로 이동, 목표채널까지 +/-
def route_1(target_ch:int) -> int:
return abs(target_ch - 100)
def closest_num(target_ch:int, err_buttons:list) -> int:
closest_number = 1000000
err_buttons_set = set(map(str, err_buttons))
for num in range(1000001):
num_set = set(str(num))
if err_buttons_set.isdisjoint(num_set):
if abs(closest_number - target_ch) > abs(num - target_ch):
closest_number = num
return closest_number
def route_2(target_ch:int, err_buttons_num:int, err_buttons:list) -> int:
ans = 0
if err_buttons_num == 0:
ans = len(str(target_ch))
elif err_buttons_num == 10:
ans = abs(target_ch - 100)
elif err_buttons_num == 9 and 0 not in err_buttons:
ans = target_ch + 1
else:
closest_ch = closest_num(target_ch, err_buttons)
ans = len(str(closest_ch)) + abs(closest_ch - target_ch)
return ans
def solve(target_ch:int, err_buttons_num:int, err_buttons:list) -> None:
if target_ch == 100:
print(0)
return
else:
print(min(route_1(target_ch), route_2(target_ch, err_buttons_num, err_buttons)))
return
target_ch = int(input())
err_buttons_num = int(input())
if err_buttons_num:
err_buttons = list(map(int, input().split()))
else:
err_buttons = []
solve(target_ch, err_buttons_num, err_buttons)
피드백을 통해 배운 것 3가지
-
임의의 채널로 이동할 때 고장난 숫자버튼을 사용하지 않고 이동할 수 있는 지 여부
set( ) 자료형 및 메소드 활용
- 이동하려는 채널에 활용된 숫자들의 집합과 고장난 버튼의 숫자 집합에 교집합이 없으면 됨
err_buttons_set.isdisjoint(num_set)
- 교집합이 없으면
True
, 있으면False
-
함수를 정의할 때 매개변수의 자료형과 출력값의 자료형 표시 방법
def route_1(target_ch:int) -> int:
def solve(target_ch:int, err_buttons_num:int, err_buttons:list) -> None:
-
map( )은 입력 받을 때만 활용하는 것이 아니다. 배열의 각 요소들의 자료형을 한 번에 바꾸고 싶을 때 활용
배열의 각 요소 자료형을 한 번에 바꿀 때 활용
- 리스트에 있는 고장난 버튼의 숫자들의 자료형을 문자열로 바꾸어야 할 필요가 있는 상황
err_buttons_set = set(map(str, err_buttons))
Author And Source
이 문제에 관하여(백준 1107번 파이썬 풀이), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@terryst/백준-1107번-파이썬-풀이저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)