-
Programmers Lv2) 방금그곡Algorithm/Programmers 2020. 8. 28. 13:42728x90
출처: programmers.co.kr/learn/courses/30/lessons/17683#qna
분류: 카카오 블라인드 2018
접근방식
musicinfos를 이용해 정보를 가공하고 주어진 music이 포함되는지 확인하는 문제입니다.
주의할 점은 # 이 포함되어 있는 음을 처리해주는 일인데요,
단순히 "ABC" 가 포함되어 있는지 확인한다면 "ABC#" 인 경우를 걸러주지 못합니다.이를 체크하기 위해서는 대표적으로 두 가지 방법이 있습니다.
- 토큰화
"ABC#" 를 ["A", "B", "C#"] 와 같이 의미있는 단위로 쪼개서 비교하는 방법입니다. - 치환
이 문제에서 의미있는 음표는 12개 뿐입니다. 따라서 "A#" 과 같은 음을 "a" 와 같이 의미없는 문자로 치환시켜서 해결해줍니다.
저는 토근화를 시키면 배열끼리 비교하는 부분이 까다로울 것 같아서 치환으로 해결했습니다.
해결방법
Parsing
1차적으로 musicinfo를 제가 원하는 정보 형태로 바꾸는 과정이 필요했습니다. 그리고 재생시간만큼 총 재생 된 음악을 만들어줬습니다.
그리고 동시에 포함될 경우 재생시간이 더 긴 것을 선택해야 하기 때문에 재생시간으로 sort 까지 해줬습니다.let parsedInfos = musicinfos .map { info -> (Int, String, String) in let (playTime, title, music) = parseMusic(for: info) let replacedMusic = replaceSharp(music: music) let playedMusic = repeatMusic(playTime: playTime, music: replacedMusic) return (playTime, title, playedMusic) } .sorted { $0.0 > $1.0 }
조금 더 구체적으로 살펴보겠습니다.
"," 를 이용해서 쪼개고 재생 시간을 계산했습니다.
재생 시간은 ":"로 쪼개고 분에 60을 곱해서 초 단위로 변경해줬습니다.func parseMusic(for info: String) -> (Int, String, String) { let parsed = info.split(separator: ",").map { String($0) } let playTime = parseToSecond(parsed[1]) - parseToSecond(parsed[0]) return (playTime, parsed[2], parsed[3]) } func parseToSecond(_ time: String) -> Int { let parsed = time.split(separator: ":").map { Int($0)! } return parsed[0] * 60 + parsed[1] }
재생시간만큼 음악을 반복시켜줬는데요,
재생시간을 음악의 길이로 나눴을 때 몫은 음악의 풀로 반복되어야 하고,
나눈 나머지는 그만큼만 재생되어야 합니다.func repeatMusic(playTime: Int, music: String) -> String { var repeatedMusic = "" let musicTime = music.count repeatedMusic += String(repeating: music, count: (playTime / musicTime)) repeatedMusic += music.dropLast(musicTime - (playTime % musicTime)) return repeatedMusic }
치환
말씀드렸다시피 저는 # 음 처리에 치환을 사용했는데요, 더 스마트한 방법이 있을 것 같으나.. 그냥 replacingOccurrences 을 사용해서 일일히 변경해줬습니다 😅
func replaceSharp(music: String) -> String { var replacedMusic = music replacedMusic = replacedMusic.replacingOccurrences(of: "C#", with: "c") replacedMusic = replacedMusic.replacingOccurrences(of: "D#", with: "d") replacedMusic = replacedMusic.replacingOccurrences(of: "F#", with: "f") replacedMusic = replacedMusic.replacingOccurrences(of: "G#", with: "g") replacedMusic = replacedMusic.replacingOccurrences(of: "A#", with: "a") return replacedMusic }
나머지는 String이 포함되어 있는지 contains 메소드를 사용했고, 일치하는 음악이 없을 때는
(None) 로 꼭 괄호를 포함해서 써주셔야 합니다!!!이제 전체 코드를 보시면 이해되실 것 같습니다 :)
import Foundation func solution(_ m:String, _ musicinfos:[String]) -> String { let m = replaceSharp(music: m) let parsedInfos = musicinfos .map { info -> (Int, String, String) in let (playTime, title, music) = parseMusic(for: info) let replacedMusic = replaceSharp(music: music) let playedMusic = repeatMusic(playTime: playTime, music: replacedMusic) return (playTime, title, playedMusic) } .sorted { $0.0 > $1.0 } for info in parsedInfos { let (_, title, playedMusic) = info if playedMusic.contains(m) { return title } } return "(None)" } func replaceSharp(music: String) -> String { var replacedMusic = music replacedMusic = replacedMusic.replacingOccurrences(of: "C#", with: "c") replacedMusic = replacedMusic.replacingOccurrences(of: "D#", with: "d") replacedMusic = replacedMusic.replacingOccurrences(of: "F#", with: "f") replacedMusic = replacedMusic.replacingOccurrences(of: "G#", with: "g") replacedMusic = replacedMusic.replacingOccurrences(of: "A#", with: "a") return replacedMusic } func parseMusic(for info: String) -> (Int, String, String) { let parsed = info.split(separator: ",").map { String($0) } let playTime = parseToSecond(parsed[1]) - parseToSecond(parsed[0]) return (playTime, parsed[2], parsed[3]) } func parseToSecond(_ time: String) -> Int { let parsed = time.split(separator: ":").map { Int($0)! } return parsed[0] * 60 + parsed[1] } func repeatMusic(playTime: Int, music: String) -> String { var repeatedMusic = "" let musicTime = music.count repeatedMusic += String(repeating: music, count: (playTime / musicTime)) repeatedMusic += music.dropLast(musicTime - (playTime % musicTime)) return repeatedMusic }
배운점
# 음을 처리하는 부분에서 막혔었던 문제다.
치환과 토크나이즈.. 메모... ✍️
화이팅!!!
'Algorithm > Programmers' 카테고리의 다른 글
Programmers Lv2) 파일명 정렬 (0) 2020.08.28 Programmers Lv2) 압축 (0) 2020.08.28 Programmers Lv2) 후보키 (0) 2020.08.25 Programmers Lv2) 캐시 (0) 2020.08.24 Programmers Lv3) 방문 길이 (0) 2020.07.10 - 토큰화