오늘은 일단 어제 해야 한다고 했던 아이디어의 필수기능을 채우기 시작했다.
생각보다 기능이 이것저것 들어가긴 하지만
내가 낸 아이디어는 혼자 solo로 하려고 헀던 가벼운 느낌이 강했기 때문에
이걸 굳이 5명이서 메인으로 잡고 진행할 볼륨인가? 라는 고민이 생긴다.

다른 아이디어는 재료관리를 하는 페이지인데
핸드폰으로 보통 진행하는게 맞는데 이걸 굳이 웹페이지에 들어와서 이용할 고객이 있을까?
라는 생각을 해보면 이 사이트도 만들기는 이상하다.

물론 CRUD 및 상태관리 등을 연습하기에는 좋은 주제인건 확실하다(그 목적으로 solo 설계했기 때문에)
하지만 너무 빨리 끝나버리면 더 추가할만한 기능도 없는데 애매하지 않나 싶다.

문제를 풀다가 현재 10일 5시가 다 되어가는 시간인데(회고는 예약을 먼저 해두고 항상 자기 전 또는 그날의 공부가 마무리 됐을 때 올린다) 30시간 전쯤 예기했던 추가기능에 대해 작성한 사람이 없었다..

중간에 회의까지 잡혀서 이야기하고 적기로 해놓고 적은 사람이 아무도 없는 부분은 상당히 의아하다.

 

 

 

 

CT(1).Cow Pinball이라는 문제는 일반적 dp와 유사하지만 대각선 위로는 이동하지 못했던 루트와 조금 유사한 느낌이었다. 물론 길찾기라 가능한 가짓수를 더하는 것과 하나만 택하는 차이는 있었다. 해결 코드는 아래와 같다.

let input = `5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5`.split('\n')

for(let i = 0 ; i < input.length ; i++){ // idx 0을 제외한 나머지 배열처리
    if(i < 1){
        input[i] = Number(input[i])
    }
    else{
        input[i] = input[i].split(' ').map(Number)
    }
}

for(let i = 2 ; i <= input[0] ; i++){ // idx 1은 배열의 첫번째라 더할 값이 없어서 통과
    for(let j = 0 ; j < input[i].length ; j++){
        if(j === 0){ // 왼쪽 벽인 경우 바로 위 맨 왼쪽경로에서만 올 수 있다.
            input[i][j] += input[i-1][j]
        } 
        else if(j === input[i].length -1){ //맨 오른쪽일 경우 상단 맨 오른쪽에서만 올 수 있다.
            input[i][j] += input[i-1][j-1]
        }
        else{ // 왼쪽, 오른쪽 위 중 큰 값을 선택
            input[i][j] += Math.max(input[i-1][j-1], input[i-1][j])
        }
    }
}

console.log(Math.max(...input[input[0]])) //맨 마지막 줄에서 가장 큰 값 선택




CT(2).다음 큰 숫자는 for문으로 1씩 더해가며 2진법의 1의 갯수를 비교해줬으나 오답이 좀 많이 나왔다. 왜 그런지 돌려보며 공곰히 생각해보니 n+1이 해당하면 n+1을 체크해주지 않는 문제가 있어 result의 default 값을 n+1로 지정하고 돌리니 통과했다.



CT(3).예산이라는 문제는 sort로 정렬해준 후 작은 값부터 더하다 예산이 초과되기 전까지 진행하면 되는 문제였다.



CT(4).1차 비밀지도라는 문제는 은근히 문자열을 다루는 기술이 필요한데 이진법화, 빈 공간을 대비한 0 문자열 추가, slice이용 등의 방식을 사용했다.
중간에 틀려서 원인을 파악해보니 앞에 0을 더하는 갯수가 내가 생각한 부분이랑 다르게 유동적이었으며 slice도 size가 5가 아니므로 n을 넣어줘야했다.
예산같은 문제보다 주는 점수가 낮다는 것이 이해는 되지 않는다..(2점)
풀이 코드는 아래와 같다.

function solution(n, arr1, arr2) {
    var answer = [];
    let map1 = [] //1번지도 배열화 준비
    let map2 = [] //2번지도 배열화 준비
    for(let i = 0 ; i < n ; i++){
        answer.push(new Array().fill())
        map1.push(('0'.repeat(n)+arr1[i].toString(2)).slice(-n).split('').map(Number)) // 1등의 낮은 숫자를 대비해 앞에 0을 채워주고 2진법화 한 숫자->문자열을 더해준 다음 slcie로 원하는 자릿수만큼 만들고 각자 배열로 쪼개준 후 숫자로 변환시킨다.
        map2.push(('0'.repeat(n)+arr2[i].toString(2)).slice(-n).split('').map(Number)) //위와 같은 작업을 map2에도 해준다.
    }
    for(let i = 0 ; i < n ; i++){
        for(let j = 0 ; j < n ; j++){ //2차원 배열 조회
            if(map1[i][j] === 0 && map2[i][j] === 0){ //둘다 0인 경우 빈공간 push
                answer[i].push(' ')
            }
            else{   //하나라도 1이 있으면 막혔으므로 벽'#' 입력
                answer[i].push('#')
            }
        }
        answer[i] = answer[i].join('') // i단위가 끝나면 배열에 저장(출력요구사항)
    }
    return answer;
}




CT(5).최소직사각형은 가로,세로 중 어떤 부위가 더 길게 할 것인지를 정해 입력값을 정렬한 순서대로 비교하면 쉽게 해결할 수 있다.(max값 갱신)



CT(6).카펫은 내부 노란색을 한겹의 갈색으로 덮는 문제인데 가로 세로의 길이를 구하는 문제였다. 조금 복잡했지만 갈색은 가로*2 + 세로*2 -4라는 규칙을 가지고 있고
노란색은 가로*세로 - 가로*2 -세로*2 +4라는 규칙을 가지고 있기 때문에
이중for문을 통해 해당하는 결과가 나오면 멈추게 하여 완전탐색을 하는 방식으로 해결했다.
조금은 생각해야 하는 문제였는데 점수가 짜다..



CT(7).영어 끝말잇기는 끝말잇기가 제대로 진행되지 않거나 같은 단어를 말할 경우 현재 몇바퀴째 진행중이며 몇번째 사람이 틀렸는지를 출력하는 문제였다.
문자열이 배열로 입력되었기 때문에 현재 입력한 문자를 새로운 배열'arr'에 추가한 후 indexOf로 중복값이 있는지 찾을 수 있었고 이전값의 slice(-1)과 현재값의 [0] idx를 비교해 쉽게 풀 수 있었다.




CT(8).짝지어 제거하기는 13번까지의 테스트케이스가 모두 해결됐지만 효율성 검사는 도대체 몇초를 요구하는지 시간초과가 대부분이었다. 길이가 100만인데 뭘 바라는지는 모르겠다.
일단 정상적인 while문으로 변화가 없을 경우 while을 종료하고 넘겨줬는데
이번에는 split, join을 사용해봐야겠다.
join, split을 사용한 결과 시간초과가 나와버렸다.
저번에 괄호를 지우듯 각자 객체로 0을 할당한 다음 덧셈을 해줘야 할 것 같다.
그것보다는 순차적으로 배열에 넣어준 후 indexOf로 이미 들어온 값이라면 그 값이 제일 마지막에 있는 경우 pop처리를 해주고 그게 아니면 0(실패)을 리턴해주면 될 것 같다.
이 방식으로 처리하자 시간은 엄청 단축되었지만 실패가 많이 나왔다.

같은 느낌이지만 length-1로 최종값을 비교했으나 문제가 생겼다..
스택을 구현해주지 않으면 비효율일 것 같은 느낌이 들었다.

문제는 잘 맞추지만 ms단위로 문제가 해결되는데 시간 초과가 나온다는 부분은 조금 어이가 없다.
return을 if문이 아닌 삼항연산자로 했으나 시간은 더 늘어나버렸다.

결국 해결했다. 처음에 사용한 indexOf가 문제였던 것이었다..
생각해보면 예전에 배웠던 opener/closer와 관련된 문제랑은 다르게 ababababbabababa처럼 중복되는 문자가 계속 들어온다고 하더라도 후반에 해결만 되는 것이었다.
해결 코드는 아래와 같다.

function solution(s){
    let stack = []
    for(let i = 0 ; i < s.length ; i++){
        if(stack.length === 0){
            stack.push(s[i])
        }
        else if(stack[stack.length-1] === s[i]){
            stack.pop()
        }
        else{
            stack.push(s[i])
        }
    }
    
    if(stack.length === 0){
        return 1
    }
    else{
        return 0
    }
}



@CT(9).문자열 내 마음대로 정렬하기는 sort를 이용하면 된다고 간단하게 생각하고 시도했지만 문자열은 ((a,b) => a-b)로 해결되지 않았다. 검색해보니 문자열의 정렬은 sort((a, b) => a < b ? -1 : 1)로 처리해야 사전식으로 된다고 한다.



CT(10).k번째 수는 for문 내부에서 구조분해 할당으로 commands[i]의 값을 a,b,c에 할당해준 후 배열 slice 처리를 해 정렬한 후 결과에 push해서 해결했다.


CT(11).구명보트는 거의 다 해결됐는데 문제가 풀리지 않아 의아했는데 obj[i]%2를 비교해야 하는 부분에서 i%2를 해버렸다. 복잡한 문제일수록 사소한 부분에서 오류가 잘 나올 수 있는 것 같다. 해결 코드는 아래와 같다.

function solution(people, limit) {
    let obj = {}
    let count = 0
    for(let i = 40 ; i <= limit ; i++){ // obj에 0 초기값 설정
        obj[i] = 0
    }
    for(let i = 0 ; i < people.length ; i++){ // obj에 해당 무게 인원 증가
        obj[people[i]]++
    }
    for(let i = 40 ; i <= limit ; i++){ // obj 순회로 무게 0 만들수 있는지 확인하기
        if(obj[i] === 0){ // 현재 해당무게 인원이 없으면 통과
            continue
        }
        else{
            for(let j = limit ; j >= i ; j--){ //i무게가 있는 경우 역순으로 무게 제거할 사람 구해오기
                if(obj[j] === 0 || i+j > limit){ // j가 0명이거나 i+j의 무게가 한도 초과라면 무시
                }
                else if(j === i){ // 만약 너무 내려와서 현재값까지 내려왔다면 count에 /2로 처리해 추가해주기
                     if(obj[i]%2){
                       count += Math.ceil(obj[i]/2) // 홀수인 경우
                        obj[i] = 0
                    }
                    else{
                        count += obj[i]/2  //짝수인 경우
                        obj[i] = 0
                    }
                }
                else{
                    if(obj[i] === 0){ //0이면 통과 ( continue를 굳이 안적어도 else로 하위 처리이기 때문에 지웠다.(오류일 때))
                    }
                    else if(obj[i] < obj[j]){ // obj[i]의 수치만큼 제거하고 종료
                        count += obj[i] //물론 count에는 그 수치만큼 증가시켜줘야한다
                        obj[j] -= obj[i]
                        obj[i] = 0
                    }
                    else{
                        count += obj[j] // obj[i]가 작은 경우이므로 위와 반대
                        obj[i] -= obj[j]
                        obj[j] = 0
                    }
                }
            }
        }
    }

    for(let key in obj){ //처리 후 남은 객체 숫자들 count에 정리해주기
        count += obj[key]
    }
    return count
}



CT(12).N개의 최소공배수는 엄청 쉬운 문제인데 7점이나 받았다.
일반적 최소공배수를 구해주는 문제를 유클리드 호제법을 이용해 반환하는 함수를 만든 후 그 함수에 for문으로 순차적으로 값을 투입해준 결과값을 출력하면 된다.


CT(13).멀리뛰기는 정말 쉬운 dp문제로 피보나치를 구하는 것과 같은 느낌이었다.
-1, -2까지의 경로 가짓수를 더해주는 문제로 2분도 안걸려서 해결했지만 오답이 나와서 상당히 당황했는데 피보나치 하면 %로 %기호를 사용하라는 주의사항을 무시하고 너무 빨리 풀어서 나온 오답이었다. %1234567로 해결됐다.


CT(14).두 개 뽑아서 더하기는 이중 for문에서 i,j의 값이 같지 않은 경우만 arr i,j의 값을 더한 다음 push하고 new Set으로 중복을 없앤다음 sort를 사용해 정렬해 출력했다.


CT(15).예상 대진표도 쉬운 문제였는데 b = (b+1)/2에서 /2를 빼먹고 제출했다..
웃기게도 예시문제는 이걸로 통과가 되어버려서 문제를 즉각적으로 파악하지 못한 것 같다.
문제의 2^n는 무시해도 상관없고 현재의 대진표가 a+1 = b가 되면서 b가 짝수인지 그리고 a<b의 조건으로 시작하는지만 체크해주면 된다.


CT(16).최고의 집합은 예전 수능을 떠올리는 문제였다. 언제나 곱셈의 최댓값은 중앙값들의 곱인 것 처럼 단순한 방식으로 풀 수 있었다.
재귀로 시도해서 모든 경우를 다 넣었지만 시간초과가 걸려 생각해보면 곱셈은 중앙값이고
중앙값으로 넣어서 했으나 내부 값이 만개까지 넘어가서 효율성에서 걸려버렸다.
1ms가 아마 리미트인 것 같은데 상당히 빡빡하다.
결국 for문으로 push를 해주는 것이 아닌 new Array를 사용해보니 시간초과 문제가 해결되었다.


CT(17).2 x n 타일링은 간단한 dp 피보나치 문제였다.
1,1,2,3,5등의 규칙을 가지고 있다.

'회고' 카테고리의 다른 글

[Main-Project 개발일지]-4(추석)  (0) 2022.09.11
[Main-Project 개발일지]-3(추석)  (0) 2022.09.10
[Main-Project 개발일지]-1  (0) 2022.09.08
Pre-Project 개발회고  (2) 2022.09.07
[Pre-Project 개발일지]-13  (0) 2022.09.06

+ Recent posts