8일차 알고리즘

태권·2022년 8월 8일
0

알고리즘

목록 보기
3/8

오늘의 알고리즘

문제 1번

두개 뽑아서 더하기

정수 배열 numbers가 주어집니다. numbers에서 서로 다른 인덱스에 있는 두 개의 수를 뽑아 더해서 만들 수 있는 모든 수를 배열에 오름차순으로 담아 return 하도록 solution 함수를 완성해주세요.

// a =[2,1,3,4,1]
// arr = []
// function(num){
//     let num = 0
//     while(num<a.length){
//         b = a.map((v)=> a[num]+v)
//         arr.push()
//         num++   
//     }
// }

틀린 코드 인데 맨처음 각 다른 인덱스의 요소를 더해서 하나의 배열로 만들고 그것을 중복을 없애는 set을 사용하면되겠다고 생각했다.
풀이과정은 잘 되었는데 구현하는데 중간에 push를 하는경우 arr =[] 안에 또 []가 들어가 NaN가 만들어진것이다.

 function solution(a) {
let arr = []
num = 0
while(num<a.length){
    a.map((v,i)=> num == i? false : arr +=  (a[num]+v)+ " ")
    num ++
}
let b = arr.split(" ")
let c = new Set(b)
let d = [...c]
d.pop()
let g = d.map((k)=> parseInt(k)).sort((t,y)=>(t-y))
return g}

그래서 push 가아니라 +=를 사용하였다.
이렇게 하면 내가 원하는 의도대로 시행이 됐고 이후 숫자를 string으로 만들기 위해 쓴 " " 를 사용해 글자로만든 배열을 봤는데 중간에 값이 " " 이 들어가 있었고 split " " 을 하니 사라졌다.
이후 set을 써서 중복을 없애고 배열의 마지막에 오는 ''를 pop으로 마지막 배열을 없앴다.
그래고 나머진 int로 바꾸고 오름차순으로 바꾸어준다, 끝

push는 더해주고 그 배열의 크기를 리턴하는것이였다!

a =[1,2,3,4]
b = a.push(5) 이면 로그를 찍을 때 a는 1,2,3,4,5이고 b는 6이 되는것이였다!
이러한 작은 차이를 알았다면 처음의 풀이에서 해결했을지도..

function solution(numbers) {
    const temp = []

    for (let i = 0; i < numbers.length; i++) {
        for (let j = i + 1; j < numbers.length; j++) {
            temp.push(numbers[i] + numbers[j])
        }
    }

    const answer = [...new Set(temp)]

    return answer.sort((a, b) => a - b)
}

다른분이 올린 깔끔버젼

!tmep.includes() 를 써도 되었다!

function solution(a) {
    let arr = []
    num = 0
    while(num<a.length){
        a.map((v,i)=> num == i? false : arr.push(a[num]+v)) //arr +=  (a[num]+v)+ " "
        num ++
    }
    console.log(arr)
    let c = [...new Set(arr)]
    let g = c.map((k)=> parseInt(k)).sort((t,y)=>(t-y))
    return g
}

처음 풀었던 걸 더 깔끔하게 고쳤다

문제 2

로또의 최고순위와 최저 순위

function solution(a, f) {
    let g = []
console.log(g.length)
let b =  a.toString().match(/[0]/ig).length  //['0', '0'] 여기서 0은 문자로 10일떄도 0을 가져온다 이래서 안되는거였어..
for(let i =0; i<6; i++){
    if(a.includes(f[i])){
        g.push(f[i]) 
    }
}
let max = g.length + b
let min = g.length
let ansf = 1
let ansl = 6
switch(max){
    case 6 : ansf = 1; break;
    case 5 : ansf = 2; break;
    case 4 : ansf = 3; break;
    case 3 : ansf = 4; break;
    case 2 : ansf = 5; break;
    case 1 : ansf = 6; break;
}
switch(min){
    case 6 : ansl = 1; break;
    case 5 : ansl = 2; break;
    case 4 : ansl = 3; break;
    case 3 : ansl = 4; break;
    case 2 : ansl = 5; break;
    case 1 : ansl = 6; break;
    case 0 : ansl = 6; break;
}
let answer = [ansf, ansl]
return answer
}

의식의 흐름대로 풀었는데 채점에서 오류가 났다
일단 0의 갯수를 새고 a,f 중 같은 숫자가 있으면 g에 넣고
g의 길이와 0의 갯수를 가지고 최대값 최소값을 만둘었다.
총 맞은 갯수를 구했고 등수를 구해면 끝 그건 switch를 써서 구했는데 어디서 오류인지 잘모르겠다.

function solution(a, f) {
    let g = []
let b =  []
for(let i =0; i<6; i++){
    if(a.includes(f[i]) == 0){
        b.push(f[i]) 
    }else if(a.includes(f[i])){
        g.push(f[i]) 
    }
}

let max = g.length + b.length
let min = g.length

let ansf = 1
let ansl = 6
if(max == 0){ansf = 6}
else{ansf = 7-max}
if(min == 0){ansl = 6}
else{ansl = 7-min}
let answer = [ansf, ansl]
return answer
}

결국 오래걸려 해결한 코드

function solution(a, f) {
    let g = []
    let b = []

for(let i =0; i<6; i++){
    if(a[i] === 0){
        b.push(0) 
    }
    }
for(let i =0; i<6; i++){
    if(a.includes(f[i])){
        g.push(f[i]) }
}
console.log(b,g)
let max = g.length + (b.length)
let min = g.length
console.log(max,min)

let ansf = 1
let ansl = 6
if(max == 0){ansf = 6}
else{ansf = 7-max}
if(min == 0){ansl = 6}
else{ansl = 7-min}
let answer = [ansf, ansl]
return answer
}

요건데
중간에 includes for문을 두개 썼는데 이상하게 1이 포함되있으면 하나의 for문안에서 해결이 안됬음

for(let i =0; i<6; i++){
    if(a[i] == 0){
        b.push(0) 
    }else if(a.includes(f[i])){
        g.push(f[i]) 
    }
}

이거가 계속 하나가 부족하게 나왔음

for(let i =0; i<6; i++){
    if(a[i] == 0){
        b.push(0) 
    }else if(f.includes(a[i])){
        g.push(a[i]) 
    }
}

근데 이거는 또 해결이된다...??

function solution(lottos, win_nums) {
    const rank = [6, 6, 5, 4, 3, 2, 1];

    let minCount = lottos.filter(v => win_nums.includes(v)).length;
    let zeroCount = lottos.filter(v => !v).length;

    const maxCount = minCount + zeroCount;

    return [rank[maxCount], rank[minCount]];
}

filter로 간단하게 만든 코드이다. !0은 true 란걸 이용

문제3

모의고사 수포자들..

function solution(answers) {
    const answer = [];
    const firstPattern = [1, 2, 3, 4, 5];
    const firstPLength = firstPattern.length;
    const secondPattern = [2, 1, 2, 3, 2, 4, 2, 5];
    const secondPLength = secondPattern.length;
    const thirdPattern = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5];
    const thirdLength = thirdPattern.length;
    let correctCount = [0, 0, 0];
  
    for (let i = 0, len = answers.length; i < len; i++) {
      if (answers[i] === firstPattern[i % firstPLength]) correctCount[0] += 1;
      if (answers[i] === secondPattern[i % secondPLength]) correctCount[1] += 1;
      if (answers[i] === thirdPattern[i % thirdLength]) correctCount[2] += 1;
    }
  
    const maxScore = Math.max(...correctCount);
    for (let i = 0; i < 3; i++) {
      if (correctCount[i] === maxScore) answer.push(i + 1);
    }
  
    return answer;
  }

4,5시간 소비하여 질문을 봤다
정답의 길이와 패턴의 길이를 사용했는데 첫번째 패턴의 i%패턴의 길이의 자리의 값과 답의 값이 같다면 정답 갯수를 더해주는 방식이다.

answer = [1,3,4,2,3,4,1,2,3,4,5,1,2,3,4,5,1,2,3]
  c = '12345'
  a = c.repeat(Math.ceil(answer.length/c.length)).split('').slice(0,answer.length)

이 방식은 패턴을 문자열로 두고 그것을 repeat하여 배열로 바꾸고 slice 하여 정답의 길이와 맞추는 방법 이후도 위와 같이 위치값 비교해서 같으면 정답 카운트를 올려주고 마지막에
최대값이 하나면 그거를 리턴 여러개면 그 index+1을 배열에 넣어서 주면 끝

function solution(answers) {
    let aanswer = [];
    let banswer = [];
    let canswer = [];
    let apatten = '12345'
    let bpatten = '21232425'
    let cpatten = '3311224455'
    let aarr = apatten.repeat(Math.ceil(answers.length/apatten.length)).split('').slice(0,answers.length)
    let barr = bpatten.repeat(Math.ceil(answers.length/bpatten.length)).split('').slice(0,answers.length)
    let carr = cpatten.repeat(Math.ceil(answers.length/cpatten.length)).split('').slice(0,answers.length)

    for(let i =0; i<answers.length; i++){
        if(aarr[i]==answers[i]){aanswer.push(aarr[i])}
        if(barr[i]==answers[i]){banswer.push(barr[i])}
        if(carr[i]==answers[i]){canswer.push(carr[i])}
    }
    let acout = aanswer.length
    let bcout = banswer.length
    let ccout = canswer.length
    let last = [acout,bcout,ccout]
    let maxlast = Math.max(...last)
    let result = []
    for(let j=0; j<3; j++){
        if(last[j]==maxlast){result.push(j+1)}
        
    }
    return result
}

최종적으로 푼것

문제 4

문자열 내 마음대로 정렬하기

function solution(str, n) {
    let bbb = []
    let ccc = []
    let aaa = str
    for(let i=0; i<str.length; i++){
        bbb.push(aaa[i][n])
    }
    let ddd = aaa.sort()
    bbb.sort()
    console.log(bbb, ddd)
    for(let j=0; j<bbb.length; j++){
        for(let k=0; k<bbb.length; k++){
            bbb[j] == ddd[k][n] ? ccc.push(ddd[k]) : false
        }
    }
    let answer =[...new Set(ccc)]
    return answer
}

일단 문자열 str의 n번째 문자를 빼내서 bbb에 넣었고 그다음에 str을 오름차순한 배열을 ddd 라고 했는데 이것은 제한 조건인 사전순으로 앞선 문자열을만족시키기 위한것
그리고 이중 for문을 써서 n번째 문자와 정렬한 str에 문자중 n자리의 문자를 가지고 있는것을 ccc에 넣주었고
이것은 이미 순서대로 정렬 되있는데 이때 중복되는 값이 들어가므로 set을 통해 중복값을 없애면 끝

다른풀이

function solution(strings, n) {
  return strings.sort().sort((a, b) => {
    if (a[n] === b[n]) return 0
    if (a[n] < b[n]) return -1
    return 1
  })
}

sort를 두번써서 푼 풀이인데 처음 그냥 문자열순서대로 정렬하고 그다음 n번째 글자를 가지고 정렬을 한다
이때 n번째 글자가 같으면 0 그대로 있고
앞글자가 뒷글자보다 앞이면 -1 (숫자로 생각하면 된다123정렬은 a-b였으니)
앞글자가 더 크면 +1을 리턴해 자리를 바꾼다.
이것을 return 할때 직접 적어줘야하는데
localecampare을 쓰면 알아서 해준다

function solution(strings, n) {
    // strings 배열
    // n 번째 문자열 비교
    return strings.sort((s1, s2) => s1[n] === s2[n] ? s1.localeCompare(s2) : s1[n].localeCompare(s2[n]));
}

앞문자와 뒷문자의 n번째 글자가 같다면 localeCompare을 이용하여 위치판별
다른값이면 n번째 글자를 가지고 localeCompare해서 위치변경

문제 5

문자열 내림차순으로 배열하기

// 일단 문자 나누고 대문자 빼기 위해 소문자 대문자 구분
// i번째 글자랑 upper한게 같으면 다른데 넣고 틀리면 또 다른데 넣어서 각각 정렬 한다음 합치기!
console.log(solution("Zbcdefg"))
function solution(s) {
    let arr = s.split('')
    let lower = []
    let upper = []
    for(let i =0; i<arr.length; i++){
        if(arr[i] !== arr[i].toUpperCase()){
            lower.push(arr[i])
        }else{ upper.push(arr[i])}
    }
    lower.sort().reverse()
    upper.sort().reverse()
    console.log(lower)
    let aa = lower.join('')
    let bb = upper.join('')
    
    let answer = aa + bb;
    return answer;
}

맨처음 풀이 과정을 예상한것을 적고 풀어보니 확실이 시간이 단축되었다
이것을 구현할수 있는지 없는지 판별되고 내가 할수 있는건지아닌지 아님 더좋은방법이있는지 찾게된다.
윗걸 짧게 하면 아래와 같다

function solution(s) {
  return s
    .split("")
    .sort()
    .reverse()
    .join("");
}

문자를 배열로 바꾸고(이때 split("")말고 [...s] 방법도 있다) 그걸 배열한후 뒤집고 다시 붙여준다 그럼 끝

문제 6

소수 만들기

function solution(a) {
let mid = []
for(let i =0; i<a.length-2; i++){
    for(let j =1; j<a.length-1; j++){
        for(let k=2; k<a.length; k++){
            if(!mid.includes(a[i]+a[j]+a[k])){mid.push(a[i]+a[j]+a[k])
            }
        }    
    }
}
console.log(mid)
let answer = [] // mid = [6,7,8,9]
for(let h =0; h<mid.length; h++){
    for(let g=2; g<Math.ceil(Math.sqrt(mid[h])); g++){
        if(mid[h]%g === 0){false}
        else{mid[h]>1 && mid[h]%Math.sqrt(mid[h]) ? answer.push(mid[h]) : false
    } 
}}
return answer.length
}

처음 짠 코드 일단 첫 3중 포문을 고쳐야한다

for(let i =0; i<a.length-2; i++){
    for(let j =1; j<a.length-1; j++){
        for(let k=2; k<a.length; k++){
            if(!mid.includes(a[i]+a[j]+a[k])){mid.push(a[i]+a[j]+a[k])

이거가

for(let i =0; i<a.length; i++){
    for(let j =i+1; j<a.length; j++){
        for(let k=j+1; k<a.length; k++){
            mid.push(a[i]+a[j]+a[k])}

이렇게 고쳐야 배열안의 3가지 수를 가지고 가질수 있는 수의 경우를 만든다

for(var i=0;i<nums.length-2;i++){
        for(var j=i+1;j<nums.length-1;j++){
            for(var w=j+1;w<nums.length;w++){
                    //console.log(nums[i]+"/"+nums[j]+"/"+nums[w]);

                    if(primecheck(nums[i]+nums[j]+nums[w])){
                        //console.log(nums[i]+nums[j]+nums[w]);
                        cnt++;
                    }

아래 소수를 판별하는 식

function isPrime(num) {
    for (let i = 2; i <= Math.sqrt(num); i++) {
      if (num % i === 0) return false;
    }
    return num >= 2;
  }

소수의 최대공약수가 Math.sqrt이라고 생각하고 그것보다 작은 수에서 나누어지는지 확인 하는 함수이다.
이건 바뀌면 안된다.
문제를 함수 2개를 써서 푸는것!

function solution(nums) {
    let answer = 0;
    const length = nums.length;
    for (let i = 0; i < length; i++) {
      for (let j = i + 1; j < length; j++) {
        for (let k = j + 1; k < length; k++) {
          const sum = nums[i] + nums[j] + nums[k];
          if (isPrime(sum)) answer += 1;
        }
      }
    }

    return answer;
  }

  function isPrime(num) {
    for (let i = 2; i <= Math.sqrt(num); i++) {
      if (num % i === 0) return false;
    }
    return num >= 2;
  }
profile
2022.08 개발자 시작

0개의 댓글