Skip to content

Instantly share code, notes, and snippets.

@comfuture
Created September 29, 2017 02:53
Show Gist options
  • Save comfuture/3ab43f6b581ab4f9c997ff6118157e1a to your computer and use it in GitHub Desktop.
Save comfuture/3ab43f6b581ab4f9c997ff6118157e1a to your computer and use it in GitHub Desktop.
카카오 공채 문제풀이
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"카카오 문제풀이\n",
"===========\n",
"\n",
"## 1. 비밀지도\n",
"\n",
"네오는 평소 프로도가 비상금을 숨겨놓는 장소를 알려줄 비밀지도를 손에 넣었다. 그런데 이 비밀지도는 숫자로 암호화되어 있어 위치를 확인하기 위해서는 암호를 해독해야 한다. 다행히 지도 암호를 해독할 방법을 적어놓은 메모도 함께 발견했다.\n",
"\n",
"1. 지도는 한 변의 길이가 n인 정사각형 배열 형태로, 각 칸은 ”공백”(\" \") 또는 “벽”(\"#\") 두 종류로 이루어져 있다.\n",
"1. 전체 지도는 두 장의 지도를 겹쳐서 얻을 수 있다. 각각 “지도 1”과 “지도 2”라고 하자. 지도 1 또는 지도 2 중 어느 하나라도 벽인 부분은 전체 지도에서도 벽이다. 지도 1과 지도 2에서 모두 공백인 부분은 전체 지도에서도 공백이다.\n",
"1. “지도 1”과 “지도 2”는 각각 정수 배열로 암호화되어 있다.\n",
"1. 암호화된 배열은 지도의 각 가로줄에서 벽 부분을 1, 공백 부분을 0으로 부호화했을 때 얻어지는 이진수에 해당하는 값의 배열이다\n",
"\n",
"### 입력형식\n",
"입력으로 지도의 한 변 크기 n 과 2개의 정수 배열 arr1, arr2가 들어온다.\n",
"\n",
"> * 1 ≦ n ≦ 16\n",
"> * arr1, arr2는 길이 n인 정수 배열로 주어진다.\n",
"> * 정수 배열의 각 원소 x를 이진수로 변환했을 때의 길이는 n 이하이다. 즉, 0 ≦ x ≦ 2^n - 1을 만족한다.\n",
"\n",
"### 출력형식\n",
"\n",
"원래의 비밀지도를 해독하여 \"#\", 공백으로 구성된 문자열 배열로 출력하라."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def solution_1(n, arr1, arr2):\n",
" matrix = [a | b for (a, b) in zip(arr1, arr2)]\n",
" return[('{0:>%s}' % n).format(bin(c)[2:]).replace('0', ' ').replace('1', '#') for c in matrix]"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"assert solution_1(5, [9, 20, 28, 18, 11], [30, 1, 21, 17, 28]) == \\\n",
" ['#####', '# # #', '### #', '# ##', '#####']\n",
"\n",
"assert solution_1(6, [46, 33, 33 ,22, 31, 50], [27 ,56, 19, 14, 14, 10]) == \\\n",
" ['######', '### #', '## ##', ' #### ', ' #####', '### # ']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> 입력값의 같은위치 쌍끼리 논리합 `|`을 하고 2진수로 바꾼 뒤 0과 1을 각각 공백과 # 문자로 치환한다. \n",
"> 이때 자리수가 줄어들었을 수 있으니 주어진 길이만큼 zerofill 한다"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. 다트게임\n",
"\n",
"카카오톡 게임별의 하반기 신규 서비스로 다트 게임을 출시하기로 했다. 다트 게임은 다트판에 다트를 세 차례 던져 그 점수의 합계로 실력을 겨루는 게임으로, 모두가 간단히 즐길 수 있다.\n",
"갓 입사한 무지는 코딩 실력을 인정받아 게임의 핵심 부분인 점수 계산 로직을 맡게 되었다. 다트 게임의 점수 계산 로직은 아래와 같다.\n",
"\n",
"1. 다트 게임은 총 3번의 기회로 구성된다.\n",
"1. 각 기회마다 얻을 수 있는 점수는 0점에서 10점까지이다.\n",
"1. 점수와 함께 Single(S), Double(D), Triple(T) 영역이 존재하고 각 영역 당첨 시 점수에서 1제곱, 2제곱, 3제곱 (점수^1 , 점수^2 , 점수^3 )으로 계산된다.\n",
"1. 옵션으로 스타상(*) , 아차상(#)이 존재하며 스타상(*) 당첨 시 해당 점수와 바로 전에 얻은 점수를 각 2배로 만든다. 아차상(#) 당첨 시 해당 점수는 마이너스된다.\n",
"1. 스타상(*)은 첫 번째 기회에서도 나올 수 있다. 이 경우 첫 번째 스타상(*)의 점수만 2배가 된다. (예제 4번 참고)\n",
"1. 스타상(*)의 효과는 다른 스타상(*)의 효과와 중첩될 수 있다. 이 경우 중첩된 스타상(*) 점수는 4배가 된다. (예제 4번 참고)\n",
"1. 스타상(*)의 효과는 아차상(#)의 효과와 중첩될 수 있다. 이 경우 중첩된 아차상(#)의 점수는 -2배가 된다. (예제 5번 참고)\n",
"1. Single(S), Double(D), Triple(T)은 점수마다 하나씩 존재한다.\n",
"1. 스타상(*), 아차상(#)은 점수마다 둘 중 하나만 존재할 수 있으며, 존재하지 않을 수도 있다.\n",
"\n",
"0~10의 정수와 문자 S, D, T, *, #로 구성된 문자열이 입력될 시 총점수를 반환하는 함수를 작성하라.\n",
"\n",
"### 입력형식\n",
"\n",
"\"점수|보너스|[옵션]\" 으로 이루어진 문자열 3세트. \n",
"예) `1S2D*3T`\n",
"\n",
"* 점수는 0에서 10 사이의 정수이다.\n",
"* 보너스는 S, D, T 중 하나이다.\n",
"* 옵선은 *이나 # 중 하나이며, 없을 수도 있다.\n",
"\n",
"### 출력 형식\n",
"\n",
"3번의 기회에서 얻은 점수 합계에 해당하는 정수값을 출력한다. \n",
"예) 37"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import re\n",
"\n",
"def solution_2(d):\n",
" pattern = re.compile(r'([1-9]|10)([SDT])([#\\*]?)')\n",
" found = re.findall(pattern, d)\n",
" results = []\n",
" for i, (hit, modifier, option) in enumerate(found):\n",
" score = int(hit) ** ('*SDT'.index(modifier))\n",
" if option == '#':\n",
" score *= -1\n",
" elif option == '*':\n",
" score *= 2\n",
" if len(results):\n",
" results[-1] = results[-1] * 2\n",
" results.append(score)\n",
" return sum(results)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"assert solution_2('1S2D*3T') == 37\n",
"assert solution_2('1D2S#10S') == 9\n",
"assert solution_2('1D2S0T') == 3\n",
"assert solution_2('1S*2T*3S') == 23\n",
"assert solution_2('1D#2S*3S') == 5\n",
"assert solution_2('1T2D3D#') == -4\n",
"assert solution_2('1D2S3T*') == 59"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> 좀 더 우아한 코드가 있을 수도 있지만 조건이 복잡하지 않아서 그냥 if 중첩으로 해결했다."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. 캐시(난이도: 하)\n",
"\n",
"지도개발팀에서 근무하는 제이지는 지도에서 도시 이름을 검색하면 해당 도시와 관련된 맛집 게시물들을 데이터베이스에서 읽어 보여주는 서비스를 개발하고 있다.\n",
"이 프로그램의 테스팅 업무를 담당하고 있는 어피치는 서비스를 오픈하기 전 각 로직에 대한 성능 측정을 수행하였는데, 제이지가 작성한 부분 중 데이터베이스에서 게시물을 가져오는 부분의 실행시간이 너무 오래 걸린다는 것을 알게 되었다.\n",
"어피치는 제이지에게 해당 로직을 개선하라고 닦달하기 시작하였고, 제이지는 DB 캐시를 적용하여 성능 개선을 시도하고 있지만 캐시 크기를 얼마로 해야 효율적인지 몰라 난감한 상황이다.\n",
"어피치에게 시달리는 제이지를 도와, DB 캐시를 적용할 때 캐시 크기에 따른 실행시간 측정 프로그램을 작성하시오.\n",
"\n",
"### 입력 형식\n",
"\n",
"* 캐시 크기(cacheSize)와 도시이름 배열(cities)을 입력받는다.\n",
"* cacheSize는 정수이며, 범위는 0 ≦ cacheSize ≦ 30 이다.\n",
"* cities는 도시 이름으로 이뤄진 문자열 배열로, 최대 도시 수는 100,000개이다.\n",
"* 각 도시 이름은 공백, 숫자, 특수문자 등이 없는 영문자로 구성되며, 대소문자 구분을 하지 않는다. 도시 이름은 최대 20자로 이루어져 있다.\n",
"\n",
"### 출력 형식\n",
"\n",
"* 입력된 도시이름 배열을 순서대로 처리할 때, “총 실행시간”을 출력한다.\n",
"\n",
"### 조건\n",
"\n",
"* 캐시 교체 알고리즘은 LRU(Least Recently Used)를 사용한다.\n",
"* cache hit일 경우 실행시간은 1이다.\n",
"* cache miss일 경우 실행시간은 5이다."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def solution_3(cache_size, cities):\n",
" cache = []\n",
" t = [0]\n",
" def visit(item):\n",
" if item.lower() in cache:\n",
" t[0] += 1\n",
" else:\n",
" t[0] += 5\n",
" cache.append(item.lower())\n",
" if len(cache) > cache_size:\n",
" cache.pop(0)\n",
" [visit(city) for city in cities]\n",
" return t[0]"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"assert solution_3(3, ['Jeju', 'Pangyo', 'Seoul', 'NewYork', 'LA', 'Jeju',\n",
" 'Pangyo', 'Seoul', 'NewYork', 'LA']) == 50\n",
"assert solution_3(2, ['Jeju', 'Pangyo', 'NewYork', 'newyork']) == 16\n",
"\n",
"assert solution_3(2, ['Jeju', 'Pangyo', 'Seoul', 'NewYork', 'LA',\n",
" 'SanFrancisco', 'Seoul', 'Rome', 'Paris', 'Jeju',\n",
" 'NewYork', 'Rome']) == 60\n",
"assert solution_3(0, ['Jeju', 'Pangyo', 'Seoul', 'NewYork', 'LA']) == 25"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> LRU 캐시를 구현하는 문제지만 실행시간만 얻으면 되므로 정해진 실행시간의 합을 리턴하는 함수로 대체. 문제해설에 보니 cacheSize = 0 인 케이스를 특수 케이스라고 설명하는데, 별도 처리 안해도 캐시버퍼에 넣었다 바로 빼는 비효율이 있지만 잘 돌아서 그냥 뒀다."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. 뉴스 클러스터링(난이도: 중)\n",
"\n",
"여러 언론사에서 쏟아지는 뉴스, 특히 속보성 뉴스를 보면 비슷비슷한 제목의 기사가 많아 정작 필요한 기사를 찾기가 어렵다. Daum 뉴스의 개발 업무를 맡게 된 신입사원 튜브는 사용자들이 편리하게 다양한 뉴스를 찾아볼 수 있도록 문제점을 개선하는 업무를 맡게 되었다.\n",
"개발의 방향을 잡기 위해 튜브는 우선 최근 화제가 되고 있는 “카카오 신입 개발자 공채” 관련 기사를 검색해보았다.\n",
"\n",
"* 카카오 첫 공채..’블라인드’ 방식 채용\n",
"* 카카오, 합병 후 첫 공채.. 블라인드 전형으로 개발자 채용\n",
"* 카카오, 블라인드 전형으로 신입 개발자 공채\n",
"* 카카오 공채, 신입 개발자 코딩 능력만 본다\n",
"* 카카오, 신입 공채.. “코딩 실력만 본다”\n",
"* 카카오 “코딩 능력만으로 2018 신입 개발자 뽑는다”\n",
"\n",
"기사의 제목을 기준으로 “블라인드 전형”에 주목하는 기사와 “코딩 테스트”에 주목하는 기사로 나뉘는 걸 발견했다. 튜브는 이들을 각각 묶어서 보여주면 카카오 공채 관련 기사를 찾아보는 사용자에게 유용할 듯싶었다.\n",
"\n",
"유사한 기사를 묶는 기준을 정하기 위해서 논문과 자료를 조사하던 튜브는 “자카드 유사도”라는 방법을 찾아냈다.\n",
"\n",
"자카드 유사도는 집합 간의 유사도를 검사하는 여러 방법 중의 하나로 알려져 있다. 두 집합 A, B 사이의 자카드 유사도 J(A, B)는 두 집합의 교집합 크기를 두 집합의 합집합 크기로 나눈 값으로 정의된다.\n",
"\n",
"예를 들어 집합 A = {1, 2, 3}, 집합 B = {2, 3, 4}라고 할 때, 교집합 A ∩ B = {2, 3}, 합집합 A ∪ B = {1, 2, 3, 4}이 되므로, 집합 A, B 사이의 자카드 유사도 J(A, B) = 2/4 = 0.5가 된다. 집합 A와 집합 B가 모두 공집합일 경우에는 나눗셈이 정의되지 않으니 따로 J(A, B) = 1로 정의한다.\n",
"자카드 유사도는 원소의 중복을 허용하는 다중집합에 대해서 확장할 수 있다. 다중집합 A는 원소 “1”을 3개 가지고 있고, 다중집합 B는 원소 “1”을 5개 가지고 있다고 하자. 이 다중집합의 교집합 A ∩ B는 원소 “1”을 min(3, 5)인 3개, 합집합 A ∪ B는 원소 “1”을 max(3, 5)인 5개 가지게 된다. 다중집합 A = {1, 1, 2, 2, 3}, 다중집합 B = {1, 2, 2, 4, 5}라고 하면, 교집합 A ∩ B = {1, 2, 2}, 합집합 A ∪ B = {1, 1, 2, 2, 3, 4, 5}가 되므로, 자카드 유사도 J(A, B) = 3/7, 약 0.42가 된다.\n",
"\n",
"이를 이용하여 문자열 사이의 유사도를 계산하는데 이용할 수 있다. 문자열 “FRANCE”와 “FRENCH”가 주어졌을 때, 이를 두 글자씩 끊어서 다중집합을 만들 수 있다. 각각 {FR, RA, AN, NC, CE}, {FR, RE, EN, NC, CH}가 되며, 교집합은 {FR, NC}, 합집합은 {FR, RA, AN, NC, CE, RE, EN, CH}가 되므로, 두 문자열 사이의 자카드 유사도 J(\"FRANCE\", \"FRENCH\") = 2/8 = 0.25가 된다.\n",
"\n",
"### 입력 형식\n",
"\n",
"입력으로는 str1과 str2의 두 문자열이 들어온다. 각 문자열의 길이는 2 이상, 1,000 이하이다.\n",
"\n",
"입력으로 들어온 문자열은 두 글자씩 끊어서 다중집합의 원소로 만든다. 이때 영문자로 된 글자 쌍만 유효하고, 기타 공백이나 숫자, 특수 문자가 들어있는 경우는 그 글자 쌍을 버린다. 예를 들어 “ab+”가 입력으로 들어오면, “ab”만 다중집합의 원소로 삼고, “b+”는 버린다.\n",
"다중집합 원소 사이를 비교할 때, 대문자와 소문자의 차이는 무시한다. “AB”와 “Ab”, “ab”는 같은 원소로 취급한다.\n",
"\n",
"### 출력 형식\n",
"\n",
"입력으로 들어온 두 문자열의 자카드 유사도를 출력한다. 유사도 값은 0에서 1 사이의 실수이므로, 이를 다루기 쉽도록 65536을 곱한 후에 소수점 아래를 버리고 정수부만 출력한다."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import string\n",
"from collections import Counter\n",
"\n",
"only_alpha = lambda s: all((c in string.ascii_letters for c in s))\n",
"\n",
"def bigram(s):\n",
" return filter(only_alpha, [s[i:i+2].lower() for i in range(len(s) - 1)])\n",
"\n",
"def jacquard(l1, l2):\n",
" c1, c2 = Counter(l1), Counter(l2)\n",
" if not len(list((c1 & c2).elements())):\n",
" return 1\n",
" return len(list((c1 & c2).elements())) / float(len(list((c1 | c2).elements())))\n",
"\n",
"def solution_5(str1, str2):\n",
" b1, b2 = bigram(str1), bigram(str2)\n",
" return int(jacquard(b1, b2) * 65536)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"assert solution_5('FRANCE', 'french') == 16384\n",
"assert solution_5('handshake', 'shake hands') == 65536\n",
"assert solution_5('aa1+aa2', 'AAAA12') == 43690\n",
"assert solution_5('E=M*C^2', 'e=m*c^2') == 65536"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> 다중집합 개념이 생소해서 구글링결과 Counter가 multiset과 유사한 특징을 가지며 상호 변환이 될 수 있음을 인지했다."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"only_alpha('abc')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 7. 추석 트래픽(난이도: 상)\n",
"\n",
"이번 추석에도 시스템 장애가 없는 명절을 보내고 싶은 어피치는 서버를 증설해야 할지 고민이다. 장애 대비용 서버 증설 여부를 결정하기 위해 작년 추석 기간인 9월 15일 로그 데이터를 분석한 후 초당 최대 처리량을 계산해보기로 했다. 초당 최대 처리량은 요청의 응답 완료 여부에 관계없이 임의 시간부터 1초(=1,000밀리초)간 처리하는 요청의 최대 개수를 의미한다.\n",
"\n",
"### 입력 형식\n",
"\n",
"* solution 함수에 전달되는 lines 배열은 N(1 ≦ N ≦ 2,000)개의 로그 문자열로 되어 있으며, 각 로그 문자열마다 요청에 대한 응답완료시간 S와 처리시간 T가 공백으로 구분되어 있다.\n",
"* 응답완료시간 S는 작년 추석인 2016년 9월 15일만 포함하여 고정 길이 2016-09-15 hh:mm:ss.sss 형식으로 되어 있다.\n",
"* 처리시간 T는 0.1s, 0.312s, 2s 와 같이 최대 소수점 셋째 자리까지 기록하며 뒤에는 초 단위를 의미하는 s로 끝난다.\n",
"* 예를 들어, 로그 문자열 2016-09-15 03:10:33.020 0.011s은 “2016년 9월 15일 오전 3시 10분 33.010초”부터 “2016년 9월 15일 오전 3시 10분 33.020초”까지 “0.011초” 동안 처리된 요청을 의미한다. (처리시간은 시작시간과 끝시간을 포함)\n",
"* 서버에는 타임아웃이 3초로 적용되어 있기 때문에 처리시간은 0.001 ≦ T ≦ 3.000이다.\n",
"* lines 배열은 응답완료시간 S를 기준으로 오름차순 정렬되어 있다.\n",
"\n",
"### 출력 형식\n",
"\n",
"solution 함수에서는 로그 데이터 lines 배열에 대해 초당 최대 처리량을 리턴한다.\n",
"\n",
"### 입출력 예제\n",
"\n",
"#### 예제 1\n",
"\n",
"입력: [ “2016-09-15 01:00:04.001 2.0s”, “2016-09-15 01:00:07.000 2s” ] \n",
"출력: 1\n",
"\n",
"#### 예제 2\n",
"\n",
"입력: [ “2016-09-15 01:00:04.002 2.0s”, “2016-09-15 01:00:07.000 2s” ] \n",
"출력: 2 \n",
"설명: 처리시간은 시작시간과 끝시간을 포함하므로 첫 번째 로그는 01:00:02.003 ~ 01:00:04.002에서 2초 동안 처리되었으며, 두 번째 로그는 01:00:05.001 ~ 01:00:07.000에서 2초 동안 처리된다. 따라서, 첫 번째 로그가 끝나는 시점과 두 번째 로그가 시작하는 시점의 구간인 01:00:04.002 ~ 01:00:05.001 1초 동안 최대 2개가 된다.\n",
"\n",
"#### 예제 3\n",
"\n",
"입력: [ “2016-09-15 20:59:57.421 0.351s”, “2016-09-15 20:59:58.233 1.181s”, “2016-09-15 20:59:58.299 0.8s”, “2016-09-15 20:59:58.688 1.041s”, “2016-09-15 20:59:59.591 1.412s”, “2016-09-15 21:00:00.464 1.466s”, “2016-09-15 21:00:00.741 1.581s”, “2016-09-15 21:00:00.748 2.31s”, “2016-09-15 21:00:00.966 0.381s”, “2016-09-15 21:00:02.066 2.62s” ] \n",
"출력: 7 \n",
"설명: 아래 타임라인 그림에서 빨간색으로 표시된 1초 각 구간의 처리량을 구해보면 (1)은 4개, (2)는 7개, (3)는 2개임을 알 수 있다. 따라서 초당 최대 처리량은 7이 되며, 동일한 최대 처리량을 갖는 1초 구간은 여러 개 존재할 수 있으므로 이 문제에서는 구간이 아닌 개수만 출력한다."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from datetime import datetime, timedelta\n",
"from collections import namedtuple\n",
"\n",
"Timerange = namedtuple('Timerange', ['start', 'end'])\n",
"\n",
"def solution_7(logs):\n",
"\n",
" def stack_count(stack, current):\n",
" new_stack = [t for t in stack[1] if t.end >= current.start]\n",
" new_stack.append(current)\n",
" stack[0].append(len(new_stack))\n",
" return [stack[0], new_stack]\n",
"\n",
" def make_timerange(log):\n",
" t, _, d = log.rpartition(' ')\n",
" start = datetime.strptime(t, '%Y-%m-%d %H:%M:%S.%f')\n",
" end = start + timedelta(seconds=float(d[:-1]))\n",
" return Timerange(start, end)\n",
"\n",
" stack, _ = reduce(stack_count, map(make_timerange, logs), [[], []])\n",
" return max(stack)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> 입력예제에 따옴표를 아스키따옴표(\") 가 아닌 겹낫표(“)로 올려둔 바람에 테스트 케이스를 만드는데 몇분이나 소모하게 됐다.\n",
"> 이 문제는 요구사항 하나를 놓쳐서 오답이 되었지만, 접근 방법은 이쪽이 좀 더 정확한 동시접속자 수를 계산할 수도 있을 것 같고 시간 공간 복잡도도 작을것 같아 그대로 둔다. 이 풀이로는 \"1분 최대 처리량\" 대신 실제 동시처리되는 최대 갯수가 산출된다. 전체 timeseries를 메모리에 올리고 moving window로 1분을 찾는것보다 reduce를 이용하여 새 작업이 시작되는(작업수가 늘어나는) 시점마다만 총 작업수를 카운트하는게 훨씬 효율적이라고 생각했다."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment