본문 바로가기
알고리즘 풀이

[algorithm] 페어 - 프로그래머스: 비밀지도

by 째깍단 2023. 4. 28.

알고리즘은 돌아오는거야...!

 

답: 

더보기

vscode에서 풀이할 때는 잘 돌아갔는데 제출하면 오류가 난다!

 

IndexError: string index out of range

테스트 결과 (~˘▾˘)~
2개 중 1개 성공
 

원인 찾아보자...

 

 

zfill을 5로 설정해서 생긴 문제

n으로 바꾸면 성공!!!

 
def solution(n, arr1, arr2):
    array1 = []
    array2 = []
    
    for a in arr1:
        a = format(a, 'b')
        print(a)
        if len(a) != n:
            a = a.zfill(n)   # 5 x   n으로 지정
            array1.append(a)
        else:
            array1.append(a)  
    for r in arr2:
        r = format(r, 'b')
        if len(r) != n:
            r = r.zfill(n)   # 5 x   n으로 지정
            array2.append(r)
        else:
            array2.append(r)
    
    answer = []
    for i in range(0,n):
        answer_str = '' 
        for a in range(len(array1[i])):
            if array1[i][a] == '0' and array2[i][a] == '0':
                answer_str += " "
            elif array1[i][a] == '1' or array2[i][a] == '1':
                answer_str += '#'
        answer.append(answer_str)
    return answer

 

길고도 길다..ㅋㅋ

 

 

 

 

 

> 팀원들의 풀이

더보기

적어두고 분석해보자!

 

1) 

def solution(n, arr1, arr2):
    answer = []
    for i in range(n):
        array = bin(arr1[i] | arr2[i])
        array = array[2:].zfill(n)
        array = array.replace('1','#').replace('0',' ')
        answer.append(array)
    return answer

 

2)

def solution(n, arr1, arr2):
    answer = []
    for i, j in zip(arr1,arr2):
        a = str(bin(i|j)[2:])
        a = a.rjust(n,'0')
        # rjust : 오른쪽 정렬해서 n보다 길이가 작으면 앞에는 0으로 채운다.
        a = a.replace('1', '#')
        a = a.replace('0', ' ')
        answer.append(a)
    return answer

 

 

 

 

 

 

- 해당 문제 풀이에 쓸만한 함수들 +a 공부하여 정리 -

 

 

bin() 바이너리 함수!

Convert an integer number to a binary string prefixed with “0b”.

int를 받아  '0b'를 붙인 이진수 문자열을 만들어준다.

>>> bin(3)
'0b11'
>>> bin(-10)
'-0b1010'

 

 

 

접두사 "0b"가 필요한 경우 다음 방법 중 하나를 사용할 수 있습니다

format()

f-string

#format()
>>> format(14, '#b'), format(14, 'b')
('0b1110', '1110')

#f-string
>>> f'{14:#b}', f'{14:b}'
('0b1110', '1110')

 

 

format(value, format_spec='')

2개의 인자를 받아 format_spec에 따라 값을 변환해준다.

기본 format_spec은 일반적으로 호출과 동일한 효과를 제공하는 빈 문자열  = str(value)

 

 

 

 

+++ python에서 2진수 8진수 16진수 다루기

 

bin() = 2진수

oct() = 8진수

hex() = 16진수

 

 

동일한 숫자값 42를 넘겨준 것이기 때문에 str(value)에 넣었을때 모두 '42'가 나온다!

 

>>> bin(0b101010)
'0b101010'
>>> oct(0b101010)
'0o52'
>>> hex(0b101010)
'0x2a'
>>> str(0b101010)
'42'

 

 

int()로 정수형으로 바꾸어줄 수 있음. 이때 인자는 첫번째에 진수값, 두번째는 base값을 넣어준다.

 

 

>>> int('0b101010', 2)
42
>>> int('0o52', 8)
42
>>> int('0x2a', 16)
42

#int의 두번째 인자는 default값이 10임!
>>> int('42', 10)
42
>>> int('42')
42

 

 

 

 

[참조] :

https://docs.python.org/3/library/functions.html?highlight=bin#bin +format()

https://deepnote.com/workspace/dale-seo-dc7078e7-0cb4-468a-9bd6-576063fa0466/project/Blog-61ddfe0e-c57f-41e1-aaa3-801467b1721e/notebook/python-int-bases-c32d922a68994405877ea71fee83f625

 

 

formet_spec mini-language 심심할때 읽어보자!

https://docs.python.org/3/library/string.html#formatspec

 

 

 

 

 

 

> 문자열에 0을 추가하기

 

 

zfill() 문자열 메서드

: 원하는 문자열 길이를 지정하는 숫자를 매개변수로 사용하고, 문자열 왼쪽에 0을 추가해준다.

매개변수로 전달된 숫자가 원래 문자열 길이보다 작으면 변화X

 

A = '1'
B = '101101'
print(A.zfill(5))  # '00001'   = 정수로 변환하면 1만 남음 주의
print(B.zfill(5))  # '101101'  = 변화 없음

 

 

 

rjust()  ljust() 문자열 메서드

: 필수 매개변수로 원하는 길이를 지정하는 숫자, 문자를 옵션 매개변수로 사용

rjust는 왼쪽, ljust는 오른쪽에 선택적 문자를 추가한다

문자를 지정하지 않으면 기본값은 공백 " "

 

A = '123'
B = 'HI'
print(A.rjust(5,"0"))  # '00123'
print(B.ljust(5,"0"))  # 'HI000'

 

 

 

format()

A = '1'
print('{:0>5}'.format(A))

이 방법은 Python 2~Python 3.5에서만 사용 = 내 python은 ver3.9 이상이어서 못쓰는 방법이었다. 왜 안되나 했네!

 

 

 

 

f-string으로 문자열 채우기

: 최신 버전에서 추가, 문자열의 빠른 형식지정을 제공해준다!

A = '1'
print(f'{A:0>5}')  # '00001'

 

 

 

# 2023년1월30일 글

[참조] : https://www.delftstack.com/ko/howto/python/pad-string-with-zeros-in-python/

 

 

 

 

 

 

 

 

 

문제 분석 및 해석

 

> 문제

지도는 한 변의 길이가 n인 정사각형 배열.

각 칸은 공백 " ", 벽 "#" 두 종류

 

전체 지도는 두장의 지도를 겹쳐서 얻을 수 있다.

어느하나라도 벽이 있으면 벽("#") 둘다 공백이면 공백(" ")

= 1이 있으면 #

= 0이면 공백

 

암호화된 배열은 지도의 각 가로 줄에서 벽 부분을 1 공백을 0으로 했을때 얻어지는 이진수에 해당하는 값의 배열

 

 

> 입 출력 값

입력 : n 과 2개의 정수 배열 arr1, arr2가 들어온다.

출력 :  '#', 공백으로 이주어진 배열

 

 

매개변수   

n              5

arr1         [9, 20, 28, 18, 11]

arr2         [30, 1, 21, 17, 28]

출력         ["#####","# # #", "### #", "# ##", "#####"]

 

 

 

 

 

 

> 분석

1) 풀이에 필요한 함수 예상

bin() 바이너리 함수?

 

 

 

2) 내가 생각한 풀이

arr1, arr2를 이진수로 바꾸고

+추가+ 길이를 맞춰주기

 

바꾼 숫자에서 1이 있는 부분을 합치고   =>이 부분을 조금 더 자세하게 생각해야했다!

 

#, ' '으로 변환하여 출력

 

 

 

 

 

 

 

 

 

- 과정1 -

이진수를 만드는 bin()함수로 arr1, arr2 바꾸기

 

arr1 = [9, 20, 28, 18, 11]

def solution(n, arr1, arr2):
    for a in arr1:
        arr1 = bin(a)
        print(arr1)

#arr1 변환 결과 값
0b1001
0b10100
0b11100
0b10010
0b1011

 

 

 

0b를 떼어내기 위해서 format()함수를 사용하고, zfill() 함수로 5자리를 맞추어 주었다

 

array1 = []

for a in arr1:
    a = format(a, 'b')
    if len(a) != n:
        a = a.zfill(5)
        array1.append(a)
    else:
        array1.append(a)   
        
#결과 값
arr1 = ['01001', '10100', '11100', '10010', '01011']

 

 

 

 

 

잠시 int값으로도 넣어보았는데 열심히 넣어준 0이 싹 사라지는 것을 볼 수 있다!

 

for r in arr2:
    r = format(r, 'b')
    if len(r) != n:
        r = r.zfill(5)
        array2.append(int(r))
    else:
        array2.append(int(r))



# [11110, 1, 10101, 10001, 11100]

 

 

 

 

각각의 자리를 비교해 1과 0을 넣기위해 이차원배열에 각각의 문자열을 쪼개어 넣고, 비교하고자했는데

 

코드가 너무 복잡해지고, 어떤 값을 넣어 비교해야할지 헷갈리는 상태가 되었다.

 

 

 

 

 

 

 

 

과정2.

 

이 시점에서 막혔는데, 팀원과 문제점을 공유하고 방법을 추천받았다

문자열도 인덱스가 된다는 것을 재확인.

 

 

for문으로 문자열의 길이를 만큼의 index값을 받아오고, 각각의 자리를 비교하여 바꾸어주는 방법을 사용했다.

 

for i in range(0,n):
    answer_str = '' # 문제점: 1초기화를 못하고 있고, 2공백이 안 넣어지고 있다
    
    for a in range(len(array1[i])):
        if array1[i][a] and array2[i][a] == 0:
            answer_str += " "
        elif array1[i][a] or array2[i][a] == 1:
            answer_str += '#'

    answer.append(answer_str)


# 값이...?
# ['#####', '##########', '###############', '####################', '#########################']

 

 

 

ㅋㅋㅋ 문자열 초기화를 위해 for문 바깥으로 answer_str을 빼줬다

 

answer_str = ''       # 남은문제점 : 2공백이 안 넣어지고 있다  
for i in range(0,n):
    ...

 

 

 

 

오류.. and 로 비교하기 위해  a and b를 사용하면 a, b에 모두 비교하는 내용을 적어주어야했다!

 

그러니까 array1[i][a]가 1이어서 계속 #이 들어가는 상태였던 것.

 

if array1[i][a] and array2[i][a] == 0:
    answer_str += " "
    ...

# ['#####', '#####', '#####', '#####', '#####']

 

 

 

아래와 같이 각각의 값을 비교하여 변환하도록 변경!

 

if array1[i][a] == '0' and array2[i][a] == '0':
    answer_str += " "
elif array1[i][a] == '1' or array2[i][a] == '1':
    answer_str += '#'

 

 

 

 

 


느낀점: 

혼자 해결하지 못한 것은 아쉽지만, 문제를 바라보는 시각에 대해 배웠다.

진짜로 혼자서만 해결하려고 했으면 더 많은 시간이 걸렸을 것 같다...ㅠㅠ

 

어떤 문제점이있는지 딱 잡아내는 시야와 정리하여 표현하는 부분을 배워야겠다는 생각이 들었다!

 

 

이렇게 좋은 페어프로그래밍!

동료가 있을때 함께하세요! 캬

 

 

다음에는 짧고 예쁜 코드로 보이는 동기들의 방법으로 풀어보고싶다..!