Updated:

Theme 1. μž…λ ₯ λͺ¨λ“ˆ

""" Compare to Input module """
import sys

N = int(inputs())
K = int(sys.stdin.readline())

νŒŒμ΄μ¬μ—μ„œ μ‚¬μš©μžλ‘œλΆ€ν„° μž…λ ₯을 λ°›λŠ” λͺ¨λ“ˆμ€ 보톡 inputs(), sys.stdin.readline() 을 μ‚¬μš©ν•œλ‹€. inputs() λŠ” μž…λ ₯ λ°›λŠ” λ°μ΄ν„°μ˜ 길이가 κΈΈκ³ , λ§Žμ•„μ§ˆμˆ˜λ‘ μž…λ ₯ 효율이 λ–¨μ–΄μ§€λŠ” 단점이 μžˆλ‹€. κ·Έλž˜μ„œ 이λ₯Ό λ³΄μ™„ν•˜κΈ° μœ„ν•΄ λŒ€λΆ€λΆ„μ˜ μ½”λ”©ν…ŒμŠ€νŠΈ ν™˜κ²½μ—μ„œ μž…λ ₯을 받을 λ•ŒλŠ” sys.stdin.readline() λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€. μ–΄μ°¨ν”Ό ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€κ°€ 맀우 κΈΈκ³  많기 λ•Œλ¬Έμ— μΌλ°˜μ μœΌλ‘œλŠ” ν›„μžκ°€ 훨씬 νš¨μœ¨μ μ΄λ‹€.

ν•˜μ§€λ§Œ λ§Œμ•½, 문제 μ‘°κ±΄μ—μ„œ μ£Όμ–΄μ§€λŠ” μž…λ ₯ λ°μ΄ν„°μ˜ κ°œμˆ˜μ™€ κ·Έ ν˜•νƒœκ°€ 적고 λ‹¨μˆœν•œ 편이라면 μ „μžμ˜ μ‚¬μš©λ„ κ³ λ €ν•΄μ•Ό ν•œλ‹€. ν›„μžλŠ” 기본적으둜 sys λͺ¨λ“ˆ 내뢀에 λ‚΄μž₯된 λ©”μ„œλ“œλΌμ„œ sys λͺ¨λ“ˆμ„ λΆˆλŸ¬μ™€μ•Ό ν•œλ‹€. λͺ¨λ“ˆμ„ import ν•˜λŠ” μ‹œκ°„λ„ κ½€λ‚˜ 걸리기 λ•Œλ¬Έμ—, 데이터가 λ‹¨μˆœν•˜λ‹€λ©΄ μ „μž μ‚¬μš©λ„ κ³ λ €ν•΄λ³΄μž.

Theme 2. μ„ μ–Έ/ν• λ‹Ή/μž¬κ΅¬μ„± 횟수 쀄이기

νŒŒμ΄μ¬μ€ 자료ꡬ쑰 μ‚¬μš©μ„ μœ„ν•΄ λͺ…μ‹œμ μœΌλ‘œ λ©”λͺ¨λ¦¬λ₯Ό ν• λ‹Ήν•˜κ³  ν•΄μ œν•˜λŠ” 과정이 μƒλž΅λ˜μ–΄ μžˆμ–΄μ„œ, 이 뢀뢄에 λŒ€ν•œ 인지λ₯Ό ν•˜μ§€ λͺ»ν•˜λŠ” κ²½μš°κ°€ λ§Žλ‹€. ν•˜μ§€λ§Œ C/C++/JAVA ν˜Ήμ€ 운영체제 곡뢀λ₯Ό ν•΄λ΄€λ‹€λ©΄ μ•Œ 것이닀. λ©”λͺ¨λ¦¬ 할당을 μš”κ΅¬ν•˜λŠ” 일이 μ–Όλ§ˆλ‚˜ μ‹œκ°„μ„ 많이 μž‘μ•„ λ¨ΉλŠ” 일인지 말이닀. ν”„λ‘œκ·Έλž˜λ¨Έκ°€ μž‘μ„±ν•œ μ½”λ“œμ—μ„œ λ©”λͺ¨λ¦¬ 할당을 μš”κ΅¬ν•œλ‹€λ©΄, 컴파일러/μΈν„°ν”„λ¦¬ν„°λŠ” 운영체제 컀널에 λ©”λͺ¨λ¦¬ 할당을 μš”κ΅¬ν•΄μ•Ό ν•œλ‹€. κ·Έ λ‹€μŒ 컀널은 λ‹€μ‹œ κ°€μž₯ κΉŠμˆ™ν•œ κ³³κΉŒμ§€ λ‚΄λ €κ°€ λ©”λͺ¨λ¦¬ 할당을 ν•˜λ“œμ›¨μ–΄μ— μš”μ²­ν•œ λ’€, μž‘μ—… κ²°κ³Όλ₯Ό μ»΄νŒŒμΌλŸ¬μ— 전달해야 ν•œλ‹€. λ”°λΌμ„œ μ΅œλŒ€ν•œ ν• λ‹Ήκ³Ό μž¬κ΅¬μ„±ν•˜λŠ” μ‹œκ°„μ„ 쀄여야 효율적으둜 μ½”λ“œλ₯Ό μž‘μ„±ν•  수 μžˆλ‹€.

""" 1. 리슀트 κ³±μ…ˆ """

arr1 = [0 for _ in range(100)]
arr2 = [0] * 100

arr1, arr2λŠ” λͺ¨λ‘ 길이가 100이고 λͺ¨λ“  μ›μ†Œκ°’μ΄ 0인 같은 λ°°μ—΄(리슀트)을 κ°€μ§€κ²Œ λœλ‹€. ν•˜μ§€λ§Œ, μ‹€ν–‰ μ‹œκ°„μ€ μ–΄λŠμͺ½μ΄ 더 λΉ λ₯ΌκΉŒ?? ν›„μžκ°€ λ‹Ήμ—°νžˆ 더 λΉ λ₯΄λ‹€. ν›„μžλŠ” μž¬κ΅¬μ„±(resize)μ—°μ‚° 없이 ν•œ λ²ˆμ— 할당이 마무리 되기 λ•Œλ¬Έμ΄λ‹€. 반면 μ „μžλŠ” μ„ μ–Έκ³Ό ν• λ‹Ή 및 μž¬κ΅¬μ„± μ‹œμ μ΄ μ„œλ‘œ λ‹€λ₯΄λ‹€. κ·Έλž˜μ„œ 일정 νšŸμˆ˜λ§ˆλ‹€ μž¬κ΅¬μ„± 연산이 ν•„μš”ν•΄μ§„λ‹€. μ•žμ„œλ„ μ–ΈκΈ‰ν–ˆλ“―, 컀널에 λ©”λͺ¨λ¦¬λ₯Ό μš”κ΅¬ν•˜λŠ” νšŸμˆ˜κ°€ μž‘μ•„μ§€λŠ”κ²Œ μ‹€ν–‰ μ‹œκ°„μ— μœ λ¦¬ν•˜λ‹€. λ”°λΌμ„œ λͺ…λ°±νžˆ ν›„μžμ˜ μ‹€ν–‰ μ‹œκ°„μ΄ 더 λΉ λ₯΄λ‹€.

νžˆμ§€λ§Œ, 리슀트 κ³±μ…ˆμ„ μ‚¬μš©ν•  λ•Œ λ°˜λ“œμ‹œ μ£Όμ˜ν•΄μ•Όν•  점이 μžˆλ‹€. 방금 μ‚΄νŽ΄λ³Έ μ˜ˆμ‹œλŠ” 1차원 배열에 리슀트 κ³±μ…ˆμ„ ν•˜κΈ° λ•Œλ¬Έμ—, 이후 ν•΄λ‹Ή 배열을 μ‘°μž‘ν•΄λ„ λ¬Έμ œκ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€. ν•˜μ§€λ§Œ, 2차원 배열을 리슀트 κ³±μ…ˆν•˜μ—¬ μ„ μ–Έν•˜λ©΄ μ–΄λ–»κ²Œ 될까??

arr1 = [[0, 0]]*5
arr2 = [[0, 0] for _ in range(5)]

# Question 1.
for i in range(5):
	arr1[i][0] += 1

# Question 2.
for i in range(5):
	arr2[i][0] += 1

1번과 2번의 μΌ€μ΄μŠ€μ— λŒ€ν•œ 좜λ ₯을 μ˜ˆμΈ‘ν•΄λ³΄μž. μ–΄λ–»κ²Œ λ‚˜μ˜¬κΉŒ??

# Question 1.
>>> [[0, 5], [0, 5], [0, 5], [0, 5], [0, 5]]

# Question 2.
>>> [[0, 1], [0, 1], [0, 1], [0, 1], [0, 1]]

얼핏 λ³΄κΈ°μ—λŠ” λ˜‘κ°™μ€ κ²°κ³Όκ°€ λ‚˜μ™€μ•Ό ν•œλ‹€κ³  μƒκ°ν•˜κΈ° 쉽닀. ν•˜μ§€λ§Œ 1차원 λ°°μ—΄μ˜ κ²½μš°μ™€ λͺ…λ°±νžˆ λ‹€λ₯Έμ μ΄ μžˆλ‹€. λ°”λ‘œ, 리슀트의 μ›μ†Œκ°€ λ¦¬μŠ€νŠΈλΌλŠ” 것이닀. λ¦¬μŠ€νŠΈλŠ” mutable κ°μ²΄λ‘œμ„œ, resize 연산을 가지고 μžˆμ–΄μ„œ λ³„λ„μ˜ μ‘°μž‘μ„ 해도 객체의 μ£Όμ†Œκ°’μ΄ λ³€κ²½λ˜μ§€ μ•ŠλŠ”λ‹€. λ‹€μ‹œ 말해 λ©”λͺ¨λ¦¬ 볡사가 λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.

ν•˜μ§€λ§Œ 1차원 λ°°μ—΄μ˜ κ²½μš°λŠ” μ›μ†Œκ°€ immutable 객체인 μ •μˆ˜λ‹€. λ”°λΌμ„œ μ΄ˆκΈ°μ— λͺ¨λ“  μ›μ†Œκ°€ 같은 μ£Όμ†Œλ₯Ό κ³΅μœ ν•˜κ³  μžˆμ–΄λ„, 순차적으둜 μ‘°μž‘μ΄ λ°œμƒν•˜λ©΄μ„œ λ©”λͺ¨λ¦¬μ— μƒˆλ‘œμš΄ 값이 λ³΅μ‚¬λ˜κ³  μ„œλ‘œ λ‹€λ₯Έ μ£Όμ†Œλ₯Ό κ°–κ²Œ 되기 λ•Œλ¬Έμ— λ¬Έμ œκ°€ μ—†λŠ” 것이닀. μ΄λŸ¬ν•œ 차이 λ•Œλ¬Έμ— 이차원 λ°°μ—΄μ˜ 경우 리슀트 볡사λ₯Ό μ‚¬μš©ν•˜κ²Œ 되면, λͺ¨λ“  μ›μ†Œκ°€ 같은 μ£Όμ†Œλ₯Ό κ³„μ†ν•΄μ„œ κ³΅μœ ν•˜κΈ° λ•Œλ¬Έμ— λͺ¨λ‘ 같은 값을 κ°–κ²Œ λœλ‹€.

# Question 1. memory id
[0, 1]
140226858532160
[0, 2]
140226858532160
[0, 3]
140226858532160
[0, 4]
140226858532160
[0, 5]
140226858532160

# Question 2. memory id
[0, 1]
140226858828416
[0, 1]
140226858785472
[0, 1]
140226858828160
[0, 1]
140226858828480
[0, 1]
140226858830016

κ°œλ³„ μ›μ†Œμ— 순차적으둜 μ ‘κ·Όν•  λ•Œ, μ›μ†Œμ˜ μ£Όμ†Œλ₯Ό 좜λ ₯ν•œ κ²°κ³Όλ‹€. Question 1 은 μ„œλ‘œ λ‹€λ₯Έ 인덱슀의 μ›μ†Œμ— 접근해도 κ³„μ†ν•΄μ„œ λ™μΌν•œ μ£Όμ†Œ μœ„μΉ˜λ₯Ό μ°Έμ‘°ν•˜κ³  μžˆμŒμ„ μ•Œ 수 μžˆλ‹€.

ν•œνŽΈ, Question 2 의 경우, μ²˜μŒλΆ€ν„° μ„œλ‘œ λ‹€λ₯Έ μ£Όμ†Œκ°’μ„ κ°–λŠ” 리슀트λ₯Ό μ›μ†Œλ‘œ ν• λ‹Ήν–ˆκΈ° λ•Œλ¬Έμ— μ„œλ‘œ λ‹€λ₯Έ μ£Όμ†Œκ°’μ„ κ°–κ²Œ λœλ‹€.

""" 2. νŠœν”Œ μ‚¬μš© """

tdy, tdx = (-1, 1, 0, 0), (0, 0, -1, 1)  # tuple
ldy, ldx = [-1, 1, 0, 0], [0, 0, -1, 1]  # list

μ§€κΈˆκΉŒμ§€ μ„€λͺ…ν•œ λ‚΄μš©κ³Ό 같은 λ§₯λ½μ—μ„œ, λ°°μ—΄ λ‚΄λΆ€μ˜ κ΅¬μ„±μš”μ†Œμ— 변경이 μ—†λŠ”κ²Œ ν™•μ‹€μ‹œ λ˜λŠ” 경우, 배열을 νŠœν”Œλ‘œ μ„ μ–Έν•˜λŠ” 것이 μ’‹λ‹€. μœ„μ— μ„ μ–Έλœ 배열은 κ·Έλž˜ν”„ 탐색 λ¬Έμ œμ—μ„œ μƒν•˜μ’Œμš° λ°©ν–₯ 탐색을 κ΅¬ν˜„ν•  λ•Œ 자주 μ‚¬μš©ν•˜λŠ” 방법이닀. μƒν•˜μ’Œμš° λ°©ν–₯을 ν‘œν˜„ν•˜λŠ”κ²Œ λͺ©μ μ΄λΌμ„œ, ν•΄λ‹Ή 배열은 λ―Έλž˜μ— 변경될 일이 μ—†λ‹€κ³  보μž₯ν•  수 μžˆλ‹€. 이런 κ²½μš°μ—λŠ” μŠ΅κ΄€μ μœΌλ‘œ 리슀트λ₯Ό μ‚¬μš©ν•˜μ§€λ§κ³ , νŠœν”Œμ„ μ“°μž.

νŠœν”Œμ΄ λ¦¬μŠ€νŠΈλ³΄λ‹€ λ‚˜μ€ μ΄μœ λŠ” immutable κ°μ²΄λΌλŠ” 점이닀. immutable κ°μ²΄λŠ” λ³€κ²½λ˜μ§€ μ•ŠλŠ”λ‹€λŠ” 것을 μ „μ œλ‘œ ν•˜κΈ° λ•Œλ¬Έμ— resize λ©”μ„œλ“œκ°€ 객체에 μ—†λ‹€. 이에 λ”°λΌμ„œ κ΄€λ ¨λœ 메타 정보도 μ €μž₯ν•˜κ³  μžˆμ„ ν•„μš”κ°€ 사라진닀. κ·Έλž˜μ„œ 리슀트 보닀 가볍고 λΉ λ₯Έ 계산이 κ°€λŠ₯ν•˜λ‹€. λ˜ν•œ νŠœν”Œμ€ 20μ΄ν•˜μ˜ 크기λ₯Ό κ°–λŠ” κ°μ²΄λŠ” 래퍼런슀 μΉ΄μš΄νŠΈκ°€ 0이라도 Python GCκ°€ λ©”λͺ¨λ¦¬λ₯Ό νšŒμˆ˜ν•˜μ§€ μ•ŠλŠ”λ‹€. λŒ€μ‹  λ©”λͺ¨λ¦¬ 상에 μ €μž₯ν•˜κ³  μžˆλ‹€κ°€, 같은 크기의 νŠœν”Œμ΄ λ‹€μ‹œ ν•œ 번 선언될 λ•Œ, 이것을 μž¬ν™œμš©ν•œλ‹€.

λ¦¬μŠ€νŠΈμ™€ νŠœν”Œμ˜ 전체 생애주기λ₯Ό 비ꡐ해보면, νŠœν”Œμ˜ 컀널&ν•˜λ“œμ›¨μ–΄ ν˜ΈμΆœνšŸμˆ˜κ°€ λ¦¬μŠ€νŠΈλ³΄λ‹€ 훨씬 적어진닀. κ·Έλž˜μ„œ μž¬κ΅¬μ„±μ΄ ν•„μš”μ—†λŠ” κ²½μš°λŠ” λ°˜λ“œμ‹œ νŠœν”Œλ‘œ μ„ μ–Έν•˜λŠ”κ²Œ 이득이라고 λ³Ό 수 μžˆλ‹€.

""" λ¬Έμžμ—΄ ν•©μΉ˜κΈ° """

arr1, arr2 = 'I am a boy, ', 'you are a girl'

src = time.time()
result = arr1 + arr2
end = time.time()
print(f"Execution Time: {src-end}")
print(f"Result: {result}")

src = time.time()
result2 = ''.join([arr1, arr2])
end = time.time()
print(f"Execution Time: {src-end}")
print(f"Result: {result2}")

Execution Time: -3.600120544433594e-05
Result: I am a boy, you are a girl
Execution Time: -3.504753112792969e-05
Result: I am a boy, you are a girl

λ¬Έμžμ—΄μ€ νŒŒμ΄μ¬μ—μ„œ immutable 객체둜 κ°„μ£Όν•œλ‹€. λ”°λΌμ„œ 일반 μ—°μ‚°μž(+, *)λ₯Ό μ‚¬μš©ν•΄ λ¬Έμžμ—΄μ„ μˆ˜μ •ν•  경우, 여타 immutable 객체처럼 μƒˆλ‘œμš΄ λ©”λͺ¨λ¦¬ 할당이 λ°œμƒν•œλ‹€. 이λ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄ 파이썬 λ‚΄λΆ€μ μœΌλ‘œ μ΅œμ ν™” λ˜μ–΄ μžˆλŠ” str.join() 을 μ‚¬μš©ν•΄ λ¬Έμžμ—΄μ„ μ‘°μž‘ν•˜λ„λ‘ ν•˜μž.

Theme 3. μ»΄ν”„λ¦¬ν—¨μ…˜/μ œλ„ˆλ ˆμ΄ν„°

src = time.time()
arr1 = [i**2 for i in range(100000)]  # list comprehension
end = time.time()

print(f"Execution Time: {src-end}")
print(f"Memory Size: {sys.getsizeof(arr1)} byte")
# print(f"Result: {arr1}")

src = time.time()
arr2 = (i**2 for i in range(100000))  # init of generator
end = time.time()

print(f"Execution Time: {src-end}")
print(f"Memory Size: {sys.getsizeof(arr2)} byte")
print(f"Result: {arr2}")

Execution Time: -0.023138046264648438
Memory Size: 800984 byte
Execution Time: -5.2928924560546875e-05
Memory Size: 112 byte
Result: <generator object <genexpr> at 0x1058c3f20>

속도, ν•„μš”ν•œ λ©”λͺ¨λ¦¬ 크기 λͺ¨λ‘ μ œλ„ˆλ ˆμ΄ν„°κ°€ μ••λ„μ μœΌλ‘œ 효율적인 λͺ¨μŠ΅μ΄λ‹€. μ œλ„ˆλ ˆμ΄ν„°μ˜ 경우, μ‹€μ œλ‘œλŠ” λͺ¨λ“  연산값을 κ°–κ³  μžˆλŠ”κ²Œ μ•„λ‹ˆκΈ° λ•Œλ¬Έμ΄λ‹€. κ·Έλž˜μ„œ 인덱싱, μŠ¬λΌμ΄μ‹±λ“± 파이썬 λ°°μ—΄μ˜ μ—¬λŸ¬ 연산을 ν™œμš©ν•  수 μ—†λ‹€. λ”°λΌμ„œ 상황에 λ”°λΌμ„œ μ»΄ν”„λ¦¬ν—¨μ…˜κ³Ό μ œλ„ˆλ ˆμ΄ν„°λ₯Ό μ‚¬μš©ν•˜λ©΄ λœλ‹€. λ§Œμ•½ 인덱싱, μŠ¬λΌμ΄μ‹± μ—°μ‚°μ²˜λŸΌ 일뢀에 μ ‘κ·Όν•˜λŠ” 연산을 μ΄μš©ν•΄μ•Ό ν•œλ‹€λ©΄ μ»΄ν”„λ¦¬ν—¨μ…˜μ„, sum()처럼 전체 λ°°μ—΄ λ‹¨μœ„ μ—°μ‚° ν˜Ήμ€ λ‹¨μˆœνžˆ 순차적으둜 μ›μ†Œ ν•˜λ‚˜ ν•˜λ‚˜μ— μ ‘κ·Όν•΄ 무엇인가 ν•΄μ•Ό ν•˜λŠ” 상황(range() λ“±)이라면 μ œλ„ˆλ ˆμ΄ν„°λ₯Ό ν™œμš©ν•˜μž.

Leave a comment