티스토리 뷰

문제 - (https://programmers.co.kr/learn/courses/30/lessons/17683)

다른사람 풀이를 보고 현타왔던 문제다...

이 문제를 풀 때 가장 애를 먹었던 것은 C, C#, D, D#, E, F, F#, G, G#, A, A#, B 의 입력이었다.

입력이 쉼표를 제외하고 주어지는데, #이 붙은 문자가 없었다면 그냥 contains를 써서 풀면 됐었다.

하지만 ABC#과 ABC는 엄연히 다른 음계인데 contains를 쓰면 true가 반환된다 ㅠㅠ

그래서 나는 더 깊게 생각안해보고 위에 쉼표로 구분하듯이 리스트에 담는 방법을 선택했다.

ex) 입력 : CC#BCC#BCC#BCC#B

        // 악보 파싱
        ArrayList<String> akbo = new ArrayList<>();
        for (int i = 0; i < m.length(); i++) {
            if (i + 1 < m.length() && m.charAt(i + 1) == '#') {
                akbo.add(m.substring(i, i + 2));
                i++;
            } else
                akbo.add(String.valueOf(m.charAt(i)));
        }

이렇게하면 리스트에는 [C] [C#] [B] [C] [C#] ... [C#] [B] 가 담긴다.

이 코드도 이렇게보면 어렵지 않아보이는데 짤 때 굉장히 시간을 많이 잡아먹었다 ㅠㅠ 왜냐하면

AB#C과 같은 입력은 처음부터 인덱스로 돌다가 현재 인덱스의 다음 문자가 #이면 substring, 아니면 현재 문자를 list에 추가하면 되는데 이런 방법을 쓰면 ABC#은 ArrayOutOfIndex에러가 떠버리거나 [A] [B] [C] [#] 이렇게 저장되어 버릴 수도 있다.

그래서 생각을 하다가 현재 인덱스에 1을 더한 인덱스가 배열의 범위를 벗어나지 않으면서 그 인덱스가 가리키는 문자가 #인 경우에만 substring을 하는 방법을 생각해냈다.

 

하 지 만

많은 사람들이 String의 replace 메소드를 활용하여 풀었다.

현타왔다..

C# 은 c로

D# 은 d로...

바꾼다음에 contains를 쓰셨더라.........

 

다음부턴 효율적으로 풀 수 있는 방법 고민하는 시간을 늘려야겠다


📌주의할 점

  • 시간관련 계산은 시간에 * 60을 함으로써 분과 맞춰서 계산하면 더 편하다!
  • 1, 2개 정도의 연산에 연연하지 말고 큰 그림을 보자... 몇 개의 연산 때문에 문제풀이 시간에 영향이 끼친다면 배보다 배꼽이 큰 경우가 된다 ㅠㅠ 생각하고 조건이 까다로워진다면 최대한 단순하게 생각하자

 


코드

package week4;

import java.util.ArrayList;

/**
 * 9:40
 * 12:13
 * ...하...
 */
public class JustNowSong {

    public String solution(String m, String[] musicinfos) {
        String answer = "";
        int maxPlayTime = 0;

        // 악보 파싱
        ArrayList<String> akbo = new ArrayList<>();
        for (int i = 0; i < m.length(); i++) {
            if (i + 1 < m.length() && m.charAt(i + 1) == '#') {
                akbo.add(m.substring(i, i + 2));
                i++;
            } else
                akbo.add(String.valueOf(m.charAt(i)));
        }

        // musicinfos 파싱하면서 정답구하기
        for (int i = 0; i < musicinfos.length; i++) {
            String[] musicinfo = musicinfos[i].split(",");

            String[] start = musicinfo[0].split(":");
            String[] end = musicinfo[1].split(":");
            String title = musicinfo[2];
            String melody = musicinfo[3];

            int sTime = Integer.parseInt(start[0]) * 60 + Integer.parseInt(start[1]);
            int eTime = Integer.parseInt(end[0]) * 60 + Integer.parseInt(end[1]);
            int playTime = eTime - sTime;

            // melody 파싱
            ArrayList<String> mels = new ArrayList<>();
            for (int j = 0; j < melody.length(); j++) {
                if (j + 1 < melody.length() && melody.charAt(j + 1) == '#') {
                    mels.add(melody.substring(j, j + 2));
                    j++;
                } else {
                    mels.add(String.valueOf(melody.charAt(j)));
                }
            }

            // mels를 이용해서 재생시간동안 재생했을 때 완성되는 악보 만들기
            int melSize = mels.size();
            int restPlaySize = playTime - melSize; // restPlaySize만큼만 더 재생하면 된다

            int k = 0;
            if (restPlaySize > 0) {
                // restPlaySize가 양수이면 restPlaySize만큼 더 재생
                while (k < restPlaySize) {
                    mels.add(mels.get(k++ % melSize));
                }
            } else if (restPlaySize < 0) {
                // restPlaySize가 음수이면 재생된 시간보다 멜로디의 크기가 큰 것이므로
                // 멜로디의 크기를 줄여서 재생시간과 맞춰야 함
                for (int j = playTime; j < mels.size(); j++) {
                    mels.remove(j);
                    j--;
                }
            }

            // 네오가 기억한 악보(akbo)와 재생 후 완성된 악보(mels)를 비교
            // 재생후 완성된 악보보다 네오가 기억한 악보가 더 크다면 해당 곡은 일치하는지 알 수 없음
            for (int l = 0; l < mels.size() - akbo.size() + 1; l++) {
                boolean find = true;
                int lStart = l;
                for (int n = 0; n < akbo.size(); n++) {
                    if (!mels.get(lStart++).equals(akbo.get(n))) {
                        find = false;
                        break;
                    }
                }
                if (find) {
                    // 조건이 일치하는 음악이 여러 개일 때에는 라디오에서 재생된 시간이 제일 긴 음악 제목을 반환한다.
                    // 재생된 시간도 같을 경우 먼저 입력된 음악 제목을 반환한다.
                    if (maxPlayTime < mels.size()) {
                        answer = title;
                        maxPlayTime = mels.size();
                    }
                }
            }
        }

        return answer.length() == 0 ? "(None)" : answer;
    }

    public static void main(String[] args) {
        JustNowSong justNowSong = new JustNowSong();

//        String m = "ABCDEFG";
//        String m = "CC#BCC#BCC#BCC#B";
        String m = "ABCD";
//        String[] musicinfos = {"12:00,12:14,HELLO,CDEFGAB", "13:00,13:05,WORLD,ABCDEF"};
//        String[] musicinfos = {"03:00,03:30,FOO,CC#B", "04:00,04:08,BAR,CC#BCC#BCC#B"};
        String[] musicinfos = {"03:00,03:03,FOO,ABCDE", "04:00,04:08,BAR,CC#BCC#BCC#B"};

        System.out.println(justNowSong.solution(m, musicinfos));
    }
}

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함