Boot Camp/[우테코] 프리코스

[1주차] on-boarding 미션

계란💕 2022. 11. 1. 12:09

1.  포비, 크롱 책 페이지 펼치기

<hide/>
## 🚀 기능 요구 사항

포비와 크롱이 페이지 번호가 1부터 시작되는 400 페이지의 책을 주웠다. 책을 살펴보니 왼쪽 페이지는 홀수, 오른쪽 페이지는 짝수 번호이고 모든 페이지에는 번호가 적혀있었다. 책이 마음에 든 포비와 크롱은 페이지 번호 게임을 통해 게임에서 이긴 사람이 책을 갖기로 한다. 페이지 번호 게임의 규칙은 아래와 같다.

1. 책을 임의로 펼친다.
2. 왼쪽 페이지 번호의 각 자리 숫자를 모두 더하거나, 모두 곱해 가장 큰 수를 구한다.
3. 오른쪽 페이지 번호의 각 자리 숫자를 모두 더하거나, 모두 곱해 가장 큰 수를 구한다.
4. 2~3 과정에서 가장 큰 수를 본인의 점수로 한다.
5. 점수를 비교해 가장 높은 사람이 게임의 승자가 된다.
6. 시작 면이나 마지막 면이 나오도록 책을 펼치지 않는다.

포비와 크롱이 펼친 페이지가 들어있는 리스트/배열 pobi와 crong이 주어질 때, 포비가 이긴다면 1, 크롱이 이긴다면 2, 무승부는 0, 예외사항은 -1로 return 하도록 solution 메서드를 완성하라.

### 제한사항

- pobi와 crong의 길이는 2이다.
- pobi와 crong에는 [왼쪽 페이지 번호, 오른쪽 페이지 번호]가 순서대로 들어있다.

### 실행 결과 예시

| pobi | crong | result |
| --- | --- | --- |
| [97, 98] | [197, 198] | 0 |
| [131, 132] | [211, 212] | 1 |
| [99, 102] | [211, 212] | -1 |

 

  MySol)

<hide/>
package onboarding;

import java.util.ArrayList;
import java.util.List;

class Practice1 {

    public static int solution(List<Integer> pobi, List<Integer> crong) {
        int answer = Integer.MAX_VALUE;

        if (pobi.get(1) - pobi.get(0) != 1) {
            return -1;
        }
        if (crong.get(1) - crong.get(0) != 1) {
            return -1;
        }

        String pobiLeft = String.valueOf(pobi.get(0));  // 97
        int sum = 0;
        int mul = 1;
        for (int i = 0; i < pobiLeft.length(); ++i) {
            sum += Integer.parseInt(pobiLeft.charAt(i) + "");
            mul *= Integer.parseInt(pobiLeft.charAt(i) + "");
        }
        int maxOfPobi = Math.max(sum, mul);

        String pobiRight = String.valueOf(pobi.get(1));  // 97
        sum = 0;
        mul = 1;
        for (int i = 0; i < pobiRight.length(); ++i) {
            sum += Integer.parseInt(pobiRight.charAt(i) + "");
            mul *= Integer.parseInt(pobiRight.charAt(i) + "");
        }
        maxOfPobi = Math.max(maxOfPobi, Math.max(sum, mul));
//        System.out.println("maxOfPobi " + maxOfPobi);

        String crongLeft = "" + crong.get(0);
        sum = 0;
        mul = 1;
        for (int i = 0; i < crongLeft.length(); ++i) {
            sum += Integer.parseInt(crongLeft.charAt(i) + "");
            mul *= Integer.parseInt(crongLeft.charAt(i) + "");
        }
        int maxOfcrong = Math.max(sum, mul);

        String crongRight = String.valueOf(crong.get(1));
        sum = 0;
        mul = 1;
        for (int i = 0; i < crongRight.length(); ++i) {
            sum += Integer.parseInt(crongRight.charAt(i) + "");
            mul *= Integer.parseInt(crongRight.charAt(i) + "");
        }
        maxOfcrong = Math.max(maxOfcrong, Math.max(sum, mul));
//        System.out.println("maxOfcrong " + maxOfcrong);

        if (maxOfcrong == maxOfPobi) {
            return 0;
        } else if (maxOfPobi > maxOfcrong) {
            return 1;
        } else {
            return 2;
        }
    }

    public static void main(String[] args) {

        List<Integer> pobi = new ArrayList<>();
        pobi.add(97);
        pobi.add(98);
        List<Integer> crong = new ArrayList<>();
        crong.add(197);
        crong.add(198);
        System.out.println(solution(pobi, crong));

        pobi = new ArrayList<>();
        pobi.add(131);
        pobi.add(132);
        crong = new ArrayList<>();
        crong.add(211);
        crong.add(212);
        System.out.println(solution(pobi, crong));

        pobi = new ArrayList<>();
        pobi.add(99);
        pobi.add(102);
        crong = new ArrayList<>();
        crong.add(211);
        crong.add(212);
        System.out.println(solution(pobi, crong));
        
    }
}

 

 


2. 암호문 해독

<hide/>
## 🚀 기능 요구 사항

암호문을 좋아하는 괴짜 개발자 브라운이 이번에는 중복 문자를 이용한 새로운 암호를 만들었다. 예를 들어 "browoanoommnaon"이라는 암호문은 다음과 같은 순서로 해독할 수 있다.

1. "browoanoommnaon"
2. "browoannaon"
3. "browoaaon"
4. "browoon"
5. "brown"

임의의 문자열 cryptogram이 매개변수로 주어질 때, 연속하는 중복 문자들을 삭제한 결과를 return 하도록 solution 메서드를 완성하라.

### 제한사항

- cryptogram은 길이가 1 이상 1000 이하인 문자열이다.
- cryptogram은 알파벳 소문자로만 이루어져 있다.

### 실행 결과 예시

| cryptogram | result |
| --- | --- |
| "browoanoommnaon" | "brown" |
| "zyelleyz" | "" |

 

  MySol)

<hide/>
public class Practice2 {

    public static String solution(String cryptogram) {

        String ans = "";
        char pre = cryptogram.charAt(0);

        Stack<Character> stack = new Stack<>();
        stack.push(pre);

        for (int i = 1; i < cryptogram.length(); ++i) {
            if (cryptogram.charAt(i) == stack.peek()) {
                stack.pop();
            } else {
                stack.push(cryptogram.charAt(i));
            }
        }

        for (int i = 0; i < stack.size(); ++i) {
            ans += stack.get(i);
        }

        return ans;
    }

    public static void main(String[] args) {

        System.out.println(solution("browoanoommnaon"));
        System.out.println(solution("zyelleyz"));

    }
}

 


3. 3 6 9 게임

<hide/>
## 🚀 기능 요구 사항

배달이가 좋아하는 369게임을 하고자 한다. 놀이법은 1부터 숫자를 하나씩 대면서, 3, 6, 9가 들어가는 숫자는 숫자를 말하는 대신 3, 6, 9의 개수만큼 손뼉을 쳐야 한다.

숫자 number가 매개변수로 주어질 때, 1부터 number까지 손뼉을 몇 번 쳐야 하는지 횟수를 return 하도록 solution 메서드를 완성하라.

### 제한사항

- number는 1 이상 10,000 이하인 자연수이다.

### 실행 결과 예시

| number | result |
| --- | --- |
| 13 | 4 |
| 33 | 14 |

 

  MySol)

<hide/>
public class Practice3 {

    public static int solution(int number) {
        int answer = 0;

        for (int i = 1; i <= number; ++i) {
            String tmp = "" + i;
            for (int j = 0; j < tmp.length(); ++j) {
                if (tmp.charAt(j) == '3' || tmp.charAt(j) == '6' || tmp.charAt(j) == '9') {
                    ++answer;
                }
            }
        }

        return answer;
    }

    public static void main(String[] args) {

        System.out.println(solution(13));
        System.out.println(solution(33));

    }
}

 

 

 

4.  청개구리

<hide/>
## 🚀 기능 요구 사항

어느 연못에 엄마 말씀을 좀처럼 듣지 않는 청개구리가 살고 있었다. 청개구리는 엄마가 하는 말은 무엇이든 반대로 말하였다.

엄마 말씀 word가 매개변수로 주어질 때, 아래 청개구리 사전을 참고해 반대로 변환하여 return 하도록 solution 메서드를 완성하라.

| A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Z | Y | X | W | V | U | T | S | R | Q | P | O | N | M | L | K | J | I | H | G | F | E | D | C | B | A |

### 제한사항

- word는 길이가 1 이상 1,000 이하인 문자열이다.
- 알파벳 외의 문자는 변환하지 않는다.
- 알파벳 대문자는 알파벳 대문자로, 알파벳 소문자는 알파벳 소문자로 변환한다.

### 실행 결과 예시

| word | result |
| --- | --- |
| "I love you" | "R olev blf" |

 

  MySol)

<hide/>
public class Practice4 {

    public static String solution(String word) {
        String answer = "";
        for (int i = 0; i < word.length(); ++i) {
            int tmp = 0;
            if ('a' <= word.charAt(i) && word.charAt(i) <= 'z') {
                tmp = 'a' + 'z' - word.charAt(i);
                answer += (char) tmp;

            } else if ('A' <= word.charAt(i) && word.charAt(i) <= 'Z') {
                tmp = 'A' + 'Z' - word.charAt(i);
                answer += (char) tmp;

            }else{
                answer += word.charAt(i);
            }

        }
        return answer;
    }

    public static void main(String[] args) {

        System.out.println(solution("I love you"));

    }
}

 

 

 

5.  화폐 동전 거슬러 주는 배열 출력

<hide/>
## 🚀 기능 요구 사항

계좌에 들어있는 돈 일부를 은행에서 출금하고자 한다. 돈 담을 지갑이 최대한 가볍도록 큰 금액의 화폐 위주로 받는다.

돈의 액수 money가 매개변수로 주어질 때, 오만 원권, 만 원권, 오천 원권, 천 원권, 오백원 동전, 백원 동전, 오십원 동전, 십원 동전, 일원 동전 각 몇 개로 변환되는지 금액이 큰 순서대로 리스트/배열에 담아 return 하도록 solution 메서드를 완성하라.

### 제한사항

- money는 1 이상 1,000,000 이하인 자연수이다.

### 실행 결과 예시

| money | result |
| --- | --- |
| 50237	| [1, 0, 0, 0, 0, 2, 0, 3, 7] |
| 15000	| [0, 1, 1, 0, 0, 0, 0, 0, 0] |

 

  MySol)

<hide/>
public class Practice5 {

    public static List<Integer> solution(int money) {
        List<Integer> answer = new ArrayList<>();
        int[] moneyArr = {50000, 10000, 5000, 1000, 500, 100, 50, 10, 1};

        for (int i = 0; i < moneyArr.length; ++i) {
            int q = money / moneyArr[i];
            answer.add(q);
            money %= moneyArr[i];
        }
        return answer;
    }

    public static void main(String[] args) {

        System.out.println(solution(50237));
        System.out.println(solution(15000));
    }
}

 

 

 

6.  닉네임이 중복 되는 경우의 지원이 이메일 반환

<hide/>
## 🚀 기능 요구 사항

우아한테크코스에서는 교육생(이하 크루) 간 소통 시 닉네임을 사용한다. 간혹 비슷한 닉네임을 정하는 경우가 있는데, 이러할 경우 소통할 때 혼란을 불러일으킬 수 있다.

혼란을 막기 위해 크루들의 닉네임 중 **같은 글자가 연속적으로 포함** 될 경우 해당 닉네임 사용을 제한하려 한다. 이를 위해 같은 글자가 연속적으로 포함되는 닉네임을 신청한 크루들에게 알려주는 시스템을 만들려고 한다.


신청받은 닉네임 중 **같은 글자가 연속적으로 포함** 되는 닉네임을 작성한 지원자의 이메일 목록을 return 하도록 solution 메서드를 완성하라.

### 제한사항

- 두 글자 이상의 문자가 연속적으로 순서에 맞추어 포함되어 있는 경우 중복으로 간주한다.
- 크루는 1명 이상 10,000명 이하이다.
- 이메일은 이메일 형식에 부합하며, 전체 길이는 11자 이상 20자 미만이다.
- 신청할 수 있는 이메일은 `email.com` 도메인으로만 제한한다.
- 닉네임은 한글만 가능하고 전체 길이는 1자 이상 20자 미만이다.
- result는 이메일에 해당하는 부분의 문자열을 오름차순으로 정렬하고 중복은 제거한다.

### 실행 결과 예시

| forms | result |
| --- | --- |
| [ ["jm@email.com", "제이엠"], ["jason@email.com", "제이슨"], ["woniee@email.com", "워니"], ["mj@email.com", "엠제이"], ["nowm@email.com", "이제엠"] ] 
| ["jason@email.com", "jm@email.com", "mj@email.com"] |

 

  MySol)

<hide/>
public class Practice6 {

    static Map<String, Integer> nicknameMap = new HashMap<>();

    public static List<String> solution(List<List<String>> forms) {
        List<String> answer = new ArrayList<>();
        List<List<String>> allNicknameList = new ArrayList<>();

        for (List<String> list : forms) {

            String nickname = list.get(1);
            List<String> nicknameList = nicknameList(nickname);
            allNicknameList.add(nicknameList);
            for (String s : nicknameList) {
                nicknameMap.put(s, nicknameMap.getOrDefault(s, 0) + 1);
            }
        }

        for (int i = 0; i < allNicknameList.size(); ++i) {

            List<String> list = allNicknameList.get(i);
            for (String s : list) {
                int value = nicknameMap.get(s);
                if (value >= 2) {
                    answer.add(forms.get(i).get(0));
                    break;
                }
            }
        }

        Collections.sort(answer);
        return answer;
    }


    public static List<String> nicknameList(String nickname) {

        List<String> list = new ArrayList<>();

        for (int i = 0; i < nickname.length() - 1; ++i) {
            for (int j = i + 2; j <= nickname.length(); ++j) {

                String subStr = nickname.substring(i, j);// ???
                if (!list.contains(subStr)) {
                    list.add(subStr);
                }
            }
        }
        return list;
    }


    public static void main(String[] args) {

        List<List<String>> forms = new ArrayList<>();
        forms.add(List.of("jm@email.com", "제이엠"));
        forms.add(List.of("jason@email.com", "제이슨"));
        forms.add(List.of("woniee@email.com", "워니"));
        forms.add(List.of("mj@email.com", "엠제이"));
        forms.add(List.of("nowm@email.com", "이제엠"));
        System.out.println(solution(forms).toString());
    }
}

 

 

 

7.  SNS 친구 추천

<hide/>
## 🚀 기능 요구 사항

레벨 2의 팀 프로젝트 미션으로 SNS(Social Networking Service)를 만들고자 하는 팀이 있다. 
팀에 속한 크루 중 평소 알고리즘에 관심이 많은 미스터코는 친구 추천 알고리즘을 구현하고자 아래와 같은 규칙을 세웠다.

- 사용자와 함께 아는 친구의 수 = 10점 
- 사용자의 타임 라인에 방문한 횟수 = 1점

사용자 아이디 user와 친구 관계 정보 friends, 사용자 타임 라인 방문 기록 visitors가 매개변수로 주어질 때, 
미스터코의 친구 추천 규칙에 따라 점수가 가장 높은 순으로 정렬하여 최대 5명을 return 하도록 solution 메서드를 완성하라.
이때 추천 점수가 0점인 경우 추천하지 않으며, 추천 점수가 같은 경우는 이름순으로 정렬한다.

### 제한사항

- user는 길이가 1 이상 30 이하인 문자열이다.
- friends는 길이가 1 이상 10,000 이하인 리스트/배열이다.
- friends의 각 원소는 길이가 2인 리스트/배열로 [아이디 A, 아이디 B] 순으로 들어있다.
  - A와 B는 친구라는 의미이다.
  - 아이디는 길이가 1 이상 30 이하인 문자열이다.
- visitors는 길이가 0 이상 10,000 이하인 리스트/배열이다.
- 사용자 아이디는 알파벳 소문자로만 이루어져 있다.
- 동일한 친구 관계가 중복해서 주어지지 않는다.
- 추천할 친구가 없는 경우는 주어지지 않는다.

### 실행 결과 예시

| user | friends | visitors | result |
| --- | --- | --- | --- |
| "mrko" |

[ ["donut", "andole"], ["donut", "jun"], ["donut", "mrko"], ["shakevan", "andole"], ["shakevan", "jun"], ["shakevan", "mrko"] ] | 
["bedi", "bedi", "donut", "bedi", "shakevan"] |
["andole", "jun", "bedi"] |
  • 문제가 너무 이해가 안 가서 고민했다.
  • User와 직접적인 친구 관계 포함이 안되고 간접적으로 중간 친구가 있는 경우에만 10점이 플러스되는 거였다.
  • 그리고 중간 친구가 없는 경우에는 아예 결과에 포함이 안되는건지 되는건지가 모호했다.

 

 

  MySol)

<hide/>package onboarding;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.TreeMap;

public class Practice7_2 {

    public static List<String> solution(String user, List<List<String>> friends,
        List<String> visitors) {

        List<String> answer = new LinkedList<>();
        HashMap<String, List<String>> friendMap = new HashMap<>();
        TreeMap<String, Integer> friendScore = new TreeMap<>();
        int cnt = 0;

        for (List<String> friend : friends) {
            String friend1 = friend.get(0);
            String friend2 = friend.get(1);

            List<String> list1 = friendMap.getOrDefault(friend1, new ArrayList<>());
            List<String> list2 = friendMap.getOrDefault(friend2, new ArrayList<>());

            list1.add(friend2);
            list2.add(friend1);

            friendMap.put(friend1, list1);
            friendMap.put(friend2, list2);
        }

        for (String visitor : visitors) {
            if (!friendMap.get(user).contains(visitor) && !visitor.equals(user)) {
                friendScore.put(visitor, friendScore.getOrDefault(visitor, 0) + 1);
            }
        }

        for (String friend : friendMap.get(user)) {
            List<String> mutual = friendMap.get(friend);
            for (String m : mutual) {
                if (!friendMap.get(user).contains(m) && !m.equals(user)) {
                    friendScore.put(m, friendScore.getOrDefault(m, 0) + 10);
                }

            }
        }

        while (!friendScore.isEmpty() && cnt < 5) {
            int max = Integer.MIN_VALUE;
            String maxFriend = "";
            for (Entry<String, Integer> friend : friendScore.entrySet()) {
                String name = friend.getKey();
                int score = friend.getValue();
                if (score > max) {
                    max = score;
                    maxFriend = name;
                }
            }
            answer.add(maxFriend);
            friendScore.remove(maxFriend);
            cnt++;
        }
        return answer;

    }


    public static void main(String[] args) {

        List<List<String>> friends = new ArrayList<>();
        friends.add(List.of("donut", "andole"));
        friends.add(List.of("donut", "jun"));
        friends.add(List.of("donut", "mrko"));
        friends.add(List.of("shakevan", "andole"));
        friends.add(List.of("shakevan", "jun"));
        friends.add(List.of("shakevan", "mrko"));
        List<String> visitors = new ArrayList<>(
            List.of("bedi", "bedi", "donut", "bedi", "shakevan"));
        System.out.println(solution("mrko", friends, visitors));
        
    }
}

 

 

 

 

미션을 마친 후, 소감

  • 2번, 7번이 특히 어려웠다.
  • 커밋을 문제 마다 넣었는데 다음 부터는 커밋 쪼개는 연습을 해야겠다고 생각했다.
  • 다른 사람들의 PR을 보니까 기능마다 하나씩 커밋 올렸는데 훨씬 가독성이 좋았다.
    • 왜 커밋을 최소 단위로 쪼개라는지 알 것 같았다.

 

'Boot Camp > [우테코] 프리코스' 카테고리의 다른 글

[4주차] bridge 미션  (0) 2022.11.20
[3주차] lotto 미션  (1) 2022.11.16
[2주차] baseball game 미션  (0) 2022.11.09