본문 바로가기

개발일지/TIL

TIL 23-05-02 페어프로그래밍 - OX 퀴즈

1. 페어프로그래밍 - OX 퀴즈

 문제점

https://school.programmers.co.kr/learn/courses/30/lessons/120907

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 시도해 본 것들

네비게이터로 문제 분석 

# quiz는 "X [연산자] Y = Z"를 원소로 n만큼 가진 리스트
# return은 X [연산자] Y == Z면 O, else X
# 공백으로 구분됨 <= split 사용
# eval()함수 사용 가능

문제를 해석했을 때 split()과 eval()함수를 사용하면 풀이가 가능해 보였음

 

팀원의 코드 구현 eval() 사용

def solution(quiz):
    answer = []
    # "X [연산자] Y = Z"를 원소로 n만큼 가진 리스트
    # return은 X [연산자] Y == Z면 O, else X

    # for문으로 quiz의 인덱스를 split한 리스트 num 만들기
    for n in quiz:
        num = n.split()
        # eval로 X [연산자] Y 계산하기
        eval_num = eval(''.join(num[0:3]))
        # if문으로 X [연산자] Y 과 Z 비교하기 
        if eval_num != int(num[4]):
            answer.append('X')
        else:
            answer.append('O')
    return answer

어렵지 않게 문제를 풀 수 있었지만, eval의 사용법과 함께 알게된 보안상의 이슈 문제로  eval() 함수를 제거한 방식도 시도했다.

 

팀원의 리팩토링 eval() 제거

def solution(quiz):
    answer = []
    for n in quiz:
        num = n.split()
        # eval 대신 if문으로 연산자 확인
        if num[1] == '-':
            an = int(num[0]) - int(num[2])
        elif num[1] == '+':  
            an = int(num[0]) + int(num[2])
            
        if an != int(num[4]):
            answer.append('X')
        else:
            answer.append('O')
    return answer

코드가 길어지긴 했지만 eval로 한 번 풀어보고 코드를 재활용해서 리팩토링하면서 금방할 수 있었다.

 해결 방법

def solution(quiz):
    answer = []
    for n in quiz:
        num = n.split()
        if num[1] == '-':
            an = int(num[0]) - int(num[2])
        elif num[1] == '+':  
            an = int(num[0]) + int(num[2])
            
        if an != int(num[4]):
            answer.append('X')
        else:
            answer.append('O')
    return answer

 알게 된 점

한 번에 좋은 코드를 만드는 것 보다 적당한 코드를 만든 뒤 그것을 개선하는 게 이해하기도 편하고 시간도 조금 쓰는 것 같다. 

 

 

1. 백준 알고리즘 - 꼬리를 무는 숫자 나열

 문제점

https://www.acmicpc.net/submit/1598/60171490

 

로그인

 

www.acmicpc.net

# 표는 n* 4의 이차원 배열
# 각 원소는 밑으로 1씩 증가
# 입력은 출발점, 도착점
# 출력은 직각 거리

 시도해 본 것들

while문 사용

# N, M = map(int, input().split())
N, M = 11, 33
width = (M-1)//4+1
length = N-width
count = 0
while True:
    M -= 4
    count += 1
    if width == M:
        break
print(count+length)
  • 의도
    width로 M의 가로 칸 구하기
    length로 N이 과 M의 세로 칸 차이 구하기
    while문으로 M을 한칸씩 당기면서 M의 가로 칸 - N의 가로 칸
  • 실제
    length값이 11, 33의 경우만 가능한 이상한 값 배출
    while문 if문 설정도 이상해서 무한루프 발생, 무한루프가 아니어도 길이가 10,000,000까지 가능하므로 사용 불가능 해보임

수식 수정하기 & 반례 찾기 1

N, M = 4, 12
width = (M-1)//4+1
length = N-width
count = (M-width)//4
print(count+length) # 정답 : 2 출력 : 3

4 ,12의 경우 같은 세로칸에 존재하지만 세로칸을 뜻하는 length의 값이 1이나옴

 

수식 수정하기 & 반례 찾기 2

N, M = 20, 39
N, M = 7, 32
width = M//4 - (N//4)
length = width*4+N - M
print(width+length)

4, 12의 경우는 2로 잘 출력하지만  20과 39에서 length가 1칸 차이인데 -3으로 음수로 바뀜

7과 32의 경우 width = 6, length = 1이지만 7과 3으로 출력함 width의 수식도 수정해야함을 찾음

 

수식 수정하기 & 반례 찾기 3

N, M = map(int, input().split())
width = (M-1)//4 - (N-1)//4
length = abs(width*4+N - M)
print(width+length)

(M-1)을 해줘야 M이 4의 배수일 때 이동한 칸 계산 가능

(N-1)을 해줘야 N이 4의 배수일 때 이동한 칸 계산 가능 

abs를 사용하면서 N이 더 높은 위치에 있는 경우 포함시키기

기존에 작성한 테스트 코드 모두 통과 

제출시 실패

 

수식 수정하기 & 반례 찾기 4

N, M = 39, 20
if N > M:
    N, M = M, N
width = (M-1)//4 - (N-1)//4
length = abs(width*4+N - M)
print(width, length)
print(width+length)

문제를 다시 읽어보자 N이 시작점이고 M이 종료지점이라는 말은 없었다.

그래서N과 M을 뒤집어 봤을 때 당연히 전혀 다른 결과가 나왔고 if문을 사용해서 큰 숫자가 M이 되도록 고정

제출 통과 

 해결 방법

N, M = map(int, input().split())
if N > M:
    N, M = M, N
width = (M-1)//4 - (N-1)//4
length = abs(width*4+N - M)
print(width+length)

최초의 while문부터 왜 저렇게 썼을까? 싶은 상태로 시작해서 일단 만들고 틀리면 수정하고 반복해서 이해도 없이 시간으로 푼 것 같다. 

 알게 된 점

지금 이 글을 작성하기 위해서 코드를 다시 들여다 보며 수식이 이제야 이해됐다.

의도한 바는 아니지만 문제에대한 이해도가 없이 코드를 구현하려면 어떤일이 벌어지는지 직접 체험했다.