늦은 프로그래밍 이야기

230109 TIL (SQL, 알고리즘) 본문

내일배움캠프/TIL, WIL

230109 TIL (SQL, 알고리즘)

한정규 2023. 1. 9. 21:58

SQL 강의

이번 주는 SQL 강의를 듣고 공부하는 주차로 오늘은 데이터 조회 파트를 공부하였다. 사전 캠프에서 SQL 기초 강의를 들었는데, 두달 넘게 한번을 안 봤더니 Select와 from 이외는 하나도 생각나지 않았다. 그래도 강의를 들으며 다시 리마인드 하며 예전에 들었던 기억이 새록새록 났는데, 예전에 배우지 않았던 부분도 있는 것 같고 배웠던 것을 배우지 않는 것도 있는 것 같아서 예전에 작성했던 블로그를 하나하나 찾아보며 비교하여 정리를 다시 해야겠다.

 


알고리즘

알고리즘 문제를 최소 하루에 한 문제 이상 풀어보기로 계획하고, 오늘은 프로그래머스 0레벨 문제 중 정답률이 낮은 문제 페이지에 있는 두문제를 풀어 보았다.

옹알이 (1)

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

 

프로그래머스

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

programmers.co.kr

문제를 보고 그동안 알고리즘에서 풀었던 replace 함수를 사용해서 주어진 옹알이들을 빈칸으로 대체해서 모두 빈칸으로 대체되면 해당 원소는 빈칸으로 남기 때문에 원소값이 빈칸인 원소들만 카운트해서 answer에 1씩 더해주는 식으로 하였는데 한가지 문제가 발생하였다.

class Solution {
    public int solution(String[] babbling) {
        int answer = 0;
        for (String b : babbling) {
            b = b.replace("aya", "");
            b = b.replace("ye", "");
            b = b.replace("woo", "");
            b = b.replace("ma", "");
            if (b.equals("")) answer++;
        }
        return answer;
    }

주어진 테스트 케이스 리스트의 [”aya”, “yee”, “u”, “maa”, “wyeoo”] 중 “wyeoo”의 경우 ye가 먼저 replace 되어서 사라지고 남은 woo가 replace 되어서 사라지며 모두 빈칸이 되어서 answer에 카운트 되지 말아야 할 원소임에도 모두 빈칸이 되었으므로 카운트 되어 올라가는 문제가 발생했다.

그래서 다음으로 적용해 본 것은 contains 함수였다. aya, ye, woo, ma가 포함되어 있으면 answer를 하나씩 올려주는 방식으로 코드를 작성했다.

class Solution {
    public int solution(String[] babbling) {
        int answer = 0;
        for (String b : babbling) {
            if (b.contains("aya") answer++;
            if (b.contains("ye") answer++;
            if (b.contains("woo") answer++;
            if (b.contains("ma") answer++;
        }
        return answer;
    }

하지만 테스트 케이스 리스트의 [”aya”, “yee”, “u”, “maa”, “wyeoo”] 2번째, 4번째, 5번째 인덱스에 해당 값이 정확하지 않지만 포함이 되어 있어서 카운트 되어 answer가 올라가는 문제가 발생하여 contains는 사용하지 못할 것 같다.

리스트를 작성해서 해야하나 이런 저런 방법을 생각해보며 고민하다가 한 문제에 너무 시간이 지체되는 것 같아서 질문하기 버튼에 들어가서 사람들의 힌트를 보기로 했는데 자바스크립트를 사용하는 유저가 위의 replace와 동일한 방법으로 풀었고, 같은 문제가 발생하는 것을 빈칸 대신 1을 replace 하여 해당 원소가 숫자인지 확인하는 방법으로 풀었다고 적혀 있었다.

자바도 되는지 확신이 안 들어서 다른 방법을 사용하려 하다가 숫자인지 확인하는 방법이 가장 좋은 것 같아서 구글에 자바 정수 확인하기를 검색하여 자바로 구현하는 방법을 알게 되었다. 방법은 두가지였다.

하나는 ParseInt를 사용하여 해당 문자열을 int로 형 변환하면 숫자 이외의 값이 들어 있으면 NumberFormatException이 발생한다. boolean 타입의 메소드를 구현하여 형 변환이 되면 true를 반환하고 예외가 발생하면 false를 반환하여 모두 1로 대체된 원소만 카운트한다.

public static boolean isInteger(String s) {
    try {
        Integer.parseInt(s);
        return true;
    } catch (NumberFormatException e) {
        return false;
    }
}

public int solution(String[] babbling) {
    int answer = 0;
    for (String b : babbling) {
        b = b.replace("aya", "1");
        b = b.replace("ye", "1");
        b = b.replace("woo", "1");
        b = b.replace("ma", "1");
        if (isInteger(b)) answer++;
    }
    return answer;
}

또 다른 한가지 방법은 정규 표현식을 사용하는 방법이다.

public int solution(String[] babbling) {
    int answer = 0;
    for (String b : babbling) {
        b = b.replace("aya", "1");
        b = b.replace("ye", "1");
        b = b.replace("woo", "1");
        b = b.replace("ma", "1");
        if (b.matches("\\d*")) answer++;
    }
    return answer;
}

답안을 작성하고 다른 사람의 코드를 구경하는데 훨씬 간단하고 직관적으로 보이는 코드가 있었다. 위의 replace를 1로 해준 후 1을 다시 빈칸으로 replace를 해주는 방식인데 왜 문제를 풀 때 이런 것이 생각이 안나는지..

public int solution(String[] babbling) {
    int answer = 0;
    for (String b : babbling) {
        b = b.replace("aya", "1");
        b = b.replace("ye", "1");
        b = b.replace("woo", "1");
        b = b.replace("ma", "1");
        b = b.replace("1", "");
        if (b.equals("")) answer++;
    }
    return answer;
}

처음에 의도했던 빈칸을 이용하여 조건문을 사용해 빈칸인 원소를 카운팅 하는 방식과 1을 replace 먼저 해 줌으로써 카운팅 되지 말아야할 원소를 카운팅 하는 문제도 해결한 방식의 코드이다.

문제를 혼자 끝까지 풀어내지는 못했지만, 처음 공부를 시작할 때 보았던 알고리즘 문제였고, 그때는 아무것도 하지 못하고 어떻게 접근해야 할지 감도 안 잡혔었는데 그래도 어떻게 풀어나가야 할지 방법이 생각나는 것 보니 그때보다는 확실히 실력이 늘은 것 같다. 후발대 강의 학습을 통해 자바 기본 문법도 소홀히 하지 말아야겠다.


문자열 밀기

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

 

프로그래머스

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

programmers.co.kr

이번 문제는 쉽다고 생각했다. 처음에는 문제를 잘못 이해하고 맨 뒤에 있는 문자를 앞으로 끌어오고 나머지를 뒤로 밀어서 원래 문자열(A)와 밀어낸 후 문자열(B)이 같으면 1을 반환, 원래 같으면 0을 반환, 같지 않으면 -1을 반환하는 문제인 줄 알고 풀었다. substring을 사용하여 맨 뒤 문자를 잘라내고 맨 뒤 문자를 제외한 나머지를 잘라내서 맨 뒤 문제와 나머지 문자열을 붙여 넣어주었다.

public int solution(String A, String B) {
    if (A.equals(B)) return 0;
    A = A.substring(A.length() - 1) + A.substring(0, (A.length() - 1));
    if (A.equals(B)) return 1;
    else return -1;
}

테스트 케이스에서는 모두 정답이라서 맞는 줄 알았는데 코드를 실행해보니 거의 다 틀렸다. 다시 읽어보니 뒤에서 끌어오고 밀어낸 횟수를 카운팅 해서 반환하는 문제였던 것이다. 문제를 꼼꼼히 잘 읽어봐야 한다..

public int solution(String A, String B) {
    if (A.equals(B)) return 0;

    int answer = 0;
    for (int i = 0; i < A.length(); i++) {
        answer++;
        A = A.substring(A.length() - 1) + A.substring(0, (A.length() - 1));
        if (A.equals(B)) break;
    }

    if (answer == A.length()) return -1;
    return answer;
}

A와 B가 처음부터 같으면 0을 반환하고 반복문으로 뒤의 문자를 앞으로 계속 가져오면서 answer를 1씩 카운트 하며 A와 B가 같아지면 반복문을 중단한다. answer가 A의 길이와 같아지면 끝까지 A와 B가 같아지지 않았다는 뜻이므로 -1을 반환하고 나머지의 경우는 카운트 횟수만큼의 answer를 반환한다.

위와 같이 작성하고 제출 후 다른 사람의 코드 보기를 하였는데, 아주 짧고 간결한 코드를 보게 되어 한번 분석해 보았다.

public int solution2(String A, String B) {
    String tempB = B.repeat(2);
    return tempB.indexOf(A);
}

A = “hello”를 B = “ohell”로 만들 경우, B를 두번 반복하면 “ohellohell”이 된다. 그 후 tempB에서의 A의 인덱스 위치를 반환하면 1이 된다. A = “abc”, B = “abc”인 경우, B를 두번 반복하면 “abcabc”가 된다. 그 후 tempB에서의 A의 인덱스 위치를 반환하면 0이 된다. 마지막으로 A = “apple”, B = “elppa”인 경우, B를 두번 반복하면 “elppaelppa”가 되고, tempB에서의 A의 인덱스 위치를 찾을 수 없으므로 -1이 반환되는 것 같다.

문제의 제시된 내용만 보면 이 방식이 정확한 정답인 듯 하다. 자바 기본 문법 두가지를 사용하여 짧고 간결하게 코드를 작성하였다. 다른 사람의 코드를 뜯어보며 배우는 것이 많다는 것을 느꼈고, 다시 한번 자바 기본 문법의 중요성을 깨닫는 계기가 되었다.


'내일배움캠프 > TIL, WIL' 카테고리의 다른 글

230112 TIL (n진법 변환, H-Index)  (0) 2023.01.13
230111 TIL (대댓글 기능, 유클리드 호제법)  (1) 2023.01.11
10주차 WIL  (0) 2023.01.09
230106 TIL (KPT 회고)  (0) 2023.01.06
230105 TIL  (0) 2023.01.05
Comments