[파이썬 코드카타]
3진법 뒤집기
https://school.programmers.co.kr/learn/courses/30/lessons/68935
1) 어떤 문제가 있었나: N진법 개념을 몰라서 공부해봄
- 문제: 자연수 n을 3진법 상에서 앞뒤로 뒤집은 후, 이를 다시 10진법으로 표현한 수를 반환
① N진법의 의미
- 진법이란? 수를 셀 때, 자릿수가 올라가는 단위를 기준으로 하는 셈법의 총칭. 수를 표기하는 기수법 중 하나
- 표기에 사용되는 수의 개수에 따라 N진법으로 이름이 붙음
└ 일반적으로 사용하는 0 1 2 3 4 5 6 7 8 9 로 이뤄진, 10개 문자를 이뤄진 표기법이 바로 10진법 (ex 34,205 등)
└ 컴퓨터 공항에서 주로 쓰이는 2진법에서는 숫자 표기에 0, 1만 사용
- 숫자의 밑(base)에 각 진법에 해당되는 숫자를 적어서 표기 (ex. 2진법: 1010112 , 10진법: 34,21510 등)
② 10진법 계산하는 법
34,215
= 30,000 + 4,000 + 200 + 10 + 5
= 3 * 104 + 4 * 103 + 2 * 102 + 1 * 101 + 5 * 100
▽ 식으로 표현한 경우
③ N진법 계산 응용
- N진법은 첫째 자릿수(오른쪽)부터 0, 1, 2 제곱을, 즉 N자릿수을 해주면 됨
a*Nb
(a는 각 자리에 위치한 상수, b는 자릿수(0부터시작), N은 진법)
- 2진법 예시:
1010112
= 1* 25 + 1* 23 + 1* 21 + 1* 20
= 32 + 8 + 2 +1
= 4310
③ 10진법 > N진법으로 변환
- 10진법 숫자를 N으로 나눠 나머지 값을 구하기를 반복 > 맨 마지막에 나온 나머지 값부터 앞에 배열하면 완료
2) 내가 시도해본 건 무엇인가
- N집법을 구하는 것에 대해서 순서 대로 정리 해봄
- 첫 번째 시도: 주어진 n값은 고정하고 3의 제곱값을 늘려서 나머지 값을 추출하면 어떨까?
# 45 / 3**1 = 15 #0
# 45 / 3**2 = 5 #0
# 45 / 3**3 = 1.6 #18 #1
(결과) 분모의 크기가 달라 나머지 값이 다르게 나와서 실패
- 재시도
[코드 순서]
① n값을 3으로 나눠서 나온 값의 리스트를 뽑는 함수가 필요. list = [45, 15, 5, 1.6]
② 3을 나눈 값 리스트에서 원소를 하나씩 뺀 다음 3을 나눈 나머지와 마지막 몫을 자리에 맞게 배치
③ 3진법으로 숫자를 다시 10진법으로 표현
- n=125인 경우에서 실패
#n=45일 때를 기준으로 작성
def solution(n):
answer = 0
result = 0
list = []
list_length = []
for i in range(n):
if (n / 3**i) > 3:
list.append(n / 3 ** i) # list = [45.0, 15.0, 5.0]
for j, k in zip(list, range(len(list))): #j, k = [(45, 0), (15,1), (5, 2)]
if k == 0:
#맨 오른쪽 - 첫째 자리수(K==0)는 나머지만 45%3
answer = int(j % 3) #첫째 자리수(K==0)는 나머지만 45%3
else:
#둘째 자리수부터는 10의 제곱 곱해서 자리수 만들기
answer = int(answer + (j % 3)*10**k)
if j / 3 < 3:
#맨 왼쪽 - 앞자리수는 몫을 앞에 넣기
#3으로 더이상 나눌 수 없는 경우에 해당
answer = int( answer + (j // 3)*10**(k+1) )
# 숫자 뒤집기는 pass #10진법으로 다시 바꿀 때, 뒤에 숫자부터 들어가니까
# reversed_answer = str(answer)[::-1] #숫자 뒤집기는 pass #'0021'
#answer 값을 하나씩 빼기 위해 str 처리
str_answer = str(answer) #'1200'
for r in range(len(str_answer)): # r =[0, 1, 2, 3]
result = result + (int(str_answer[r])*3**r)
return result
- 나머지(%)와 몫(// )을 구한뒤 소수점 처리 되었는데 10의 제곱을 곱하면서 전체 값이 틀림 > 나머지(%)와 몫(// ) 부분에 int 상수처리를 해주고 재시도 하였으나 정확성 30점으로 또 실패
def solution(n):
answer = 0
result = 0
list = []
list_length = []
for i in range(n):
if (n / 3**i) > 3:
list.append(n / 3 ** i) # list = [45.0, 15.0, 5.0]
for j, k in zip(list, range(len(list))): #45, 0 / 15,1 / 5/2
if k == 0:
answer = int(j % 3) # 첫째 자리수는 나머지만 45%3
else:
answer = answer + int(j % 3)*10**k # 두번째자리수부터는 10의 제곱처리
if j / 3 < 3:
answer = int( answer + int(j // 3)*10**(k+1) ) #마지막 3으로 더이상 나눌 수 없으면 몫을 앞에 넣기
# reversed_answer = str(answer)[::-1] #숫자 뒤집기 #'0021'
str_answer = str(answer) #'1200'
for r in range(len(str_answer)): # 0 1 2 3
result = result + (int(str_answer[r])*3**r)
return result
3) 어떻게 해결했나
- 도저히 모르겠어서, 결국 다른 사람 풀이를 보고 진법과 관련한 내장함수 추가 공부
def solution(n):
answer = "" #빈 문자열 준비
while n > 0: #while로 n이 0 미만일 때까지 반복 설정
answer = answer + str(n % 3) #n%3(나머지값)을 문자열로 해서 answer에 더하기
n = n // 3 #n을 3으로 나눌 때 마다 나오는 몫을 n에 새롭게 지정 > while식 n 값이 적어짐
answer = int(answer, 3)
return answer
4) 무엇을 새롭게 알았나
① int()
- int(x) : 문자열 혹인 실수 형태의 값을 정수로 반환하는 함수. 실수일 경우 버림처리
# 문자열
int('3') # 3
int('3.5') # error
#실수
int(3.1) # 3
int(3.96556) # 3
- int(x, N): 문자열 x를 N진수로 변환 후 반환! > 처음 알게된 사실
int('1332', 4) #126
int('12201', 3) #154
② while
- while은 특정 조건이 만족되기까지 계속 반복되는 함수라는 것을 알고 있었으나 활용 방식을 제대로 이해못함
- 만약 while n > 0 과 같은 조건이 있다면, while이 반복되는 과정에서 n이 0 이하가 되어 멈출 수 있는 식이 필요함
- 본 문제에서는 n = n // 3 조건을 통해 n을 3으로 나눴을 때 몫을 n변수로 새롭게 지정해서 값을 줄여나감
n = 45
answer = []
while n > 0:
answer.append(n)
n = n // 3
answer # [45, 15, 5, 1]
③ divmod()
- 두 개의 숫자를 인자로 받아, 첫 번째 숫자를 두 번째 숫자로 나눈 몫과 나머지를 튜플(tuple) 형태로 반환
divmod(x, y) = (x // y, x % y)
#예시
divmod(3, 8) #(0, 3)
3//8 == 0
3 % 8 == 3
- divmod()를 활용한 다른 사람 문제 풀이
└ n 조건을 3이상으로 해서 마지막 몫은 별도 추가 함
arr=[]
while n >= 3:
n,r = divmod(n, 3) #n은 나누기의 몫, r은 나머지
arr.append(r) # 나머지는 리스트에 넣고, 3으로 나눈 몫 n은 다시 while로
arr.append(n) # n을 3으로 나눌 수 있는 마지막 숫자의 몫은 마지막으로 추가
print(arr) #[0, 0, 2, 1]
# map 복습: map(함수명, 함수를 적용할 iterator)
# join 복습: 구분자.join(리스트) / 각 리스트에 있는 문자열을 하나로 합쳐줌
# arr 각각 요소가 str 문자열이 되도록 한뒤,
answer = ''.join(map(str,arr))
answer = int(answer,3)
└ while의 n 조건을 0 이상으로하므로, 나머지값(mod)만 리스트에 추가해도 됨
n = 45
#3진법으로 변환 과정(뒤집힌 순으로 되어있음)
rev_base = []
while n > 0:
n, mod = divmod(n, 3)
rev_base.append(mod)
print(rev_base) # [0, 0, 2, 1]
answer=0
for i in range(len(rev_base)):
answer+=(3**i)*rev_base[::-1][i]
# rev_base[::-1] 이 리스트 순서를 거꾸로 한 것
# [1, 2, 0, 0]으로 리스트를 바꿔서, 10진법으로 바꾸는 계산 적용
answer
'TIL' 카테고리의 다른 글
[240315] 스파크(spark): 컴퓨터와 데이터, 메모리, 클라우드 (1) | 2024.03.15 |
---|---|
[240314] 파이썬: 코드카타 41 (0) | 2024.03.14 |
[240312] 실전 프로젝트: 대시보드 스케치 & 피그마 배경 생성 및 태블로 적용 (0) | 2024.03.12 |
[240311] 실전 프로젝트: 태블로 대시보드 시뮬레이션 대시보드 (0) | 2024.03.12 |
[240308] 실전 프로젝트: 태블로 도넛 안에 파이 차트(다중 차원-동일 측정값) (0) | 2024.03.12 |