알고리즘, 백준 문제풀이, 혼공파

주제무·2022년 3월 4일
0

알고리즘

목록 보기
9/21
post-thumbnail

학기가 시작했다.

요번 학기 목표는 이어드림스쿨 등록과 우수한 학점이다.

방학 때 하던 프로그래밍 맛만 보기는 끝났고, 이제는 체계적으로 진행하려고 한다.

우선, 혼공파 정리를 끝내고, Java 문법을 조금 정리하려고 한다. 이어드림스쿨이 3월 말에 결과가 나오므로 만약 등록이 된다면 AI와 Digital Transformation에 집중하고 아니라면 5~6월 캠프 시험 대비를 위해 알고리즘에 집중하려고 한다.

일단 지금은 파이썬과 인공지능에 대한 학습이 중요하지만 그러기엔 지루하므로 백준 문제를 조금씩 풀어보려고 한다.

백준 14891

import sys


def clockwise(arr, number, k):
    if k == 1:
        arr[number].insert(0, arr[number].pop())
    else:
        arr[number].append(arr[number].pop(0))


li = []
for _ in range(4):
    li.append(list(map(int, sys.stdin.readline().rstrip('\n'))))

num = int(input())

for i in range(num):
    N, M = map(int, input().split())
    N -= 1
    n, m = N, M
    clockwise(li, n, m)
    for _ in range(3):
        # right-side effect
        if n < 3:
            if li[n + 1][6] != li[n][2 + m]:
                clockwise(li, n + 1, -m)
                m = -m
                n += 1
            else:
                break

    n, m = N, M
    for _ in range(3):
        # left-side
        if n > 0:
            if li[n-1][2] != li[n][6 + m]:
                clockwise(li, n-1, -m)
                m = -m
                n -= 1
            else:
                break
result = 0
for i in range(4):
    result += (2**i)*li[i][0]

print(result)

그리고 이어지는 우수한 코드

import sys
read = sys.stdin.readline
gears = []
for _ in range(4):
    gears.append(read().strip())

def rotate(target, num, spin, left = True, right= True):
    left_target, right_target = False, False
    if (left):
        if num > 0 and num <= 3:
            left_target = gears[num-1]
        else: left = False
    if (right):
        if num >= 0 and num < 3:
            right_target = gears[num+1]
        else:
            right = False

    if left_target and left_target[2] != target[6]:
        rotate(left_target, num-1, -spin, left= True, right= False)
    if right_target and right_target[6] != target[2]:
        rotate(right_target, num+1, -spin, left= False, right= True)

    if spin == 1:
        gears[num] = target[-1] + target[0:-1]
    else:
        gears[num] = target[1::] + target[0]

for i in range(int(read())):
    num, spin = map(int, read().split())
    rotate(gears[num-1],num-1, spin)
ans = ''
for i in range(3,-1,-1):
    ans += gears[i][0]

print(int(ans,2))

결과

ans = ''
for i in range(3,-1,-1):
    ans += gears[i][0]

print(int(ans,2))
  • 요구한 답이 자리별로 2^ 만큼 커져서 나는 2** 또는 pow()를 생각했다. 요런 방법도 있다는 것을 알았다.

  • 입력받은 리스트를 매개변수로 함수에 전달하고 이를 처리한 다음에 원래의 리스트를 수정함으로 insert와 append를 사용하지 않았다.

백준 1244번

def reverse_switch(idx):
    if switch[idx] == 1:
        switch[idx] = 0
    else:
        switch[idx] = 1


num = int(input())
switch = list(map(int, input().split()))
n = int(input())

for _ in range(n):
    x, y = map(int, input().split())

    # 남자
    if x == 1:
        for i in range(len(switch)//y):
            reverse_switch((i+1)*y-1)
    # 여자
    else:
        rng = 0
        y -= 1  # index 고려
        flag = True
        while 0 <= y - rng and y + rng < len(switch) and flag:
            q = []
            start = y-rng
            end = y+rng
            for i in range(start, end+1):
                if i < y:
                    q.append(switch[i])
                elif i > y:
                    if q.pop() != switch[i]:
                        rng -= 1
                        flag = False

                        for j in range(2*rng + 1):
                            reverse_switch(start+j+1)
                        break
            rng += 1
        if flag:
            rng -= 1
            for j in range(2 * rng + 1):
                reverse_switch(y-rng + j)

li = [switch[:20]]
li.append(switch[20:40])
li.append(switch[40:60])
li.append(switch[60:80])
li.append(switch[80:100])

for i in range(5):
    if li[i]:
        print(*li[i])

이어지는 굿 답

import sys
input = lambda: sys.stdin.readline().rstrip()

n = int(input())
a = [0] + list(map(int, input().split()))
s_n = int(input())

switch = {0:1, 1:0}

for _ in range(s_n):
    g, num = map(int, input().split())
    if g == 1:
        for i in range(num, n+1, num):
            a[i] = switch[a[i]]
    else:
        a[num] = switch[a[num]]
        i = 1
        while (num - i >= 1) and (num + i <= n) and (a[num - i] == a[num + i]):
            a[num-i], a[num+i] = switch[a[num-i]], switch[a[num+i]]
            i+=1

for idx, el in enumerate(a[1:], start = 1):
    print(el, end=" ")
    if not idx % 20:
        print()

결과

구질구질한 마지막 처리까지, 무조건 답은 맞춘다는 생각으로 했다. 그래도 구현에 있어서 자세한 부분은 역시 많은 입력을 필요로 하지만 큰 틀을 짜는 것에 있어서 능숙해지고 있음을 느꼈다. index 에러에 주의깊게 대처할 수 있다.

결과 정리

  • switch = {0:1, 1:0} 를 이용하여 따로 함수를 만들지 않아도 된다.

  • _for idx, el in enumerate(a[1:], start = 1):
    print(el, end=" ")
    if not idx % 20:
    print()

    이 부분이 핵심인데, enumerate 함수를 이용하면 index와 element를 동시에 접근할 수 있다. _

  • for i in range(num, n+1, num):
    a[i] = switch[a[i]]

    이러한 접근법이 있다는 것을 참고하였다.

  • 구현에서의 디테일 참고사항 : 여학생의 경우 바로 바꾸지 않고 for 반복문을 통해 구역을 정한 다음에 한번에 바꾸는 것으로 구현했는데, 그럴 필요가 없었다. 이처럼 구현 방법의 다양성을 처음부터 생각할 필요가 있음을 알았다.

혼공파 파이썬

인덱싱(indexing)

[ ]을 이용하여 특정위치를 참조하는 것

슬라이싱(Slicing)

[ : ]와 같이 ':'을 이용해서 문자열의 일부 추출하는 것

부동소수점 지수표현

Ex> 0.34e5

자료형 변환(cast)

literal

data, 자료

format 함수 활용

자리수 맞춰서 출력

Ex> "{:05d}".format(52) -> 00052

부호 선택 출력 가능

Ex> "{:+d}".format(52) -> +52, (format(-52) -> -52)

부동소수점 아래 자릿수 설정

Ex> "{:15.1f}".format(52.273) -> 52.1

의미없는 0 제거

:g Ex> 0.0 -> 0

문자열 내부함수

isalnum

알파벳과 숫자 True or False

isspace

공백으로만 이루어진 문자열일 때, True; empty string일 경우 False

find & rfind

각각 왼쪽, 오른쪽부터 시작해서 주어진 매개변수를 찾아 인덱스값을 반환

0개의 댓글