feat(ko): add the Korean online edition (#2006)

* feat(ko): add the complete Korean online edition

* Use UTF-8 for Python CI output on Windows

* Remove print-book promotion from the Korean site

* fix(ko): preserve emphasis before Korean particles
This commit is contained in:
Yudong Jin
2026-10-29 03:46:43 +08:00
committed by GitHub
parent 71a773df64
commit 2f561d3d51
2072 changed files with 110884 additions and 102 deletions
@@ -0,0 +1,100 @@
"""
File: array.py
Created Time: 2022-11-25
Author: krahets ([email protected])
"""
import random
def random_access(nums: list[int]) -> int:
"""원소에 임의 접근"""
# 구간 [0, len(nums)-1]에서 숫자 하나를 무작위로 뽑는다
random_index = random.randint(0, len(nums) - 1)
# 무작위 원소를 가져와 반환한다
random_num = nums[random_index]
return random_num
# Python의 list는 동적 배열이므로 직접 확장할 수 있다
# 학습의 편의를 위해 이 함수에서는 list를 길이가 고정된 배열로 취급한다
def extend(nums: list[int], enlarge: int) -> list[int]:
"""배열 길이 확장"""
# 길이를 확장한 배열을 초기화한다
res = [0] * (len(nums) + enlarge)
# 원래 배열의 모든 원소를 새 배열에 복사한다
for i in range(len(nums)):
res[i] = nums[i]
# 확장한 새 배열을 반환한다
return res
def insert(nums: list[int], num: int, index: int):
"""배열의 인덱스 index에 원소 num 삽입"""
# 인덱스 index와 그 뒤에 있는 모든 원소를 한 칸씩 뒤로 이동한다
for i in range(len(nums) - 1, index, -1):
nums[i] = nums[i - 1]
# index 위치의 원소에 num을 대입한다
nums[index] = num
def remove(nums: list[int], index: int):
"""인덱스 index에 있는 원소 삭제"""
# 인덱스 index 뒤에 있는 모든 원소를 한 칸씩 앞으로 이동한다
for i in range(index, len(nums) - 1):
nums[i] = nums[i + 1]
def traverse(nums: list[int]):
"""배열 순회"""
count = 0
# 인덱스를 통해 배열을 순회한다
for i in range(len(nums)):
count += nums[i]
# 배열의 원소를 직접 순회한다
for num in nums:
count += num
# 데이터의 인덱스와 원소를 함께 순회한다
for i, num in enumerate(nums):
count += nums[i]
count += num
def find(nums: list[int], target: int) -> int:
"""배열에서 지정한 원소 탐색"""
for i in range(len(nums)):
if nums[i] == target:
return i
return -1
"""실행 코드"""
if __name__ == "__main__":
# 배열 초기화
arr = [0] * 5
print("배열 arr =", arr)
nums = [1, 3, 2, 5, 4]
print("배열 nums =", nums)
# 임의 접근
random_num: int = random_access(nums)
print("nums에서 무작위로 가져온 원소", random_num)
# 길이 확장
nums: list[int] = extend(nums, 3)
print("배열 길이를 8로 확장한 후 nums =", nums)
# 원소 삽입
insert(nums, 6, 3)
print("인덱스 3에 숫자 6을 삽입한 후 nums =", nums)
# 원소 삭제
remove(nums, 2)
print("인덱스 2의 원소를 삭제한 후 nums =", nums)
# 배열 순회
traverse(nums)
# 원소 탐색
index: int = find(nums, 3)
print("nums에서 원소 3을 탐색하여 얻은 인덱스 =", index)
@@ -0,0 +1,85 @@
"""
File: linked_list.py
Created Time: 2022-11-25
Author: krahets ([email protected])
"""
import sys
from pathlib import Path
sys.path.append(str(Path(__file__).parent.parent))
from modules import ListNode, print_linked_list
def insert(n0: ListNode, P: ListNode):
"""연결 리스트의 노드 n0 뒤에 노드 P 삽입"""
n1 = n0.next
P.next = n1
n0.next = P
def remove(n0: ListNode):
"""연결 리스트의 노드 n0 바로 뒤에 있는 노드 삭제"""
if not n0.next:
return
# n0 -> P -> n1
P = n0.next
n1 = P.next
n0.next = n1
def access(head: ListNode, index: int) -> ListNode | None:
"""연결 리스트에서 인덱스가 index인 노드에 접근"""
for _ in range(index):
if not head:
return None
head = head.next
return head
def find(head: ListNode, target: int) -> int:
"""연결 리스트에서 값이 target인 첫 번째 노드 탐색"""
index = 0
while head:
if head.val == target:
return index
head = head.next
index += 1
return -1
"""실행 코드"""
if __name__ == "__main__":
# 연결 리스트 초기화
# 각 노드를 초기화한다
n0 = ListNode(1)
n1 = ListNode(3)
n2 = ListNode(2)
n3 = ListNode(5)
n4 = ListNode(4)
# 노드 사이의 참조를 설정한다
n0.next = n1
n1.next = n2
n2.next = n3
n3.next = n4
print("초기화한 연결 리스트")
print_linked_list(n0)
# 노드 삽입
p = ListNode(0)
insert(n0, p)
print("노드를 삽입한 후의 연결 리스트")
print_linked_list(n0)
# 노드 삭제
remove(n0)
print("노드를 삭제한 후의 연결 리스트")
print_linked_list(n0)
# 노드 접근
node: ListNode = access(n0, 3)
print("연결 리스트에서 인덱스 3에 있는 노드의 값 = {}".format(node.val))
# 노드 탐색
index: int = find(n0, 2)
print("연결 리스트에서 값이 2인 노드의 인덱스 = {}".format(index))
@@ -0,0 +1,56 @@
"""
File: list.py
Created Time: 2022-11-25
Author: krahets ([email protected])
"""
"""실행 코드"""
if __name__ == "__main__":
# 리스트 초기화
nums: list[int] = [1, 3, 2, 5, 4]
print("\n리스트 nums =", nums)
# 원소 접근
x: int = nums[1]
print("\n인덱스 1의 원소에 접근하여 얻은 x =", x)
# 원소 갱신
nums[1] = 0
print("\n인덱스 1의 원소를 0으로 갱신한 후 nums =", nums)
# 리스트 비우기
nums.clear()
print("\n리스트를 비운 후 nums =", nums)
# 맨 뒤에 원소 추가
nums.append(1)
nums.append(3)
nums.append(2)
nums.append(5)
nums.append(4)
print("\n원소를 추가한 후 nums =", nums)
# 중간에 원소 삽입
nums.insert(3, 6)
print("\n인덱스 3에 숫자 6을 삽입한 후 nums =", nums)
# 원소 삭제
nums.pop(3)
print("\n인덱스 3의 원소를 삭제한 후 nums =", nums)
# 인덱스를 통해 리스트를 순회한다
count = 0
for i in range(len(nums)):
count += nums[i]
# 리스트의 원소를 직접 순회한다
for num in nums:
count += num
# 두 리스트 연결
nums1 = [6, 8, 7, 10, 9]
nums += nums1
print("\n리스트 nums1을 nums 뒤에 연결한 후 nums =", nums)
# 리스트 정렬
nums.sort()
print("\n리스트를 정렬한 후 nums =", nums)
@@ -0,0 +1,118 @@
"""
File: my_list.py
Created Time: 2022-11-25
Author: krahets ([email protected])
"""
class MyList:
"""리스트 클래스"""
def __init__(self):
"""생성자"""
self._capacity: int = 10 # 리스트 용량
self._arr: list[int] = [0] * self._capacity # 배열(리스트 원소 저장)
self._size: int = 0 # 리스트 길이(현재 원소 개수)
self._extend_ratio: int = 2 # 리스트의 용량을 확장할 때마다 적용하는 배수
def size(self) -> int:
"""리스트 길이(현재 원소 개수) 반환"""
return self._size
def capacity(self) -> int:
"""리스트 용량 반환"""
return self._capacity
def get(self, index: int) -> int:
"""원소 접근"""
# 인덱스가 범위를 벗어나면 예외를 발생시킨다. 아래에서도 동일하다
if index < 0 or index >= self._size:
raise IndexError("인덱스가 범위를 벗어났다")
return self._arr[index]
def set(self, num: int, index: int):
"""원소 갱신"""
if index < 0 or index >= self._size:
raise IndexError("인덱스가 범위를 벗어났다")
self._arr[index] = num
def add(self, num: int):
"""맨 뒤에 원소 추가"""
# 원소 개수가 용량을 초과하면 용량 확장을 수행한다
if self.size() == self.capacity():
self.extend_capacity()
self._arr[self._size] = num
self._size += 1
def insert(self, num: int, index: int):
"""중간에 원소 삽입"""
if index < 0 or index >= self._size:
raise IndexError("인덱스가 범위를 벗어났다")
# 원소 개수가 용량을 초과하면 용량 확장을 수행한다
if self._size == self.capacity():
self.extend_capacity()
# 인덱스 index와 그 뒤의 원소를 모두 한 칸씩 뒤로 이동한다
for j in range(self._size - 1, index - 1, -1):
self._arr[j + 1] = self._arr[j]
self._arr[index] = num
# 원소 개수를 갱신한다
self._size += 1
def remove(self, index: int) -> int:
"""원소 삭제"""
if index < 0 or index >= self._size:
raise IndexError("인덱스가 범위를 벗어났다")
num = self._arr[index]
# 인덱스 index 뒤의 원소를 모두 한 칸씩 앞으로 이동한다
for j in range(index, self._size - 1):
self._arr[j] = self._arr[j + 1]
# 원소 개수를 갱신한다
self._size -= 1
# 삭제한 원소를 반환한다
return num
def extend_capacity(self):
"""리스트 용량 확장"""
# 원래 배열 길이의 _extend_ratio 배인 새 배열을 만들고 원래 배열을 새 배열에 복사한다
self._arr = self._arr + [0] * self.capacity() * (self._extend_ratio - 1)
# 리스트 용량을 갱신한다
self._capacity = len(self._arr)
def to_array(self) -> list[int]:
"""유효한 길이만큼의 리스트 반환"""
return self._arr[: self._size]
"""실행 코드"""
if __name__ == "__main__":
# 리스트 초기화
nums = MyList()
# 맨 뒤에 원소 추가
nums.add(1)
nums.add(3)
nums.add(2)
nums.add(5)
nums.add(4)
print(f"리스트 nums = {nums.to_array()}, 용량 = {nums.capacity()}, 길이 = {nums.size()}")
# 중간에 원소 삽입
nums.insert(6, index=3)
print("인덱스 3에 숫자 6을 삽입한 후 nums =", nums.to_array())
# 원소 삭제
nums.remove(3)
print("인덱스 3의 원소를 삭제한 후 nums =", nums.to_array())
# 원소 접근
num = nums.get(1)
print("인덱스 1의 원소에 접근하여 얻은 num =", num)
# 원소 갱신
nums.set(0, 1)
print("인덱스 1의 원소를 0으로 갱신한 후 nums =", nums.to_array())
# 용량 확장 동작 테스트
for i in range(10):
# i = 5일 때 리스트 길이가 용량을 초과하므로 용량 확장이 수행된다
nums.add(i)
print(f"용량을 확장한 리스트 {nums.to_array()}, 용량 = {nums.capacity()}, 길이 = {nums.size()}")