반응형

오늘은 파이썬 문법 리뷰의 마지막 시간이다. 
지금까지 배운것들을 생각해보며 풀어볼 수 있는 예제를 리뷰 할 것이다.
모두들 재미있게 파이썬은 공부하면 좋겠다.

# 08장 종합문제

#-----------------------------------------------------------------------------------------------------------------------

# Q1 문자열 바꾸기
# 다음과 같은 문자열이 있다.
#
# a:b:c:d
# 문자열의 split와 join 함수를 사용하여 위 문자열을 다음과 같이 고치시오.
#
# a#b#c#d

# [Q1 풀이]
a = "a:b:c:d"
b = a.split(":")
print(b)
c = "#".join(b)
print(c)

#-----------------------------------------------------------------------------------------------------------------------

# Q2 딕셔너리 값 추출하기
# 다음은 딕셔너리의 a에서 'C'라는 key에 해당하는 value를 출력하는 프로그램이다.
#
# >>> a = {'A':90, 'B':80}
# >>> a['C']
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# KeyError: 'C'
# a 딕셔너리에는 'C'라는 key가 없으므로 위와 같은 오류가 발생한다. 'C'에 해당하는 key 값이 없을 경우 오류 대신 70을 얻을 수 있도록 수정하시오.

# [Q2 풀이]
a = {'A':90, 'B':80}
print(a.get('C', 70)) #딕셔너리의 get 함수를 사용하면 key가 없을 경우에는 두 번째 매개변수로 전달된 default 값을 대신 도려준다.

#-----------------------------------------------------------------------------------------------------------------------

# Q3 리스트의 더하기와 extend 함수
# 다음과 같은 리스트 a가 있다.
#
# >>> a = [1, 2, 3]
# 리스트 a에 [4, 5]를 + 기호를 사용하여 더한 결과는 다음과 같다.
#
# >>> a = [1, 2, 3]
# >>> a = a + [4,5]
# >>> a
# [1, 2, 3, 4, 5]
# 리스트 a에 [4,5]를 extend를 사용하여 더한 결과는 다음과 같다.
#
# >>> a = [1, 2, 3]
# >>> a.extend([4, 5])
# >>> a
# [1, 2, 3, 4, 5]
# + 기호를 사용하여 더한 것과 extend한 것의 차이점이 있을까? 있다면 그 차이점을 설명하시오.

# [Q3 풀이]
# 리스트 a에 +기호를 사용하는 경우에 대해서 먼저 살펴보자.
a = [1, 2, 3]
print(id(a))
# id 함수는 입력을 받은 리스트 a의 주소 값을 돌려준다.
# 현재 a라는 리스트는 2267994099072 이라는 주소에 저장되어 있다.
a = a + [4, 5]
print(a)
# 리스트 a에 +기호를 사용하여 [4, 5]라는 리스트를 더해 보았다.
# 그리고 다시 다음과 같이 리스트 a의 주소 값을 확인해 보자.
print(id(a))
# 이전에 리스트 a가 저장되어 있던 주소와 다른 값을 돌려주는 것을 확인할 수 있다.
# 주소 값이 다르기 때문에 +를 사용하면 리스트 a의 값이 변하는 것이 아니라 두 리스트가 더해진 새로운 리스트가 반환된다는 것을 확인할 수 있다.

# 이번에는 extend 함수를 사용해 보자.
a = [1, 2, 3]
print(id(a))
# 리스트 a를 생성하고 그 주소 값을 출력해 보았다.
a.extend([4, 5])
print(a)
# 그리고 리스트 a에 extend를 사용하여 [4, 5]라는 리스트를 더해 주었다.
# 그리고 다시 다음과 같이 리스트 a의 주소 값을 확인해 보도록 하자.
print(id(a))
# + 기호를 사용하여 더한 경우와는 달리 주소 값이 변하지 않고 그대로 유지되는 것을 확인할 수 있다.

#-----------------------------------------------------------------------------------------------------------------------

# Q4 리스트 총합 구하기
# 다음은 A학급 학생의 점수를 나타내는 리스트이다. 다음 리스트에서 50점 이상 점수의 총합을 구하시오.
#
# A = [20, 55, 67, 82, 45, 33, 90, 87, 100, 25]

# [Q4 풀이]
# 리스트 총합 구하기 문제이다

A = [20, 55, 67, 82, 45, 33, 90, 87, 100, 25]

result = 0
while A:            # A 리스트에 값이 있는 동안
    mark = A.pop()  # A 리스트의 가장 마지막 항목을 하나씩 뽑아냄
    if mark >= 50:  # 50점 이상의 점수만 더함
        result += mark

print(result)       # 481 출력

#-----------------------------------------------------------------------------------------------------------------------

# Q5 피보나치 함수
# 첫 번째 항의 값이 0이고 두 번째 항의 값이 1일 때, 이후에 이어지는 항은 이전의 두 항을 더한 값으로 이루어지는 수열을 피보나치 수열이라고 한다.
#
# 0, 1, 1, 2, 3, 5, 8, 13, ...
# 입력을 정수 n으로 받았을 때, n 이하까지의 피보나치 수열을 출력하는 함수를 작성해 보자.

# [Q5 풀이]
# 피보나치 함수에 관한 문제이다.
# 피보나치 수열은 다음과 같은 순서로 결괏값을 반환한다.

# 1. fib(0) → 0 반환
# 2. fib(1) → 1 반환
# 3. fib(2) → fib(0) + fib(1) → 1 반환
# 4. fib(3) → fib(1) + fib(2) → 2 반환
# 5. fib(4) → fib(2) + fib(3) → 3 반환
# 6. ...

# n이 0일 때는 0을 반환, 1일 떄는 1을 반환한다.
# n이 2 이상일 경우에는 이전의 두 값을 더하여 반환한다.

# 재귀 호출을 사용하면 피보나치 함수를 다음과 같이 간단하게 작성할 수 있다.

def fib(n):
    if n == 0 : return 0        # n이 0일 때는 0을 반환
    if n == 1 : return 1        # n이 1일 때는 1을 반환
    return fib(n-2) + fib(n-1)  # n이 2 이상일 때는 그 이전의 두 값을 더하여 반환

for i in range(10):
    print(fib(i))

# 0부터 9까지의 피보나치 수열을 결괏값을 출력하여 그 값을 확인해 보았다.

#-----------------------------------------------------------------------------------------------------------------------

# Q6 숫자의 총합 구하기
# 사용자로부터 다음과 같은 숫자를 입력받아 입력받은 숫자의 총합을 구하는 프로그램을 작성하시오. (단 숫자는 콤마로 구분하여 입력한다.)
#
# 65,45,2,3,45,8

# [Q6 풀이]
# 사용자가 입력한 숫자의 합을 구하는 것이고 숫자는 콤마로 구분되어 있다.
user_input = input("숫자를 입력하세요: ")
numbers = user_input.split(",")
total = 0
for n in numbers:
    total += int(n)
print(total)
# 수행하여 숫자(65,45,2,3,45,8)를 입력하면 숫자의 총합 168이 출력된다.

#-----------------------------------------------------------------------------------------------------------------------

# Q7 한 줄 구구단
# 사용자로부터 2~9의 숫자 중 하나를 입력받아 해당 숫자의 구구단을 한 줄로 출력하는 프로그램을 작성하시오.
#
# 실행 예)
#
# 구구단을 출력할 숫자를 입력하세요(2~9): 2
# 2 4 6 8 10 12 14 16 18

# [Q7 풀이]
# 한 줄 구구단을 구현하는 문제이다.
user_input = input("구구단을 출력할 숫자를 입력하세요(2~9):")
dan = int(user_input)           # 입력 문자열을 숫자로 변환
for i in range(1, 10):
    print(i*dan, end = " ")     # 한 줄로 출력하기 위해 줄 바꿈 문자 대신 공백 문자를 마지막에 출력한다.

#-----------------------------------------------------------------------------------------------------------------------

# Q8 역순 저장
# 다음과 같은 내용의 파일 abc.txt가 있다.
#
# AAA
# BBB
# CCC
# DDD
# EEE
# 이 파일의 내용을 다음과 같이 역순으로 바꾸어 저장하시오.
#
# EEE
# DDD
# CCC
# BBB
# AAA

# [Q8 풀이]
# 파일 객체의 readlines를 사용하여 모든 라인을 읽은 후에 reversed를 사용하여 역순으로 정렬할 다음 다시 파일에 저장한다.

f = open('abc.txt', 'r')
lines = f.readlines()       # 모든 라인을 읽음
f.close()

lines.reverse()             # 읽은 라인을 역순으로 정렬

f = open('abc.txt', 'w')
for line in lines:
    line = line.strip()     # 포함되어 있는 줄 바꿈 문자 제거
    f.write(line)
    f.write('\n')           # 줄 바꿈 문자 삽입
f.close()

#-----------------------------------------------------------------------------------------------------------------------

# Q9 평균값 구하기
# 다음과 같이 총 10줄로 이루어진 sample.txt 파일이 있다. sample.txt 파일의 숫자 값을 모두 읽어 총합과 평균 값을 구한 후 평균 값을 result.txt 파일에 쓰는 프로그램을 작성하시오.
#
# 70
# 60
# 55
# 75
# 95
# 90
# 80
# 80
# 85
# 100

# [Q9 풀이]
# 총 10줄로 이루어진 sample.txt 파일의 숫자값을 모두 읽어서 평균값을 구해야 한다.

f = open('sample.txt')
lines = f.readlines()       # sample.txt를 줄 단위로 모두 읽는다.
f.close()

total = 0
for line in lines:
    score = int(line)       # 줄에 적힌 점수를 숫자형으로 변환한다.
    total += score
    average = total / len(lines)

f = open("result.txt", "w")
f.write(str(average))
f.close()

# sample.txt의 점수를 모두 읽기 위해 파일을 열고 readlines를 사용하여 각 줄의 점수 값을 모두 읽어 들여 총 점수를 구한다.
# 총 점수를 sample.txt 파일의 라인(line)수로 나누어 평균 값을 구한 후 그 결과를 result.txt 팡리에 쓴다.
# 숫자 값은 result.txt 파일에 바로 쓸 수 없으므로 str 함수를 사용하여 문자열로 변경한 후 파일에 쓴다.

#-----------------------------------------------------------------------------------------------------------------------

# Q10 사칙연산 계산기
# 다음과 같이 동작하는 클래스 Calculator를 작성하시오.
#
# >>> cal1 = Calculator([1,2,3,4,5])
# >>> cal1.sum() # 합계
# 15
# >>> cal1.avg() # 평균
# 3.0
# >>> cal2 = Calculator([6,7,8,9,10])
# >>> cal2.sum() # 합계
# 40
# >>> cal2.avg() # 평균
# 8.0

# [Q10 풀이]
class Calculator:
    def __init__(self, numberList):
        self.numberList = numberList

    def sum(self):
        result = 0
        for num in self.numberList:
            result += num
        return result

    def avg(self):
        total = self.sum()
        return total / len(self.numberList)

cal1 = Calculator([1, 2, 3, 4, 5])
print(cal1.sum())
print(cal1.avg())

cal2 = Calculator([6, 7, 8, 9, 10])
print(cal2.sum())
print(cal2.avg())

#-----------------------------------------------------------------------------------------------------------------------

# Q11 모듈 사용 방법
# C:\doit 디렉터리에 mymod.py 파이썬 모듈이 있다고 가정해 보자. 명령 프롬프트 창에서 파이썬 셸을 열어 이 모듈을 import해서 사용할 수 있는 방법을 모두 기술하시오. (즉 다음과 같이 import mymod를 수행할 때 오류가 없어야 한다.)
#
# >>> import mymod
# >>>

# [Q11 풀이]
# 이 문제는 모듈 사용방법에 관한 문제이다.
# 파이썬 셸에서 mymod.py 모듈을 인식하기 위해서는 다음과 같은 3가지 방법이 있을 수 있다.

# 1) sys 모듈 사용하기
# 다음가 같이 sys.path에 C:\doit 이라는 디렉터리를 추가하면 c:\doit 이라는 디렉터리에 있는 mymod 모듈을 사용할 수 있게 된다.

# import sys
# sys.path.append("c:\doit")
# import mymod

# 2) PYTHONPATH 환경 변수 사용하기

# 다음처럼 PYTHONPATH 환경 변수에 c:\doit 디렉터리를 지정하면 c:\doit 디렉터리에 있느 mymod 모듈을 사용할 수 있게 된다.

# C:\Users\home>set PYTHONPATH=c:\doit
# C:\Users\home>python
# >>> import mymod

# 3) 현재 디렉토리 사용하기
# 파이썬 셸을 mymod.py가 있는 위치로 이동하여 실행해도 mymod 모듈을 사용할 수 있게 된다.
# 왜냐하면 sys.path에는 현재 디렉터리인 . 이 항상 포함되어 있기 떄문이다.

# C:\Users\home>cd c:\doit
# C:\doit>python
# >>> import mymod

#-----------------------------------------------------------------------------------------------------------------------

# Q12 오류와 예외 처리
# 다음 코드의 실행 결과를 예측하고 그 이유에 대해 설명하시오.
#
# result = 0
#
# try:
#     [1, 2, 3][3]
#     "a"+1
#     4 / 0
# except TypeError:
#     result += 1
# except ZeroDivisionError:
#     result += 2
# except IndexError:
#     result += 3
# finally:
#     result += 4
#
# print(result)

# [Q12 풀이]
# 오류와 예외처리에 관한 문항이다.

# 1. result의 초깃값은 0이다.
# 2. try문 안의 [1, 2, 3][3]이라는 문장 수행 시 indexError 가 발생하여 except
#     Indexerror: 구문으로 이동하게 되어 result에 3이 더해져 3이 된다.
# 3. 최종적으로 finally 구문이 실행되어 result에 4가 뎌허재ㅕ 7이 된다.
# 4. print(result)가 수행되어 result의 최종 값인 7이 출력된다.

#-----------------------------------------------------------------------------------------------------------------------

# Q13 DashInsert 함수
# DashInsert 함수는 숫자로 구성된 문자열을 입력받은 뒤 문자열 안에서 홀수가 연속되면 두 수 사이에 - 를 추가하고, 짝수가 연속되면 * 를 추가하는 기능을 갖고 있다. DashInsert 함수를 완성하시오.
#
# 입력 예시: 4546793
# 출력 예시: 454*67-9-3

# [Q13 풀이]
data = "4546793"
numbers = list(map(int, data))                      # 숫자 문자열을 숫자 리스트로 변경
result = []

for i, num in enumerate(numbers):
    result.append(str(num))
    if i < len(numbers)-1:                          # 다음 수가 있다면
        is_odd = num % 2 == 1                       # 현재 수가 홀수
        is_next_odd = numbers[i+1] % 2 == 1         # 다음 수가 홀수
        if is_odd and is_next_odd:                  # 연속 홀수
            result.append("-")
        elif not is_odd and not is_next_odd:         # 연속 짝수
            result.append("*")

print("".join(result))

#-----------------------------------------------------------------------------------------------------------------------

# Q14 문자열 압축하기
# 문자열을 입력받아 같은 문자가 연속적으로 반복되는 경우에 그 반복 횟수를 표시해 문자열을 압축하여 표시하시오.
#
# 입력 예시: aaabbcccccca
# 출력 예시: a3b2c6a1

# [Q14 풀이]
# 먼저 입력 문자열의 문자를 확인하여 동일한 문자가 들어올 경우에는 해당 문자의 숫자값을 증가시킨다.
# 만약 다른 문자가 들어올 경우에는 해당 문자의 숫자 값을 1로 초기화 하는 방법을 사용하여 작성한 코드이다.

def compress_string(s):
    _c = ""
    cnt = 0
    result = ""
    for c in s:
        if c != _c:
            _c = c
            if cnt: result += str(cnt)
            result += c
            cnt = 1
        else:
            cnt += 1
    if cnt : result += str(cnt)
    return result

print(compress_string("aaabbcccccca"))          # a3b2c6a1 출력

#-----------------------------------------------------------------------------------------------------------------------

# Q15 Duplicate Numbers
# 0~9의 문자로 된 숫자를 입력받았을 때, 이 입력값이 0~9의 모든 숫자를 각각 한 번씩만 사용한 것인지 확인하는 함수를 작성하시오.
#
# 입력 예시: 0123456789 01234 01234567890 6789012345 012322456789
# 출력 예시: True False False True False

# [Q15 풀이]
def chkDupNum(s):
    result = []
    for num in s:
        if num not in result:
            result.append(num)
        else:
            return False
    return len(result) == 10

print(chkDupNum("0123456789"))      # True 리턴
print(chkDupNum("01234"))           # False 리턴
print(chkDupNum("01234567890"))     # False 리턴
print(chkDupNum("6789012345"))      # True 리턴
print(chkDupNum("012322456789"))    # False 리턴

# 리스트 자료형을 사용하여 중복된 값이 있는 지 먼저 조사한다.
# 중복된 값이 있을 경우는 False를 리턴한다.
# 최종적으로 중복된 값이 없을 경우 0~9 까지의 숫자가 모두 사용되었는지 판단하기 위해 입력 문자열의 숫자 값을 저장한 리스트 자료형의 총 개수가 10인지를 조사하여
# 10일경우는 True, 아닐 경우는 Flase를 리턴한다.

#-----------------------------------------------------------------------------------------------------------------------

# Q16 모스 부호 해독
# 문자열 형식으로 입력받은 모스 부호(dot:. dash:-)를 해독하여 영어 문장으로 출력하는 프로그램을 작성하시오.
#
# 글자와 글자 사이는 공백 1개, 단어와 단어 사이는 공백 2개로 구분한다.
# 예를 들어 다음 모스 부호는 "HE SLEEPS EARLY"로 해석해야 한다.
# .... .  ... .-.. . . .--. ...  . .- .-. .-.. -.--
# 모스부호 규칙 표
#
# 문자	부호	문자	부호
# A	.-	N	-.
# B	-...	O	---
# C	-.-.	P	.--.
# D	-..	Q	--.-
# E	.	R	.-.
# F	..-.	S	...
# G	--.	T	-
# H	....	U	..-
# I	..	V	...-
# J	.---	W	.--
# K	-.-	X	-..-
# L	.-..	Y	-.--
# M	--	Z	--..

# [Q16 풀이]
dic = {
    '.-':'A','-...':'B','-.-.':'C','-..':'D','.':'E','..-.':'F',
    '--.':'G','....':'H','..':'I','.---':'J','-.-':'K','.-..':'L',
    '--':'M','-.':'N','---':'O','.--.':'P','--.-':'Q','.-.':'R',
    '...':'S','-':'T','..-':'U','...-':'V','.--':'W','-..-':'X',
    '-.--':'Y','--..':'Z'
}

def morse(src):
    result = []
    for word in src.split("  "):
        for char in word.split(" "):
            result.append(dic[char])
        result.append(" ")
    return "".join(result)

print(morse(".... .  ... .-.. . . .--. ...  . .- .-. .-.. -.--"))

#-----------------------------------------------------------------------------------------------------------------------

# Q17 기초 메타 문자
# 다음 중 정규식 a[.]{3,}b과 매치되는 문자열은 무엇일까?
#
# acccb
# a....b
# aaab
# a.cccb

# [Q17 풀이]
# 보기 중 이 조건에 해당되는 것은 B이다.
# 다음은 위 문제의 정규식 매치 결과를 확인해 보는 파이썬 코드이다.
import re

p = re.compile("a[.]{3,}b")

print(p.match("acccb"))         # None
print(p.match("a....b"))        # 매치 객체 출력
print(p.match("aaab"))          # None
print(p.match("a.cccb"))        # None

#-----------------------------------------------------------------------------------------------------------------------

# Q18 문자열 검색
# 다음 코드의 결괏값은 무엇일까?
#
# >>> import re
# >>> p = re.compile("[a-z]+")
# >>> m = p.search("5 python")
# >>> m.start() + m.end()

# [Q18 풀이]
# 정규식 [a-z]+은 소문자로 이루어진 단어를 뜻하므로 5 python 문자열에서 python과 매치될 것이다.
# 따라서 python 문자열의 인덱스 범위는 m.start()에서 m.end()까지이므로 10이 출력된다.

import re
p = re.compile('[a-z]+')
m = p.search("5 python")
print(m.start() + m.end())      # 10 출력

# 5 python 문자열에서 n이 7번째 문자여서 m.end()의 값이 7이 나올것 같지만, 다음과 같은 슬라이싱 규칙을 떠올려보면 왜 8이 나오는지 쉽게 이해될 것이다.
a = "5 python"
print(a[2:8])                   # "python" 출력
print(a[2:7])                   # "pytho" 출력

#-----------------------------------------------------------------------------------------------------------------------

# Q19 그루핑
# 다음과 같은 문자열에서 휴대폰 번호 뒷자리인 숫자 4개를 ####로 바꾸는 프로그램을 정규식을 사용하여 작성하시오.
#
# """
# park 010-9999-9988
# kim 010-9909-7789
# lee 010-8789-7768
# """

# [Q19 풀이]
# 전화번호 패턴은 다음과 같이 작성할 수 있다.
# pat = re.compile("\d{3}[-]\d{4}[-]\d{4}")
# 이 전화번호 패턴 중 뒤의 숫자 4개를 변경할 것이므로 필요한 앞부분을 다음과 같이 그루핑 한다.
# pat = re.compile("(\d{3}[-]\d{4})[-]\d{4}")
# 컴파일된 객체 pat에 sub 함수를 사용하여 다음과 같이 문자열을 변경한다.

import re

s = """
park 010-9999-9988
kim 010-9909-7789
lee 010-8789-7768
"""

pat = re.compile("(\d{3}[-]\d{4})[-]\d{4}")
result = pat.sub("\g<1>-####", s)

print(result)

#-----------------------------------------------------------------------------------------------------------------------

# Q20 전방 탐색
# 다음은 이메일 주소를 나타내는 정규식이다. 이 정규식은 park@naver.com, kim@daum.net, lee@myhome.co.kr 등과 매치된다. 긍정형 전방 탐색 기법을 사용하여 .com, .net이 아닌 이메일 주소는 제외시키는 정규식을 작성하시오.
#
# .*[@].*[.].*$

# [Q20 풀이]
# .com과 .net에 해당되는 이메일 주소만을 매치하기 위해서 이메일 주소의 도메인 부분에 다음과 같은 긍정형 전방탐색 패턴을 적용한다.
# pat = re.compile(".*[@].*[.](?=com$|net$).*$")
# 다음은 위 패턴을 적용한 파이썬 코드이다.
import re

pat = re.compile(".*[@].*[.](?=com$|net$).*$")

print(pat.match("pahkey@gmail.com"))
print(pat.match("kim@daum.net"))
print(pat.match("lee@myhome.co.kr"))

# Review complete.

파이썬 문법 예제

파이썬 문법 예제 리뷰의 핵심

  • 문자열 바꾸기
  • 딕셔너리 값 추출하기
  • 리스트의 더하기와 extend 함수
  • 리스트 총합 구하기
  • 피보나치 함수
  • 숫자의 총합 구하기
  • 한 줄 구구단
  • 역순 저장
  • 평균값 구하기
  • 사칙연산 계산기
  • 모듈 사용 방법
  • 오류와 예외 처리
  • DashInsert 함수
  • 문자열 압축하기
  • Duplicate Numbers
  • 모스 부호 해독
  • 기초 메타 문자
  • 문자열 검색
  • 그루핑
  • 전방탐색

오늘은 파이썬 문법 예제를 리뷰하며 작성한 코드를 공유한다.
프로그램의 세계에 들어온 것을 환영한다. 항상 즐겁게 프로그래밍 하길 바란다.
https://github.com/mgkim-developer/Python-Basic-Grammar

 

GitHub - mgkim-developer/Python-Basic-Grammar: Python Basic Grammar Study

Python Basic Grammar Study. Contribute to mgkim-developer/Python-Basic-Grammar development by creating an account on GitHub.

github.com

 

반응형