백준 문제풀이, 파이썬 변수 참조값

주제무·2022년 3월 11일
0

알고리즘

목록 보기
12/21

이어드림스쿨 온라인 인적성 검사를 끝내고 선거 알바에 학기 개강까지 겹치다보니 프로그래밍에 소홀해졌다. 시간 있을 때 실버 수준의 알고리즘 문제를 풀었는데 수정을 여러번 해야하는 것을 보고 자신이 너무 한심해서 현타가 오기도 했다. 일단 문제은행식으로 마구잡이로 풀 예정이다. 브론즈 수준의 문제를 구현, 그리디 모두 풀고 추가로 사용에 어려움을 느끼는 재귀 함수문제도 많이 풀 예정이다.

이어드림스쿨에 불합격 통보를 받았다. 교육생 모집이라서 너무 안일하게 대비했던 탓일까. 5, 6월 국비지원 소프트웨어 학습에 전념하자.

백준

백준 1837번 암호제작

def is_hard(a, n):
    if n == 2:
        return ("GOOD", )
    if a % 2 == 0:
        return "BAD", 2
    save = [True] * (n // 2)
    for i in range(3, int(n ** 0.5) + 1, 2):
        if save[i // 2]:
            k = i * i
            save[k // 2::i] = [False] * ((n - k - 1) // (2 * i) + 1)
    for i in range(1, n // 2):
        if save[i] and a % (2 * i + 1) == 0:
            return "BAD", 2 * i + 1
    return ("GOOD", )

print(*is_hard(*map(int, input().split())))

우수코딩 그리고 나의 코딩

def a():
    if k > 2 and p%2 == 0:
        print("BAD", 2)
        return
    for i in range(3, k, 2):
        if p % i == 0:
            print("BAD", i)
            return
    print("GOOD")
    
    
p, k = map(int, input().split())
a()

결과

위의 우수 코딩으로부터 *의 정확한 쓰임새를 알게되었다. 더불어 숙련된 코드에서 자주 보이는 [0](정수), [True](정수) 형태를 익힐 필요가 있다.

추가로 list slicing 활용에 대해서도 배웠다.

save[k // 2::i] = [False] * ((n - k - 1) // (2 * i) + 1)

이런 구문이면 항상 반복문을 사용했었는데, 편리한 기능을 제공하고 있었다.

백준 bj2447 별 찍기 - 10

def zero(order, row, col):
    if order == 3:
        for i in range(3):
            for j in range(3):
                result[row+i][col+j] = '*'
        result[row+1][col+1] = ' '
        return
    o = order // 3
    for i in range(row, row+order, o):
        for j in range(col, col+order, o):
            if i-row == o and j-col == o:
                continue
            #print("order, i, j :", order, i, j)
            zero(o, i, j)


n = int(input())
# all element is ' '
result = []
for i in [[' ']*n]*n:
    result.append(i[:])

zero(n, 0, 0)
#print(result)

for i in range(n):
    print(*result[i], sep='')

충격적인 실행 시간을 가지므로 사실상 오답에 해당한다. 오늘은 이만하고 내일 다시 할 예정

현재 모르는 것

함수 내부 참조에 관한 것

r = [[1, 2]]


def a():
    r[0] += [2]


a()
print(r)
r = 2
def a():
    r += 2
a()
print(r)

내용

위에는 되고 아래는 안되는 이유를 모르겠다. 외부에서 선언한 변수에 참조를 함수 내부에서는 할 수 없기 때문에 정수 오브젝트를 참고하고 있는 r(밑)에 함수에서 접근 못하는 것은 당연하다. 하지만 위의 리스트를 참고하고 있는 r은 접근하여 수정이 가능하다.
잠정적인 결론은 'identifier의 주소값만 건들지 않으면 참조 가능하다'이다

도대체 이해가 안되는 것

def zero(order, row, col):
    global result

    if n == 3:
        for i in range(3):
            for j in range(3):
                result[row+i][col+j] = 1
        print(result)
        result[2][1] = 0
        print(result)
        return
    for i in range(order):
        print()


n = int(input())
result = [[0]*n]*n
zero(n, 0, 0)
print(result)
for i in range(n):
    print(*result[i], sep='')

그리고 출력

3
[[1, 1, 1], [1, 1, 1], [1, 1, 1]]
[[1, 0, 1], [1, 0, 1], [1, 0, 1]]
[[1, 0, 1], [1, 0, 1], [1, 0, 1]]
101
101
101

내용

백준의 별 찍기 - 10 구현 중 recursion의 return에서 이와같은 현상을 발견했다. 도저히 이해가 가질 않고 파이썬 오류 발견이라고 납득하고 넘어가려 했다.

문제의 부분은

result[2][1] = 0

의 처리 결과로 result[... (설명 생략)


유레카, 포스팅하면서 깨달았다. 혹시

result = [[0]*n]*n

위의 결과로 각 element가 같은 object를 참조하고 있는 것 아닐까?
했더니 역시나 였다.

0개의 댓글

관련 채용 정보