ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 손으로 적으면 보이는 것들
    OFF THE RECORD/회고 2023. 12. 30. 17:19

     

    A회사에 지원한 서류가 통과되어서 코딩테스트를 볼 기회가 주어졌습니다.

    가벼운 마음으로 보았고 그런대로 면접은 가지 않을까 했는데 다음 날 바로 탈락ㅎㅎ

     

    문제를 풀면서 확신이 없었던 부분들을 확인차 정리를 해봅니다.

    완전히 동일한 문제를 올리면 이슈가 있을 수도 있어서 조금 각색해서 올려보았습니다.

     

     


     

     

     

    문제1. 별찍기

    자바를 사용해서 콘솔에 아래와 같은 내용이 찍히도록 하세요.

     

    *

    **

    ***

    ****

    ***

    **

    *

    (반복)

     

     

    시험 제출 버전

    (아마 이런 느낌으로 적었던 것 같다)

    public class LogStarts {
    	public static void main(String[] args) {
        	
            int count = 0;
            boolean shouldWorking = true;
            
            while (shouldWorking) {
           	    int targetIndex = getTargetIndex(count);
                String text = createStar(targetIndex);
                System.out.println(text);
            }
        
        }
        
        private getTargetIndex(int count) {
        	final int LOOP = 6;
            final int HALF = 3;
            
            int target = count % LOOP;
            return target > HALF ? LOOP - target : target;
        }
        
        private createStar(int length) {
        	String text = "";
            for (int i = 0; i < length; i++) {
            	text += "*";
            }
            
            return text;
        }
        
     }

     

    일단 실행도 안됬고 결과도 이상하다..

    *
    **
    ***
    **
    *
    
    *
    **
    ***

     

    손코딩이라서 생각지 못했는데 static함수에서 private를 가져다 쓰는 실수도 하고 난리도 아니다.. ㅋㅋㅋ 부끄럽기 그지없다

    집에서 다시 풀어보니까 굳이 O(n^2)으로 풀 필요도 없는 문제였다.

     

     

    다시 풀어본 코드

    public class question1 {
    
      public static void main (String[] args) {
        
        final int CYCLE = 8;
        final int HALF = CYCLE / 2;
        String[] text = { "*", "**", "***", "****", "*****" };
    
        int i = 0;
        while (i < 10) {
    
          int currentIdx = i % CYCLE;
          int targetIdx = currentIdx > HALF ? CYCLE - currentIdx  : currentIdx;
    
          System.out.println(text[targetIdx]);
          i++;
        }
      }
      
    }

     

    CYCLE과 HALF를 두지 않는 건 다른 방법이 떠오르지 않지만 

    동일한 텍스트의 반복이니 미리 선언해두고 찾아다가 호출하는 식으로 변경하여 O(n)으로 변경하였다.

     

     

     


     

     

     

    문제2. 랜덤 알파벳 콘솔 찍기

    자바를 사용해서 콘솔에 중복이 없이 알파벳이 찍히게 작성하세요

     

     

    시험 제출 버전

    (잘 기억은 안나지만, 이것도 static 빼먹었던 것 같고 불필요한 코드들도 들어갔던 것 같다.)

    public class question2 {
    
      public static void main(String[] args) {
        List<Character> alphabets = new ArrayList<>();
        Map<Character, Boolean> history = new Map();
    
        while(alphabets.size() < 5) {
          Character alphabet = randomAlphabet();
          Boolean isPicked = history.get(alphabet);
    
          if (isPicked == null || isPicked == false) {
            alphabets.add(alphabet);
            history.put(alphabet, true);
          }
        }
    
        alphabets.stream().forEach((n) -> System.out.println(n));
      }
    
      private static Character randomAlphabet() {
        Character[] alphabets = {'a', 'b', 'c', 'd', 'e'};
        Random ran = new Random();
        int index = ran.nextInt(5);
        return alphabets[index];
      }
    }

     

     

    다시 풀어본 코드1

    원래 제출한 것과 비슷한 풀이

    public class question2 {
    
      public static void main(String[] args) {
        List<Character> alphabets = new ArrayList<>();
        Map<Character, Boolean> history = new HashMap<>();
    
        while(alphabets.size() < 5) {
          Character alphabet = randomAlphabet();
          Boolean isPicked = history.get(alphabet);
    
          if (isPicked == null) {
            alphabets.add(alphabet);
            history.put(alphabet, true);
          }
        }
    
        alphabets.stream().forEach((n) -> System.out.println(n));
      }
    
      private static Character randomAlphabet() {
        Character[] alphabets = {'a', 'b', 'c', 'd', 'e'};
        Random ran = new Random();
        int index = ran.nextInt(5);
        return alphabets[index];
      }
      
    }

     

    Map 대신에 HashMap을 쓰는게 맞다. 이것도 그냥 손가는대로 쓰다보니 놓쳣던 것 같다.

    그리고 isPicked에서 null만 체크해주면 됬다.

     

    하면서 확신하지 못했던 부분에는 이런 것들이 있었다.

    - Map에서 없는 키를 사용해서 get을 하면 무엇을 반환하는지?

    - String말고 다른 것도 키로 쓸 수 있는지?

     

    => 없는 키를 사용해서 get을 하면 null을 반환하고, String 아닌 것도 키로 당연히 사용 가능하다.

     

     

    다시 풀어본 코드2

    그리고 중복이 없는 것을 원햇을 때는 Set을 사용하는지 보고 싶었던게 아닐까 싶기도하다

    public class question2 {
    
      public static void main(String[] args) {
        Set<Character> alphabets = new HashSet<>();
    
        while (alphabets.size() < 5) {
          alphabets.add(randomAlphabet());
        }
    
        alphabets.stream().forEach((c) -> System.out.println(c));
      }
    
      private static Character randomAlphabet() {
        Character[] alphabets = {'a', 'b', 'c', 'd', 'e'};
        Random ran = new Random();
        int index = ran.nextInt(5);
        return alphabets[index];
      }
      
    }

     

    보통 1번 풀이로 접근하기는 하는데, 2번 풀이도 괜찮은 것 같다.

     

     

     


     

     

     

    문제3. 게시글 제목이 'Hello World'인 게시글의 지난 3개월 동안 좋아요 숫자를 구하는 sql 문을 작성하세요.

    또 그에 맞는 ERD도 그려주세요.

     

    이미 여기에 왔을 때 시간은 5분도 안남은 상태였다... 앞에서 적당히 풀고 넘어왔어야됬는데 빠르게 풀지 못했다. 실력이 부족했다

    호다닥 썻던 터라 문제에서 주어진 조건을 만족시키지 못했고, 특히 기간을 조건으로 필터링하는 부분은 내가 할 줄 몰랐다가 봐야할 것 같다.

     

     

    ERD

    지난 3개월 간의 좋아요 목록에서 A게시글에 해당되는 row를 추출하려고 생각했다.

    문제를 다시 생각하다 보니 당일에 완전 잘못 접근했다는 생각이 드는군요.

     

     

    SQL

    테이블 세팅하고 더미 데이터를 넣습니다.

    use derd;
    
    CREATE TABLE IF NOT EXISTS users(
    	user_id BIGINT AUTO_INCREMENT PRIMARY KEY,
        user_name VARCHAR(50) NOT NULL
    );
    
    CREATE TABLE IF NOT EXISTS posts(
    	post_id BIGINT AUTO_INCREMENT PRIMARY KEY,
        post_title VARCHAR(100) NOT NULL,
        author_id BIGINT NOT NULL,
        FOREIGN KEY (author_id) REFERENCES users(user_id)
    );
    
    CREATE TABLE IF NOT EXISTS likes(
    	like_id BIGINT AUTO_INCREMENT PRIMARY KEY,
    	user_id BIGINT NOT NULL,
        post_id BIGINT NOT NULL,
        created_at DATETIME default CURRENT_TIMESTAMP,
        FOREIGN KEY (user_id) REFERENCES users(user_id),
        FOREIGN KEY (post_id) REFERENCES posts(post_id)
    );
    
    INSERT INTO users VALUES (1, 'sam');
    INSERT INTO users VALUES (2, 'ariana');
    INSERT INTO users VALUES (3, 'ad');
    INSERT INTO users VALUES (4, 'mariah');
    INSERT INTO users VALUES (5, 'sia');
    INSERT INTO users VALUES (6, 'cardi');
    INSERT INTO users VALUES (7, 'bruno');
    INSERT INTO users VALUES (8, 'justin');
    INSERT INTO users VALUES (9, 'tailor');
    
    INSERT INTO posts VALUES (1, 'Hi World', 1);
    INSERT INTO posts VALUES (2, 'Hello World', 2);
    
    INSERT INTO likes values (1, 1, 1, now());
    INSERT INTO likes values (2, 2, 1, now());
    INSERT INTO likes values (3, 3, 1, now());
    INSERT INTO likes values (4, 4, 2, now());
    INSERT INTO likes values (5, 5, 2, now());
    INSERT INTO likes values (6, 6, 2, '2000-10-10');
    INSERT INTO likes values (7, 7, 2, '2010-10-10');
    INSERT INTO likes values (8, 8, 2, '2023-9-10');

     

    찾아야 하는 조건은 아래와 같습니다.

    - 게시글 제목은 'Hello World'

    - 해당 게시글의 좋아요

    - 위의 데이터의 count

    - 그 중에서 5년 이내의 데이터

     

    -- step1) 게시글 제목은 'Hello World'
    select * from posts where post_name = 'Hello World';
    
    
    -- step2) 해당 게시글의 좋아요
    select * from posts p 
        inner join likes l on p.post_id = l.post_id 
        where p.post_title = 'Hello World';
        
        
    -- step3) 해당 게시글의 count
    select p.post_id, count(*) like_count from posts p
        inner join likes l on p.post_id = l.post_id
        where p.post_title = 'Hello World'
        group by p.post_id;
        
        
    -- step4) 이 중에서 최근 3년의 데이터
    select p.post_id, count(*) like_count from posts p
        inner join likes l on p.post_id = l.post_id
        where p.post_title = 'Hello World'
        and l.created_at > '2018-01-01'
        group by p.post_id;
        
        
    -- step5) 
    -- 함수를 사용한 개선1
    select p.post_id, count(*) like_count from posts p
        inner join likes l on p.post_id = l.post_id
        where p.post_title = 'Hello World'
        and l.created_at > now() - interval 5 YEAR
        group by p.post_id;
     
    -- 함수를 사용한 개선2
    select p.post_id, count(*) like_count from posts p
        inner join likes l on p.post_id = l.post_id
        where p.post_title = 'Hello World'
        and l.created_at > date_sub(now(), interval 5 YEAR)
        group by p.post_id;

     

    특정 기간을 이용해서 필터를 해야되면 생성일이나 변경일을 기준으로 >, < 등의 연산을 해주면 된다.

    orm이랑 gpt를 자꾸 쓰다보니까 손에 익지 않는 것 같다.

     

     

     

     


     

    정리하다보니 부족했던 부분을 많이 찾을 수 있었다.

    최소한 동일한 실수는 앞으로 하지 않도록 하자.

Designed by Tistory.