본문 바로가기

Algorithm/Algorithm Test

[프로그래머스] 방금그곡 (Java)

카테고리

문자열 처리

나만의 카테고리

문자열 처리

문제 링크

https://programmers.co.kr/learn/courses/30/lessons/17683

 

코딩테스트 연습 - [3차] 방금그곡

방금그곡 라디오를 자주 듣는 네오는 라디오에서 방금 나왔던 음악이 무슨 음악인지 궁금해질 때가 많다. 그럴 때 네오는 다음 포털의 '방금그곡' 서비스를 이용하곤 한다. 방금그곡에서는 TV,

programmers.co.kr

요점

  • 문자열에서 정보를 추출하기
  • ChronoUnit과 DateTimeFormatter를 이용하면 시간 차이를 구할 수 있다
  • Java 11 이상이라면 String.repeat()를 활용하여 반복을 처리할 수 있다
  • char 형을 완벽한 빈 값으로는 선언할 수는 없고 \0 값을 활용해야 한다

참고 지식

  • String.repeat()
  • ChronoUnit, DateTimeFormatter

풀이 (Java)

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;

class Solution {
    public String solution(String m, String[] musicinfos) {
        String answer = "";
        long maxTime = 0l;
        
        for (String musicInfo : musicinfos) {
            String[] splitMusicInfo = musicInfo.split(",");
            
            long diffTime = getDiffTime(splitMusicInfo[0], splitMusicInfo[1]);
        
            String fullMusic = getFullMusicInfo(changeSharp(splitMusicInfo[3]), Long.valueOf(diffTime).intValue());
            if (fullMusic.contains(changeSharp(m))) {
                if (maxTime < diffTime) {
                    maxTime = diffTime;
                    answer = splitMusicInfo[2];
                }
            }
        }
        
        return answer.equals("") ? "(None)" : answer;
    }
    
    private String changeSharp(String str) {
        char[] chars = str.toCharArray();
        
        String returnStr = "";
        char beforeChar = '\0';
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == '#') {
                beforeChar = Character.toLowerCase(beforeChar);
                
                returnStr += beforeChar;
                beforeChar = chars[i];
            } else if (beforeChar != '#') {
                returnStr += beforeChar == '\0' ? "" : beforeChar;
                beforeChar = chars[i];
            } else if (beforeChar == '#') {
                beforeChar = chars[i];
            }
        }
        
        if (beforeChar != '#') returnStr += beforeChar;
        
        return returnStr;
    }
    
    private long getDiffTime(String before, String after) {
        return ChronoUnit.MINUTES.between(
            LocalTime.parse(before, DateTimeFormatter.ofPattern("HH:mm")),
            LocalTime.parse(after, DateTimeFormatter.ofPattern("HH:mm")));
    }
    
    private String getFullMusicInfo(String musicInfo, int diffTime) {
        String fullMusicInfo = "";
        
        fullMusicInfo = fullMusicInfo + musicInfo.repeat(diffTime / musicInfo.length());
        fullMusicInfo = fullMusicInfo + musicInfo.substring(0, diffTime % musicInfo.length());
        
        return fullMusicInfo;
    }
}

코드는 굉장히 난잡합니다. 앞으로 시간 내서 좀 더 좋은 코드로 리펙토링을 해야 할 것 같습니다. 이 문제를 위의 방식대로 풀 때 주의할 점은 두 가지가 있습니다.

  • #이 붙은 문자를 다른 문자로 변경해야 할 텐데 어떻게 변경할지 고민 필요
  • \0으로 char형을 선언해서 사용한다면 이는 문자열에 표시는 안되지만 문자열 길이를 차지한다

#이 붙은 문자를 변경할 때는 처음에는 음계에 없는 다른 문자로 변경하려고 했습니다. 이렇게 하니 if를 너무 많이 써야 했습니다. 그래서 다른 방법으로 소문자로 변경하는 방법을 택했습니다.

 

\0은 문자열에 표시는 안되면서 문자열의 길이는 차지해서 문자열 반복 횟수를 판단하는 로직 (diffTime / musicInfo.length()) 에서 문제가 생겼습니다. 따라서 \0를 사용할 때는 조심히 사용해야 할 것 같습니다.


알고리즘 초보가 정리한 글입니다

더 좋은 방법이나 코드에 대한 코멘트 언제나 환영합니다!

 

 

 

반응형