ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 항해 99 5기 TIL_9
    항해 99 2022. 1. 18. 22:04

    ▶ Today I Learned

     

    <CS 스터디>

     

    [컴퓨터와 인간의 소통]

     

    우리는 말 소리로도 이야기를 나눌 수 있지만 컴퓨터는 오직 문자로 소통해야한다.

    컴퓨터에게도 문자가 있고 인간에게도 문자가 있다. 하지만 둘은 문자는 통하지 않기에 인간이 컴퓨터 언어를 배워 소통해야 한다.

     

    그렇다면 언어를 담을 곳이 필요하고 컴퓨터에서는 그게 비트가 된다.

    비트에는 0이나 1과 같은 값이 담기지만 사실 기호가 무엇이 되었든 간에 1) Yes or No가 확실히 나뉠 것, 2) 문맥상 의미가 통할 것

    이 두 가지가 잘 지켜진다면 소통에는 지장이 없을 것이다.

     

    [드모르간 법칙]

     

    드모르간 법칙은 A and B 와 Not(Not A or Not B)가 서로 같다는 것이다.

    예를 들어, 철수는 방학이고 겨울이면 스키를 타러간다. 는 명제가 있다.

    철수는 방학이 아니거나 겨울이 아니면 스키를 타러가지 않는다. 방학이나 겨울이어야만 스키를 타러가곤 한다. 말로 해도 같은 게 느껴진다.

    (물론 방학이고 겨울이라고 해서 반드시 스키를 타러가는 것은 아니며 이는 다른 개념으로 다루어볼 문제이다.

    '방학이고 겨울이다'는 '스키를 타러간다'의 필요조건이다. 전제가 성립하더라도 결론이 성립할 수도 있고 아닐 수도 있다.)

     

    방학이다의 Not => 방학이 아니다.

    겨울이다의 Not => 겨울이 아니다.

    ~고(and)의 Not => ~거나(or)

    '스키를 타러간다'라는 전체의 Not => 스키를 타러가지 않는다.

     

     

    <알고리즘 기초>

     

    [자연수 뒤집어 배열로 만들기]

     

    https://programmers.co.kr/learn/courses/30/lessons/12932

    소요시간: 1시간 7분

     

    처음 짠 코드

    function solution(n) {
    
        let arr = n.toString().split("").sort((a, b) => b - a)
        return arr.map((v, i) => arr[i] = arr[i]/1)
     // 숫자를 문자열로 바꾼 다음 배열로 쪼개서 오름차순으로 정렬하고 그것을 다시 문자화하는 과정
    }

    그간 배웠던 기능들을 알차게 넣어보았다.

    보기 테스트 케이스는 당연 성공!

    그러나 다른 테스트 케이스에서 막혔다.

    왜냐하면 n이 두 자리 이상 자연수라면 결과 값이 10, 9 .. 가아니라 9... 1, 0 과 같은 식으로 뒤엉켜버리기 때문이다.

    그렇담 sort()를 쓰지 않고 다른 방법으로 값을 뒤바꿔 봐야겠다.

     

    제출한 코드

    function solution(n) {
    
    let arr = n.toString().split('')
    let a = "";
    let i = 0;
    
    
    for (i ; i < Math.floor(arr.length/2) ; i++) {
    // n의 길이가 만약 홀수라면 소수점을 내림해버린다.
    	ex) n = 12345
    	i < 2.5가 되어버리면 arr[2], 즉, 값의 중간위치에 있는 것 까지 바꾸는 작업을 하게 됨
        => 소수점 버려야 함.
    
        a = arr[i] // arr[0] 값 하나 임시보관
        arr[i] = arr[arr.length-1-i] //arr[끝 인덱스]값이 arr[0]에 들어감
        arr[arr.length-1-i] = a // arr[0]값을 arr[끝 인덱스]에 넣어줌
        // 이렇게 두 값이 교환됨
    }
    
    let answer = arr.map((v, i) => arr[i] = arr[i]/1) // 문자열 배열이었던 것을 숫자 배열로 재출력
        return answer;
    
    }

    ㅎㅎ 깔끔하게 짜서 뿌듯하다.

     

    다른 구조의 풀이법도 있을까?

     

    프로그래머스 모범답안

    function solution(n) {
        // 문자풀이
        // return (n+"").split("").reverse().map(v => parseInt(v));
    		숫자를 문자열로 만들고 배열로 쪼갠 다음 순서를 뒤집어서 각각의 값들을 다시 숫자로 바꿔줌
    
        // 숫자풀이
        var arr = [];
    
        do {
            arr.push(n%10); // 10의 나머지를 하나씩 넣어줌
            n = Math.floor(n/10); 넣어준 숫자를 소수점으로 만들어버리고 내림해서 숫자 날아감
        } while (n>0); // 위 작업이 마무리될 때 까지
    
        return arr;
    }

    n은 어차피 자연수이기때문에 1이상의 정수밖에 나올 수 없다.

    즉 앞자리에 0이 올리는 없고 오더라도 중간이나 뒤에만 오기 때문에 10으로 나눈 후 소수점 뒤를 제거해도 문제가 없다.

    n이 모두 이동되었을 때 arr가 반환된다..

    천재들...

     

    그 외 많이들 사용했을 parseInt()는 문자열을 정수로 바꾸어주는 함수이다.

    parseInt(string, radix)

    이것이 기본 형태이며 radix는 선택 값이다. 공식문서에서는 비워뒀을 때 디폴트 값이 10이 아니라고 하지만 다른 블로그들에서 보면

    디폴트가 10이라고 나와 있다. 몇 진법이냐를 써주는 공간으로 보인다.

    +

    공식문서를 한 번 더보니 이런 설명이 있었다.

    인풋 문자열이 위의 16진법 예시처럼 0x, 0X로 시작하는 게 아닌 다른 값이라면 radix는 10(10진법)이라고 나와 있다 :)

     

    reverse()는 배열의 요소들 순서를 뒤집어주는 기능이다.

     

     

    [자릿수 더하기]

     

    https://programmers.co.kr/learn/courses/30/lessons/12931

    소요시간: 41분 28초

     

    처음 짠 코드

    function solution(n)
    {
        [...(n + "")].reduce((a, b) => a/1 + b/1)
    }

    하지만 테스트 케이스 하나에서 걸렸다..

    왜지.. 사람들도 보면 내가 걸린 마지막 케이스에서 걸렸다고 하는데..

    문제는 n이 자연수, 즉 1 이상의 정수이기 때문에 위 코드에서 빠뜨릴 부분이 없다..

    n사이나 끝에 0이 들어가도 마찬가지다.

    코드를 구현해본 결과 모두 정상작동한다..그러나 제출 시에는 오류가 나타난다..

    우선은 다른 코드를 짜보자..

     

    function solution(n)
    {
        let arr = (n+"").split("")
    
        let i = 0
        let total = 0
    
        for (i ; i < arr.length ; i++) {
          total += Number(arr[i])
        }
        return total
    }

    이렇게 하니 통과가 되었다. 사실 똑같은 구조의 코드인데 위에껀 왜 안되었는지 의문..

     

    프로그래머스 모범답안

    function solution(n){
        // 쉬운방법
        return (n+"").split("").reduce((acc, curr) => acc + parseInt(curr), 0)
    }
    

     

    내가 푼 것과 비슷하다.

     

    모범답안 (2)

    function solution(n){
        // 문자 풀이
        // return (n+"").split("").reduce((acc, curr) => acc + parseInt(curr), 0)
    
        // 숫자풀이
        var sum = 0;
    
        do {
            sum += n%10;
            n = Math.floor(n/10);
        } while(n > 0);
    
        return sum;
    }

    와.. 사실 앞에서 본 이 구조를 쓸수도 있겠다 생각했는데 진짜였다..! 다음에는 꼭 한번 써 봐야지

     

    [자릿수 더하기]

     

    https://programmers.co.kr/learn/courses/30/lessons/12933

    소요시간: 8분 50초

     

    내가 쓴 코드

    function solution(n) {
        return [...(n+"")].sort((a,b) => b-a).join("")/1
    }

     

    sort()를 쓰지 않고 조금 원시적인 방법으로 풀어본 게 있을까?

     

    function solution(n) {
        var answer = "";
        n = n + "";
        var emptyArray = [];
        for (var i = 0; i < n.length; i++) {
            emptyArray.push(n[i]);
        }
        for (var j = 0; j < emptyArray.length; j++) {
            if (emptyArray[j] < emptyArray[j+1]) {
                var temp = emptyArray[j];
                emptyArray[j] = emptyArray[j+1];
                emptyArray[j+1] = temp;
                j = -1; // 이 부분이 실행되는 건 앞 뒤 값을 따졌을 때 뒷 값이 더 크다 이므로
                // 해당 값들의 순서를 바꾸어주는 것이다. 그러나 내림차순을 할 때는 
               // 한 값의 앞 뒤만 비교하는 것이 아닌 전체를 비교해야 하기 때문에 
               //저렇게 j -1를 주게 되면 맨처음 인덱스인 0부터 비교할 수 있게 되는 것이다..!
            }
        }
        for (var k = 0; k < emptyArray.length; k++) {
            answer += emptyArray[k];
        }
        answer = Number(answer);
        return answer;
    }

     

    답안 중 한 분께서 쓰신 코드이다. 다른 건 시도해봤는데

    앞뒤 값의 크기를 구하는 부분에서 나와 한 가지가 달랐다.

    바로 증감문에 쓰이는 값에 -1을 주는 것이다! 전체의 크기를 비교해서 어떻게 순서대로 넣지 고민했을 때 저렇게 작성하는 것이 가능했다..

    신기... 이렇게 하나 또 배운다 히히 즐거운 코딩 :)

     

     

    [정수의 제곱근 판별]

     

    https://programmers.co.kr/learn/courses/30/lessons/12934

    소요시간: 1시간 30분

     

    처음 쓴 코드

    // 처음 생각한 것은 정수를 1부터 50조까지 나열한 다음 그것들의 제곱을 한 배열을 만들어주고
    // 그들과 비교하는 것, 하지만 연산이 너무 많아 성능 떨어짐
    애초에 제한 사항에 'n은 1이상, 50000000000000 이하인 양의 정수입니다.' 가 있었음
    
    function solution(n) {
    
        let root_num = 1
        while(root_num < n/root_num) { 
        root_num++
        } // root_num와 n/root_num를 비교하면 root_num*root_num 할 때보다
        // 반복 연산의 길이가 확 줄어든다 :3 어차피 n에 제곱근이 있다면 그건 하나 뿐이므로
        // root_num와 n/root_num 가 같거나 root_num가 더 커지는 순간이 올 때 반복문 빠져나오면 됨
    
    	return root_num == n/root_num? (root_num+1)*(root_num+1) : -1
    }

     

    혹시나 더 좋은 코드도 있을까?

     

    모범답안 첫 페이지에 나오는 식들 중 나와 같은 코드는 없었다.. 오 신기.. 나 좀 잘 푼건가 싶어 조금 뿌듯하다 ㅎㅎ

    아! 모범 답안 가장 첫번째 분이 나와 가장 비슷하기는 한데 그분은 나와는 달리 root_num*root_num 와 n을 비교하셔서

    연산의 길이가 훨씬 길다..! 나의 방식대로 하면 50조를 넣어도 제곱근은 700만 정도라서 비교적 양호하다고 할 수 있다!

    성능을 고려하면서 코드를 조금 바꿔본건데 이 정도로 차이가 나다니.. 성능까지 고려한 코드를 짤 수 있도록 차차 시도해보아야 겠다..

     

    코드를 살펴보던 중 댓글에 이런 코드가 있었다.

    return Math.sqrt(n) === parseInt(Math.sqrt(n)) ? (Math.sqrt(n) + 1) ** 2 : -1

     

    생각보다 코드에 Math.sqrt(n)가 있는 경우가 많았는데 저 기능은 무엇일까?

    그것은 바로 숫자의 스퀘어 루트, 즉 해당 숫자의 루트를 반환해주는 함수였다..!

    parseInt()는 정수로 변환해주는 식이기에 소수점이 떨어져 나가게 되고,

    제곱근이 나온 경우에만 소수점이 없을 것이므로 양측이 같을 것이다.

    비교 후 참이면 (루트값 + 1)**2(거듭제곱 연산자, 오른쪽 숫자를 왼쪽 값의 지수로 활용해 제곱을 해줌),

    거짓이면 -1을 반환하는 식이었던 것이다..!

    덕분에 또 새로운 기능을 알았다.

     

    잠깐) parseInt()는 문자열을 정수로 반환해주는 기능 아니었나? Math.sqrt(n)는 숫자인데..?

    https://lngnat.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%A0%95%EC%88%98-%EB%B3%80%ED%99%98-parseInt-%ED%95%A8%EC%88%98-%EC%82%AC%EC%9A%A9-Using-javascript-parseInt-function

    숫자에도 사용할 수 있었다..! 오케이 해결!! ;)

     

     

    ▶ 느낀 점

     

    CS스터디 첫날인데, 이 공부를 매일같이 6주동안이나 하게되면 확실히 기초 지식정도는 잡힐 것 같았다.

    비전공자라 CS에 대한 걱정이 많았는데 이걸 공부하면 컴퓨터에 대해 좀 더 알게 되겠지?? :)

    이전에 컴퓨터 공학 개론과 정보처리기사 필기 공부를 한 적이 있기 때문에 좀 더 빨리 이해할 수도 있지 않을까..?

    라고도 기대해본다. 얼른 또 공부하고 싶다. 정말 좋았다.

     

    알고리즘도 이야기 해보자면 나는 알고리즘을 하면서 논리 향상을 위한 원시적인 코드 하나,

    메서드를 총동원한 효율적인 코드 하나를 짜려는 편이다.

    이것말고 또 어떤 것을 하면 도움이 될까 생각하던 중 오늘 팀원 분이 성능좋은 코드를 짜고 싶다는 이야기를 하셨다.

    생각해보면 세상의 데이터 크기는 어마어마할 것이고 단순반복문처럼 연산이 오래걸리는 코드로만

    문제를 해결하려다 보면 처리 속도가 느려질 수 있다.

    어떤 코드가 성능 좋은 코드인지는 잘 모르지만 차차 알아가면서 성능도 고려한 코드를 짤 수 있도록 해보아야 겠다.

    덧붙여 클린코드도 짜야겠다. 밥먹으며 유튜버 니콜라스님의 영상을 보니 협업을 위해 코드를

    클린하게 짜는 것의 중요성을 알 수 있었다. 위 두 가지 사항을 오늘 새삼 마음 속에 되뇌여 본다.

     

    그래도 오늘도 알고리즘 공부를 열심히 했다 :)

    풀리지 않던 문제도 있었지만 남들과는 조금 다르게, 신박하게 풀어내기도 해서 매우 뿌듯했다.

     

    오늘도 수고많았다, 나 자신. 히히

     

     

    ▶ 공부 시 참고 링크들

     

    https://blog.naver.com/reductionist101/221318832952

     

    충분조건과 필요조건 쉽게 이해하기

    충분조건과 필요조건. 많이 들어본 용어이긴 하지만, 사실 이름만 봐서는 어떤 개념인지 잘 이해가 안 된다...

    blog.naver.com

     

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt

     

    parseInt() - JavaScript | MDN

    The parseInt() function parses a string argument and returns an integer of the specified radix (the base in mathematical numeral systems).

    developer.mozilla.org

     

    https://www.codingfactory.net/11026

     

    JavaScript / 함수 / parseFloat(), parseInt() - 문자열을 수로 바꾸는 함수

    parseFloat() parseFloat()는 문자열을 실수로 바꾸는 함수입니다. 문법 parseFloat( string ) 수로 시작할 때 그 수를 실수로 바꿉니다. 띄어 쓰기로 여러 개의 수가 있으면 첫번째 수만 바꿉니다. 공백으로

    www.codingfactory.net

     

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse

     

    Array.prototype.reverse() - JavaScript | MDN

    The reverse() method reverses an array in place. The first array element becomes the last, and the last array element becomes the first.

    developer.mozilla.org

     

    https://beomy.tistory.com/10

     

    [자바스크립트] 비동기프로그래밍 - 콜백함수(Callback function)

    콜백함수(Callback function) 자바스크립트에서 함수는 객체(object) 입니다. MDS(Mozilla Developer Site)에서는 밑에와 같이 설명하고 있습니다. In JavaScript, functions are first-class objects, because t..

    beomy.tistory.com

     

    https://ko.javascript.info/while-for

     

    while과 for 반복문

     

    ko.javascript.info

    https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Exponentiation

     

    거듭제곱 (**) - JavaScript | MDN

    거듭제곱 연산자(**)는 왼쪽 피연산자를 밑, 오른쪽 피연산자를 지수로 한 값을 구합니다. BigInt도 피연산자로 받을 수 있다는 점을 제외하면 Math.pow()와 같습니다.

    developer.mozilla.org

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sqrt

     

    Math.sqrt() - JavaScript | MDN

    The Math.sqrt() function returns the square root of a number, that is

    developer.mozilla.org

     

    '항해 99' 카테고리의 다른 글

    항해 99 5기 TIL_11  (0) 2022.01.21
    항해 99 5기 TIL_10  (0) 2022.01.19
    항해 99 5기 TIL_8  (0) 2022.01.18
    항해 99 5기 WIL_1  (0) 2022.01.16
    항해 99 5기 TIL_7  (0) 2022.01.16
Designed by Tistory.