• TIL: 알고리즘 스터디 시작

    2023. 6. 2.

    by. Soozinyy

    ✔️ 학습 범위

    • 코드잇 프로그래밍과 데이터 in JavaScript | 3-07~08
    • 알고리즘 스터디_프로그래머스 8문제
    • 웹개발 종합반 3주차

     

     

    📄 오늘 공부한 내용

    ● 코드잇: 문자열과 배열

    let myString = 'Hi Codeit';
    
    // 요소 탐색
    console.log(myString.indexOf('a')); // -1 : 앞부터 탐색
    console.log(myString.lastIndexOf('i')); // 7 : 뒤부터 탐색
    
    // 요소 접근
    console.log(myString[3]); // C : 대괄호 표기법
    console.log(myString.charAt(3)); // C : charAt 메소드
    
    // 문자열 길이
    console.log(myString.length); // 9 : length 프로퍼티
    
    // 부분 문자열 접근 slice(start, end)
    console.log(myString.slice(0, 2)); // Hi
    console.log(myString.slice(3)); // Codeit
    console.log(myString.slice()); // Hi Codeit

    배열을 다룰 때 유용한 for..of문을 문자열에 활용할 수도 있다.

     

    let myString = 'Codeit';
    
    for (let str of myString) {
      console.log(str);
    }
    
    /* 실행 결과
    C
    o
    d
    e
    i
    t
    */

    가장 중요한 차이는 배열은 'mutable(바뀔 수 있는)' 자료형인 반면 문자열은 'immutable(바뀔 수 없는)' 자료형이라는 것.

    // 배열은 mutable
    let myArray = ['C', 'o', 'd', 'e', 'i', 't'];
    myArray[0] = 'B';
    console.log(myArray);
    
    // 문자열은 immutable
    let myString = 'Codeit';
    myString[0] = 'B';
    console.log(myString);
    
    /* 실행 결과
    (6) ["B", "o", "d", "e", "i", "t"]
    Codeit
    */

    문자열이 가진 메소드들은 모두 return 값들을 활용하고, 본래의 문자열 값을 수정하지 않는다. 같은 의미에서 문자열에 splice 같은 메소드들은 사용할 수 없다.

     

     

     

    ● 알고리즘 스터디

    문제1 | 프로그래머스 > 코딩테스트 입문 > 양꼬치

    https://school.programmers.co.kr/learn/courses/30/lessons/120830

     

    나의 풀이

    function solution(n, k) {
        var answer = 0;
    
        answer = n * 12000 + (k - Math.trunc(n / 10)) * 2000
        return answer;
    }

     

    문제2 | 프로그래머스 > 코딩테스트 입문 > 피자 나눠먹기 (1)

    https://school.programmers.co.kr/learn/courses/30/lessons/120814

     

    나의 풀이

    function solution(n) {
        var answer = 0;
        answer = Math.ceil(n / 7)
        return answer;
    }

    다른 분들이 쓴 코드를 보니 굳이 식별자로 지정해주지 않아도 풀이가 가능하였다.

     

    문제3 | 프로그래머스 > 코딩테스트 입문 > 피자 나눠먹기 (3)

    https://school.programmers.co.kr/learn/courses/30/lessons/120816

     

    나의 풀이

    function solution(slice, n) {
        return Math.ceil(n / slice);
    }

    문제2와 비슷해서 배운대로 식별자 지정 과정을 없애보았다.

     

     

    문제4 | 프로그래머스 > 코딩테스트 입문 > 점의 위치 구하기

    https://school.programmers.co.kr/learn/courses/30/lessons/120841

     

    나의 풀이

    function solution(dot) {
        if(dot[0] > 0) {
            return dot[1] > 0 ? 1 : 4;
        } else {
            return dot[1] > 0 ? 2 : 3;
        }
    }

     

    다른사람의 풀이

    function solution(dot) {
        const [num,num2] = dot;
        const check = num * num2 > 0;
        return num > 0 ? (check ? 1 : 4) : (check ? 3 : 2);
    }

     

    문제5 | 프로그래머스 > 코딩테스트 입문 > 아이스 아메리카노

    https://school.programmers.co.kr/learn/courses/30/lessons/120819

     

    나의 풀이

    function solution(money) {
        let answer = [];
        answer.push(Math.floor(money / 5500))
        answer.push(money % 5500)
        return answer;
    }

    다른사람의 풀이

    function solution(money) {
        return [Math.floor(money / 5500), money % 5500];
    }

    식별자로 배열을 정의하거나 .push를 쓰지 않더라도 return문에서 바로 배열을 만들 수 있다는 것을 알게되었다.

     

     

    문제6 | 프로그래머스 > 코딩테스트 입문 > 각도기

    https://school.programmers.co.kr/learn/courses/30/lessons/120829

     

    나의풀이

    function solution(angle) {
        var answer = 0;
        if(0 < angle && angle < 90) {
            answer = 1
        } else if(90 < angle && angle < 180) {
            answer = 3
        } else if(angle === 90) {
            answer = 2
        } else if(angle === 180) {
            answer = 4
        }
        return answer;
    }

     

    다른사람의 풀이

    function solution(angle) {
        switch(angle) {
            case 90: return 2;
            case 180: return 4;
            default:
                return angle > 0 && angle < 90 ? 1 : 3;
        }
    }

    내가 쓴 if문과 별반 다르지 않은 switch문도 생각했지만 이렇게 쓰는 것은 생각하지 못했다. default에서 삼항연산자 사용하기 !

    function solution(angle) {
        return angle < 90 ? 1 : angle === 90 ? 2 : angle < 180 ? 3 : 4;
    }

    깊이감 있는 삼항연산자.

    function solution(angle) {
        return [0, 90, 91, 180].filter(x => angle>=x).length;
    }

    값을 걸러낼 때 쓰는 .filter()는 새로 알게 되었다. 경계값인 [0, 90, 91, 180]에 .filter()로 값을 하나씩 조건식에 대입하여 걸러낸 결과의 배열 길이를 리턴. 앞의 두 가지 풀이는 문법을 알면 생각하기 어렵지 않지만, 이 풀이는 다르다. 이렇게 생각을 다르게 하는 것도 많이 학습해야겠다.

    https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

     

    Array.prototype.filter() - JavaScript | MDN

    filter() 메서드는 주어진 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열로 반환합니다.

    developer.mozilla.org

     

     

    문제7 | 프로그래머스 > 코딩테스트 입문 > 옷가게 할인 받기

    https://school.programmers.co.kr/learn/courses/30/lessons/120818

     

    나의 풀이

    function solution(price) {
        return price >= 500000 ? Math.trunc(price * 0.8) : price >= 300000 ? Math.trunc(price * 0.9) : price >= 100000 ? Math.trunc(price * 0.95) : price;
    }

    문제6에서 배운대로 깊이감 있는 삼항연산자를 사용해보려고 노력(?) 했다. 정답 맞히기까지 7번정도 틀렸다. 세 가지 문제점이 있었는데,

     

    Q1. 조건문의 순서

    Q2. 끝부분을 어떻게 처리하는가?

    Q3. 소수점처리를 간과함

     

    A1. 10만원 조건부터 썼더니 모든 값이 첫번째 true 값으로만 return되어, 거꾸로 범위가 작은 조건을 먼저 작성했다.

    A2. 처음엔 끝부분에 임의의 숫자인 0으로 썼다가 경우의 수를 생각해보니 할인 적용이 안되는 price도 있으니 price 그대로 쓰기로 했다.

    A3. 소수점처리의 경우는 이유를 모른채로 '왜 안되지?' 하고 생각하다가 이럴 땐 항상 소수점이 문제였기 때문에 Math.trunc을 사용하여 정수만 반환해주었다.

     

    다른사람의 풀이

    function solution(price) {
        if (price >= 500000)
            return parseInt(price*(1-0.2));
    
        if (price >= 300000)
            return parseInt(price*(1-0.1));
    
        if (price >= 100000)
            return parseInt(price*(1-0.05));  
    
        return price
    }

    이 풀이도 역시 50만원부터 조건식이 시작된다. 할인율 계산에서 (1 - 할인율)로 처리하는 것이 인상적이다.

     

    const discounts = [
        [500000, 20],
        [300000, 10],
        [100000,  5],
    ]
    
    const solution = (price) => {
        for (const discount of discounts)
            if (price >= discount[0])
                return Math.floor(price - price * discount[1] / 100)
        return price
    }

    주어진 조건을 배열로 만들어서 for문으로 풀이.

     

     

    문제8 | 프로그래머스 > 코딩테스트 입문 > 제곱수 판별하기

    https://school.programmers.co.kr/learn/courses/30/lessons/120909

     

    나의 풀이

    function solution(n) {
        return Math.sqrt(n) % 1 === 0 ? 1 : 2;
    }

    이 문제의 문제점은 두 가지로, 구글링하여 해결하였다.

     

    Q1. 제곱근을 구하는 메서드가 무엇인지 모름

    Q2. 실수와 소수를 판별하는 방법을 모름 (n % 1을 생각했으나 확실치 않아서 바로 검색)

     

    A1. 제곱 또는 제곱근 구하기

    // 제곱 구하기 Math.pow([대상 숫자], [거듭제곱 횟수]);
    Math.pow(2, 10) // 1024
    Math.pow(3, 3) // 27
    Math.pow(5, 6) // 15625
       
    // 제곱급 구하기 Math.sqrt([대상 숫자]);
    Math.sqrt(1024) // 32

     

    A2. 실수와 소수 판별 방법

    // Number.isInteger() 메서드
    Number.isInteger(0);         // true
    Number.isInteger(1);         // true
    Number.isInteger(-100000);   // true
    Number.isInteger(99999999999999999999999); // true
    
    Number.isInteger(0.1);       // false
    Number.isInteger(Math.PI);   // false
    
    Number.isInteger(NaN);       // false
    Number.isInteger(Infinity);  // false
    Number.isInteger(-Infinity); // false
    Number.isInteger('10');      // false
    Number.isInteger(true);      // false
    Number.isInteger(false);     // false
    Number.isInteger([1]);       // false
    
    
    // 나머지 연산자(%) 활용
    let n = 1.234
    console.log(n%1===0); //false 
    
    let c = NaN
    console.log(c%1===0); //false
    
    let a = 3
    console.log(a%1===0); //true

     

    다른사람의 풀이

    function solution(n) {
      return Number.isInteger(Math.sqrt(n)) ? 1 : 2;
    }

    나의 풀이와 실수와 소수 판별 부분만 다른 풀이다.

     

     

     

    웹개발 종합반: 작동원리

    02 python 라이브러리(패키지)로 웹스크래핑하기

    from pymongo import MongoClient
    client = MongoClient('mongodb+srv://url')
    db = client.dbsparta
    
    import requests
    from bs4 import BeautifulSoup
    
    # 가져올 DB 주소
    URL = "https://movie.daum.net/ranking/reservation"
    headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
    data = requests.get(URL, headers=headers)
    soup = BeautifulSoup(data.text, 'html.parser')
    
    # 가져올 DB 위치
    lis = soup.select('#mainContent > div > div.box_ranking > ol > li')
    
    # 가져올 데이터의 class를 활용하여 식별자 지정
    for li in lis:
        rank = li.select_one('.rank_num').text
        title = li.select_one('.link_txt').text
        rate = li.select_one('.txt_grade').text
        
        # DB에 저장할 데이터
        doc = {
            'title':title,
            'rank':rank,
            'rate':rate
        }
        
        # DB의 movies에 저장
        db.movies.insert_one(doc)

     

    03 mongoDB에 스크래핑 결과 저장하기

    from pymongo import MongoClient
    client = MongoClient('mongodb+srv://url')
    db = client.dbsparta
    
    # 저장 - 예시
    doc = {'name':'bobby','age':21}
    db.users.insert_one(doc)
    
    # 한 개 찾기 - 예시
    user = db.users.find_one({'name':'bobby'})
    
    # 여러개 찾기 - 예시 ( _id 값은 제외하고 출력)
    all_users = list(db.users.find({},{'_id':False}))
    
    # 바꾸기 - 예시
    db.users.update_one({'name':'bobby'},{'$set':{'age':19}})
    
    # 지우기 - 예시
    db.users.delete_one({'name':'bobby'})

     

     

    ☁️ 노트

    알고리즘 스터디를 처음 시작했다. 프로그래머스에 있는 다른 사람들의 풀이와 우리 팀원들의 풀이를 보며, 같은 문제라도 다른 풀이 방법도 많다는 것을 알게되었다. 지금껏 코딩테스트 문제는 어쩌다 하루 1~2문제 푸는 것이 고작이었지만 오늘 8문제 풀었더니 이전 문제에서 배운 방법을 바로 사용해 볼 수 있어서 좋았다. 많이 풀다보면 자연스럽게 외워지는 메서드도 생길거라는 기대를 하며...

    댓글