2주차 시간표
2주차는 금요일부터 추석 연휴이기 때문에 일과가 더 짧게 느껴졌다. 이번 주에 한 것을 되짚어보면 파이썬 문법 실시간 강의 진행 및 과제, 효율적인 코딩 공부법 특강, 협업을 위한 GIT 활용 기초 원격 강의, Git 활용을 위한 특강, 그리고 매일 해야되는 알고리즘 실습 문제풀이 등이 있었다.
파이썬 문법 실시간강의
-이창호 튜터님
저번주와는 다르게 이번주부터는 원격강의가 아닌 실시간 화상 강의로 튜터님이 직접 우리에게 파이썬 문법 강의를 해 주셨다.
코드 컨벤션이란 코드를 개발하다보면 타인이 작성한 코드를 알아 볼 수 없는 경우가 빈번하게 발생하기 때문에 이를 방지하기 위해 스타일을 통일하는 '약속' 같은 것이다. 코드 컨벤션은 개발하는 언어에 따라서 다르기 때문에 본인이 개발에 사용하는 언어에 따라 코드 컨벤션의 스타일도 바뀌는 것에 유의해야 한다.
파이썬에서는 네이밍 컨벤션으로 변수 / 함수를 네이밍할 때는 Snake 표기법을, Class를 네이밍할 때는 Pascal 표기법을 사용한다.
Pascal 표기법은 각 단어를 대문자로 구분하는 표기법이고(PythonIsVeryGood)
Snake 표기법은 각 단어를 언더바(_)로 구분하는 표기법이다.(python_is_very_good)
선언할 변수 명 = 변수에 넣고 싶은 값
과 같은 형태로 변수를 선언할 수 있습니다.description = “변수를 선언 하는 방법입니다.”
a, b, c = 1, 2, 3
list_ = [1,2,3,4]
number = 10
과 같이 사용되며, 정수 자료형이기 때문에 소수점은 지원하지 않습니다.number = 10.3
과 같이 사용되며, 소수점을 지원합니다.hello = "world!!"
와 같이 사용되며, 변수에 문자를 저장할 수 있습니다.numbers = [1, 2, 3, 4, 5]
와 같이 사용되며 1개 이상의 값을 한 변수에 담아 사용할 수 있습니다.numbers = (1, 2, 3 ,4, 5)
와 같이 사용되며 리스트와 동일한 방법으로 선언할 수 있습니다.numbers = {1, 2, 3, 4, 5}
와 같이 사용되며 리스트와 동일한 방법으로 선언할 수 있습니다.members = {”1”: “lee”, “2”: “park”, “3”: “kim”}
과 같이 사용되며 {key: value} 쌍으로 이루어져 있습니다.flag = True
와 같이 사용되며 True 혹은 False 두 값만 사용할 수 있습니다.사칙연산
# num에 정수를 할당하고, 할당된 값에 1을 더하고 싶을 때
# case 1
num = 10
num = num + 1
# result: 11
# case 2
num = 10
num += 1
# result: 11
# case 1, 2 모두 동일한 동작을 하고 동일한 결과를 내는 수식이다.
# 이와 같은 축약식은 + 이외에 다른 수식에서도 사용할 수 있다.
num -= 3 # num = num - 3
num *= 3 # num = num * 3
num **= 3 # num = num ** 3
num /= 3 # num = num / 3
num //= 3 # num = num // 3
num %= 3 # num = num % 3
string
list
tuple
set
dictionary(중요!!)
def 함수명():
과 같은 형태로 선언할 수 있다.import random
lotto = set() # lotto 변수를 set 자료형으로 선언
def get_lotto_number(count):
result = []
if count < 1:
print("1 이상의 값을 입력해주세요")
for _ in range(count): # count만큼 반복해서 실행
lotto = set()
while len(lotto) < 8: # lotto의 요소 갯수가 8 이하일 경우 계속해서 반복
lotto.add(random.randint(1, 45)) # lotto에 1~45 사이의 랜덤 값을 입력
result.append(lotto)
return result
lotto_numbers = get_lotto_number(10)
print(lotto_numbers)
# result print
"""
[
{1, 3, 4, 6, 9, 44, 18, 22, 26},
{2, 5, 9, 11, 44, 45, 19, 23, 28},
{1, 4, 39, 41, 16, 18, 27, 29, 31},
{2, 5, 8, 9, 14, 20, 22, 24, 31},
{33, 37, 6, 40, 41, 42, 19, 30, 31},
{33, 1, 36, 8, 41, 9, 17, 24, 30},
{5, 39, 41, 10, 12, 16, 23, 25, 26},
{3, 35, 37, 11, 14, 17, 19, 20, 30},
{33, 35, 3, 11, 43, 15, 16, 27, 30},
{33, 36, 38, 6, 43, 24, 25, 30, 31}
]
"""
# 랜덤 값을 사용하기 때문에 코드를 실행할 때마다 결과는 달라진다.
이창호 튜터님이 강의해주신 강의 내용의 핵심 요약이다. 주로 기초 개념과 이론적인 측면들 위주로 강의 해주셨는데 너무 개념적인 측면이라 아직 이해가 안될거라는 설명을 덧붙이면서 강의를 진행해 주셨는데, 확실히 무슨말인지 하나도 모르겠다. 컴파일러, 인터프리터 언어, 코드 컨벤션 등 최근 한달 간 캠프를 준비하며 사전공부를 나름 열심히 했다고 생각했는데 들어보지도 못한 생소한 단어들이 계속 나오니 머리가 하얘졌다. 하지만 이 부분은 튜터님도 말씀하셨듯이 이해가 안되는게 당연한 것이니 너무 깊게 파고들지 않고 파이썬이란 이런것이다 정도로만 머리속에 넣어두기로 했다. 내가 파이썬에 대한 지식이 더 늘어서 훗날 이 WIL을 다시 보게되었을때 이걸 이해 할 수 있는 내가 되어있다면 좋겠다.
효율적인 코딩 공부법 특강
- 강민철 튜터님 특강
전공자이기 때문에 코딩에 대해 겁을 먹고있는 우리를 위해 격려의 말씀을 해 주셨는데 비전공자이기 때문에 기죽어있었던 나 자신에게 아주 큰 힘이 되었다. 그리고나서 공부법에 대한 설명을 해주셨다. 고등학교시절 수능을 공부할 때나 대학에서 학점을 따기 위해 시험공부를 할 때 처럼 공부를 하면 안된다고 하셨는데 마침 내가 그때의 학습법을 그대로 따라하고 있었기 때문에 많이 찔렸다. 아무래도 평생을 공부라고는 전부 성적을 받기위한 공부만 했기 때문에 아무래도 그 습관이 쉽게 안고쳐지는 것 같다. 오늘부터 공부 할 때 계속 이 부분에 신경쓰면서 공부를 진행해야겠다고 생각했다. 다음으로는 프로그래밍 언어 또한 '언어'이기 때문에 계속 사용해보면서 말이 되도록 하는것이 중요하다고 하셨다. 나도 너무 완성된 코드만 만들려고 하다보니 이런 점을 간과한 것 같은데 실패도 해보면서 올바른 코드를 만드는 방법을 찾아가는 것을 중요시해야겠다.
프로그래밍 언어 (언어학자 전직 X 익숙해지기 O)
↓
프레임워크/라이브러리 (프레임워크는 기계! “사용법을 익히자”는 마음가짐으로)
↓
프로젝트 (완벽하게, 면접관 앞에서 설명할 수 있을 정도로)
↓
프로젝트 발전 (배포하기, 사용자 피드백 받고 유지보수하기, 테스트하기) + 코딩 테스트 대비 (개념 잡기, 그림 그리기, 코드로 옮기기)
이런 코딩 학습의 순서도 알려주시고 최종적으로는 결국 TIL 작성을 강조해주셨다. 앞으로도 TIL 작성에는 신경을 쓰도록 해야겠다.
Git 활용 기초 원격 강의
버전 관리: 프로젝트 상태가 변경되는 정보를 알고 있다는 것. Git 은 가장 널리 쓰이는 버전관리 도구로 commit 을 사용해 관리한다.
git 초기화(git initialize) : 컴퓨터에 있는 프로젝트를 Git 이 관리하는 프로젝트로 만드는 것
커밋(commit) :
add (혹은 staging, 스테이징) : 커밋에 반영할 파일을 선택하는 것으로 커밋에 반영할지 안할지는 파일 단위로 선택이 가능하다.
commit history : 커밋 한 내역을 한눈에 볼 수 있다.
repo : 'Git으로 관리되는 프로젝트' 를 Git 에서는 repo(리포, repository 리포지토리의 약자) 라고 부른다.
push : 로컬 repo의 커밋들을 원격 repo에 반영하는 것
pull : 원격 repo의 커밋들을 로컬 repo 로 반영하는 것
clone : 원격 repo를 내 컴퓨터에 가져와서 초기 repo 세팅하는 것
혼자 Git 프로젝트를 작업 할 때는 pull -> commit -> push 순으로 하는 것이 충돌을 막을 수 있어서 좋다.
협업의 단계
1단계 : 누가 이 작업 할 것인지 정한다. - Issue
2단계 : 각자 맡은 것을 작업한다. - Branch
3단계 : 각자 작업을 프로젝트에 합친다. - merge
+@단계 : 작업한 내용을 리뷰하고 최종적으로 프로젝트에 반영한다. - PR 후 merge
Merge conflict
원격 repo
작업하다보면 commit 메시지에 오타가 났거나 파일을 까먹고 add(staging)하는 경우가 있다.
이 때 최신의 commit을 수정하는 것을 amend(어맨드,고치기) 라고 한다.
다른 사람들과 같이 협업하고 있다면 어떤 내용이 되돌려졌는지 기록으로 남기는 것이 중요하다. 어떤 내용을 되돌렸는지 새로운 commit을 남기는 것을 revert(리버트) 라고 한다.
reset (리셋) 은 commit 했던 작업내역을 말 그대로 리셋시키는 것이다.
stash(스태시) 는 프로젝트의 변경사항을 임시적으로 보관해둘 때 사용한다.
commit 메세지 작성하는 규칙은 commit 메시지 컨벤션(commit message convention)!
좋은 commit 메시지, 단위로 작성하게 되면
보통 코드리뷰는 아래의 단계에서 많이 일어난다. 주로 PR 한 내역에서 댓글을 달면서 리뷰를 남기는 방식을 많이 사용한다.
코드리뷰를 하는 이유!
코드의 품질을 높일 수 있다!
다른 사람의 눈으로 버그를 빠르게 발견할 수 있다!
서로의 지식을 나누면서, 더 나은 방법을 찾아낼 수 있다!
→ 내가 만든 코드가 아니라 팀의 코드의 품질을 높인다!
공유하거나 공개되면 안되는 파일들이 마치 이런 파일들을 없는 것처럼 무시하게 하는 설정이 바로 .gitignore이다.
프로젝트의 어마어마하게 많은 파일들을 하나하나씩 다 읽어볼 수는 없으니 Github 프로젝트에서도 README.md 를 만들어 프로젝트 소개글을 적어둔다.
이 강의를 듣기 전부터 매니저님이나 튜터님들이 깃허브나 깃에 대한 언급을 많이 해주셔서 자주 사용하게 될 내용이구나하고 어느정도 인식은 하고 있었지만 막상 사용해보니 생각보다 더 중요하고 유용하게 사용 할 수 있는 내용인 것 같았다. 기초적인 내용과 이론적 측면은 여기서 배웠으니 실제로 사용하면서 완전히 익숙해 지는 것이 중요할 것이라는 생각이든다.
협업을 위한 Git 활용 강의
- 강민철 튜터님 특강
특정 경로로 이동하기
$ cd <경로>
현재 디렉터리의 폴더 및 파일 보기 (숨김파일 및 폴더는 제외)
$ ls
현재 디렉터리에서 숨김파일 및 폴더까지 모두 보기
$ ls -a
$ ls -al
- vi/vim 편집기가 열리고 나면 바로 어떤 내용을 쓸 수 없다
- a와 i를 입력해 아래와 같이 하단에 INSERT 표시가 나와야 한다
- 입력이 끝났다면 ESC를 누른다 (하단에 INSERT 표시가 사라진다)
- :w 로 저장할 수 있다
- :q 로 (저장하지 않고) vi/vim 창을 닫을 수 있다
- :wq 로 저장 후 닫을 수 있다
로컬 저장소 만들기
$ git init
스테이지에 추가하기
$ git add <파일이름> <파일이름>
현재 작업 디렉터리의 변경사항을 모두 스테이지에 추가하기
$ git add .
커밋하기 (커밋 메세지의 헤더만을 작성하기)
$ git commit -m "커밋 메세지 헤더"
자세한 커밋 메세지로 커밋하기
$ git commit
스테이지에 추가와 커밋 동시에 하기 (Tracked File에 한해 사용 가능)
$ git commit -am "커밋 메세지 헤더"
현재 커밋들의 목록 조회하기
$ git log
현재 커밋들의 목록 한 줄로 조회하기
$ git log --oneline
현재 커밋들의 목록 + 각 커밋들의 변경사항까지 확인하기
$ git log -p
현재 커밋들의 목록을 그래프 형태로 조회하기
$ git log --graph
혼용하여 사용하기
$ git log --oneline --graph
$ git log --oneline -p
...
현재 작업 디렉터리에서의 작업 내역과 최신 커밋을 비교하기
$ git diff
스테이지와 작업 내역과 최신 커밋을 비교하기
$ git diff --staged
커밋끼리 비교하기
$ git log <커밋해시> <커밋해시>
revert: 특정 커밋 취소(revert)하기
작업을 취소한 새로운 커밋을 생성한다.
기존의 커밋 내역은 유지된다.
$ git revert <취소할커밋>
reset: 특정 커밋으로 되돌아가기
마치 시간을 되돌리듯 되돌아간다.
기존의 커밋 내역에 영향이 갈 수 있다.
soft reset: 커밋을 했다는 그 사실만을 되돌리기
$ git reset --soft <되돌아갈 커밋>
mixed reset: 스테이지에 추가했다는 사실까지 되돌리기
$ git reset --mixed <되돌아갈 커밋>
$ git reset <되돌아갈 커밋>
hard reset: 변경사항을 만들었다는 사실까지 되돌리기
$ git reset --hard <되돌아갈 커밋>
새로운 브랜치 생성하기
$ git branch <브랜치이름>
해당 브랜치로 체크아웃하기
$ git checkout <브랜치이름>
새로운 브랜치를 만듦과 동시에 체크아웃하기 (수업에서 다루지는 못했지만 유용합니다)
$ git checkout -b <브랜치이름>
브랜치 병합하기
$ git merge <브랜치이름>
충돌(Conflict): 같은 내용을 다르게 수정했을 경우 발생
충돌 해결법
1. 최종적으로 포함할 내용을 직접 선택한다
2. 다시 커밋한다
원격 저장소 이름 조회하기
$ git remote
원격 저장소 이름 + URL 조회하기
$ git remote -v
원격 저장소 추가하기
$ git remote add <원격저장소이름> <원격저장소경로>
clone: 원격 저장소의 내용을 내 컴퓨터로 복제해오기
$ git clone <원격저장소경로>
push: 로컬의 변경사항을 원격저장소로 밀어넣기
$ git push <원격저장소이름> <로컬브랜치이름>
* 참고) 아래와 같이 -u 옵션과 함께 push하면 이후로 <원격저장소이름> <로컬브랜치이름> 생략 가능
$ git push -u <원격저장소이름> <로컬브랜치이름>
fetch: 원격저장소의 변경사항을 로컬로 '일단 갖고만' 오기 (로컬 브랜치에는 변함이 없다!)
$ git fetch <원격저장소이름> <로컬브랜치이름>
pull: 원격저장소의 변경사항을 로컬로 갖고와서 합치기
$ git pull <원격저장소이름> <로컬브랜치이름>
Pull Request를 보내는 단계
1. 기여하려는 저장소를 본인의 계정으로 fork하기
2. fork한 저장소를 clone하기
3. 브랜치 생성 후 생성한 브랜치에서 작업하기
4. 작업한 브랜치 Push 하기
5. Pull Request 보내기
소스트리 프로그램이 아닌 Git Bash를 이용한 명령어 만으로 GitHub에 커밋하고 기타 작업들을 하는 법에 대한 특강이었기 때문에 사용되는 명령어 위주로 정리하게 되었다. 튜터님이 실제로 사용하는 모습을 보면서 따라하긴 해봤지만 실전에서 사용해봐야 어느정도 감을 잡을 수 있을 것 같다.
파이썬 이번 주의 과제
- 계산기 만들기, 숫자야구게임 만들기
요구조건
main.py
from calculator import calc
num1, operator, num2 = input().split()
num1 = int(num1)
num2 = int(num2)
calc(num1, operator, num2)
calculator.py
def calc(num1, operator, num2):
if operator == '+':
print(num1 + num2)
elif operator == '-':
print(num1 - num2)
elif operator == '*':
print(num1 * num2)
elif operator == '/':
if num2 == 0:
print('0으로는 나눌 수 없습니다.')
else:
print(num1 / num2)
else:
print('error!')
calculator.py에 사칙연산을 하는 함수를 만들고 해당 함수를 main.py에서 import를 통해 가져와 계산식을 넣으면 답을 알려주는 방식으로 만들었다.
from random import randint
import time
import datetime
print('숫자야구 게임을 몇 자리 숫자로 하시겠습니까?(최대 10자리까지 선택 가능합니다.)')
N = int(input())
if 0 < N <= 10:
print(f'{N}자리로 게임을 시작합니다.')
else:
print('최대 10자리까지만 선택이 가능합니다.')
def get_numbers(): # 무작위로 숫자 3개를 뽑는 함수
numbers = []
while len(numbers) < N:
num = randint(0, 9)
if num not in numbers:
numbers.append(num)
print(f'{N}자리의 숫자가 선정되었습니다.')
return numbers
def take_guess(): # 플레이어에게 숫자 3개를 입력받는 함수
print('숫자 3개를 차례대로 입력하세요.')
new_guess = []
while len(new_guess) < N:
new_num = int(input("{}번째 숫자를 입력하세요:".format(len(new_guess) + 1)))
if new_num < 0 or new_num > 9:
print('범위를 벗어나는 숫자입니다. 다시 입력하세요.')
elif new_num in new_guess:
print('중복되는 숫자입니다. 다시 입력하세요.')
else:
new_guess.append(new_num)
return new_guess
def get_score(guess,answer): # 무작위로 뽑힌 숫자 3개와 플레이어가 입력한 숫자 3개를 비교해 스트라이크, 볼, 아웃 점수를 계산하는 함수
strike_count = 0
ball_count = 0
out_count = 0
for i in range(N):
if guess[i] == answer[i]:
strike_count += 1
elif guess[i] in answer:
ball_count += 1
else:
out_count += 1
return strike_count, ball_count, out_count
ANSWER = get_numbers()
tries = 0
start = time.time()
while True:
user_guess = take_guess()
strike, ball, out = get_score(user_guess, ANSWER)
print("{}S {}B {}O".format(strike, ball, out))
tries += 1
if strike == N:
break
sec = time.time()-start
times = str(datetime.timedelta(seconds=sec)).split(".")
times = times[0]
now = datetime.datetime.now()
nowDatetime = now.strftime('%Y-%m-%d %H:%M:%S')
print(f"정답입니다! 시도한 횟수 : {tries}회, 걸린 시간 : {times}, 맞힌 시간 : {nowDatetime}")
random의 randint 기능을 가져와 0에서 9사이의 숫자중 N개의 숫자를 뽑아 순서를 랜덤하게 설정하였고 내가 입력하는 N가지의 숫자 중 숫자와 순서가 모두 맞으면 스트라이크, 숫자만 맞고 순서는 틀릴경우 볼, 숫자가 맞지 않는 경우 아웃으로 하여 각각 그 횟수를 카운팅해서 알려주도록 하였고 N개의 숫자가 모두 스트라이크가 되었을 경우 정답으로 표기되며 시도한 횟수, 걸린 시간, 맞힌 시간이 표시되도록 설정하였다. 이 과정에서 그동안 배운 for문,while문,if문이 모두 사용되었으며 시간 표시하는 법은 구글링을 통해 time과 datetime의 사용법을 배워서 적용하였다. 내가 지금까지 만들어본 파이썬 파일 중 가장 어렵고 가장 많은 기능이 들어간 것 같다. 그만큼 시간도 많이 걸려서 추석연휴를 거의 다 날려버린 것 같지만 완성되었을 때의 그 기분은 말로 표현할 수 없었다.
알고리즘 실습
매일 진행되는 알고리즘 실습 문제 풀이 역시 빼놓을 수 없다. 이번 주는 반복문, 1차원 배열, 함수, 문자열을 주제로 문제들이 나왔는데 저번주보다 난이도가 올라간 것을 느낄 수 있었다. 역시나 이번주도 많은 문제가 있었지만 그 중에서 특히 어려웠던 문제 몇가지만 뽑아서 정답과 풀이를 정리해보도록 하겠다.
문제
0보다 크거나 같고, 99보다 작거나 같은 정수가 주어질 때 다음과 같은 연산을 할 수 있다. 먼저 주어진 수가 10보다 작다면 앞에 0을 붙여 두 자리 수로 만들고, 각 자리의 숫자를 더한다. 그 다음, 주어진 수의 가장 오른쪽 자리 수와 앞에서 구한 합의 가장 오른쪽 자리 수를 이어 붙이면 새로운 수를 만들 수 있다. 다음 예를 보자.
26부터 시작한다. 2+6 = 8이다. 새로운 수는 68이다. 6+8 = 14이다. 새로운 수는 84이다. 8+4 = 12이다. 새로운 수는 42이다. 4+2 = 6이다. 새로운 수는 26이다.
위의 예는 4번만에 원래 수로 돌아올 수 있다. 따라서 26의 사이클의 길이는 4이다.
N이 주어졌을 때, N의 사이클의 길이를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N이 주어진다. N은 0보다 크거나 같고, 99보다 작거나 같은 정수이다.
출력
첫째 줄에 N의 사이클 길이를 출력한다.
답
original_num = input()
if len(original_num) == 1:
original_num = "0"+ original_num
current_num = original_num
count = 0
while True:
sum_num = int(current_num[0]) + int(current_num[1])
sum_num = str(sum_num)
current_num = current_num[-1] + sum_num[-1]
count += 1
if current_num == original_num:
print(count)
break
풀이
첫 줄에서 original_num으로 input값을 받는다. original_num의 값이 10보다 작을경우는 한 자리 수라는 뜻이기 때문에 len(original_num) == 1이다. 이때 앞에 0을 붙여서 두 자리 수로 만들어준다. 그리고 current_num를 original_num로 count를 0으로 선언해둔 뒤 original_num의 첫 번째 자리 수와 두 번째 자리 수를 서로 더한 다음 이 값을 문자열로 변환해 준다. 이 값을 sum_num이라 하고 current_num의 값은 current_num의 맨 뒷 자리 수와 sum_num의 맨 뒷 자리 수를 더한 값이 current_num의 값이 되며 한 사이클이 돌았기 때문에 count의 값을 +1 해준다. 이렇게 사이클을 돌리다 current_num의 값이 처음 설정한 original_num의 값과 같아지면 함수를 멈추고 몇 사이클이 돌았는지 출력하도록 설정하였다.
문제
"OOXXOXXOOO"와 같은 OX퀴즈의 결과가 있다. O는 문제를 맞은 것이고, X는 문제를 틀린 것이다. 문제를 맞은 경우 그 문제의 점수는 그 문제까지 연속된 O의 개수가 된다. 예를 들어, 10번 문제의 점수는 3이 된다.
"OOXXOXXOOO"의 점수는 1+2+0+0+1+0+0+1+2+3 = 10점이다.
OX퀴즈의 결과가 주어졌을 때, 점수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 길이가 0보다 크고 80보다 작은 문자열이 주어진다. 문자열은 O와 X만으로 이루어져 있다.
출력
각 테스트 케이스마다 점수를 출력한다.
답
T = int(input())
for _ in range(T):
answers = input()
total_score = 0
point = 1
for answer in answers:
if answer == 'O':
total_score += point
point += 1
else:
point = 1
print(total_score)
풀이
첫 줄에서 테스트 케이스의 갯수를 input으로 받는다. 두번째 줄 부터 OX문자열을 input으로 받는다. 문제의 총점의 값을 total_score라 하고 0으로 선언해 둔다. point는 정답을 맞출 때 마다 얻는 점수이고 처음엔 1로 설정해 둔다. 만약 정답을 맞췄을 경우 얻는 점수가 1점식 추가되고 오답일 경우 얻는 점수는 다시 1점으로 초기화가 되도록 if문을 설정해 둔다. 마지막에 총점을 print하면 코드작성은 끝이 난다. 막상 풀이를 보니 생각보다는 쉬운 문제였는데 문제 자체의 이해가 난해하다보니 코드작성을 어떻게 해야할 지 몰랐었고 결국 해설을 보고 나서야 겨우 이해하고 문제를 풀 수 있었다.
문제
대학생 새내기들의 90%는 자신이 반에서 평균은 넘는다고 생각한다. 당신은 그들에게 슬픈 진실을 알려줘야 한다.
입력
첫째 줄에는 테스트 케이스의 개수 C가 주어진다.
둘째 줄부터 각 테스트 케이스마다 학생의 수 N(1 ≤ N ≤ 1000, N은 정수)이 첫 수로 주어지고, 이어서 N명의 점수가 주어진다. 점수는 0보다 크거나 같고, 100보다 작거나 같은 정수이다.
출력
각 케이스마다 한 줄씩 평균을 넘는 학생들의 비율을 반올림하여 소수점 셋째 자리까지 출력한다.
답
C = int(input())
for _ in range(C):
scores = list(map(int, input().split()))
sum_score = 0
num_people = scores[0]
for i in range(1, num_people+1):
sum_score += scores[i]
avg_score = sum_score / num_people
above_avg = 0
for i in range(1,num_people+1):
if scores[i] > avg_score:
above_avg += 1
print(f"{above_avg/num_people*100:.3f}%")
풀이
첫 줄에서 테스트 케이스의 개수 C를 input값으로 받고 각 학생의 수와 그 학생들의 점수를 input받아 list로 저장한다. 이 값을 scores라고 한다. 점수의 총합은 0으로 선언해 두고 학생의 수는 둘째줄에서 입력한 값 중 가장 첫번째로 오는 값이 학생 수이기 때문에 scores의 0번째 값을 받으면 된다. 다음으로 list내의 값중에 0번째는 학생의 수이기 때문에 범위를 1번째부터 학생수 +1번째의 값까지로 지정하면 모든 학생들의 점수를 범위로 지정할 수 있다. 이제 이 점수들의 합 나누기 학생의 수가 평균점수가 되는 것이다. 이제 평균점수를 넘은 사람의 수를 above_avg로 잡고 0으로 지정해둔 다음 평균보다 점수가 높은 사람의 수만큼 above_avg의 숫자를 더해주도록 for문을 만들었다. 마지막으로 평균점수보다 높은 점수를 받은 학생 수에서 전체 학생 수를 나누고 백분율이니 100을 곱한뒤 %를 붙여주고 입력값에 따라 결과가 나오도록 f스트링을 설정해 두면 끝! .3f는 소숫점 셋째자리까지만 표기한다는 뜻이므로 외워두면 유용하게 쓸 수 있다.
그동안 풀었던 알고리즘 문제 중 가장 어려웠던 것 같다. for문도 많이 쓰이고 범위 지정에 있어 실수가 있을 수도 있는데 풀이를 보며 차근차근 다시 풀어보면 그래도 어느정도 이해가 되는 편이다.
이번주를 마치며
드디어 내일배움캠프 2주차도 끝이 났다. 이번 주차는 프로젝트가 없이 강의와 과제, 문제풀이가 계속 반복되다보니 아무래도 개념적인 측면에서의 요약이 많을 수 밖에 없는 주차였다. 2주차에는 1주차에 비해 난이도가 오른 것이 체감이 되어 고생도 많이 했지만 아직까지 이해하려고 시간을 오래 들인다면 이해를 못하고 넘어갈 수준은 아닌 것 같다. 하지만 방심을 할 수는 없는 것이 이 모든 내용을 한 주만에 정리하고 따라가는데 시간이 부족했고 다음주에는 난이도가 더 올라갈 수 있기 때문에 더 많은 노력을 해야만 할 것이다. 그리고 이번주는 추석 연휴 직전이라 들뜬 마음이 있어서 그런 것일지도 모르겠지만 집중력이 조금씩 흐트러지고 있는 것을 스스로 느끼기 시작했다. 캠프는 장기간 진행되고 아직 초반부 중 극 초반부임에도 벌써 이런 현상이 발생하는 것은 좋지 않은 징조이다. 갈수록 집중력 싸움이 될 것인데 마음 단단히 먹고 그날 당일에 해야하는 것들만이라도 당일에 끝낼 수 있도록 더욱 집중해 보겠다. 그리고 단 것을 많이 챙겨먹어야 할 것 같다. 머리를 많이 썼더니 당이 부족해...