λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

🐍 Python/solve-algorithm

λ°±μ€€ 2108 [톡계학] : 파이썬 & κ΅¬ν˜„ ,μ •λ ¬ (with for 반볡문 & Counter & statistics) 3가지 λ°©λ²•μœΌλ‘œ 풀어보기

πŸ“Œ 문제 

https://www.acmicpc.net/problem/2108

 

2108번: 톡계학

첫째 쀄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진닀. 단, N은 ν™€μˆ˜μ΄λ‹€. κ·Έ λ‹€μŒ N개의 μ€„μ—λŠ” μ •μˆ˜λ“€μ΄ 주어진닀. μž…λ ₯λ˜λŠ” μ •μˆ˜μ˜ μ ˆλŒ“κ°’μ€ 4,000을 λ„˜μ§€ μ•ŠλŠ”λ‹€.

www.acmicpc.net


πŸ” 풀이 

총 세가지 λ°©λ²•μœΌλ‘œ ν’€μ–΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€. κ°œμΈμ μœΌλ‘œλŠ” Counter λͺ¨λ“ˆλ‘œ ν‘ΈλŠ” 방법이 κ°€μž₯ κΉ”λ”ν•˜κ³  λ§ˆμŒμ— λ“€μ—ˆμŠ΅λ‹ˆλ‹€πŸ₯•

μ‚°μˆ ν‰κ· , 쀑앙값, λ²”μœ„λŠ” μ•„λž˜μ™€ 같이 λ¬Έμ œμ— κ·ΈλŒ€λ‘œ λ‚˜μ™€μžˆμ–΄μ„œ 뢀가적인 μ„€λͺ…은 ν•˜μ§€μ•Šκ² μŠ΅λ‹ˆλ‹€:) ν˜Ήμ‹œλ‚˜ κΆκΈˆν•˜μ‹œλ©΄ λŒ“κΈ€μ£Όμ‹œλ©΄ μ„€λͺ…λ“œλ¦¬κ² μŠ΅λ‹ˆλ‹€.

  1. μ‚°μˆ ν‰κ·  : N개의 μˆ˜λ“€μ˜ 합을 N으둜 λ‚˜λˆˆ κ°’
  2. 쀑앙값 : N개의 μˆ˜λ“€μ„ μ¦κ°€ν•˜λŠ” μˆœμ„œλ‘œ λ‚˜μ—΄ν–ˆμ„ 경우 κ·Έ 쀑앙에 μœ„μΉ˜ν•˜λŠ” κ°’
  3. μ΅œλΉˆκ°’ : N개의 μˆ˜λ“€ 쀑 κ°€μž₯ 많이 λ‚˜νƒ€λ‚˜λŠ” κ°’
  4. λ²”μœ„ : N개의 μˆ˜λ“€ 쀑 μ΅œλŒ“κ°’κ³Ό μ΅œμ†Ÿκ°’μ˜ 차이

1. 첫번째 방법   : Counter

counterλŠ” collections에 λŒ€ν•œ λŒ€μ•ˆμ„ μ œκ³΅ν•˜λŠ” λͺ¨λ“ˆ 쀑 ν•˜λ‚˜λ‘œ, ν•΄μ‹œ κ°€λŠ₯ν•œ 객체λ₯Ό μ„ΈλŠ” 데 μ‚¬μš©ν•˜λŠ” λ”•μ…”λ„ˆλ¦¬ μ„œλΈŒ ν΄λž˜μŠ€μž…λ‹ˆλ‹€.

μš”μ†Œκ°€ λ”•μ…”λ„ˆλ¦¬ ν‚€λ‘œ, κ°œμˆ˜κ°€ λ”•μ…”λ„ˆλ¦¬ κ°’μœΌλ‘œ μ €μž₯λ©λ‹ˆλ‹€. κ°œμˆ˜λŠ” 0 λ˜λŠ” 음수λ₯Ό ν¬ν•¨ν•˜λŠ” μž„μ˜ μ •μˆ«κ°’μ΄ 될 수 μžˆμŠ΅λ‹ˆλ‹€.

λ‹€λ₯Έ μ•Œκ³ λ¦¬μ¦˜ 문제λ₯Ό ν’€λ•Œλ„ μœ μš©ν•©λ‹ˆλ‹€!✨ documentationd은 μ•„λž˜λ₯Ό μ°Έκ³ ν•΄μ£Όμ„Έμš”! (μ˜ˆμ‹œ μ½”λ“œλ„ μžˆλ‹΅λ‹ˆλ‹€!)

* documentaition : https://docs.python.org/ko/3/library/collections.html

 

collections — μ»¨ν…Œμ΄λ„ˆ λ°μ΄ν„°ν˜• — Python 3.10.1 λ¬Έμ„œ

collections — μ»¨ν…Œμ΄λ„ˆ λ°μ΄ν„°ν˜• μ†ŒμŠ€ μ½”λ“œ: Lib/collections/__init__.py 이 λͺ¨λ“ˆμ€ 파이썬의 λ²”μš© λ‚΄μž₯ μ»¨ν…Œμ΄λ„ˆ dict, list, set 및 tuple에 λŒ€ν•œ λŒ€μ•ˆμ„ μ œκ³΅ν•˜λŠ” 특수 μ»¨ν…Œμ΄λ„ˆ λ°μ΄ν„°ν˜•μ„ κ΅¬ν˜„ν•©λ‹ˆλ‹€. named

docs.python.org

[전체 μ½”λ“œ]

# μ΅œμ’… μ œμΆœμ½”λ“œ(1)
import sys
from collections import Counter
N = int(sys.stdin.readline())
numbers = sorted([int(sys.stdin.readline()) for _ in range(N)])

# μ‚°μˆ ν‰κ· 
print(round(sum(numbers) / N))

# 쀑앙값
print(numbers[N // 2])

# μ΅œλΉˆκ°’
count_list = sorted(Counter(numbers).items(), key = lambda x : (-x[1], x[0]))
if N == 1:
    print(numbers[0])
else:
    if count_list[0][1] != count_list[1][1]:
        print(count_list[0][0])
    else:
        print(count_list[1][0])

# λ²”μœ„ : μ΅œλŒ“κ°’ - μ΅œμ†Ÿκ°’
print(max(numbers) - min(numbers))

[ν•΄μ„€]

πŸ₯• μ΅œλΉˆκ°’ μ„€λͺ…

1. Counterλ₯Ό μ΄μš©ν•΄μ„œ 갯수λ₯Ό μ„Όλ‹€.
2. 1번의 κ°’은 λ”•μ…”λ„ˆλ¦¬μ΄λ―€λ‘œ, items λ©”μ†Œλ“œλ₯Ό μ΄μš©ν•΄μ„œ (key, value) νŠœν”Œμ„ λ½‘λŠ”λ‹€.
3. λ¬Έμ œμ— μ •μ˜λœ 쑰건에 따라, value(μΉ΄μš΄νŒ… 갯수) - key(숫자 자체) 순으둜 μ •λ ¬ν•œλ‹€.

      * 정렬에 κ΄€λ ¨ν•΄μ„œ ν—·κ°ˆλ¦¬μ‹œλ©΄, https://imdona.tistory.com/14?category=985565 닀쀑 쑰건 μ •λ ¬ 포슀트 μ°Έκ³ λ°”λžλ‹ˆλ‹€ πŸ‘€
4. μΈλ±μŠ€ λ²”μœ„ μ΄ˆκ³Ό λ¬Έμ œλ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄μ„œ,
    N = 1μΌλ•ŒλŠ” μžκΈ°μžμ‹ μ΄ μ΅œλΉˆκ°’μœΌλ‘œ
    N > 1μΌλ•ŒλŠ” μ΅œλΉˆκ°’이 ν•œ κ°œμΌ λ•Œ(= μ •λ ¬ν•œ λ¦¬μŠ€νŠΈμ˜ μ²«λ²ˆμ§Έμ™€ λ‘λ²ˆμ§Έ κ°’이 λ‹€λ₯Ό λ•Œ)λŠ” ν•΄λ‹Ή κ°’을
                        μ΅œλΉˆκ°’μ΄ 두 개 이상일 λ•ŒλŠ” 더 λ‘λ²ˆμ§Έ κ°’(μΈλ±μŠ€λ²ˆν˜ΈλŠ” 1번)을 ν”„λ¦°νŠΈν•˜λŠ” if문으둜 κ΅¬μ„±ν•˜μ˜€λ‹€.

## 풀이 방법 μ„€λͺ…
# readline κΉŒλ¨Ήμ§€μ•Šκ²Œ μ‚¬μš©ν•˜λ©΄μ„œ μΉœν•΄μ§€κΈ°!
import sys
from collections import Counter
N = int(sys.stdin.readline())
numbers = sorted([int(sys.stdin.readline()) for _ in range(N)])

# μ‚°μˆ ν‰κ·  : 합계 / 갯수
# print("----------------")
# print(f"μ‚°μˆ ν‰κ·  : {round(sum(numbers) / N)}")
print(round(sum(numbers) / N))

# 쀑앙값 : μ •λ ¬ν•΄μ„œ μ€‘κ°„μœ„μΉ˜ - μΈλ±μŠ€λŠ” λͺ«μœΌλ‘œ
print(numbers[N // 2])

# μ΅œλΉˆκ°’ : κ°€μž₯ 많이 λ‚˜νƒ€λ‚˜λŠ” κ°’
count_list = sorted(Counter(numbers).items(), key = lambda x : (-x[1], x[0]))
# print(count_list)
if N == 1:
    print(numbers[0])
else:
    if count_list[0][1] != count_list[1][1]:
        print(count_list[0][0])
    else:
        print(count_list[1][0])

# λ²”μœ„ : μ΅œλŒ“κ°’ - μ΅œμ†Ÿκ°’
print(max(numbers) - min(numbers))

2. λ‘λ²ˆμ§Έ 방법   : statistics

μš°μ„  python의 statistics 라이브러리λ₯Ό μ‚¬μš©ν•˜λ©΄, μ‚°μˆ ν‰κ· , 쀑앙값, λ²”μœ„λŠ” 이미 κ΅¬ν˜„λœ λ©”μ†Œλ“œλ‘œ μ‰½κ²Œ 풀이가 κ°€λŠ₯ν•©λ‹ˆλ‹€.

μ΅œλΉˆκ°’μ€ 사싀 1번 풀이 방법과 λ˜‘κ°™μ€ 것 κ°™μ•„μ„œ λ‹€λ₯Έ 방법을 연ꡬ(?)해보닀가 λ°œκ²¬ν•œ λ©”μ†Œλ“œλ₯Ό ν™œμš©ν•΄μ„œ ν’€μ–΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€.

[전체 μ½”λ“œ]

# μ΅œμ’… μ œμΆœμ½”λ“œ(2)
import sys
import statistics as st
from collections import Counter
N = int(sys.stdin.readline())
numbers = [int(sys.stdin.readline()) for _ in range(N)]

print(round(st.mean(numbers)))
print(st.median(numbers))
count_list = sorted(Counter(numbers).most_common(), key = lambda x : (-x[1], x[0]))

if N == 1:
    print(numbers[0])
else:
    if count_list[0][1] != count_list[1][1]:
        print(count_list[0][0])
    else:
        print(count_list[1][0])

print(max(numbers)-min(numbers))

[ν•΄μ„€]

πŸ₯• μ΅œλΉˆκ°’ μƒˆλ‘œμš΄ method μ‚¬μš©ν•΄λ³΄κΈ°
Counter의 most_common( )μ΄λΌλŠ” λ©”μ†Œλ“œμ„ μ‚¬μš©ν•˜λ©΄ 쑰금 더 κ°„λ‹¨ν•œ μ½”λ“œλ‘œ 첫 번째 풀이 방법과 λ˜‘κ°™μ΄ (숫자, μΉ΄μš΄νŒ…)의 νŠœν”Œν˜•νƒœλ‘œ return λ©λ‹ˆλ‹€.
πŸ” collections.Counter(a).most_common(n)   : a의 μš”μ†Œλ₯Ό μ„Έμ–΄, λ¦¬μŠ€νŠΈμ— λ‹΄κΈ΄ νŠœν”Œν˜•νƒœλ‘œ μ΅œλΉˆκ°’ n개λ₯Ό λ°˜ν™˜ν•˜λŠ” λ©”μ†Œλ“œ
➑️ documentation을 보면 λ™μΌν•œ 갯수의 μš”μ†ŒλŠ” 처음 λ°œμƒν•œ μˆœμ„œλŒ€λ‘œ 정렬이 λ˜μ–΄μ„œ, μ •λ ¬ 및 if문으둜 ν™•μΈν•΄μ£ΌλŠ” μ ˆμ°¨λŠ” ν•„μš”ν•΄μš”!
* collections documentation : https://docs.python.org/3/library/collections.html

'''statistics 라이브러리 importν•΄μ„œ ν’€κΈ° - μ‚°μˆ ν‰κ· , 쀑앙값, λ²”μœ„'''
import sys
import statistics as st
from collections import Counter
N = int(sys.stdin.readline())
numbers = [int(sys.stdin.readline()) for _ in range(N)]

print(f"μ‚°μˆ ν‰κ·  : {round(st.mean(numbers))}")
print(f"쀑앙값 : {st.median(numbers)}")
print(f"λ²”μœ„ : {max(numbers)-min(numbers)}")

# μ΅œλΉˆκ°’
count_list = sorted(Counter(numbers).most_common(), key = lambda x : (-x[1], x[0]))

if N == 1:
    print(numbers[0])
else:
    if count_list[0][1] != count_list[1][1]:
        print(count_list[0][0])
    else:
        print(count_list[1][0])

3. μ„Έλ²ˆμ§Έ 방법   : for반볡문

이 방법은 μ²˜μŒμ— Counter λͺ¨λ“ˆμ„ μƒκ°ν•˜μ§€ λͺ»ν–ˆμ„ λ•Œ, 제일 λ¨Όμ € λ“€μ—ˆλ˜ μ•„μ΄λ””μ–΄μ˜€μŠ΅λ‹ˆλ‹€! πŸ’‘

ν’€κ³  λ³΄λ‹ˆ Counter λͺ¨λ“ˆμ„ 톡해 κ΅¬ν˜„ν•œ 것과 λ˜‘κ°™μ€ output을 제 μ†μœΌλ‘œ λ§Œλ“  λŠλ‚Œμ΄κΈ΄ ν–ˆμŠ΅λ‹ˆλ‹€(?) βœ‹πŸ‘©‍🍳

μ €λŠ” λ¬Έμ œμ—μ„œ "κ·Έ λ‹€μŒ N개의 μ€„μ—λŠ” μ •μˆ˜λ“€μ΄ 주어진닀. μž…λ ₯λ˜λŠ” μ •μˆ˜μ˜ μ ˆλŒ“κ°’μ€ 4,000을 λ„˜μ§€ μ•ŠλŠ”λ‹€." 글을 보고 4000 정도면 μŒμˆ˜λž‘ μ–‘μˆ˜ 그리고 0을 λͺ¨λ‘ 해도 κ°œμˆ˜κ°€ 8001개뿐이라 μ»΄ν“¨ν„°μ—κ²Œ μ „ν˜€ 무리가 갈 μˆ«μžκ°€ μ•„λ‹ˆλΌκ³  μƒκ°ν•΄μ„œ for문으둜 풀어보고 μ‹Άλ”λΌκ΅¬μš”(?) κ²°λ‘ μ μœΌλ‘œλŠ” λΉ„μŠ·ν–ˆμ§€λ§Œ, 직접 ν•΄λ³΄λ‹ˆ 속이 ν›„λ ¨ν•˜λ„€μš”. 될까 μ•ˆλ κΉŒ 혼자 κ³ λ―Όν•˜λŠ” 거보닀 μ½”λ“œλ‘œ 직접 μ³λ³΄λŠ”κ²Œ 졜고..πŸ‘

 

[전체 μ½”λ“œ]

# μ΅œμ’… μ œμΆœμ½”λ“œ(3)
import sys
N = int(sys.stdin.readline())
numbers = sorted([int(sys.stdin.readline()) for _ in range(N)])

# μ‚°μˆ ν‰κ· 
print(round(sum(numbers) / N))

# 쀑앙값
print(numbers[N // 2])

# μ΅œλΉˆκ°’
# 숫자, count둜 리슀트 λ§Œλ“€κΈ°
count = []
for i in range(-4000, 4001):
    count.append([i, 0])
# num을 λŒλ©΄μ„œ ν•΄λ‹Ή 숫자λ₯Ό ν‘œν˜„ν•˜λŠ” μΈλ±μŠ€λ²ˆν˜Έμ— 1을 μΆ”κ°€ν•΄μ€€λ‹€
for num in numbers:
    count[num + 4000][1] += 1
# 갯수 κΈ°μ€€μœΌλ‘œ μ •λ ¬
count.sort(key = lambda x: (-x[1], x[0]))
# 좜λ ₯
if N == 1:
    print(numbers[0])
else:
    if count[0][1] != count[1][1]:
        print(count[0][0])
    else:
        print(count[1][0])

# λ²”μœ„ : μ΅œλŒ“κ°’ - μ΅œμ†Ÿκ°’
print(max(numbers) - min(numbers))