#python #anaconda #jupyter-notebook #visual-code #html #css #javascript #http

제목[월, 수 11:00 수업] Quiz3 문제 풀이 및 채점관련공지 2019-11-11 00:02
작성자

안녕하세요 조교 박형준입니다. 

Quiz3 문제 풀이 및 채점관련해서 공지할게있어서 글 남겼습니다. 

1. 채점관련 공지

우선... 총 165명중 107명이 시간안에 제출 해주셨구요  

'가장 많이 말한 사람', '가장 많이 말한 시간', '한 발화안에서 가장 길게 말한 사람'의 3가지 문제를 

모두 푼 사람은 아쉽게도 아무도 없었습니다.

그래서 수업시간에 말한 대로 부분 점수반영을 하기로 하였고. 3번의 문제는 아무도 푼 사람이 없어서 

배점을 조금 변경하여 위에 언급한 3가지 소문제로 나눠 1번+2번을 모두 풀면 100점 배점을 주고 소문제당 기준을 세워서 완성하신 만큼의

부분 점수를 반영하여 다음주 평일중으로 올리도록 하겠습니다. 


2. 문제 풀이 

난이도는 조금 어려웠다고 하나 퀴즈가 끝나고 끝까지 남아서 물어보신분들과 메일로 다 풀었는데 

성적과는 별개로 피드백요청 하신 분, 게시판이나 연구실로 찾아오시는 등 재미있게 풀어주셔서 모두 들 

감사드립니다. 


우선 문제 풀이는 문제 만든 후 저도 똑같이 시간을 5분으로 측정하고 퀴즈 제출전에 푼 코드를 기준으로 

설명하겠습니다. 아무래도 천천히 완벽하게 만든 코드보다 저도 실제 시험 당시였으면 이렇게 풀었겠다 ~ 

하는 코드니.. 이것만이 꼭 답이 아니라 다양하게 접근 하셔서 풀어보시길 추천 드리겠습니다. 


1.퀴즈 2에서도 문제를 푸는 핵심이 split을 아는지 모르는지였다라고 생각했구요  유용한 함수라 find보단 split을 써서 풀어보자 생각하였고

저도 카카오톡 데이터셋을 보고 맨처음에는 ' '인 공백기준으로 split을 해보려 했습니다. 

1-1. [박형준] [시간] 대화 의 경우는 잘 split이 되나 [신동욱 조교] 같은경우는 제가 원치 않는 부분에서 split이 되어 접었습니다.

1-2. 그래서 split을 ']' 과 ' '공백의 합성인 '] '을 사용해보면 어떨까 했습니다.

1-3. 그 경우 "[신동욱 조교] [오후1:00] 대화" 나 "[박형준] [오후1:00] 설마 누가 ] 같은걸 쓰겠어?" 의 경우 '] '으로 split하면  

     [ "[신동욱 조교", "[오후1:00", 대화 ] 처럼 split이 잘 될것 같아 '] '토큰으로 split하기로 결심했구요 

1-4. 그런데  "[박형준] [오후1:00] 설마 누가 ] 같은걸 쓰겠어?" 이런거 처럼 설마 누가 ']'를 대화에 사용하면 저것도 split이 되어서 

    추가적으로 help(str)해보니 split에 maxsplit이라는 옵션이있어서 그걸 썻습니다. maxsplit = 2 하면 딱 2개의 구분자까지만 봐서 총 3개의 결과가나옵니다

1-5. 그리고 나서 앞의 [를 없애주기 위해 [1:]를 썼구요 

1-6. 이 코드가 20~27번째줄의 코드


2. 보통 1번 과정에서 에러가 나는 경우는 크게 두가지가 있습니다. 그리고 보통 이런 에러에 대해 모든 언어는 '예외 처리' 기법이 존재합니다.  

  파이썬 예외처리를 하는 방법은 크게 2가지로 구분을 하는데요(틀린 지식일수도 있어요..ㅠㅠ)  if문을 써서 사전에 error가 날만한 상황을 피하는 방법과,  

  try문을 써서 error를 발생시키되 except나 catch구문에서 처리를 하는 구문이 있습니다. 전 후자를 썼어요 

* 시험때 수업외의 모든 문법을 써두 무관하다 라고 해서 채점을 하다 보니 lambda나 regex로 접근해주신 분들도 많더라구요 좋은 접근법이셨습니당 

* try except는 수업때 간단히 언급만 하고 지나갔지만 이런 문법이나 기법도 있구나를 보시면 좋을 것 같습니다

2-1. 우선 '] ' 토큰으로 쪼개보는겁니다 무지막지하죠

2-2. 근데 에러가 났다 ?  그건 두 가지경우중 하나죠 날짜가 나왔거나, 사람이 이어서 말했거나 그게 25, 45줄이구요

2-3. 날짜가 나온 경우를 찾는거죠  46~47줄 보시면 두개의 경우를 and로 묶습니다. (누가 혹시만약설마 대화때 ----------- 라고 칠수있자나요...)

2-4. 이어서 말한경우는 우리가 가장길게말한사람 찾아야하니까 linecnt 변수를 +1합니다.


3. 이제 파싱이 끝났으니 어떻게 누가 몇번을 말했지를 저장할까 하다가 dict 자료형을 써서 "말한 사람" : "말한 횟수"로 저장하면 좋을것 같아 
  그렇게 하기로 했구요 sort도 직접 짜라고 했으니 만들었습니다... 그게 1~13번째까지의 코드설명 

3-1. 위의 try except문을 이용해서 예를들면 talkRankDict[박형준]을 +1 해보는겁니다 무지막지하죠

3-2. 근데 에러가 났다 ? 이건 talkRankDict에 '박형준'이라는 키값이 없는 경우니 초기화를 해버리면 됩니다.

3-3. 시간도 똑같이하면됩니당 그게 29~33번줄 코드


4.자 이제 한 발화에서 가장 길게 말한 사람을 찾으면 됩니다. 

4-1. 우선 거기에 쓸 변수를 초기화하구요 그게 15~18번줄 코드에 해당합니다

4-2. isFirst 라는 booltype 변수를 만들어 처음에는 그 사람이 제일 길게 말했다고 가정합니다. 

4-3. 25~33번줄까지 갔다는건 새로운 사람이 새롭게 말해서 말한 횟수가 +1을 되었다는걸 의미합니다. 그래서 

     그 마지막줄 (35~44줄 코드)에 가장 길게 말한 maxLineCnt랑 말했던 사람을 비교해서 최대값을 갱신합니다.

4-4. except에 lineCnt + 1이 있는건 위에 2-4에서 언급했구용

4-5 이러면 가장 길게 말한 사람도 끝 


5. 자 이제 미리 짜논 dict sort함수 호출해서 출력하면 끝입니다.


아래는 코드입니다. 

보시고 난 정말 이해가 안 가시거나... 난 내 코드를 꼭 출제자한테 보여줘야겠어 등의 경우 

연구실(443-2호)로 방문주시거나, 메일(khuphj@gmail.com)로 연락주시면 답변 해드리겠습니다. 

갑자기 새벽에 두서없이 쓴 글이라... 혹 띄어쓰기 맞춤법 오타는 조금..  양해부탁드리겠습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#-*- encoding:utf-8 -*-
def get_max_k_v(_dict):
    # _dict의 value중 가장 큰 값 key와 value return
    max_v = -1 
    max_k = ''
    for k in _dict.keys():
        if max_v < _dict[k]:
            max_v = _dict[k]
            max_k = k
    return max_k, max_v
if __name__ == "__main__":
    talkRankDict = {} # 사람 랭킹 찾기위해 "사람이름" : "횟수" 식의 dict
    timeRankDict = {} # 시간 랭킹 찾기위해 "시간" : "횟수" 식의 dict
    # 한 발화에 가장 길게 말한 사람 찾기 위한 변수들 
    isFirst = False 
    maxLineTalker = '' 
    maxLineCnt = 0
    lineCnt = 0 # 한 사람이 말한 횟수 저장 변수 
    
    fileName = input('대화 파일 이름을 확장자 포함 입력하세요:').strip()
    with open(fileName, 'r', encoding='utf-8') as f:
        lines = f.readlines()
        for line in lines:
            line = line.strip()
            try:
                talker, talkTime, _ = line.split("] ", maxsplit=2)
                talker, talkTime = talker[1:], talkTime[1:]
                # 말한 횟수 증가, 없으면 1로 초기화
                try: talkRankDict[talker] += 1 
                except: talkRankDict[talker] = 1
                # 시간 횟수 증가, 없으면 1로 초기화
                try: timeRankDict[talkTime] += 1 
                except: timeRankDict[talkTime] = 1
                # 한 발화에 길게 말한 사람 찾기 
                if isFirst:# 처음이면 그 사람을 MaxLineTalker로 
                    isFirst = False
                    lineCnt = 1 
                    maxLineTalker = talker
                else:# 여기까지 온 경우는 다음 사람으로 바뀐 경우니까 
                    #가장 많이 말한거랑 비교후 lineCnt초기화
                    if maxLineCnt < lineCnt:
                        maxLineCnt = lineCnt
                        maxLineTalker = talker
                    lineCnt = 1 
            except:
                if ('---------------' in line) and ('요일' in line):# 날씨표시줄
                    pass
                else:# 이어서 말한 부분
                    lineCnt += 1
 
    maxTalker, maxTalkerCnt = get_max_k_v(talkRankDict)
    maxTalkTime, maxTalkTimeCnt = get_max_k_v(timeRankDict)
    print('가장 많이 말한 사람 : {}, 횟수 : {}'.format(maxTalker,maxTalkerCnt))
    print('가장 많이 말한 시간 : {}, 횟수 : {}'.format(maxTalkTime,maxTalkTimeCnt))
    print('가장 길게 말한 사람 : {}, 줄수 : {}'.format(maxLineTalker,maxLineCnt))
cs
 
댓글