Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions WEEK03/프로그래머스_[3차] 방금그곡/Oliver.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
func solution(_ m: String, _ musicinfos: [String]) -> String {

// 분 변환
func toMinute(_ time: String) -> Int {
let t = time.split(separator: ":").map { Int($0)! }
return t[0] * 60 + t[1]
}
Comment on lines +4 to +7

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

toMinute 함수에서 Int($0)!를 사용하여 강제 언래핑을 하고 있습니다. 이는 입력값이 항상 "HH:MM" 형식의 유효한 정수임을 가정하지만, 만약 그렇지 않은 경우 런타임 오류를 발생시켜 앱을 중단시킬 수 있습니다. compactMap을 사용하여 옵셔널을 안전하게 해제하고, guard 문으로 배열의 크기를 확인하여 코드를 더 견고하게 만드는 것이 좋습니다.

Suggested change
func toMinute(_ time: String) -> Int {
let t = time.split(separator: ":").map { Int($0)! }
return t[0] * 60 + t[1]
}
func toMinute(_ time: String) -> Int {
let components = time.split(separator: ":").compactMap { Int($0) }
guard components.count == 2 else { return 0 }
return components[0] * 60 + components[1]
}


// 반음처리
func halfStep(_ s: String) -> String {
return s
.replacingOccurrences(of: "C#", with: "c")
.replacingOccurrences(of: "D#", with: "d")
.replacingOccurrences(of: "F#", with: "f")
.replacingOccurrences(of: "G#", with: "g")
.replacingOccurrences(of: "A#", with: "a")
.replacingOccurrences(of: "B#", with: "C")
.replacingOccurrences(of: "E#", with: "F")
}
Comment on lines +10 to +19

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

replacingOccurrences(of:with:)를 연달아 호출하는 방식은 잘 동작하지만, 코드가 길어지고 새로운 치환 규칙을 추가하거나 수정하기 번거로울 수 있습니다. 치환 규칙을 딕셔너리로 정의하고 reduce를 사용하면 코드를 더 간결하고 유지보수하기 쉽게 만들 수 있습니다.

    func halfStep(_ s: String) -> String {
        let replacements = [
            "C#": "c", "D#": "d", "F#": "f", "G#": "g", "A#": "a", "B#": "C", "E#": "F"
        ]
        return replacements.reduce(s) { $0.replacingOccurrences(of: $1.key, with: $1.value) }
    }


let goal = halfStep(m)
var result = "(None)"
var maxTime = -1

for info in musicinfos {
let parts = info.split(separator: ",").map { String($0) }
let start = toMinute(parts[0])
let end = toMinute(parts[1])
let playTime = end - start
let title = parts[2]
let melody = Array(halfStep(parts[3]))

if melody.isEmpty { continue }

var played = ""
for i in 0..<playTime {
played.append(melody[i % melody.count])
}
Comment on lines +35 to +38

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

playTime 만큼 반복하면서 한 글자씩 played 문자열을 만드는 방식은 playTime이 클 경우 비효율적일 수 있습니다. Swift의 String은 값 타입이므로 append 할 때마다 새로운 문자열이 생성되고 복사될 수 있기 때문입니다. 멜로디를 필요한 만큼 반복하고 남는 부분을 붙이는 방식으로 더 효율적으로 played 문자열을 생성할 수 있습니다.

        let melodyString = String(melody)
        let repeatedCount = playTime / melody.count
        let remainingCount = playTime % melody.count
        let played = String(repeating: melodyString, count: repeatedCount) + melodyString.prefix(remainingCount)


if played.contains(goal) {
if playTime > maxTime {
maxTime = playTime
result = title
}
}
}

return result
}