시프트 연산자 <<
9 << 3 은 9 * (2^3) = 72
각자리가 3의 배수일 때마다 박수를 치고 총 박수친 횟수를 return
나는 보통 숫자를 배열로 바꿀 때 ex) num = 123
String(num).split('') 를 많이 사용 했는데
스프레드 문법을 사용하면 편하다
[...order+' '] 대신 여기서 +' ' 부분을 꼭 넣어줘야함
아래처럼 배열로 바꾸어준 다음 filter를 활용하는데 includes를 활용하면 Number로 형변환을 안 해줘도 돼서 편함
문자열로 바꾼 후 includes를 활용하여 포함한다면
indexOf 를 활용하여 index값+1 (번째를 물어봤으니) 를 반환
결국 풀지 못했던 문제..
답을 찾아보니 이중 포문을 통해
주어진 n전에 숫자들이 합성수인지 아닌지를 판단
cnt로 체크한 약수(cnt)가 3개 이상이라면 전역 변수인 answer의 값을 +1씩 올려주는 식으로 해서 해당 숫자 전에 나오는 모든 정수들의 약수가 3개 이상일 때마다 +1
여기서 유의해야할 것은 inner for문과 if문이 같은 들여쓰기 위치에 있어서 병렬적으로 동작한다는 것
function solution(n) {
var answer = 0
for(let i = 1; i <= n; i++) {
let cnt = 0
// 6이 들어왔다고 하면
// i j
// 1 1 cnt 1 answer 0
// 2 1 cnt 1 answer 0
// 2 2 cnt 2 answer 0
// 3 1 cnt 1 answer 0
// 3 2 cnt 1 answer 0
// 3 3 cnt 2 answer 0
// 4 1 cnt 1 answer 0
// 4 2 cnt 2 answer 0
// 4 3 cnt 2 answer 0
// 4 4 cnt 3 answer 1
for(j = 1; j <= i; j++) {
if(i % j === 0) cnt ++
}
if(cnt > 2) {
answer += 1
}
}
return answer
}
대문자를 소문자로 찝어서 바꾸는 일이 없길..
그냥 모두다 소문자로 바꾸어주면됨
my_stinrg.toLowerCase().split('').sort().join('')
당연히 보자마자 set을 떠올렸다
제공된 문자열을 ex) my_string = "people"
const set = new Set(my_string) 을 통해 객체로 만들어준 후 // { 'p', 'e', 'o', 'l' }
다시 전개 연산자를 통해 배열로 바꾼 후
join을 통해 문자열로 합치면 됨 [...set].join('')
객체의 키에 해당하는 값을 가져와서 문자열로 반환하는 문제
문제에선 letter = ".... . .-.. .-.. ---" 처럼 공백으로 구분하여 암호가 주어짐
가장 먼저 해야할 건 "공백으로"라는 말에 초점을 두고 바로 split(" ")을 하는 것
그렇게 만들어진 인덱스들과 morse와 비교하여 return 하면 됨
return letter.map( v => morse[v]).join('')
letter의 인덱스값들이 morse의 키에 접근해서 나온 값들을
join을 통해 문자열로 변환하여 반환
혹은 이렇게 보다 깔끔하게 reduce를 써도 됨
어렵게 생각할 거 없이 before와 after를 정렬했을 때 둘의 값이 같은지 다른지 보면됨
아쉬움이 많이 남는 문제인 것 같다.. 팩토리얼 구현까지는 알고 있었지만
i를 return 하는 과정에서 버벅거림
팩토리얼을 구현한 후
n이 factorial(i) 보다 작아질 때가 오면 그때에 해당하는 팩토리얼의 전 수를 반환
여기서 i가 11까지인 이유는 factorial 10까지를 고려해야하기 때문
splice를 활용하여 원본 배열이 변경된다는 걸 알고 이용하면 좋음
// num_list의 길이가 존재할 때 (1이상일 때)
let ans =[];
while (num_list.length) {
// 처음부터 2개씩을 넣어주세요 (길이가 0될 때 까지)
ans.push(num_list.splice(0, n)
}
return ans;
function solution(array, n) {
// n을 뺀 절대값과 array를 벗긴 값들 중에 n을 뺀 값
// (둘이 같은 말)과 일치하는 것을 지정
// 즉, 절대값의 차이가 가장 작거나 같은 애들을 filter로 선정
// 그 후, 오름차순 정렬한 후 가장 작은 애를 제거
// Math.min 사이엔 정수가 들어가야 하기 때문에 전개연산자를 사용하여 같은값을 비교해줌
return array.filter( v => Math.abs(v-n) ===
Math.min(...array.map(v => Math.abs(v-n))
.sort((a, b)=> a-b).shift()
}
emergency = [3, 76, 24];
여기서
array = emergency.sort( (a, b) => b-a )
와 array = [...emergency.sort( (a, b) => b-a ) 의 차이
이것은 참조연산 때문에 메모리 값을 직접 수정하느냐 (deep copy)
아니면 그 메모리 값을 가리킬 뿐이냐 (swallow copy) 의 차이
그렇기 때문에 전자는 emergency의 값이 바뀌어 버리고
후자는 메모리 주소를 가리키는 화살표만 복사하는 것이기 때문에 바뀌지 않음
나는 전자를 사용해서 자꾸 엉뚱한 답이 나왔었음
function solution(emergency) {
// 내림차순 정렬 [76, 24, 3]
array = [...emergency].sort( (a,b) => b - a)
// 3이 array에서 어디에 있는가 인덱스 2 (즉, +1하여 3번째 위치)
// map을 통한 반복으로 결과들을 배열에 모아줌
return emergency.map( v => array.indexOf(v)+1 )
}
sort 는 기존 배열을 변경하여 요소를 정렬 시킴.
slice()는 emergency 배열을 변경하지 않고 새로운 배열을 할당해주는 역할을 함
즉, slice()의 유무는 swallow copy인가 deep copy인가의 차이
function solution(emergency) {
let sorted = emergency.slice().sort((a,b)=>b-a);
return emergency.map(v=>sorted.indexOf(v)+1);
}
나처럼 전개연산자를 통해 sallow copy를 해도 됨
이 문제 덕분에 오랜만에 정규표현식을 복습했다.
처럼 붙어있는 숫자라면 붙어서 빼야하므로
정규표현식에 match를 활용하면 된다
[ ] : 괄호안에 문자들 중 하나 or처리묶음이라고 보면 됨
/[abc]/ : "a" 또는 "b" 또는 "c" 를 포함하는
g : 전역 (플래그)
+ : 최소 한 개 or 여러개 /apple+/ 이 친구 덕분에 여러 개도 붙어서 나옴
// 1. 정규표현식을 사용해서 my_string의 숫자 부분을 발라낸다.
// my_string이 "aAb1B2cC34oOp" 이라면 nums = [ '1', '2', '34' ]
const nums = my_string.match([0-9]+/g);
return nums.map(num => Number(num)).reduce( (a, c) => a + c, 0)
function solution(s) {
ans = [];
s = s.split('')
s.forEach((item) => {
// 앞에서 부터 찾은 값과 뒤에서 부터 찾은 값이 같다는 것은 배열에서 "한 번만" 등장한다는 것
if(s.indexOf(item) === s.lastIndexOf(item)){
// 결과로 반환할 배열에 넣어주기
ans.push(item);
}
})
// 배열을 소팅한 다음에 문자열로 변환
return ans.sort().join("");
}
우선, 2진수를 10진수로 바꾸는 문법과 10진수를 2진수로 바꾸는 문법을 알고 있어야함
이진수 -> 십진수
parseInt(이진수, 2)
십진수 -> 이진수
십진수.toString(2)
이진수 10를 십진수 4로 바꾸고 이진수 11를 6으로 바꾼 후
두 개를 더한 십진수 10을 다시 이진수로 나타내면 됨
스택을 생각한다면 쉬운 문제
반복문을 통해 배열에 있는 것들을 하나씩 넣다가 Z가 나온다면
만들어져있던 스택에서 한 개를 POP하고 그렇지 않으면 계속 넣어주면 됨
function solution(s) {
// 공백을 한 칸으로 띄워져 있기 때문에 split을 해줄 때 공백한 칸을 줘야함
s = s.split(" ")
// 스택으로 쓸 배열
res = [] ;
// res배열에서 v를 한 개 씩 꺼내올 것
// 넣을 차례가 Z라면 채우던 res에서 한 개를 빼즘, 단 여기서 에러방지용으로
// res의 길이가 1이상일 때만 허용
for (let v of s) v === "Z" ? (res.length > 0 ? res.pop() : "") : res.push(v)
// ★ 여기에서 a+ +c를 해주는 이유는 음수를 더해야하기 때문에
return res.reduce( (a, c) => a+ +c, 0)
}
다른사람 풀이
forEach를 활용하여 한 개씩 꺼내옴 여기서도 더해줄 떄 +target을 통해 음수도 넣어주는 것을 볼 수 있음
문제는 간단하게 2로 나누다가 나머지가 있으면 div의 값을 1씩 올리는 것
처음에 나눠주는 숫자를 2로 지정하여 변수로 만들고
for문 대신 while문을 활용 (for문을 i값의 증가가 번거로우니까)
function solution(n){
ans = [];
div = 2;
while( n >= 2) {
if (n % div === 0) {
res.push(div)
n = n/div
} else {
div++
}
}
// 전개연산자를 통한 set변환 가능
return [...new Set(res)]
}
영어숫자의 순서대로 인덱스에 배정해준 배열(strs)을 만든 다음
그 배열의 각 값들을 가지고 strs에서 찾아 replace을 통한 변경
function solution(numbers) {
// 숫자를 str의 인덱스순으로 맞추어 놔야 인덱스를 해당하는 문자 찾아 바꿈
let strs = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
// numbers에서 해당하는 str (영어숫자)를 strs에 존재하는 인덱스로 변경
strs.forEach( (str,i) => {
numbers = numbers.replaceAll(str, i)
})
return Number(numbers)
}
객체에 값을 담고 replace와 정규표현식을 활용한 풀이
replace도 콜백함수가 가능하다는 걸 잊지 말기
function solution(numbers) {
const obj = {
zero: 0, one: 1, two: 2, three: 3, four: 4,
five: 5, six: 6, seven: 7, eight: 8, nine: 9
};
const num = numbers.replace(/zero|one|two|three|four|five|six|seven|eight|nine/g, (v) => {
return obj[v];
});
return Number(num);
}
eval을 사용하면 되지만 eval은 evil임
반복문을 통하여 각 인덱스를 검사하고 인덱스에 연산자에 따라서 answer라는 정수 변수에 더해주거나 빼주면 됨
function solution(my_string) {
my_string = mystring.split(' ');
answer = 0;
// 연산자 초기 지정으로 삼항연산자에 활용
operator = '+';
my_string.forEach( (v, i) => {
// 배열을 순회하며 숫자가 아닌 문자가 나왔을 때 그 값을 연산자에 지정
if (isNaN(Number(my_string[i]))) {
operator = my_string[i];
} else {
// 연산자에 따라 answer에 연산을 실행
operator === '-' ? answer -= parseInt(my_string[i]) : answer += parseInt(my_string[i]);
}
})
return answer
}
let test = '10.12345';
parseInt(test); // 10
Number(test); // 10.12345
let test = '2020년도';
parseInt(test); // 2020
Number(test); // NaN
parseInt는 문자열로 된 부분에서 숫자만을 뽑아서 변환
Number는 문자열 전체가숫자일 때만 사용 가능
[...배열].splice가 아닌 배열.splice와 slice는 원본 배열에 영향을 미친다는 것을 활용하면 쉬움
substr은 원본에 영향 X
function solution(my_str, n) {
ans = [] ;
my_str = my_str.split("")
while(my_str.length > 0) {
// splice로 분해하면 각각이 한 배열에 들어가니까 join으로 뭉쳐주곤 push
ans.push(my_str.splice(0, n).join(''))
}
return ans
}
// 다른사람 풀이
물론 for문과 substr (몇 개씩 뺸다) 를 활용해도 가능
function solution(my_str, n) {
var answer = [];
for(let i=0; i < my_str.length; i+=n) {
answer.push(my_str.substr(i, n));
}
return answer;
}
substr은 앞 인덱스부터 몇 개를 빼겠다는 것이고
substring은 앞 인덱스부터 뒤 인덱스-1 까지 뺴겠다는 것
팩토리얼을 구현해서 매우 쉽게 푼 문제 3C2를 계산하면 된다
function fac(n) {
if ( n <= 1) {
return 1
} else {
n * fac(n-1)
}
}
function solution(balls, share) {
k = balls - share
// 소수점 30!/29! 인 경우 30.000000....1 같은 값이 나오기 때문에 반올림
return Math.roud(fac(balls)/(fac(k)*fac(share))
}
수학을 하도 손 뗐어서 조건이 기억 안 나던 문제지만
함수로 구현해서 풀었다
every - 배열의 모든 요소가 callbackFunction 에서 true를 리턴해야 true를 리턴,
하나라도 false가 떨어지면 false를 리턴
some - 배열의 요소 중 하나라도 callbackFunction에서 true를 리턴하면 true를 리턴
function solution(spell, dic) {
// spell에 해당하는 값들을 모두 갖고 있는 애가 있으면 걔를 배열에 담아 리턴
// includes를 통해 매치되는 애가 없으면 배열에 아무것도 들어가지 않으니 길이를 통해 삼항연산자
return dic.filter( v => spell.every( c => v.includes(c) )).length ? 1 : 2
}
나는 덕지덕지 조건문을 활용하여 풀었지만.. (일전에 프로젝트에서 로그인창에 썼던 로직)
여러가지 신박한 풀이법이 많다
Map은 객체와 비슷하지만 한 가지 다른 점은 키에 여러가지 자료형이 들어갈 수 있음
Map
new Map() – 맵을 만듭니다.
map.set(key, value) – key를 이용해 value를 저장합니다.
map.get(key) – key에 해당하는 값을 반환합니다. key가 존재하지 않으면 undefined를 반환합니다.
map.has(key) – key가 존재하면 true, 존재하지 않으면 false를 반환합니다.
map.delete(key) – key에 해당하는 값을 삭제합니다.
map.clear() – 맵 안의 모든 요소를 제거합니다.
map.size – 요소의 개수를 반환합니다.
1. 맵을 이용한 풀이
function solution(id_pw, db) {
const [id, pw] = id_pw;
const map = new Map(db);
return map.has(id) ? (map.get(id) === pw ? 'login' : 'wrong pw') : 'fail';
}
function solution(id_pw, db) {
db = db.filter(v=>v[0]===id_pw[0]);
if (!db.length) return 'fail';
for (let d of db) if (d[1] === id_pw[1]) return 'login';
return 'wrong pw';
}
function solution(chicken) {
// 쿠폰 = 치킨 수
let coupon = chicken
// 서비스 받은 치킨 수
let serviceChicken = 0
// 쿠폰이 10개 이상이라면
while(coupon >= 10) {
// 쿠폰을 10으로 나눈 몫만큼 서비스 치킨 추가
serviceChicken += Math.floor(coupon/10)
// 여기에서 쿠폰을 재귀적으로 더해줌
// 남은 쿠폰 = coupon%10, "쿠폰을 통해 주문한 치킨의 쿠폰 수" = coupon/10
coupon = coupon%10 + Math.floor(coupon/10)
}
return serviceChicken
}
indexOf(찾을값)는 배열에서 값들 중 가장 처음에 찾은 인덱스를 반환하는 것을 잊지 않으면 동점자도 쉽게 해결할 수 있다.
ex)
스코어 평균 75 70 55 65 55
내림차순 75 70 65 55 55
을 통해서 찾은 애의 인덱스값에 +1 (인덱스가 0부터이니)
function solution(score) {
// 내림차순을 통해 점수가 클수록 인덱스가 앞으로 오게 한다.
// indexOf는 찾은 인덱스 중 가장 첫번째를 반환하기 때문에
// 앞에 있는 애부터 +1씩 해주면 됨
// 1. score의 평균 점수를 구한다.
let avg = score.map(v=>(v[0]+v[1])/2);
// 2. avg를 내림차순으로 정렬한 배열 sort를 선언한다.
let sorted = avg.slice().sort((a,b)=> b-a);
// 3. avg의 요소와 동일한 sorted 배열의 index 값에 1을 더한다.
return avg.map(v => sorted.indexOf(v) + 1);
}
let arrA = [1, 4, 3, 2];
let arrB = [5, 2, 6, 7, 1];
arrA.filter(it => arrB.includes(it)); // returns [1, 2]
처음엔 약수를 구하는 함수를 만들어서 약수를 구한 다음
둘의 중첩되는 리스트를 만들어서 pop으로 최댓값을 빼서 썼지만
최대공약수라는 이유로 둘의 공약수를 모두 구할 필요없이 분모값을 활용한 for문을 통해 a와 b 둘 다 나머지가 0으로 만드는 수를 구해서 넣어줌
그후 while문 두 개를 통해 b의 값이 2나 5로 계속 나누어서 1이 되는지 확인하고
1이 됐다면 return 하는 방식을 참고하여 풀었다
function solution(a, b) {
maxNum = 0;
for (let i = 1; i<= b; i++){
if(a%i ===0 && b%i ===0) {
maxNum = i;
}
}
// 분모를 최대공약수로 나누어서 기약분수로 만듦
b = b/maxNum
while (b%2 === 0) b = b/2
while (b%5 === 0) b = b/5
// 기약분수의 소인수가 2와 5뿐이여야함
return b===1 ? 1 : 2
}
// function getNum(number) {
// res = [];
// div = 1;
// for(i=1; i<= number ; i++) {
// if (number % i === 0) {
// res.push(i)
// }
// }
// return res
// }
3의 배수가 아닌 숫자들을 다 넣어준 다음
배열에서 String을 통한 형변환 + .includes('3') 을 통해
3을 가진 친구들을 다 제거한 후 n을 인덱스값으로 받아서 하면 되는데
인덱스값을 꺼내야하므로, n-1
function solution(n) {
ans = []
for (i=1; i<200; i++) {
if(i % 3 !==0) {
ans.push(i)
}
}
ans = ans.filter( (v,i) => !String(v).includes('3'))
return ans[n-1]
}
function solution(n) {
var answer = 0;
// 3의 배수에 해당하면 n의 값을 증가시킴 (건너뛴다는 소리)
// 자연스럽게 for문속 n도 함꼐 증가
for(let i=1; i<=n; i++){
if(i%3 == 0){
n++;
}
// 3을 포함하고 있는데 3으로 깔끔히 나눠지지않으면 n을 증가시킴
// 33 같은 애들은 이미 3의 배수에서 제외해줬으니
if(String(i).includes("3")& i%3 != 0){
n++
}
}
return n;
}
sort의 콜백함수를 고쳐서 푸는 문제
function solution(numlist, n) {
return numlist.sort((a,b) => {
// 각 인덱스와 n의 거리차이 계산
const [aGab, bGab] = [Math.abs(a-n), Math.abs(b-n)]
// 거리가 같다면 더 큰 수를 우선 배치
if(aGab === bGab) return b-a
// 다르다면 거리별 오름차순 정렬
return aGab-bGab
})
}
function solution(numlist, n) {
// 내림차순으로 먼저 정렬
// 그 후 각 값들에서 n을 빼준 값이 작은 순으로 다시 오름차순 정렬
return numlist.sort((a,b)=>b-a).sort((a,b)=>Math.abs(a-n)-Math.abs(b-n))
}
문자열을 밀어서 최소로 되는 횟수와 안 되면 -1, A와 B가 같으면 0
그냥 정석대로 푼 느낌이다.
function solution(A, B) {
ANS = A.split('')
count = 0;
while(ANS.join('') !== B) {
ANS.unshift(ANS.pop())
count+=1
if(count > A.length) return -1
}
return count ? count : (A===B && 0)
}
let solution = (A,N) => (B+B).indexOf(A)
B랑 B를 더하면
"ohellohell"
이렇게 되는데 여기서 문자열 A가 시작하는 인덱스 즉, 1을 반환
존재하지 않는다면 당연히 -1이 리턴될 것이고
처음부터 같다면 0이 리턴.. 캬