04-02 자료구조 (파이썬) 문제풀이

탄팥빵·2021년 10월 24일

Python

목록 보기
8/8

04-02 자료구조 (파이썬) 문제풀이


1. 리스트 문제풀이


# 1부터 사용자가 입력한 숫자까지의 약수와 소수를 리스트에 각각 저장하고, 이것을 출력하는 프로그램 만들기

inputNum = int(input('1보다 큰 정수 입력:'))
listA = []
listB = []

# 약수
for n in range(1, inputNum+1):
    if n == 1:
        listA.append(n)
    else:
        if inputNum % n == 0:
            listA.append(n)
# 소수
for number in range(2, inputNum+1): # 1은 약수도 합성수도 아니기에 2부터 시작
    flag = True
    for n in range(2, number): # 2~num까지 반복; 예를 들어, 50을 입력했다면, 2~50까지의 수가 하나씩 내려가고
        if number % n == 0: # 그 수에 약수가 있는지 또 반복문을 돌리며 확인하게 된다; 나누어떨어지는 수가 없다면 소수이니 listB에 추가된다
            flag = False # 그 수에 약수가 있다면 소수가 아니기 때문에, 반복문은 중단되고 flag=False로 바뀌니 다음 상위의 반복문이 실행된다
            break
    if flag:
        listB.append(number)
        
print('{}의 약수: {}'.format(inputNum, listA))
print('{}까지의 소수: {}'.format(inputNum, listB))

# 1부터 100사이에 난수 10개를 생성한 후 짝수와 홀수를 구분해서 리스트에 저장하고 각각의 개수를 출력하는 프로그램 만들기

import random

randomList = random.sample(range(1, 101), 10) # 1에서 100까지의 수 중에 10개의 난수를 랜덤하게 발생
evens = []
odds = []

for n in randomList:
    if n % 2 == 0:
        evens.append(n)
    else:
        odds.append(n)
        
print('짝수 개수:', len(evens), evens)
print('홀수 개수:', len(odds), odds)

# 다음은 공원 입장료를 나타낸 표이다. 1일 총 입장객이 100명이라고 할 때, 1일 전체 입장 요금을 구하는 프로그램 만들기.
# 단, 입장 고객의 나이는 난수를 이용한다.

'''
구분 | 영유아 |  어린이 | 청소년  |   성인  |  어르신 
나이 | 0-7세  | 8-13세 | 14-19세 | 20-64세 | 65세 이상
요금 |  무료  |   200  |  300   |   500   |   무료
'''
import random

visitors = []

for n in range(100):
    visitors.append(random.randint(1, 100)) # 방문객 나이 랜덤 생상 및 리스트에 추가

group1, group2, group3, group4, group5 = 0,0,0,0,0

# 랜덤 100명중 연령대 기준에 맞춰 몇명인지 +1씩 추가
for age in visitors:
    if age >= 0 and age <= 7:
        group1 += 1
    elif age >= 8 and age <= 13:
        group2 += 1
    elif age >= 14 and age <= 19:
        group3 += 1
    elif age >= 20 and age <= 64:
        group4 += 1
    elif age >=65:
        group5 += 1

# 연령대별 요금 합계
group1Price = group1 * 0
group2Price = group2 * 200
group3Price = group3 * 300
group4Price = group4 * 500
group5Price = group5 * 0

print('-'*30)
# 연령대별 요금 합계 출력
print(f'영유아: {group1}명 : {group1Price}원')
print(f'어린이: {group1}명 : {group2Price}원')
print(f'청소년: {group1}명 : {group3Price}원')
print(f'성인: {group1}명 : {group4Price}원')
print(f'65세이상: {group1}명 : {group5Price}원')

print('-'*30)

# 1일 요금 총합계
sum = group1Price + group2Price + group3Price + group4Price + group5Price
print('1일 요금 총합계:', sum)

# 4개의 숫자 중 서로 다ㅡㄹㄴ 숫자 2개를 선택해서 만들 수 있는 모든 경우의 수를 출력하는 프로그램 만들기
# 순열 문제; 순서에 상관 없이

numbers = [4,6,7,9]
result = []

for n1 in numbers: # 일단 numbers에서 데이터 하나를 뽑아오고
    for n2 in numbers: # numbers 리스트에서 또 숫자 하나를 뽑아온다
        if n1 == n2: # 위 두 숫자가 같으면 의미가 없으니
            continue # 다음 반복문으로 넘어가라
            
        result.append([n1, n2]) # 서로 다른 숫자 2개가 선택되는 것이기 때문
        
print('result:', result)
print('result length:', len(result)) # 경우의 수 출력

# 4개의 숫자 중 서로 다른 3개를 선택해서 만들 수 있는 모든 경우의 수를 출력하는 프로그램 만들기

numbers = [4,6,7,9]
result = []

for n1 in numbers:
    for n2 in numbers:
        if n1 == n2: continue # 1번 숫자와 2번 숫자는 여기서 비교하고
        
        for n3 in numbers: # 1번-2번 둘다 다른 수이면, 여기서 3번과 각각 비교
            if n1 == n3 or n2 == n3: continue
            
            result.append([n1, n2, n3]) # 1번-2번-3번 모두 같지 않다면, result에 추가

print('result:', result)
print('result length:', len(result))


2. 튜플 문제풀이


# 자주 접속하는 웹사이트 비밀번호를 튜플에 저장하기
passwords = ('password1234', 'abc123', 'querty', 'letmein', 'welcome00')
print(f'passwords: {passwords}')

# 대학생 길동이의 1,2,3학년의 성적은 다음과 같다. 졸업할 때 4.0이상의 학점을 받기 위해 길동이가 받아야 하는 4학년 1,2학기의 최소 학점을 구해라.
scores = ((3.7, 4.2), (2.9, 4.3), (4.1, 4.2))
total = 0 # 전체학점을 담을 변수

for s1 in scores:
    for s2 in s1:
        total += s2

total = round(total, 1)
avg = total/6
        
print('3학년까지 총 학점:', total)
print('3학년까지 평균 학점:', avg)

target_for_gpa4 = round((4.0 * 8 - total), 1)
print('4학년 때 받아야 할 학점:', target_for_gpa4)

minScore = round((target_for_gpa4 / 2), 1)
print('4학년 때 필요한 한학기 최소 학점:', minScore)

scores = list(scores) # 우선 리스트로 만들면
scores.append((minScore,minScore)) #append 할 수 있으니, minScore를 튜플로 추가

scores = tuple(scores)
print('scores:', scores)

# 다음 튜플을 요구 사항에 맞춰 아이템을 슬라이스하자
numbers = (8.7,9.0,9.1,9.2,8.6,9.3,7.9,8.1,8.3)

print('index 0부터 3까지:', numbers[0:4])
print('index 2부터 4까지:', numbers[2:5])
print('index 3부터 끝까지:', numbers[3:])
print('index 2부터 뒤에서 -2까지:', numbers[2:-1])
print('index 0부터 끝까지, 3단계:', numbers[0::3])

print('최소값:', min(numbers))
print('최대값:', max(numbers))

print('최소값 index 위치:', numbers.index(min(numbers)))
print('최대값 index 위치:', numbers.index(max(numbers)))

# 시험 점수를 입력한 후 튜플에 저장하고 과목별 학점을 출력하기

korScore = int(input('국어 점수 입력: '))
engScore = int(input('영어 점수 입력: '))
matScore = int(input('수학 점수 입력: '))
sciScore = int(input('과학 점수 입력: '))
hisScore = int(input('국사 점수 입력: '))

# 딕셔너리에 저장
scores = (
    {'kor':korScore}, # 튜플은 값 변경이 안 되지만, 이경우는 튜플 안에 딕셔너리 형태로 있기에
    {'eng':engScore}, # 딕셔너리는 값 변경이 되니 아래에서 바꾸는 것
    {'mat':matScore},
    {'sci':sciScore},
    {'his':hisScore},
)

print(scores)

for item in scores: # 위 딕셔너리의 item하나가 내려가고
    for key in item.keys(): # 그 아이템의 key값을 받아 
        if item[key] >= 90: # 그 key의 값을 90과 비교해서 이상이라면
            item[key] = 'A' # 'A'로 값을 바꿔라
        elif item[key] >= 80:
            item[key] = 'B'
        elif item[key] >= 70:
            item[key] = 'C'
        else:
            item[key] = 'F'
            
print(scores)

# 다음 튜플의 과일 개수에 대해서 오름차순 및 내림차순으로 정렬해보자
fruits = ({'수박':8}, {'포도':13}, {'참외':12}, {'사과':17}, {'자두':19}, {'자몽':15})
print(fruits)
print('-'*30)

# 리스트라면 sort 등 함수를 사용해서 정렬 가능하겠지만,
# 딕셔너리에 있는 값을 기준으로 정렬을 해야 하니, 값에 접근을 먼저 해야한다.
# 딕셔너리 안에 있는 값을 빼서 정렬을 해야겠다; index를 이용할 것이다

fruits = list(fruits)
cIdx = 0 # 현재 비교를 하는 녀석의 index; 처음엔 0으로 해야겠지? 초기화
nIdx = 1 # 현재 나랑 비교를 하는 녀석이 누구냐? 그 다음 거겠지?; 처음엔 1이지만 그다음은 2, 3, 4... 계속 증가하겠다
eIdx = len(fruits) - 1 # 끝에 해댱되는 index; 리스트의 전체 길이에서 -1을 해주면 마지막 index 값이 된다

# 오름차순 정렬
flag = True
while flag:
    # 튜플 안의 딕셔너리 아이템에 접근
    curDic = fruits[cIdx] # 현재 current index에 해댱되는 current dictionary를 뽑아내도록 하겠다; 현재 기준이 되는 index, dictionary이다
    nextDic = fruits[nIdx] # 이건 next, 비교를 하는 녀석이다; 위 current index는 한번 끝까지 반복을 할 때까지 전혀 위치의 변화가 없다
                           # 반면, nIdx는 포도였다가, 참외였다가, 사과였다가, 자두였다가... 이렇게 끝에 도달할 때까지 1씩 증가해야 한다
    # 딕셔너리에서 value 값 꺼내기
    curDictCnt = list(curDic.values())[0] # indexing을 위해 리스트로 변환 후, 값이 위치한 0번째(하나밖에 없으니)
    nextDictCnt = list(nextDic.values())[0] 

    # current 값과 next 값 비교
    if nextDictCnt > curDictCnt: # next값이 current값보다 작다면; 예를 들어, 위에 보면 참외가 포도보다 작다; 그러면 참외가 포도 왼쪽으로 이동해야겠지?
        fruits.insert(cIdx, fruits.pop(nIdx)) # next index로 그 next 녀석을 잘라내고(pop은 값을 삭제 & 값을 반환), 현재 index 자리에 insert 해라 (자리바꿈)
        nIdx = cIdx + 1 # next index의 값은 항상 current index보다 1이 크면 된다; 자리바꿈을 했기 때문에 계속해서 초기화해주는 것이다
        continue
    
    # 수박 같은 경우 자리바꿈을 할 필요가 없다(가장 작아서)
    nIdx += 1 # next index가 하나씩 증가해야 하나씩 반복을 할 수 있겠지?
    if nIdx > eIdx: # index가 끝에 도달했다면,
        cIdx += 1 # current index도 1증가해야 한다; 수박이 비교가 끝났으니, 이젠 포도가 해야겠지? 그리고 또 그 다음 과일도 해야하고
        nIdx = cIdx + 1 # 그리고 again, next index의 초기설정은/값은 항상 current index보다 1이 커야한다
        
        if cIdx == 5: # 과일 하나씩 비교/반복이 끝나면, 즉, cureent index가 5에 도달한다면(수박, 포도,... 다 하고, 마지막 자몽까지 비교 다 돌렸으면)
            flag = False
            
print(tuple(fruits))

print('-'*30)

fruits = ({'수박':8}, {'포도':13}, {'참외':12}, {'사과':17}, {'자두':19}, {'자몽':15})

fruits = list(fruits)
cIdx = 0 # 현재 비교를 하는 녀석의 index; 처음엔 0으로 해야겠지? 초기화
nIdx = 1 # 현재 나랑 비교를 하는 녀석이 누구냐? 그 다음 거겠지?; 처음엔 1이지만 그다음은 2, 3, 4... 계속 증가하겠다
eIdx = len(fruits) - 1 

# 내림차순 정렬
flag = True
while flag:
    # 튜플 안의 딕셔너리 아이템에 접근
    curDic = fruits[cIdx] # 현재 current index에 해댱되는 current dictionary를 뽑아내도록 하겠다; 현재 기준이 되는 index, dictionary이다
    nextDic = fruits[nIdx] # 이건 next, 비교를 하는 녀석이다; 위 current index는 한번 끝까지 반복을 할 때까지 전혀 위치의 변화가 없다
                           # 반면, nIdx는 포도였다가, 참외였다가, 사과였다가, 자두였다가... 이렇게 끝에 도달할 때까지 1씩 증가해야 한다
    # 딕셔너리에서 value 값 꺼내기
    curDictCnt = list(curDic.values())[0] # indexing을 위해 리스트로 변환 후, 값이 위치한 0번째(하나밖에 없으니)
    nextDictCnt = list(nextDic.values())[0] 

    # current 값과 next 값 비교
    if nextDictCnt < curDictCnt: # next값이 current값보다 작다면; 예를 들어, 위에 보면 참외가 포도보다 작다; 그러면 참외가 포도 왼쪽으로 이동해야겠지?
        fruits.insert(cIdx, fruits.pop(nIdx)) # next index로 그 next 녀석을 잘라내고(pop은 값을 삭제 & 값을 반환), 현재 index 자리에 insert 해라 (자리바꿈)
        nIdx = cIdx + 1 # next index의 값은 항상 current index보다 1이 크면 된다; 자리바꿈을 했기 때문에 계속해서 초기화해주는 것이다
        continue
    
    # 수박 같은 경우 자리바꿈을 할 필요가 없다(가장 작아서)
    nIdx += 1 # next index가 하나씩 증가해야 하나씩 반복을 할 수 있겠지?
    if nIdx > eIdx: # index가 끝에 도달했다면,
        cIdx += 1 # current index도 1증가해야 한다; 수박이 비교가 끝났으니, 이젠 포도가 해야겠지? 그리고 또 그 다음 과일도 해야하고
        nIdx = cIdx + 1 # 그리고 again, next index의 초기설정은/값은 항상 current index보다 1이 커야한다
        
        if cIdx == 5: # 과일 하나씩 비교/반복이 끝나면, 즉, cureent index가 5에 도달한다면(수박, 포도,... 다 하고, 마지막 자몽까지 비교 다 돌렸으면)
            flag = False
            
print(tuple(fruits))

# 학급별 학생 수를 나타낸 튜플을 이용해서, 요구 사항에 맞는 데이터를 출력하는 프로그램 만들기
'''
- 전체 학생 수
- 평균 학생 수
- 학생 수가 가장 적은 학급
- 학생 수가 가장 많은 학급
- 학급별 학생 편차
'''

studentCnt = (
    {'cls01':18},
    {'cls02':21},
    {'cls03':20},
    {'cls04':19},
    {'cls05':22},
    {'cls06':20},
    {'cls07':23},
    {'cls08':17},
)

totalCnt = 0 # 전체 학생 수
minStdCnt = 0; minCls = '' # 가장 적은 학생, 해당 학급
maxStdCnt = 0; maxCls = '' # 가장 많은 학생, 해당 학급
deviation = [] # 편차

for idx, dic in enumerate(studentCnt):
    for k, v in dic.items():
        totalCnt += v # 전체 학생 수
        # 가장 큰 학생 수와 학급
        if minStdCnt == 0 or minStdCnt > v: # 처음엔 minStdCnt=0이 유효하니
            minStdCnt = v # 처음에 내려온 학급 학생 수가 이 변수에 할당
            minCls = k # 학급 이름도 할당; 이후부턴 minStdCnt(첫 아이템의 값)와 그 다음 내려온 v와 비교되어 만약 v가 더 작다면 min변수에 할당
            
        if maxStdCnt < v: # 처음엔 maxStdCnt=0이니 
            maxStdCnt = v # 처음에 내려온 학급 학생 수가 이 변수에 할당
            maxCls = k
            
print('전체 학생 수:', totalCnt)
avgCnt =  totalCnt/len(studentCnt)
print('평균 학생 수:', avgCnt)
print('학생 수가 가장 적은 학급:', minCls, '({})'.format(minStdCnt))
print('학생 수가 가장 많은 학급:', maxCls, '({})'.format(maxStdCnt))

# 학급별 편차
for idx, dic in enumerate(studentCnt):
    for k, v in dic.items():
        # 학생수 - 평균 = 편차
        deviation.append(v - avgCnt)
        
print('학급별 학생 편차:', deviation)


3. 딕셔너리 문제풀이


# 과목별 점수를 딕셔너리에 저장하고 출력하는 프로그램 만들기
subject = ['국어', '영어', '수학', '과학', '국사']
scores = {}

for s in subject:
    score = input('점수 입력:')
    scores[s] = score # s로 내려온 '국어'가 scores 딕셔너리의 키가 되고, 입력한 점수(score)가 그 키의 값으로 할당되어 딕셔너리에 같이 저장된다

print('과목별 점수:', scores)

# 사용자의 아이디, 비밀번호를 이용해서 로그인 프로그램을 만들어보자

members ={'hahaha':'123',
          'xxavv':'dksk',
          'pdsd':'dfef'}
myID = input('ID 입력: ')
myPW = input('PW 입력: ')

if myID in members: # 만약 입력한 ID가 members에 있다면
    if members[myID] == myPW: # 해당 ID를 key로하여 members에서 값을 조회하고 그 값이 내가 입력한 비밀번호와도 같다면
        print('로그인 성공') # 출력
    else:
        print('비밀번호를 확인해라') # ID는 맞았다는 것이니까 비밀번호만 틀린 것이니 이렇게 출력
else:
    print('ID를 확인해라') # ID부터 잘못된 것이니 이렇게 출력

# 삼각형부터 십각형까지의 내각의 합과 내각을 딕셔너리에 저장하는 프로그램을 만들어보자.
# n각형의 내각의 합 = 180 x (n-2)
dic = {}

for n in range(3, 11): # 3각형부터 10각형까지 반복하기 위해서
    hap = 180 * (n-2) # 내각의 합
    ang = int(hap /n) # 내각 = (내각의 합/각의 개수); 각의 개수: 삼각형이면 3, 사각형이면 4; 나눈것이니 소수점으로 표시되니 int로 정수화
    dic[n] = [hap, ang] # 내각의 합과 내각을 딕셔너리에 저장; n이 key값, 그거에 따른 value는 리스트 타입으로 저장

print(dic)

# 1부터 10까지의 각각의 정수에 대한 약수를 저장하는 딕셔너리를 만들고 출력하는 프로그램 만들기

dic = {}

for n1 in range(2, 11): # 1은 1이니 생략하고, 2~10까지 반복을 진행하면서
    tempList = [] 
    for n2 in range(1, n1+1): # 내려온, 해당하는 수까지, 1 ~ n1+1 까지 그 안에서 또 반복을 돌린다
        if n1 % n2 == 0: # 1부터 n1까지의 수 중에서 n1을 그 수로 나눴을 때 나누어떨어지는 수가 있다면
            tempList.append(n2) # 그건 약수이니, 리스트에 저장
    # tempLIst에는 약수들이 저장이 되어 있을 것이고
    dic[n1] = tempList # 2~10까지의 수에 대한 반복문이 하나씩 종료 될 때마다 각 수를 key로 하여 tempList를 해당 key의 값으로 할당하여 딕셔너리에 함께 저장
    
print(dic)

# 다음 문구를 공백으로 구분하여 리스트에 저장한 후, 인덱스와 단어를 이용해서 딕셔너리에 저장해보자

aboutPython = '파이썬은 1991년 프로그래머인 귀도 반 로섬이 발표한 고급 프로그래밍 언어이다.'
splitList = aboutPython.split()
print(splitList)

dic = {}

for idx, v in enumerate(splitList):
    dic[idx] = v
    
print(dic)

# 다음 문장에서 비속어를 찾고 비속어를 표준어로 변경하는 프로그램 만들기
'''
'강도는 서로 쪼개다, 짭새를 보고 빠르게 따돌리며 먹튀했다.'
==> '강도는 서로 웃다, 경찰관을 보고 빠르게 따돌리며 먹고 도망했다.'
'''
words = {'꺼지다':'가다',
        '쩔다':'엄청나다',
        '짭새':'경찰관',
        '꼽사리':'중간에 낀 사람',
        '먹튀':'먹고 도망',
        '지린다':'겁을 먹다',
        '쪼개다':'웃다',
        '뒷담 까다':'험담하다'}

txt = '강도는 서로 쪼개다, 짭새를 보고 빠르게 따돌리며 먹튀했다.'

# words에서 key값만 뽑아서 리스트로 별도 저장
keys = list(words.keys())

for key in keys:
    if key in txt:
        print(key) # key값; 비속어
        print(words[key]) # words에서 해당 key값에 연결된 value; 즉, 표준어
        txt = txt.replace(key, words[key]) # txt에서 key값에 해당되는, 즉, 비속어에 해당되는 것을 해당하는 표준어로 바꾸겠다

print(txt) # 변경된 txt 출력

# 딕셔너리를 이용해서 5명의 회원을 가입 받고 전체 회원 정보를 출력하는 프로그램 만들기
members = {} # 회원을 담을 dict
n = 1

while n < 6:
    mail = input('메일 입력: ')
    pw = input('비번 입력: ')

    # 중복 체크; 이미 회원인지
    if mail in members:
        print('이미 사용중인 메일 계정입니다.')
        # 중복회원이면 count를 하면 안되고, 다시 메일과 비번을 입력받아야하니
        continue # 반복을 새롭게 다시 진행
    else: # 기존 회원이 아니라면
        members[mail] = pw # 해당 회원의 메일을 key값으로 하고 비번을 value로 하여 딕셔너리에 저장
        n += 1 # 그리고 n +1

# 5번이 다 돌아가면 정보가 다 저장이 되었겠고, 이제 출력을 해보자
for key in members.keys():
    print(f'{key} : {members[key]}') # members의 key와 해당 key값에 해당하는 value 출력

# 위의 프로그램을 이용해서 특정 회원 계정을 삭제하는 프로그램 만들기

while True: # 삭제 될 때까지 돌리기 위해 True로 주겠다
    del_mail = input('삭제할 계정(메일) 입력: ')
    
    if del_mail in members: # 삭제를 위해 입력한 계정이 목록에 있다면
        del_pw = input('비번 입력:') # 비번 입력 받고
        if members[del_mail] == del_pw: # 계정에 연결된 비번과 입력받은 것이 같다면
            del members[del_mail] # 해당 아이템을 삭제
            print(f'{del_mail} 계정 삭제 완료')
            break # 반복문 중단
        else:
            print('비번을 확인해 주세요.')
    else:
        print('게정을 확인해 주세요.')  

# 다음은 학생 정보 테이블이다. 파이썬에서 학생 정보를 가장 효율적으로 저장하고, 관리할 수 있는 자료구조를 선택해서 컨테이너 자료형으로 만들어보자.
# 딕셔너리로 학생번호를 key로 하고 나머지 값들을 value로 하면 효율적으로 관리 할 수 있겠다
students ={'S21-0001':{'이름':'최성훈', '성구분':'M', '전공':'디자인', '연락처':'010-1234-5678', '메일': 'hun@gmail.com', '취미':['농구','음악']},
           'S21-0002':{'이름':'탁영우', '성구분':'M', '전공':'바리스타', '연락처':'010-5678-9012', '메일': 'yeong@gmail.com', '취미':'축구'},
           'S21-0003':{'이름':'황진영', '성구분':'W', '전공':'음악', '연락처':'010-9012-3456', '메일': 'jin@gmail.com', '취미':['수영','코딩']}}

for k1 in students.keys():
    print('학생번호:', k1)
    
    student = students[k1]
    for k2 in student.keys(): # student도 딕셔너리인 아이템이기에 for문으로 그 안의 key와 value 가져오기
        print('{} : {}'.format(k2, student[k2]))
        
    print('-'*30)
    
# 특정한 학생번호를 조회해서 해당 학생에 대해서만 정보 조회를 하고자 한다면
student_no = input('학생 번호 입력:')
print('{} : {}'.format(student_no, students[student_no]))


0개의 댓글