728x90

<디버깅>

1. 프로그램 오류의 종류와 디버깅
버그프로그램에 존재하는 오류
디버깅오류를 고치는 행위
컴파일 에러문법적 오류. 컴파일러는 프로그램의 구문, 데이터, 의미없는 문장 등을 검사
컴파일 경고: 오류는 아니지만, 오류의 가능성이 있는 부분
런타임 오류실행시간 오류. 프로그램의 결과가 의도와 다르거나 비정상적으로 종료되는 경우

2. 프로그램 오류 비교

1) 컴파일 오류/경고 확인 및 수정
- 컴파일 요류/경고를 고치는 과정은 매우 쉬움
- 오류로 표시된 라인과 실제 오류가 있는 라인은 다를 수 있음
ex) 세미콜론 누락, 중괄호 오류
가장먼저 표시되는 오류내용부터 확인하고 수정
- 실제 오류는 하나이지만 이로 인해 여러군데 오류가 발생하는 것처럼 보일 수 있음
- 맨 처음 오류내용을 해결하면, 나머지는 저절로 해결되는 경우 많음

2) 컴파일 오류/경고와 빌드
컴파일 오류가 있으면 실행파일이 생성되지 않음
- 컴파일 경고는 있어도 실행파일 잘 생성됨

- VS의 경우( [Ctrl+F5] )
>> 소스가 변경된 경우 프로그램 빌드에 성공하면 > 프로그램 수행
>> 프로그램 빌드에 실패하면 > 기존 실행파일 수행

3) 런타임 오류 확인 및 수정
- 프로그램 실행 시 발생하는 오류
일반적으로 오류가 어디서 발생했는지 알기가 어려움
- 대부분의 시간을 이 오류를 찾고 수정하는데 소비
- 이러한 종류의 오류를 찾아 고치는 작업 >> 디버깅

3. 디버깅

1) 방법1. 프로그램 소스를 쭉 보면서 내가 어디서 틀렸나 찾아본다
- 코드가 짧은 경우에 유효
- 코드가 긴 경우 못찾을 가능성이 훨씬 큼

2) 방법2. 실제로 프로그램을 수행시켜보면서 프로그램이 내가 예상하고 원하는 과정대로 동작하는지 체크
- 계산된 결과가 맞는지 체크
- 화면에 결과값들을 출력해 보기

3) 디버깅의 기본
- 코드 중간에 있는 오류를 찾기 위해 프로그램이 내가 의도하는 과정대로 동작하는지 체크
제어 흐름과 변수에 저장된 값 및 주소를 확인

- 간단한 방법은 화면에 결과값을 출력해서 확인하기
코드에 값 체크용 조건문을 넣어서 확인
- 또는 개발툴에서 제공되는 디버깅 기능 활용하기

4) 반복문 체크 요령
반복문 시작 또는 끝 지점에서 체크

5) 함수 체크 요령
함수 시작과 끝 지점에서 체크

728x90
728x90

20240320 백준 파이썬 공부
24267번 알고리즘 수업 - 알고리즘의 수행 시간 6

1. 문제
오늘도 서준이는 알고리즘의 수행시간 수업 조교를 하고 있다. 
아빠가 수업한 내용을 학생들이 잘 이해했는지 문제를 통해서 확인해보자.

입력의 크기 n이 주어지면 MenOfPassion 알고리즘 수행 시간을 예제 출력과 같은 방식으로 출력해보자.

MenOfPassion 알고리즘은 다음과 같다.
>>> MenOfPassion 알고리즘 코드

MenOfPassion(A[], n) {
    sum <- 0;
    for i <- 1 to n - 2
        for j <- i + 1 to n - 1
            for k <- j + 1 to n
                sum <- sum + A[i] × A[j] × A[k]; # 코드1
    return sum;
}



2. 입력
첫째 줄에 입력의 크기 n(1 ≤ n ≤ 500,000)이 주어진다.

3. 출력
첫째 줄에 코드1 의 수행 횟수를 출력한다.

둘째 줄에 코드1의 수행 횟수를 다항식으로 나타내었을 때, 최고차항의 차수를 출력한다. 
단, 다항식으로 나타낼 수 없거나 최고차항의 차수가 3보다 크면 4를 출력한다.

>>>코드

n = int(input())
print((n*(n-1)*(n-2))//6)
print(3)



>>>해설
이전과 동일하게 시간 복잡도에 관한 문제이다

해당 코드를 보면
입력된 n에 따라 i가 1 ~ n-2까지 n-3회(i), 
그리고 그 i에 따라 j가 i+1 ~ n-1까지 n-2-i회(j),
마지막으로 그 j에 따라 k가 j+1 ~ n 까지 n-1-j회(k) 반복하는 코드이다.

하니씩 풀어보면
>>n 입력
>> i 가 1~n-1 까지 일떄 더하기
>> i = 1인 경우
> j = 2일때 k = 3~n까지 i * j * k>> 시행 횟수(항의 개수) n-2
> j = 3일때 k = 4~n까지 i * j * k>> 시행 횟수(항의 개수) n-3
...
> j = n-1일때 k = n까지 i * j * k>> 시행 횟수(항의 개수) 1

>> i = 2인 경우
> j = 3일때 k = 4~n까지 i * j * k>> 시행 횟수(항의 개수) n-3
> j = 4일때 k = 5~n까지 i * j * k>> 시행 횟수(항의 개수) n-4
...
> j = n-1일때 k = n까지 i * j * k>> 시행 횟수(항의 개수) 1

>> i = 3인 경우
>> i = 4인 경우
... ...
>> i = n-2 인 경우
까지

따라서 총 시행횟수는 
1부터 n-2까지의 합 + 1부터 n-3까지의 합 + ... + 1 
= (n-2)(n-1) / 2 + (n-3)(n-2) / 2 + ... 1
n*(n-1)*(n-2) / 6 이다.
그리고 수행횟수는 n의 세제곱에 비례하고, 최고차항의 차수는 3 이다.

>>>문제링크
https://www.acmicpc.net/problem/24267

728x90
728x90

2024/03/06 백준 파이썬 공부
2108번 통계학

1. 문제
수를 처리하는 것은 통계학에서 상당히 중요한 일이다. 
통계학에서 N개의 수를 대표하는 기본 통계값에는 다음과 같은 것들이 있다. 
단, N은 홀수라고 가정하자.

- 산술평균 : N개의 수들의 합을 N으로 나눈 값
- 중앙값 : N개의 수들을 증가하는 순서로 나열했을 경우 그 중앙에 위치하는 값
- 최빈값 : N개의 수들 중 가장 많이 나타나는 값
- 범위 : N개의 수들 중 최댓값과 최솟값의 차이

N개의 수가 주어졌을 때, 네 가지 기본 통계값을 구하는 프로그램을 작성하시오.

2. 입력
첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다. 
그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.

3. 출력
첫째 줄에는 산술평균을 출력한다. 소수점 이하 첫째 자리에서 반올림한 값을 출력한다.
둘째 줄에는 중앙값을 출력한다.
셋째 줄에는 최빈값을 출력한다. 여러 개 있을 때에는 최빈값 중 두 번째로 작은 값을 출력한다.
넷째 줄에는 범위를 출력한다.

>>>코드1 => 실패

l = []
N = int(input())
for _ in range(N):
    l.append(int(input()))
l.sort()
# 산술 평균
print(round(sum(l)/N))
# 중앙값
print(l[N//2])
# 최빈값
c = [0] * (max(l)+1)
n, p = 0, 0
for i in l:
    c[i] += 1
if c.count(max(c)) == 1:
    print(c.index(max(c)))
else:
    for i in range(len(c)):
        if p != 1 and c[i] == max(c):
            p += 1
        elif p == 1 and c[i] == max(c):
            print(i)
            break
# 범위
print(max(l)-min(l))



입력 숫자가 음수일 경우를 생각하지 않았다.

>>>코드 2 => Python3로 하면 시간초과, Pypy3로는 성공

# 숫자 입력받고 저장하기
l = []
N = int(input())
for _ in range(N):
    l.append(int(input()))
l.sort()

# 산술 평균
print(round(sum(l)/N))

# 중앙값
print(l[N//2])

# 최빈값
# 각 숫자의 개수를 저장할 딕셔너리 생성
count = {}
# 딕셔너리 수와 개수 저장
for i in l:
    if i in count:
        count[i] += 1
    else:
        count[i] = 1
# 가장 많이 나온 횟수를 freq에 저장
freq = max(count.values())
# 최빈값들만 저장할 리스트 n
n = []
for key, value in count.items():
    if value == freq:
        n.append(key)
# 만약 최빈값의 수가 1개면 그냥 출력, 아니면 2번째 것 출력
if len(n)==1:
    print(n[0])
else:
    print(sorted(n)[1])
    
# 범위
print(max(l)-min(l))
728x90
728x90

11/ 24 파이썬 공부
1. 백준 25305번 커트라인

1) 문제
2022 연세대학교 미래캠퍼스 슬기로운 코딩생활에 N명의 학생들이 응시했다.
이들 중 점수가 가장 높은 k명은 상을 받을 것이다. 이 때, 상을 받는 커트라인이 몇 점인지 구하라.
커트라인이란 상을 받는 사람들 중 점수가 가장 가장 낮은 사람의 점수를 말한다.

2) 입력
첫째 줄에는 응시자의 수 N과 상을 받는 사람의 수 k가 공백을 사이에 두고 주어진다.

둘째 줄에는 각 학생의 점수 x가 공백을 사이에 두고 주어진다.

3) 출력
상을 받는 커트라인을 출력하라.

4) 제한
- 1 ≤ N ≤ 1,000 
- 1 ≤ k ≤ N 
- 0 ≤ x ≤ 10,000 

>>>코드

# n 과 k 입력받기
n, k = map(int, input().split())
# 한 줄에 각 인원의 성적을 입력받아 리스트에 저장 후 내림차순으로 정렬
score = sorted(list(map(int, input().split())), reverse = True)
# 처음에서 k번째 성적 출력
print(score[k-1])


>>>문제 링크
https://www.acmicpc.net/problem/25305

728x90
728x90

11/ 23 파이썬 공부
1. 백준 2587번 대표값2

1) 문제
어떤 수들이 있을 때, 그 수들을 대표하는 값으로 가장 흔하게 쓰이는 것은 평균이다. 
평균은 주어진 모든 수의 합을 수의 개수로 나눈 것이다. 
예를 들어 10, 40, 30, 60, 30의 평균은 (10 + 40 + 30 + 60 + 30) / 5 = 170 / 5 = 34가 된다.

평균 이외의 또 다른 대표값으로 중앙값이라는 것이 있다. 
중앙값은 주어진 수를 크기 순서대로 늘어 놓았을 때 가장 중앙에 놓인 값이다. 

예를 들어 10, 40, 30, 60, 30의 경우, 크기 순서대로 늘어 놓으면

10 30 30 40 60

이 되고 따라서 중앙값은 30이 된다.

다섯 개의 자연수가 주어질 때 이들의 평균과 중앙값을 구하는 프로그램을 작성하시오.

2) 입력
첫째 줄부터 다섯 번째 줄까지 한 줄에 하나씩 자연수가 주어진다. 
주어지는 자연수는 100 보다 작은 10의 배수이다.

3) 출력
첫째 줄에는 평균을 출력하고, 둘째 줄에는 중앙값을 출력한다. 평균과 중앙값은 모두 자연수이다.

>>> 코드

n = []
for _ in range(5):
    n.append(int(input()))
n = sorted(n)
print(sum(n)//5)
print(n[2])



>>> 문제 링크
https://www.acmicpc.net/problem/2587

728x90
728x90

11/ 21 파이썬 공부
1. 백준 1018번 체스판 다시 칠하기

1) 문제
지민이는 자신의 저택에서 MN개의 단위 정사각형으로 나누어져 있는 M×N 크기의 보드를 찾았다. 
어떤 정사각형은 검은색으로 칠해져 있고, 나머지는 흰색으로 칠해져 있다. 
지민이는 이 보드를 잘라서 8×8 크기의 체스판으로 만들려고 한다.

체스판은 검은색과 흰색이 번갈아서 칠해져 있어야 한다. 
구체적으로, 각 칸이 검은색과 흰색 중 하나로 색칠되어 있고, 
변을 공유하는 두 개의 사각형은 다른 색으로 칠해져 있어야 한다. 
따라서 이 정의를 따르면 체스판을 색칠하는 경우는 두 가지뿐이다. 
하나는 맨 왼쪽 위 칸이 흰색인 경우, 하나는 검은색인 경우이다.

보드가 체스판처럼 칠해져 있다는 보장이 없어서, 
지민이는 8×8 크기의 체스판으로 잘라낸 후에 몇 개의 정사각형을 다시 칠해야겠다고 생각했다. 
당연히 8*8 크기는 아무데서나 골라도 된다. 
지민이가 다시 칠해야 하는 정사각형의 최소 개수를 구하는 프로그램을 작성하시오.

2) 입력
첫째 줄에 N과 M이 주어진다. N과 M은 8보다 크거나 같고, 50보다 작거나 같은 자연수이다. 
둘째 줄부터 N개의 줄에는 보드의 각 행의 상태가 주어진다. B는 검은색이며, W는 흰색이다.

3) 출력
첫째 줄에 지민이가 다시 칠해야 하는 정사각형 개수의 최솟값을 출력한다.

>>>코드

n, m = map(int, input().split()) # 주어진 체스판 재료의 크기 입력
chess = [] # 체스판 재료를 입력받을 리스트
paint = [] # 필요한 색칠 횟수를 저장할 리스트
for _ in range(n):
    chess.append(input()) # 체스판 재료 입력받기
for i in range(n-7): # 체스판의 크기는 8*8이므로 재료 내에서 가능한 범위 모두 검사
    for j in range(m-7):
        case1 = 0 # 왼쪽 위가 검은색인 케이스
        case2 = 0 # 왼쪽 위가 흰색인 케이스
        for k in range(i, i+8):
            for l in range(j, j+8):
                if (k+l)%2 == 0: # 짝수 번째 칸 검사하기 ex) (0,0) (0,2) (2,2) (1,3)
                    if chess[k][l] == 'B':
                        case1 += 1
                    elif chess[k][l] == 'W':
                        case2 += 1
                elif (k+l)%2 != 0: # 홀수 번째 칸 검사하기 ex) (1,0) (0,1) (3,2) (0,3)
                    if chess[k][l] == 'B':
                        case2 += 1
                    elif chess[k][l] == 'W':
                        case1 += 1
        paint.append(min(case1, case2)) # 그중 가장 적은 횟수로 칠하는 법 리스트에 추가
print(min(paint)) # 최소 경우의 수 출력

 

좀 빡세다. 그래도 기본 틀은 모든 경우의 수를 계산해보는 브루트 포스 방식이다.

>>>문제 링크
https://www.acmicpc.net/problem/1018

728x90
728x90

11/ 20 파이썬 공부
1. 백준 19532번 수학은 비대면강의입니다

1) 문제
수현이는 4차 산업혁명 시대에 살고 있는 중학생이다. 
코로나 19로 인해, 수현이는 버추얼 학교로 버추얼 출석해 버추얼 강의를 듣고 있다. 
수현이의 버추얼 선생님은 문자가 2개인 연립방정식을 해결하는 방법에 대해 강의하고, 
다음과 같은 문제를 숙제로 냈다.

다음 연립방정식에서 x와 y의 값을 계산하시오.
 
- ax+by=c
- dx+ey=f 

4차 산업혁명 시대에 숙제나 하고 앉아있는 것보다 버추얼 친구들을 만나러 가는 게 더 가치있는 일이라고 생각했던 수현이는 이런 연립방정식을 풀 시간이 없었다. 
다행히도, 버추얼 강의의 숙제 제출은 인터넷 창의 빈 칸에 수들을 입력하는 식이다. 
각 칸에는 -999 이상 999 이하의 정수만 입력할 수 있다. 
수현이가 버추얼 친구들을 만나러 버추얼 세계로 떠날 수 있게 도와주자.

2) 입력
정수 a, b, c, d, e, f가 공백으로 구분되어 차례대로 주어진다. (-999 <= a,b,c,d,e,f <= 999)

문제에서 언급한 방정식을 만족하는 (x,y)가 유일하게 존재하고, 
이 때 x와 y가 각각 -999 이상 999 이하의 정수인 경우만 입력으로 주어짐이 보장된다.

3) 출력
문제의 답인 x와 y를 공백으로 구분해 출력한다.

>>>코드

a, b, c, d, e, f = map(int, input().split())
for i in range(-999, 1000):
    for j in range(-999, 1000):
        if a*i + b*j == c and d*i +e*j == f:
            print(i, j)
            break



x, y로 가능한 수가 -999 ~ 999 까지의 정수로 제한되어있기 때문에 그냥 모든 경우의 수를 검사하는 방법인 브루트 포스로 해결 가능하다.

>>>문제 링크
https://www.acmicpc.net/problem/19532

728x90
728x90

11/ 19 파이썬 공부
1. 백준 2231번 분해합

1) 문제
어떤 자연수 N이 있을 때, 그 자연수 N의 분해합은 N과 N을 이루는 각 자리수의 합을 의미한다. 
어떤 자연수 M의 분해합이 N인 경우, M을 N의 생성자라 한다. 
예를 들어, 245의 분해합은 256(=245+2+4+5)이 된다. 
따라서 245는 256의 생성자가 된다. 
물론, 어떤 자연수의 경우에는 생성자가 없을 수도 있다. 
반대로, 생성자가 여러 개인 자연수도 있을 수 있다.

자연수 N이 주어졌을 때, N의 가장 작은 생성자를 구해내는 프로그램을 작성하시오.

2) 입력
첫째 줄에 자연수 N(1 ≤ N ≤ 1,000,000)이 주어진다.

3) 출력
첫째 줄에 답을 출력한다. 생성자가 없는 경우에는 0을 출력한다.

>>>코드

n = int(input()) # 숫자 입력 받기
for i in range(1, n+1): # 1부터 n 까지 가능한 경우의 수 다 해보기
    m = sum(map(int, str(i))) # 각 자릿수 더하기
    if n == m + i: # 생성자를 찾은 경우
        print(i)
        break
    elif i == n: # 생성자를 못찾은 경우
        print(0)



처음에는 이를 해결할 수 있는 수학적인 방법이 있을줄 알고 고민했는데,
그냥 하나부터 열까지 다 더해보는 방법으로 푸는 문제였다.

>>>문제 링크
https://www.acmicpc.net/problem/2231

728x90

+ Recent posts