제로베이스 데이터 파트타임 스쿨 학습 일지 [25.05.02]

[강의 요약]

[Part 03. 자료구조&알고리즘 with Python_ Ch 03. 알고리즘] 강의 수강

13_최댓값부터 22_평균(실습)까지 강의 수강하였음

🐢 100일 챌린지 🔥 : [▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰░                                       ] 47/100일 (47%)

 

 

 

[13_최댓값]

▶ 최댓값 개념

여러 개의 수 중에서 가장 큰 수

예시를 통해 이해해 보자.

[-2, -4, 5, 7, 10, 0, 8, 20, -11]

처음 값(-2)을 기준으로 삼고

나머지 값들과 하나씩 비교하면서 더 큰 값이 나오면 maxNum을 교체

끝까지 비교한 후 남은 maxNum이 최댓값임

 

 

▶ 코드 : 최댓값 클래스 구현

class MaxAlgorithm:

    def __init__(self, ns):
        self.nums = ns
        self.maxNum = 0

    def getMaxNum(self):
        self.maxNum = self.nums[0]  # 첫 번째 값을 초기 최대값으로 설정

        for n in self.nums:
            if self.maxNum < n:     # 더 큰 값이 있으면 교체
                self.maxNum = n

        return self.maxNum

# 실행
ma = MaxAlgorithm([-2, -4, 5, 7, 10, 0, 8, 20, -11])
maxNum = ma.getMaxNum()
print(f'maxNum: {maxNum}')

[출력 결과]

maxNum: 20

 



[14_최댓값(실습)]

▶ 접근 방법

알파벳 문자 중에서 아스키코드 값이 가장 큰 문자를 찾아야 한다면

['c', 'x', 'Q', 'A', 'e', 'P', 'p']

각 문자의 ord() 값으로 비교

가장 큰 아스키코드를 가진 문자가 최댓값이 된다.

 

 

▶ 실습 코드 : 리스트에서 아스키코드가 가장 큰 값을 찾는 알고리즘 만들기

class MaxAlgorithm:

    def __init__(self, cs):
        self.chars = cs
        self.maxChar = 0

    def getMaxChar(self):
        self.maxChar = self.chars[0]  # 첫 문자를 초기 최댓값으로 설정

        for c in self.chars:
            if ord(self.maxChar) < ord(c):  # 아스키코드 기준으로 비교
                self.maxChar = c

        return self.maxChar

# 실행
ma = MaxAlgorithm(['c', 'x', 'Q', 'A', 'e', 'P', 'p'])
maxChar = ma.getMaxChar()
print(f'maxChar: {maxChar}')

문자 → 숫자 변환을 통해 기존 알고리즘 재활용 가능

[출력 결과]

maxChar: x

'x'는 아스키코드 120으로 가장 크다.

 



[15_최솟값]

▶ 최솟값 개념

최솟값은 자료 구조 안에서 가장 작은 수

 

리스트에서 최솟값을 찾는 기본 원리는 다음과 같음

리스트의 첫 값을 기준 최솟값으로 설정

이후 나머지 값을 하나씩 순회하며

더 작은 값이 나타나면 갱신

리스트 끝까지 비교를 마치면 최솟값 도출

 

 

▶ 코드 : 자료구조에서 가장 작은 값을 찾는다

class MinAlgorithm:

    def __init__(self, ns):
        self.nums = ns
        self.minNum = 0

    def getMinNum(self):
        self.minNum = self.nums[0]

        for n in self.nums:
            if self.minNum > n:
                self.minNum = n

        return self.minNum

# 실행
ma = MinAlgorithm([-2, -4, 5, 7, 10, 0, 8, 20, -11])
minNum = ma.getMinNum()
print(f'minNum: {minNum}')

[출력 결과]

minNum: -11

 



[16_최솟값(실습)]

▶ 접근 방법

알파벳 문자 중에서 아스키코드 값이 가장 작은 문자를 찾아야 한다면

['c', 'x', 'Q', 'A', 'e', 'P', 'p']

각 문자의 ord() 값을 비교

가장 작은 아스키코드를 가진 문자가 최솟값임

 

 

▶ 실습 코드 : 리스트에서 아스키코드가 가장 작은 값을 찾는 알고리즘 만들기

class MinAlgorithm:

    def __init__(self, cs):
        self.chars = cs
        self.minChar = 0

    def getMinChar(self):
        self.minChar = self.chars[0]

        for c in self.chars:
            if ord(self.minChar) > ord(c):
                self.minChar = c

        return self.minChar

# 실행
ma = MinAlgorithm(['c', 'x', 'Q', 'A', 'e', 'P', 'p'])
minChar = ma.getMinChar()
print(f'minChar: {minChar}')

[출력 결과]

minChar: A

'A'는 아스키코드 65로, 리스트 내에서 가장 작은 문자임

 



[17_최빈값]

▶ 최빈값 개념

최빈값은 데이터셋에서 가장 자주 등장하는 값

 

nums = [1, 3, 7, 6, 7, 7, 7, 12, 12, 17]

7이 총 4번 등장하여 최빈값

12는 2번, 나머지는 1번 이하 등장

 

 

▶ 코드 : 최빈값 구현

class MaxAlgorithm:

    def __init__(self, ns):
        self.nums = ns
        self.maxNum = 0
        self.maxNumIdx = 0

    def setMaxIdxAndNum(self):
        self.maxNum = self.nums[0]
        self.maxNumIdx = 0

        for i, n in enumerate(self.nums):
            if self.maxNum < n:
                self.maxNum = n
                self.maxNumIdx = i

    def getMaxNum(self):
        return self.maxNum

    def getMaxNumIdx(self):
        return self.maxNumIdx

# 원본 데이터
nums = [1, 3, 7, 6, 7, 7, 7, 12, 12, 17]

# 가장 큰 수를 기준으로 빈도 리스트 크기 결정
maxAlo = MaxAlgorithm(nums)
maxAlo.setMaxIdxAndNum()
maxNum = maxAlo.getMaxNum()

# 빈도 리스트 생성
indexes = [0 for _ in range(maxNum + 1)]

# 등장 횟수 기록
for n in nums:
    indexes[n] += 1

# 가장 많이 등장한 횟수와 그 인덱스(=값)를 찾음
maxAlo = MaxAlgorithm(indexes)
maxAlo.setMaxIdxAndNum()
maxNum = maxAlo.getMaxNum()
maxNumIdx = maxAlo.getMaxNumIdx()

print(f'즉, {maxNumIdx}의 빈도수가 {maxNum}로 가장 높다.')

indexes 리스트를 만들어서 등장 횟수 누적

MaxAlgorihm을 통해 최댓값 알고리즘 재활용

[출력 결과]

즉, 7의 빈도수가 4로 가장 높다.

 

 

 

[18_최빈값(실습)]

▶ 실습 문제

 

▶ maxScore.py : 최댓값 알고리즘 모듈

class MaxAlgorithm:

    def __init__(self, ns):
        self.nums = ns
        self.maxNum = 0
        self.maxNumIdx = 0

    def setMaxIdxAndNum(self):
        self.maxNum = self.nums[0]
        self.maxNumIdx = 0

        for i, n in enumerate(self.nums):
            if self.maxNum < n:
                self.maxNum = n
                self.maxNumIdx = i

    def getMaxNum(self):
        return self.maxNum

    def getMaxNumIdx(self):
        return self.maxNumIdx

 


▶ modeEx.py : 실습 메인 코드

import random
import maxScore as ms

# 점수 100명 생성 (70~100 사이 5점 단위)
scores = []
for i in range(100):
    rn = random.randint(71, 100)
    if rn != 100:
        rn = rn - (rn % 5)
    scores.append(rn)

# 최댓값(최고 점수)을 기준으로 인덱스 리스트 크기 생성
maxAlo = ms.MaxAlgorithm(scores)
maxAlo.setMaxIdxAndNum()
maxNum = maxAlo.getMaxNum()

# 각 점수별 빈도수 기록 리스트
indexes = [0 for i in range(maxNum + 1)]
for n in scores:
    indexes[n] += 1

# 가장 높은 빈도수부터 하나씩 출력 (중복 피하기 위해 사용 후 0으로 초기화)
n = 1
while True:
    maxAlo = ms.MaxAlgorithm(indexes)
    maxAlo.setMaxIdxAndNum()
    maxNum = maxAlo.getMaxNum()
    maxNumIdx = maxAlo.getMaxNumIdx()

    if maxNum == 0:
        break

    print(f'{n}. {maxNumIdx}빈도수: {maxNum}\t', end='')
    print('+' * maxNum)

    indexes[maxNumIdx] = 0  # 출력한 값은 다시 선택되지 않도록 초기화
    n += 1

점수별 등장 횟수를 기록 → 최댓값 알고리즘으로 최빈값 출력

[출력 결과]

1. 80빈도수: 19	+++++++++++++++++++
2. 90빈도수: 17	+++++++++++++++++
3. 75빈도수: 16	++++++++++++++++
...

+ 막대가 길수록 해당 점수를 받은 학생이 많다는 의미

 



[19_근삿값]

▶ 근삿값 개념

근삿값은 어떤 기준값과 가장 가까운 값

 

기준값과 리스트의 각 값을 뺀 후 abs()로 차이를 계산

그중 가장 차이가 작은 값이 근삿값

nums = [7, 43, 14, 44, 6, 26, ...]
inputNum = 11

→ abs(7 - 11) = 4  
→ abs(14 - 11) = 3  
→ abs(6 - 11) = 5  
→ ...  
→ 가장 차이가 작은 값: 14 → 근삿값

 

 

▶ 코드

import random

# 0~49 사이 중복 없는 20개 숫자 생성
nums = random.sample(range(0, 50), 20)
print(f'nums: {nums}')

# 사용자 입력값
inputNum = int(input('input number: '))
print(f'inputNum: {inputNum}')

# 초기값 설정
nearNum = 0
minNum = 50  # 차이의 최소값 (초기에는 최대값으로 설정)

# 반복문으로 절대값 차이 계산
for n in nums:
    absNum = abs(n - inputNum)
    if absNum < minNum:	# 최솟값 갱신
        minNum = absNum
        nearNum = n

# 결과 출력
print(f'nearNum: {nearNum}')

[출력 결과]

nums: [7, 43, 14, 44, 6, 26, 24, 3, 25, 47, 2, 32, 27, 38, 18, 17, 33, 29, 28, 0]
input number: 11
nearNum: 14

 

 

 

[20_근삿값(실습)]

▶ 실습 문제

 

 

▶ near.py : 근삿값 기반 학점 판별 함수

def getNearNum(an):
    baseScore = [95, 85, 75, 65, 55]
    nearNum = 0
    minNum = 100

    for n in baseScore:
        absNum = abs(n - an)
        if absNum < minNum:
            minNum = absNum
            nearNum = n

    if nearNum == 95:
        return 'A'
    elif nearNum == 85:
        return 'B'
    elif nearNum == 75:
        return 'C'
    elif nearNum == 65:
        return 'D'
    elif nearNum <= 55:
        return 'F'

 


▶ nearEx.py : 실습 실행 파일

import near

scores = []

kor = int(input('input kor score: '))
scores.append(kor)
eng = int(input('input eng score: '))
scores.append(eng)
mat = int(input('input mat score: '))
scores.append(mat)
sci = int(input('input sci score: '))
scores.append(sci)
his = int(input('input his score: '))
scores.append(his)

totalScore = sum(scores)
print(f'totalScore: {totalScore}')

avgScore = totalScore / len(scores)
print(f'avgScore: {avgScore}')

grade = near.getNearNum(avgScore)
print(f'grade: {grade}')

[출력 결과]

input kor score: 90
input eng score: 80
input mat score: 85
input sci score: 90
input his score: 85
totalScore: 430
avgScore: 86.0
grade: B

 



[21_평균]

▶ 평균 개념

여러 수나 양의 중간값을 갖는 수를 평균이라 함

 

 

▶ 코드 : 전체 리스트 평균 구하기

import random

nums = random.sample(range(0, 100), 30)
print(f'nums: {nums}')

total = 0
for n in nums:
    total += n

average = total / len(nums)
print(f'average: {round(average, 2)}')

[출력 결과]

nums: [88, 3, 2, 89, 59, 27, 20, 48, 17, 63, 35, 6, 73, 4, 71, 67, 22, 30, 60, 43, 50, 76, 42, 25, 18, 8, 14, 0, 5, 80]
average: 40.7

 

 

▶ 코드 : 50 이상 90 이하 평균

nums = random.sample(range(0, 100), 30)

targetNums = []
total = 0
for n in nums:
    if 50 <= n <= 90:
        total += n
        targetNums.append(n)

print(f'targetNums: {targetNums}')
average = total / len(targetNums)
print(f'average: {round(average, 2)}')

[출력 결과]

targetNums: [89, 59, 63, 73, 71, 67, 60, 50, 76, 80]
average: 68.8



▶ 코드 : 정수만 골라 평균 구하기

nums = [4, 5.12, 0, 5, 7.34, 9.1, 9, 3, 3.159, 1, 11, 12.789]

targetNums = []
total = 0
for n in nums:
    if n - int(n) == 0:
        total += n
        targetNums.append(n)

print(f'targetNums: {targetNums}')
average = total / len(targetNums)
print(f'average: {round(average, 2)}')

[출력 결과]

targetNums: [4, 0, 5, 9, 3, 1, 11]
average: 4.71

 

 

▶ 코드 : 소수(실수)만 골라 평균 구하기

nums = [4, 5.12, 0, 5, 7.34, 9.1, 9, 3, 3.159, 1, 11, 12.789]

targetNums = []
total = 0
for n in nums:
    if n - int(n) != 0:
        total += n
        targetNums.append(n)

print(f'targetNums: {targetNums}')
average = total / len(targetNums)
print(f'average: {round(average, 2)}')

[출력 결과]

targetNums: [5.12, 7.34, 9.1, 3.159, 12.789]
average: 7.9

 

 

 

[22_평균(실습)]

▶ 실습 문제

 

 

▶ averageEx.py : 메인 로직

import near

scores = (8.9, 7.6, 8.2, 9.1, 8.8, 8.1, 7.9, 9.4, 7.2, 8.7)
top5PlayerScores = [9.12, 8.95, 8.12, 7.90, 7.88]

print(f'Current scores: {top5PlayerScores}')

total = 0
for n in scores:
    total += n

average = round(total / len(scores), 2)

print(f'total: {total}')
print(f'average: {average}')

tp = near.Top5Players(top5PlayerScores, average)
tp.setAlignScore()
top5PlayerScores = tp.getFinalTop5Scores()

print(f'Final scores: {top5PlayerScores}')

 

▶ near.py : Top5 Players 클래스

class Top5Players:

    def __init__(self, cs, ns):
        self.currentScores = cs
        self.newScore = ns

    def setAlignScore(self):
        nearIdx = 0
        nearScore = 0
        minNum = 10.0

        for i, s in enumerate(self.currentScores):
            absNum = abs(self.newScore - s)

            if absNum < minNum:
                minNum = absNum
                nearIdx = i
                nearScore = s

        if self.newScore >= self.currentScores[nearIdx]:
            for i in range(len(self.currentScores)-1, nearIdx, -1):
                self.currentScores[i] = self.currentScores[i-1]
            self.currentScores[nearIdx] = self.newScore
        else:
            for i in range(len(self.currentScores)-1, nearIdx+1, -1):
                self.currentScores[i] = self.currentScores[i-1]
            self.currentScores[nearIdx+1] = self.newScore

    def getFinalTop5Scores(self):
        return self.currentScores

 

[출력 결과]

Current scores: [9.12, 8.95, 8.12, 7.9, 7.88]
total: 83.9
average: 8.39
Final scores: [9.12, 8.95, 8.39, 8.12, 7.9]

평균 8.39는 기존 점수 중 8.12와 가장 가까우므로 그 앞에 삽임 됨

 

 

 

[나의 생각 정리]

다양한 리스트 기반 알고리즘을 정리했다.

반복문과 조건문만으로 평균, 최빈값, 최댓값 등의 기능들을 구현할 수 있었다.

클래스와 함수로 기능을 분리하면서 코드도 재사용할 수 있었다.

 

 

[적용점]

데이터 분석할 때 데이터 정제, 이상치 탐색, 분포 확인에 오늘 정리한 로직들을 응용할 수 있을 것 같다.

근삿값과 최빈값 같은 알고리즘은 추천 시스템이나 점수 보정 등에 활용 가능할 것 같다.

조건에 따른 필터링 후 계산하면 문제 해결 과정이 간단해질 것 같다.

 

 

“이 글은 제로베이스 데이터 스쿨 주 3일반 강의 자료 일부를 발췌하여 작성되었습니다.”