python 공부 2024.04.11
투포인터
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# ---------------------------좋은 수(투포인터)-----------------------------------
import sys
input = sys.stdin.readline # 표준 입력을 빠르게 받기 위해 sys.stdin.readline을 input으로 재정의
N = int(input()) # 리스트 A의 길이를 입력받음
Res = 0 # 결과를 저장할 변수 초기화
A = list(map(int, input().split())) # 리스트 A를 입력받고 정수형으로 변환하여 리스트로 만듦
A.sort() # 리스트 A를 정렬함
# 리스트 A에서 합이 특정 원소와 같은 두 원소를 찾는 반복문
for k in range(N):
find = A[k] # 현재 찾아야 하는 값 설정
i = 0 # 리스트 A의 가장 작은 값의 인덱스
j = N - 1 # 리스트 A의 가장 큰 값의 인덱스
# i와 j가 만날 때까지 반복
while i < j:
# 현재 인덱스 i와 j에 있는 두 원소의 합이 find와 같다면
if A[i] + A[j] == find:
# 현재 인덱스 i와 j가 k와 다르다면 (k를 두 번 사용하지 않은 경우)
if i != k and j != k:
Res += 1 # 결과값 증가
break # 반복문 종료
# 현재 인덱스 i와 k가 같다면
elif i == k:
i += 1 # i를 한 칸 뒤로 이동
# 현재 인덱스 j와 k가 같다면
elif j == k:
j -= 1 # j를 한 칸 앞으로 이동
# 현재 인덱스 i와 j에 있는 두 원소의 합이 find보다 작다면
elif A[i] + A[j] < find:
i += 1 # i를 한 칸 뒤로 이동
# 그렇지 않으면
else:
j -= 1 # j를 한 칸 앞으로 이동
print(Res) # 결과 출력
스택과 큐
- 스택은 핫케잌 쌓기, 큐는 파이프
- 스택은 LIFO, 큐는 FIFO
- 스택은 깊이우선탐색(후입선출은 개념자체가 재귀 함수 알고리즘 원리와 일맥상통), 큐는 너비우선탐색
스택으로 수열만들기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
N = int(input()) # 입력으로 주어지는 수열의 길이를 입력받음
A = [0] * N # 수열을 저장할 리스트를 생성
for i in range(N):
A[i] = int(input()) # 수열의 각 원소를 입력받음
stack = [] # 스택을 초기화
num = 1 # 스택에 push할 다음 숫자를 나타내는 변수
result = True # 수열을 만들 수 있는지 여부를 나타내는 변수
answer = "" # 스택의 push와 pop 과정을 저장할 문자열
for i in range(N):
su = A[i] # 현재 수열의 원소를 나타내는 변수
if su >= num:
# 현재 원소가 다음 숫자보다 크거나 같다면
while su >= num:
stack.append(num) # 스택에 숫자를 push
num += 1 # 다음 숫자로 넘어감
answer += "+\n" # 스택에 push하는 과정을 문자열에 추가
stack.pop() # 마지막으로 push한 숫자를 pop하여 현재 수열의 원소를 만듦
answer += "-\n" # 스택에서 pop하는 과정을 문자열에 추가
else:
# 현재 원소가 다음 숫자보다 작다면
n = stack.pop() # 스택에서 원소를 pop하여 현재 수열의 원소를 만듦
if n > su:
print("NO") # 주어진 수열을 만들 수 없는 경우 "NO"를 출력하고
result = False # result를 False로 설정하여 프로그램을 종료함
break
else:
answer += "-\n" # 스택에서 pop하는 과정을 문자열에 추가
if result:
print(answer) # 주어진 수열을 만들 수 있는 경우 스택의 과정을 출력함
카드게임
1
2
3
4
5
6
7
8
9
10
11
12
13
N = int(input())
q = []
num = N
for i in range(N, 0, -1):
print(i)
q.append(i)
while num > 1:
q.pop()
q.insert(0,q.pop())
num -= 1
print(q[0])
이렇게 풀었는데 백준에 가서 돌려보니까 시간초과가 떴다.
다른 방식을 참고하던가 다른 방식으로 풀어봐야겠다.
1
2
3
4
5
6
7
8
9
10
11
12
from collections import deque
a = int(input())
dt = deque(range(1, a+1))
# 먼저 가장 위에 있는 카드를 버리고 그 다음 가장 위에 있는 카드를 가장 아래에 있는 카드 밑으로 옮기기
while len(dt) > 1:
dt.popleft()
dt.append(dt.popleft())
print(dt[0])
아래의 수 정렬과 마찬가지로 deque를 써야함
버븥정렬
수 정렬하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
n = int(input())
dt = []
res = [0] * n
for i in range(n):
dt.append(int(input()))
res[0] = min(dt)
res[n-1] = max(dt)
for i in range(1, n):
for j in range(i, n-1):
if dt[i] > dt[j]:
res[j] = dt[i]
else:
res[i] = dt[i]
for i in res:
print(i)
이렇게 햇는데 틀렸다. 다시 해야할거같다…
1
2
3
4
5
6
7
8
9
10
from collections import deque
N = int(input())
q = deque(range(1, N+1))
while len(q) > 1:
q.popleft() # 가장 위의 카드를 버림
q.append(q.popleft()) # 그 다음 카드를 맨 아래로 이동
print(q[0])
데크(deque)는 스택처럼 사용할 수도 있고, 큐 처럼 사용할 수도 있다.
시작점의 값을 넣고 빼거나, 끝 점의 값을 넣고 빼는 데 최적화된 연산 속도를 제공한다.
즉, 대부분의 경우에 데크(deque)는 리스트(list)보다 월등한 옵션이다.
데크는 특히 push/pop 연산이 빈번한 알고리즘에서 리스트보다 월등한 속도를 자랑한다.Python - 데크(deque) 언제, 왜 사용해야 하는가?
넘파이
왜 넘파이를 사용할까?
넘파이(NumPy)는 파이썬에서 과학적 및 수학적 계산을 위한 핵심 라이브러리로, 다차원 배열 객체와 이러한 배열을 다루는 다양한 함수를 제공한다.
넘파이를 사용하는 이유:
효율적인 다차원 배열 처리: 넘파이 배열은 파이썬 리스트보다 효율적으로 메모리를 사용하고, 빠르게 연산할 수 있습니다. 넘파이는 C로 구현되어 있어 빠른 속도를 제공.
다양한 수학 함수 제공: 넘파이는 다양한 수학 함수를 제공하여 선형 대수, 푸리에 변환, 통계 및 수치 계산 등을 수행할 수 있다. 이러한 함수들은 벡터화된 연산을 지원하여 반복문 없이 배열에 대한 연산을 수행할 수 있다.
브로드캐스팅(Broadcasting): 넘파이는 서로 다른 크기의 배열 간에도 산술 연산을 수행할 수 있도록 브로드캐스팅 기능을 제공. 이를 통해 배열 간의 연산을 간단하고 효율적으로 수행할 수 있다.
편리한 인덱싱과 슬라이싱: 넘파이는 배열을 인덱싱하고 슬라이싱하는 다양한 방법을 제공하여 데이터를 효율적으로 조작할 수 있다.
데이터 분석 및 시각화: 넘파이는 다른 데이터 분석 도구와 통합하여 데이터를 분석하고 시각화하는 데 유용하다. 예를 들어, 판다스(Pandas)와 함께 사용하여 데이터프레임을 다루거나, 맷플롯립(Matplotlib)과 함께 사용하여 그래프를 그릴 수 있다.
따라서 넘파이는 과학 및 엔지니어링 분야에서 수학적 계산이나 데이터 처리 작업을 효율적으로 수행하기 위해 광범위하게 사용된다. 특히 대규모의 데이터나 다차원 배열을 다루는 작업에 있어서 넘파이는 매우 유용한 도구.
이렇게 길었던 코드가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import random # random 모듈을 임포트함
## 파이썬 2차원 리스트 생성
SIZE = 5 # 리스트의 크기를 정의함
pythonList = [[random.randint(0, 255) for _ in range(SIZE)] for _ in range(SIZE)] # 2차원 리스트를 생성하고 랜덤한 값으로 초기화함
## 리스트를 출력
for i in range(SIZE): # 행에 대한 반복문
for k in range(SIZE): # 열에 대한 반복문
print("%3d" % pythonList[i][k], end=' ') # 각 요소를 출력함
print() # 한 행을 출력한 후 줄바꿈을 수행함
print() # 모든 행을 출력한 후 빈 줄을 출력함
## 리스트에 100을 더하기
for i in range(SIZE): # 행에 대한 반복문
for k in range(SIZE): # 열에 대한 반복문
pythonList[i][k] += 100 # 각 요소에 100을 더함
## 리스트를 출력하기
for i in range(SIZE): # 행에 대한 반복문
for k in range(SIZE): # 열에 대한 반복문
print("%3d" % pythonList[i][k], end=' ') # 각 요소를 출력함
print() # 한 행을 출력한 후 줄바꿈을 수행함
이렇게 짧아짐
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np # 넘파이 모듈을 임포트함
## 넘파이 2차원 배열 생성
SIZE = 5 # 배열의 크기를 정의함
numpyAry = np.random.randint(0, 255, size=(SIZE, SIZE)) # 2차원 배열을 생성하고 0부터 255 사이의 랜덤한 정수로 초기화함
## 배열을 출력하기
print(numpyAry) # 배열을 출력함
print() # 빈 줄을 출력함
## 배열에 100을 더하기
numpyAry += 100 # 배열의 모든 요소에 100을 더함
## 배열을 출력하기
print(numpyAry) # 배열을 출력함
넘파이 행렬 배열조작
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import numpy as np
import random
# 파이썬 리스트 생성
pythonList = [random.randint(0, 255) for _ in range(5)]
print("*파이썬 리스트 ---> ", pythonList)
# 넘파이 배열로 변환
numpyAry1 = np.array(pythonList)
print("* array(pythonList) ---> ", numpyAry1)
# 0부터 4까지의 숫자로 이루어진 배열 생성
numpyAry2 = np.arange(5)
print("* arange(5) ---> ", numpyAry2)
# 3부터 7까지의 숫자로 이루어진 배열 생성
numpyAry3 = np.arange(3, 8)
print("* arange(3, 8) ---> ", numpyAry3)
# 0부터 99까지 20 간격으로 숫자로 이루어진 배열 생성
numpyAry4 = np.arange(0, 100, 20)
print("* arange(0, 100, 20) ---> ", numpyAry4)
# 모든 요소가 1로 이루어진 배열 생성
numpyAry5 = np.ones(5)
print("* ones(5) ---> \n", numpyAry5)
# 3행 4열 모든 요소가 1로 이루어진 배열 생성
numpyAry6 = np.ones((3, 4))
print("* ones((3, 4)) ---> \n", numpyAry6)
# 모든 요소가 0으로 이루어진 배열 생성
numpyAry7 = np.zeros(5)
print("* zeros(5) ---> ", numpyAry7)
# 초기화되지 않은 배열 생성
numpyAry8 = np.empty(6)
print("* empty(6) ---> ", numpyAry8)
# 모든 요소가 33으로 이루어진 배열 생성
numpyAry9 = np.full(5, 33)
print("* full(5, 33) --> ", numpyAry9)
# 대각선 요소가 1이고 나머지 요소가 0인 단위 행렬 생성
numpyAry10 = np.identity(5)
print("* identity(5) --> \n", numpyAry10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import random
SIZE = 5 # 리스트의 크기를 정의함
startRow, startCol = 1, 1 # 시작 행과 열을 정의함
nSIZE = 3 # 추출할 부분 리스트의 크기를 정의함
## 파이썬 2차원 리스트 생성
value = 1 # 초기값을 설정함
myList1 = [] # 빈 리스트를 생성함
for i in range(SIZE): # SIZE만큼 반복함
tmpList = [] # 임시 리스트를 생성함
for k in range(SIZE): # SIZE만큼 반복함
tmpList.append(value) # 임시 리스트에 값을 추가함
value += 1 # 다음 값을 설정함
myList1.append(tmpList) # 결과 리스트에 임시 리스트를 추가함
## 파이썬 2차원 리스트의 출력
for i in range(SIZE): # SIZE만큼 반복함
[print("%3d" % myList1[i][k], end='') for k in range(SIZE)] # 각 요소를 출력함
print() # 한 행을 출력한 후 줄바꿈을 수행함
print() # 모든 행을 출력한 후 빈 줄을 출력함
## 파이썬 2차원 리스트의 슬라이싱
myList2 = [] # 빈 리스트를 생성함
for i in range(startRow, startRow+nSIZE): # startRow부터 startRow+nSIZE-1까지 반복함
tmpList = [] # 임시 리스트를 생성함
for k in range(startCol, startCol+nSIZE): # startCol부터 startCol+nSIZE-1까지 반복함
tmpList.append(myList1[i][k]) # 임시 리스트에 부분 리스트의 요소를 추가함
myList2.append(tmpList) # 결과 리스트에 임시 리스트를 추가함
## 파이썬 2차원 리스트의 출력
for i in range(nSIZE): # nSIZE만큼 반복함
[print("%3d" % myList2[i][k], end="") for k in range(nSIZE)] # 각 요소를 출력함
print() # 한 행을 출력한 후 줄바꿈을 수행함
print() # 모든 행을 출력한 후 빈 줄을 출력함
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import numpy as np
SIZE = 5 # 배열의 크기를 정의함
## 넘파이 2차원 배열 생성
imageAry = np.random.randint(0, 255, size=(SIZE, SIZE)) # 0부터 255 사이의 랜덤한 정수로 이루어진 배열 생성
print("### 1. 원본 ###")
print(imageAry) # 원본 배열 출력
np.save('source', imageAry) # 원본 배열 저장
## (1) 10 증가 후 저장
imageAry += 10 # 모든 요소에 10을 더함
print('### 2. 10 증가 ###')
print(imageAry) # 증가된 배열 출력
np.save('result1', imageAry) # 증가된 배열 저장
## (2) 흑백 처리 후 저장
imageAry = np.where(imageAry < 128, 0, 255) # 픽셀 값이 128보다 작으면 0으로, 그렇지 않으면 255로 변환
print('### 3. 흑백 처리 ###')
print(imageAry) # 흑백 처리된 배열 출력
np.save('result2', imageAry) # 흑백 처리된 배열 저장
## (3) 반전 처리 후 저장
imageAry = 255 - imageAry # 모든 픽셀 값을 255에서 뺌으로써 반전 처리
print('### 4. 반전 처리 ###')
print(imageAry) # 반전 처리된 배열 출력
np.save('result3', imageAry) # 반전 처리된 배열 저장
## 복구1 ##
imageAry = np.load('result2.npy') # 흑백 처리된 배열 불러오기
print('### 복구1: result2.npy ###')
print(imageAry) # 복구된 배열 출력
## 복구2 ##
imageAry = np.load('result1.npy') # 10 증가된 배열 불러오기
print('### 복구2: result1.npy ###')
print(imageAry) # 복구된 배열 출력
## 복구3 ##
imageAry = np.load('source.npy') # 원본 배열 불러오기
print('### 복구3(원본): result2.npy ###')
print(imageAry) # 원본 배열 출력
matplotlib (시각화도구)
숫자를 가지고 다양한 모양의 그래프를 그려준다.
1
2
3
4
5
6
7
8
9
10
11
12
import matplotlib.pyplot as plt
data = [100, 250, 140, 300, 500]
plt.plot(data)
plt.show
x_data = ['1st', '2nd', '3rd', '4th', '5th']
y1_data = [90, 28, 75, 58, 78]
y2_data = [80, 80, 50, 40, 90]
y3_data = [40, 50, 90, 90, 60]
#plt.plot(x_data, y1_data, 'r-o', x_data, y2_data, 'g:x', x_data, y3_data, 'b-p')
plt.bar(x_data, y1_data)
plt.show()
모두 활용 +pandas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 입력 및 출력 파일 경로 지정
inFilename = 'C:/Users/user123/Desktop/learn-py/basic/source/Excel/singer.xlsx'
outFilename = 'C:/Users/user123/Desktop/learn-py/basic/source/Excel/singer_youtube.xlsx'
# 'senior' 시트와 'junior' 시트에서 데이터를 읽어와 데이터프레임에 저장
df_senior = pd.read_excel(inFilename, 'senior', index_col=None)
df_junior = pd.read_excel(inFilename, 'junior', index_col=None)
# 'senior'와 'junior' 데이터프레임을 합쳐 하나의 데이터프레임으로 만듦
df_singer = pd.concat([df_senior, df_junior])
# '유튜브 조회수'를 기준으로 내림차순으로 정렬하여 데이터프레임을 재구성
df_singer_youtube = df_singer.sort_values(by=['유튜브 조회수'], axis=0, ascending=False)
df_singer_youtube = df_singer_youtube.loc[:, ['아이디', '이름', '인원', '유튜브 조회수']]
# 산점도를 그리기 위한 데이터 추출
x_data = df_singer_youtube['아이디']
y_data = df_singer_youtube['유튜브 조회수']
sizeAry = np.sqrt(df_singer_youtube['유튜브 조회수']) # 조회수의 제곱근을 크기로 사용
colorAry = np.random.rand(len(x_data)) # 랜덤한 색상 생성
# 산점도 생성 및 출력
plt.scatter(x_data, y_data, s=sizeAry, c=colorAry, alpha=0.5, cmap='Spectral')
plt.show()
# 출력 파일에 데이터프레임 저장
writer = pd.ExcelWriter(outFilename)
df_singer_youtube.to_excel(writer, sheet_name='singer', index=False)
writer.save()
# 저장 완료 메시지 출력
print('Save. OK~')