파이썬, 알고리즘

파이썬 알고리즘 01. 리스트 안의 숫자 개수 세기

책먹는아인 2022. 4. 22. 15:56

※ 이 글은 비제이퍼블릭 출판사의 '말랑말랑 알고리즘'을 기반으로 하여 작성하였습니다.

이 페이지는 

문제 -> 생각하기 -> 코드짜기 -> 테스트 -> 바른 결과

 

이렇게 다섯 단계로 구성되어 있습니다. ^^

 

1) 문제

▣ 아래의 list에서 각각의 숫자가 몇개씩 들어있는지 구하는 알고리즘을 작성하시오.

list = [4, 0, 4, 4, 1, 8, 8, 2, 2, 5, 0, 6, 5, 6, 0]

 

 

: list 안에 4는 몇개가 들어있는지, 1은 몇개가 들어있는지 등을 확인하는 코드를 작성한다.

이 알고리즘을 활용하면 전체 데이터에서 특정 데이터가 몇개인지 확인이 가능하다.

 

먼저 주어지는 데이터 list를 살펴보면 아래와 같은 특징이 있다는 것을 알 수 있다.

list = [4, 0, 4, 4, 1, 8, 8, 2, 2, 5, 0, 6, 5, 6, 0]

특징 : 데이터의 숫자들은 0부터 9까지만 존재한다.

 

그리고 결과는 대충 이런 식으로 출력하기로 한다.

0 : 3 개
1 : 1 개
2 : 2 개
3 : 0 개
4 : 3 개
5 : 2 개
6 : 2 개
7 : 0 개
8 : 2 개
9 : 0 개

0은 몇개이고 1은 몇개이고 이런식으로 출력하면 된다.

 

자 이제, 문제를 해결하기 위해 단계를 잘게 쪼개어 생각해보자.

 

 


2) 생각하기

포인트 1.

먼저 list의 첫 요소부터 마지막 요소까지 한바퀴 돌아야 한다.

 

 

포인트 2.

위처럼 한바퀴 돌면서 해당 값의 개수를 누적시켜 '메모장'에 적어두어야 한다. 

 

 

 

위 두가지 포인트를 기억하고 이제 코드 작성으로 들어가보자.

우리가 만들 것은 여러개의 데이터를 던져주면 그 안에 어떤 숫자가 몇개가 들어있는지 알려주는 자동화기계이다.

 

 

! 주의 : count() 명령어는 사용하지 않기로 한다. 왜냐하면 사실 이 짓을 하는 이유는 count()와 같은 기능을 직접 구현해보는 데 목적이 있기 때문이다. 파이썬 선배님들(?)이 미리 만들어놓은 count()명령어가 하는 일을 어떤식으로 구현해 낼 수 있을지 아이디어를 내고 검증하는 데 목적이 있다. 

 


3) 코드짜기

1. 틀 만들기

이제부터 만들 자동화기계의 이름은 how_many라고 하겠다.

먼저, how_many라는 함수를 선언한다. 

그리고 사용자가 던져주는 데이터를 받아담을 빈 서랍(변수)가 필요하다.

변수 이름은 아무것이나 상관없지만 나는 data라고 지어주었다. 이 서랍은 위에서 나온 list가 들어갈 공간이다. 

def how_many(data):

 

2. 메모장 준비

일단 데이터로 주어질 list에는 0부터 9까지의 숫자만 존재하는 것을 우리는 미리 알고 있다.

그러니 메모장에 미리 0부터 9까지의 칸을 만들어둔다.

이 칸은 각각 인덱스 넘버로 구분한다. 0번째 인덱스 자리에는 숫자 0의 개수를, 1번째 인덱스 자리에는 숫자 1의 개수를 적는 식이다.

칸을 만들때 파이썬 규칙에 따라 그 칸들을 비워둘 수 없으니 초기값 0으로 채워준다.

def how_many(data):
    memo = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]   # 이 부분

이렇게 0을 10개나 일일히 찍는 것은 실수가 있을 수도 있고, 비효율적이다. 혹시 데이터가 커져서 더 많은 칸을 만들어야 할 때는 매우 귀찮아진다. 0을 100개씩 찍어야 한다거나 1,000개씩 찍어야 한다면... 오 마이갓.

그래서 아래처럼 리스트 안에서 for문을 사용하여 자동화 하자. 

def how_many(arr):
    memo = [0 for i in range(10)]   # 이 부분

이렇게 해두면 range()안의 숫자만 수정하여 0을 100개도 1,000개도 만들 수 있다.

이제 아래와 같은 10칸짜리 메모장이 준비가 되었다.

현재 memo 변수에는 위와 같은 list가 담겨있다.

 

 

3. 데이터 한바퀴 돌기

입력받은 데이터를 처음부터 끝까지 훑어야 하니 아래처럼 data를 범위로 하는 for문을 작성한다.

def how_many(data):
    memo = [0 for i in range(10)]

    for i in data:   # 이 부분

 

 

이렇게 처음부터 마지막까지 한개씩 살펴봐야 한다.

 

4. 개수 세기

첫번째 데이터부터, 메모장의 해당칸에 개수가 누적되도록 한다.

첫번째 데이터가 '4'이니까, 메모장의 4번째 칸에 +1이라고 개수를 up 해주는 것이다.

def how_many(data):
    memo = [0 for i in range(10)]

    for i in data:
        memo[i]+= 1   # 이 부분

위 코드를 모두 돌고 나면, memo장에는 data내 모든 숫자의 count된 개수가 기록되어 있다.

아래 그림을 참고하여 이해해보자.

 

 

 

5. 결과 출력하기

개수 세기가 끝나고 나면 memo 변수 안에 결과물이 아래처럼 예쁘게 담겨있을 것이다.

이제 이 결과를 보기 좋게 출력해준다.

 

memo에는 0번째 인덱스에 0의 개수가, 1번째 인덱스에 1의 개수, 2번째 인덱스에 2의 개수... 이런식으로 숫자들이 담겨 있다.

memo역시 처음부터 끝까지 한바퀴 돌아야 하니 for문을 작성한다. 

그리고 memo의 첫요소부터 마지막 요소까지 출력하도록 한다.

def how_many(data):
    memo = [0 for i in range(10)]

    for i in data:
        memo[i]+= 1

    for ii in range(len(memo)):   # 이 부분
        print(ii, '->', memo[ii])   # 이 부분

주의할 것은 for문에서 memo를 범위로 줄 때 range(len(memo )) 이런 형태로 감싸주어야 한다는 점이다.

왜 이렇게 써야 할까? 그냥 for ii in memo 라고 작성하면 안되는 걸까?

for ii in memo 라고 작성할 경우 for문이 참조하는 범위가 memo의 값 [3, 1, 2, 0, 3, 2, 2, 0, 2, 0]이 된다.

결과를 출력할 때 memo[0], memo[1], memo[2] ... memo[9] 이렇게 인덱스 넘버 순서대로 돌아야 차례대로 몇개인지 기록해놓은 값인 3, 1, 2, 0... 을 가져올 수 있. But, 만약 memo자체를 범위로 주면 값인 [3, 1, 2, 0, 3, 2, 2, 0, 2, 0]이 범위가 되고, 따라서

memo[3], memo[1], memo[2], memo[0]... 이렇게 가져오는 순서가 뒤죽박죽 엉망이 되고 만다.

※ for ii in memo 의 결과. 아래처럼 의도와 다른 결과가 나오게 된다.
 
3 -> 0
1 -> 1
2 -> 2
0 -> 3
3 -> 0
2 -> 2
2 -> 2
0 -> 3
2 -> 2
0 -> 3

그러므로 for ii in range(len(memo ))형태가 되어야 한다.

 

len(memo ) => 10

range(len(memo )) => 0, 10

 

for문은 0부터 10미만까지 반복하게 된다. 따라서 0, 1, 2... 8, 9까지 반복하게 되고, memo[0], memo[1], memo[2] ... 순으로 올바르게 값을 가져오게 된다.

 

 


4) 테스트

 

코드 작성이 끝났다면, 이제 코드를 실행시켜보자.

def how_many(arr):
    memo = [0 for i in range(10)]

    for i in arr:
        memo[i]+= 1

    for ii in range(len(memo)):
        print(ii, '->', memo[ii])


list = [4, 0, 4, 4, 1, 8, 8, 2, 2, 5, 0, 6, 5, 6, 0]	# 데이터

how_many(list)	# 함수 실행

 

 


5) 바른 결과

0 -> 3
1 -> 1
2 -> 2
3 -> 0
4 -> 3
5 -> 2
6 -> 2
7 -> 0
8 -> 2
9 -> 0

 

알아보기 좋도록 출력부분만 코드를 약간 수정해보자.

def how_many(arr):
    memo = [0 for i in range(10)]

    for i in arr:
        memo[i]+= 1

    for c in range(len(memo)):
        print('숫자', c, '->', memo[c], '개')
숫자 0 -> 3 개
숫자 1 -> 1 개
숫자 2 -> 2 개
숫자 3 -> 0 개
숫자 4 -> 3 개
숫자 5 -> 2 개
숫자 6 -> 2 개
숫자 7 -> 0 개
숫자 8 -> 2 개
숫자 9 -> 0 개

 

이 글이 알고리즘 이해에 작게나마 도움이 되었다면 아래 하트를 눌러 공감 부탁드립니다~^^*