-
[CodeKata] 위클리 프로그래머스(2월 1주차)Algorithm 2021. 2. 1. 16:31반응형
🥋 Ooooth!! (Level 1)
새벽작업이 많아지면서 10시 기상 약속을 자꾸 못지키고 있다. 내일부턴 점심전 1코드카타를 반드시 하겠다.
다음주부턴 레벨2로 올릴건데, 오전 코드카타부터 밀리게 되면 하루 전체에 차질이 생기므로 2월의 첫날 나와의 약속이다!!
👊 2.1(월) / 2016년
📜 문제
🧮 풀이
function solution(a, b) { const dayArr = ['SUN','MON','TUE','WED','THU','FRI','SAT'] const dayIndex = new Date(`2016-${a}-${b}`).getDay(); return dayArr[dayIndex]; }
- 요일값이 담긴 dayArr 를 선언한다. 여기서 정답요소를 인덱싱하여 찾을 것이다.
- dayIndex는 new Date() 객체와 getDay() 메서드를 사용했다. 먼저, new Date() 에 날짜를 입력하면 날짜정보를 반환한다.
- getDay()는 해당일의 요일을 인덱스로 반환한다.(일요일이 0, 월요일이 1 ... 토요일이 6이다.)
🖇 리뷰
function solution(a, b) { const day = new Date(`2016-${a}-${b}`).toString().slice(0,3).toUpperCase(); return day; }
더 많은 메서드로 간결하게 풀 수 있을것 같아 내가 새로 고안해본 방법이다!
new Date() 반환값 맨 앞이 요일임을 감안해서, String 변환 -> 앞에 3글자 자르기 -> 대문자 변환 처리 후 반환한 것이다.
👊 2.2(화) / 3진법 뒤집기
📜 문제
🧮 풀이
function solution(n) { var answer = parseInt(n.toString(3).split("").reverse().join(""), 3) return answer; }
- [10진수].toString(3) : 10진수 -> 3진수 변환을 해준다. string 타입으로 반환
- split() - reverse() - join() : 위 문자열을 뒤집는다.
- parseInt([10진수], 3) : 3진수 -> 10진수로 변환해준다. number 타입으로 반환
🖇 리뷰
메서드들과, 특히 toString / parseInt가 진수변환이 된다는 것은 새로 알았지만, 알고리즘적 풀이는 아니라 생각됬다.
아래 풀이는, while 반복문과 reduce 합계를 통해 정답을 도출하는 아주 유용한 답안이다.
function solution(n) { const answer = []; while(n !== 0) { answer.unshift(n % 3); n = Math.floor(n/3); } return answer.reduce((acc,v,i) => acc + (v * Math.pow(3, i)),0); }
- answer 배열의 요소들로 3진수 각 자리수를 담는다. 이 때, unshift로 앞으로 담으면서 뒤집는 효과를 동시에 도출했다.
- 3진수 자리수는 n(10진수)을 3으로 나눈 나머지로 계산했다. (9는 나머지가 0이므로 1자리 0, 8은 나머지가 2이므로 1자리 2)
- 다음 자리수를 구하려면 n(10진수)을 3으로 나눈 몫이 필요하다. (Math.floor) 이렇게 n을 3으로 나누며 0이 될 때까지 반복한다.
- 이렇게 모인 answer 배열의 값들을 10진수로 변환한다. reduce로 합을 구하고, Math.pow(3, 제곱수) 를 현재값(v)에 곱했다.
👊 2.3(수) / 같은 숫자는 싫어
📜 문제
🧮 풀이
function solution(arr) { var answer = []; answer.push(arr[0]); for (let i = 1 ; i < arr.length ; i++) { if (arr[i] !== arr[i-1]) { answer.push(arr[i]) } } return answer; }
- 중복을 확인할 배열(arr)의 첫 요소를 우선 중복요소를 누적할 배열(answer)에 push한다.
- 이후, arr의 두 번째 요소부터 순회하며, 전 요소와 같지 않을 경우 answer에 누적을 계속한다.
🖇 리뷰
이전에, 위코드 코드카타에서 풀어본 로직이라 무난하게 풀 수 있었다.
처음에는 !arr.includes(arr[i]) 조건문을 적용했는데, 그러면 중복되는 요소들까지 누적되지 않으므로 유념해야겠다!
(예를 들면, 문제사진의 첫 번째 경우 답이 [1, 3, 0, 1] 인데, 위 조건문을 쓰면 [1, 3, 0] 이 된다.)
👊 2.4(목) / 문자열 내 마음대로 정렬하기
📜 문제
🧮 풀이
function solution(strings, n) { var answer = strings.sort((a,b) => { if (a[n] > b[n]) { return 1; } else if (a[n] < b[n]) { return -1; } else { return (a > b) ? 1 : -1; } }); return answer; }
- sort() 메서드를 활용했다. strings 각 요소의 [n]번째 글자끼리 비교하면서, 앞글자가 느리면(>) 1(재배열), 빠르면(<) -1(고정)
- 두 글자가 같은 경우가 있다.(=), 이 때는, 전후 글자 자체를 비교하면 사전순으로 배열이 된다.
🖇 리뷰
sort() 메서드로 쉽게 풀었지만, sort()의 세부 문법에 대해서 다시금 공부하게 된 좋은 계기였다.
우선, sort() 자체로도 오름차순 정렬이 되지만, 내부 인자로 비교함수를 받을 수 있다는 것을 확실히 알게 되었다.
a-b 양/음 판정을 통해 숫자 비교도 가능하고, 문자의 경우는 위처럼 비교 연산자를 통해 비교한다. (return 1, -1 을 해줘야 한다.)
위 풀이에서, return 값이 0일 때(두 값이 같을 때), 별도의 처리가 없으면 기존 배열 순서가 적용되므로 위처럼 다시 글자자체를 비교해준 것이다.
👊 2.5(금) / 소수 찾기
📜 문제
🧮 풀이
도저히 풀지 못하고... 답안들을 오픈해봤다. Set() 에 대한 개념이 부족하여, 반복문으로 푼 것 중에 이해가 되는 풀이를 가져와봤다.
🖇 리뷰
function solution(n) { let answer = 0; let arr = [] for (let i = 2; i <= n; i++) { arr[i] = i; } for (let i = 2; i <= n; i++) { if (arr[i] === 0) continue; for (let j = i + i; j <= n; j += i) { arr[j] = 0; } } for (let i = 2; i <= n; i++) { if (arr[i] !== 0) answer++; } return answer }
- arr 배열에 2부터 n까지 정수들을 모두 추가해준다. (숫자 = 인덱스)
- 2의 순서에서 보면, 2+2인 4부터 그 숫자(2)의 배수들을 모두 지워준다. 본인은 소수이기 때문에 남기고, *2인 i+i가 시작 인덱스
- 해당 순서의 숫자가 0이라면 이미 전에 지워졌으므로 continue로 다음 반복문으로 넘어간 것이다.
- arr에서 남은 0이 아닌 숫자(소수에 해당하는 숫자 혹은 인덱스)들의 합을 누적하여 answer 값을 반환한다.
* 출처 : jo-c.tistory.com/38
👊 2.7(일) / 신규 아이디 추천(KAKAO) - 1단계 졸업 문제!
본래 평일만 문제를 풀었지만, 내일부터 2단계로 넘어가기 위해 1단계 중 푼 사람이 1200명인 카카오 알고리즘 문제를 마지막으로 풀어보고 1단계를 마무리하고자 했다.
📜 문제
🧮 풀이
function solution(new_id) { // 1단계 : 소문자 치환 let answer = new_id.toLowerCase(); // 2단계 : 한글, 특수문자 제거 const regexCha = /[~!@#$%^&*()=+{}:?\[\],<>\/]/g; const regexKor = /[ㄱ-ㅎ|ㅏ-ㅣ|가-힣]/g; answer = answer.replace(regexCha, ""); answer = answer.replace(regexKor, ""); // 3단계 : 연속 . 제거 const regexDot = /[.]{2,}/g; answer = answer.replace(regexDot, ".") // 4단계 : 처음과 끝 . 제거 if (answer.startsWith('.')) { answer = answer.substr(1, answer.length-1) } if (answer.endsWith('.')) { answer = answer.substr(0, answer.length-1) } // 5단계 : 빈 String인 경우 if (!answer) { answer = "a"; } // 6단계 : 최대길이 준수 if (answer.length >= 16) { answer = answer[14] === "." ? answer.substring(0, 14) : answer.substring(0,15) } // 7단계 : 최소길이 준수 if (answer.length <= 2) { while (answer.length < 3) { answer += answer[answer.length - 1] } } return answer; }
- 소문자 치환: toLowerCase() 메서드를 쓰면, 모든 대문자가 소문자로 치환된다.
- 한글, 특수문자 제거: 정규식( /[대상문자]/ ) 부합 시, replace() 메서드로 해당 문자를 ""(빈 문자열)로 치환했다.
- 연속 '.' 제거 : 연속된 '.'을 하나로 치환했다. 정규식의, {[최소 반복수], [최대 반복수]} 문법을 활용했다.
- 시작, 끝 '.' 제거: startsWith(), endsWith() 메서드를 활용했다. 해당 문자열로 시작/끝 여부를 boolean 반환한다.
- 빈 String: 문자열이 빈 경우(!answer), "a"를 대입했다.
- 최대길이 준수: 길이가 16 이상인 경우, substring() 메서드로 잘랐다. 15번째 글자가 '.' 이라면 14번째까지만 자른다.
- 최소길이 준수: 길이가 2 이하인 경우, while 반복문으로 길이가 3보다 작은 동안(=3이 될때까지) 계속 끝글자를 더해줬다.
* 본래, replaceAll()로 모든 문자를 검사 및 치환해야 했지만, 정규식 끝에 'g'가 모든 글자체크를 지시함.
🖇 리뷰
1단계에서 어려운(물론 푼 사람 기준이지만) 문제를 참고 없이 풀어내다보니 뿌듯하면서, 생각이 많이 바뀌는 계기가 되었다.
나는 알고리즘을 풀면서, 알고리즘스러운(?) 풀이를 지향해야 한다고 생각했다. (조건문, 반복문, 기본 메서드 등등)
하지만, 위 한문제에서 알게된 메서드만 해도 replace, startsWith, endsWith... 정규식 문법도 어느정도 공부하게 되었다.
물론, 위 내용들을 반복문이나 조건문으로 대체할 수 있는 부분도 많다.
하지만, 앞으로는 기본구현 방법은 머릿속으로 그리면서, 새로운 메서드나 문법을 공부하면서 풀이를 만들어나가 보려고 한다.
반응형'Algorithm' 카테고리의 다른 글
[CodeKata] 위클리 프로그래머스(2월 3주차) (0) 2021.02.15 [CodeKata] 위클리 프로그래머스(2월 2주차) (0) 2021.02.08 [CodeKata] 위클리 프로그래머스(1월 4주차) (0) 2021.01.26 [CodeKata] 위코드 5주차 코드카타 (0) 2021.01.11 [CodeKata] wecode 4주차 코드카타 (0) 2021.01.03