1차 공부/WIL

항해 2주차 알고리즘 WIL

공대탈출 2022. 11. 27. 22:36

이번 주차는 알고리즘 주차였다. 그래서 먼저 알고리즘에 관한 WIL을 작성하고, JS의 ES에 대해 알아보고자 한다.

 

풀스택때도 내가 당최 뭘한건지 라는 생각이 들었던 터라 사실 알고리즘 주차에 문제들을 잘 풀수 있을지 걱정이 됐었다.

 

프로그래머스의 알고리즘 풀이를 작성하는 창을 키고 문제를 읽고, 제한사항을 보고, 입출력예를 본 뒤

코드를 작성해야하는데 어떻게 작성해야하는지조차 생각이 나지 않았다.

 

처음 문제는 직사각형 별 찍기였다. 분명 책으로 혼자 공부할때 for문을 사용하여 작성했었는데,

방법이 전혀 떠오르지않아 처음 문제부터 타인의 답안을 보고 코드를 이해하도록 하였다.

 

두번째 문제부터 if문을 사용하기 시작했고, 문제해석이 잘되어 생각보다 막히는 문제가 없이 쭉쭉 풀렸던 것 같다.

여러문제들을 for문과 if문을 사용하다보니 뭔가 불안함이 느껴졌다.

내가 for문과 if문으로 어찌저찌 풀고나서 타인의 답을 보면, reduce()라던지, map()이라던지,

다양한 JS의 메소드를 사용해서 푸는 것이었다.

 

솔직히 자괴감이 들었다.

나는 중첩반복문, 반복문속의 조건문... 등 코드의 길이가 엄청나게 길어지는데,

메소드를 사용해서 한줄, 두줄, 세줄로 간단하게 풀이한 것을 보고 나도 저렇게 될 수 있을까? 라는 생각을 했다.

 

그렇게 알고리즘 모의고사를 보게되었다.

//2번 문제 (몇시간 했더라?)
function solution(arr1, arr2){
	let answer=0;                               //새벽5시 = 29시

    for (let i=0; i<arr1.length; i++) {         
        if (arr2[i]<29) {                       //만약 체크아웃 시간이 새벽5시 이전일때
            answer += arr2[i]-arr1[i]           //체크아웃 시간을 기준으로 공부기록을 남긴다.
        } 
        else {                                //만약 체크아웃 시간이 새벽5시를 포함한 이상일때
            answer += 21-arr1[i]                //21시를 체크아웃 시간으로 삼고, 공부기록을 남긴다.
        }
    }
	return answer;
}
let arr1=[9, 9, 9, 9, 7, 9, 8];
let arr2=[23, 23, 30, 28, 30, 23, 23];
console.log(solution(arr1, arr2))

내가 풀었던 문제는 체크인 시간과 체크아웃시간을 입력받고, 사이의 시간을 합해서 반환하는 것 이었다.

 

Date()메소드를 사용하는 문제는 그때 당시 메소드에 대한 이해가 부족하여 시험문제로는 선택을 하지 않고,

시험을 풀고 와서 공식문서를 찾아보며 풀게 되었다.

//1번 문제 (신대륙 발견)
function solution(month, day){
	let result=""       //98일 후에 수료 / 달은 1~12 일은 1~31 / 2월은 28일 고정
    let year = new Date().getFullYear() //현재 년도 가져오기
    let startday = new Date(year, month-1, day)   //현재년도, 입력된월 일 startday설정
    startday.setDate(startday.getDate()+98)     //시작일로부터 98일 후의 날짜로 startday변경
    let endmonth = startday.getMonth() +1       //startday에서 월을 가져옴
    let enddate = startday.getDate()            //startday에서 일을 가져옴
    result = `${endmonth}월 ${enddate}일`
	return result;
}
console.log(solution(1,18))

 

마지막 문제는 문자열로 입력된 숫자들을 소수인지 아닌지 판별하고,

소수들 중 최댓값과 소수가 아닌 것들 중 최소값을 반환하는 문제였다.

function issosu(x) {        //소수인지 판별해주는 함수
    if (x===2) return true;     //주어진 값이 2라면 소수이므로 true반환
    for(let i=2; i<Math.floor(Math.sqrt(x)); i++) {    //i가 2부터 x-1까지 x를 나누며 소수인지 판별
        if (x%i===0){           //만약 특정 i값에서 나누어 떨어진다면 소수가 아니다.
            return false;       //소수가 아니므로 false반환
        }
    }
    return true;    //for문을 다 할동안 if문에 해당하지 않는다면 true반환
}

function solution(s){
	let answer="";
    let arr = s.split(' ')
    let sosuarr = arr.filter(x=> issosu(x) === true).map(Number)        //소수판별함수를true반환한 값들을 filter하고, Number형식으로 바꿈
    let notsosuarr = arr.filter(x=> issosu(x) === false).map(Number)    //소수판별함수를false반환한 값들을 filter하고, Number형식으로 바꿈
    let minnotsosu = Math.min(...notsosuarr)   //소수가 아닌 수들 중 최솟값 지정
    let maxsosu = Math.max(...sosuarr)         //소수가 맞는 수들 중 최댓값 지정
    answer = `${minnotsosu} ${maxsosu}`         //순서대로 answer에 넣음
	return answer;
}
let s="97 75 88 99 95 92 73";

console.log(solution(s))

위 코드는 다른 분들과 코드리뷰를 하면서 소수판별함수를 고친 것이다.

function issosu(x) {        //소수인지 판별해주는 함수
    if (x===2) return true;     //주어진 값이 2라면 소수이므로 true반환
    for(let i=2; i<x; i++) {    //i가 2부터 x-1까지 x를 나누며 소수인지 판별
        if (x%i===0){           //만약 특정 i값에서 나누어 떨어진다면 소수가 아니다.
            return false;       //소수가 아니므로 false반환
        }
    }
    return true;    //for문을 다 할동안 if문에 해당하지 않는다면 true반환
}

이건 원래 내가 만들었던 소수판별 함수인데, 위에서의 바뀐 함수와 다른점은 판별하는 구간이 절반-1이라는 것이다.

소수에 대한 이해도가 적어 효율성이 떨어지게 작성했던 것 같다.

 

모의고사가 끝나고 또 문제들을 풀었다. 그 중 하나를 소개하고자 한다.

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

위 링크속 문제 였다.

여태껏 코딩을 배우며 배열에 관한 여러 메소드들을 알게되었었는데,

나는 그 중 splice, includes를 사용하려고 했었다.

function solution(participant, completion) {
    var answer = '';
    for (let i =0; i<=completion.length; i++) {
        if (participant.includes(completion[i])===true) {
            participant.splice(participant.indexOf(completion[i]), 1)
        }
    }
    answer = participant.join('')
    return answer;
}

문제에서 주어진 테스트들은 통과를 했지만, 효율성테스트에서 모두 실패하였다.

그 이유를 나중에 알게 되었는데, includes, splice는 for문과 비슷하게 모든 요소들을 검사해 보기 떄문이었다.

위의 코드는 for문 안에 if문속 includes를 지났을 때 splice를 사용하기 때문에, 사실상 3중 for문을 돌리는 것과 같은 것이었다.

그래서 효율성이 떨어진다고 했던 것 같다.

그래서 다시 문제를 읽으며 효율적으로 할 수 있는 방법이 없을까 생각을 해보았다.

주어지는 배열 두개는 같은 값들을 가지고 있지만, 단 한가지만 없는 것이기 때문에 sort메소드를 사용하기로 했다.

function solution(participant, completion) {
    var answer = '';
    participant.sort()  //참여자 배열 정렬
    completion.sort()   //완주자 배열 정렬
    //비교를 위해 최대길이인 참여자의 길이로 설정
    for (let i=0;i<participant.length; i++) {
        //만약 처음으로 값이 같지 않은게 나오면 정렬이 되었으므로
        //처음 나온 곳의 participant요소가 완주하지 못한 사람이다.
        if (participant[i]!==completion[i]) { 
            answer = participant[i] 
            //탈락자를 찾아냈으므로 for문을 마무리하기위해 break를 사용한다.
            break
        }
    }
    return answer;
}

이중, 삼중 for문을 돌리는 것들이 사라지고 간단하게 하나의 for문으로 풀었기 때문에 효율성 검사도 무사히 통과하게되었다.

 

결과적으로 알고리즘 주차때 알게된 것은, 간단한 코드도 좋지만 효율적이고 가독성 좋은 코드가 더 좋다는 것이다.

단순히 메소드만 남발하는 것이아니라, 사용자가 웹에 접속할 때 더빠르게 화면을 그려내고, 타인이 내 코드를 보았을 때 가독성이 좋은 것이 더 좋은 코드라는 것을 알게 되었다.

 

 

 

ES

JavaScript는 10일만에 만들어진 언어이기 때문에 설계미스가 있을 수 밖에 없다.

그래서 지속적으로 업데이트를 하고, 그 것을 나타내는 표준이다.

 

ES5에서 ES6으로 넘어오며 let 과 const키워드가 추가되었다. 이전에는 var로만 사용했다고 한다.

 

Arrow function이 추가되었다.

 

Default Parameter이 추가되었다.

 

Template literal이 추가되었다.

 

Multi-ling string이 추가되었다.

 

클래스가 추가되었다.

 

모듈이 추가되었다.

 

디스트럭처링 할당이 추가되었다.

 

프로미스가 도입되었다.

 

string매서드(includes, startsWith, endsWith)이 추가되었다.

'1차 공부 > WIL' 카테고리의 다른 글

항해 6주차 미니프로젝트  (0) 2022.12.26
항해 5주차 주특기 심화 WIL  (0) 2022.12.18
항해 4주차 주특기 숙련 WIL  (1) 2022.12.13
항해 3주차 주특기 입문 WIL  (0) 2022.12.05
항해 1주차 풀스택프로젝트 WIL  (0) 2022.11.20