글 작성에 앞서 본 블로그의 모든 게시글은 블로그 주인의 개발 일지(일기) 형태의 게시글입니다.
정보를 나누는 방식보단, 제가 했던 방식을 공유하는 식의 글이라 읽어도 제대로 이해를 못 하실 수 있거나 더 좋은 다른 방법이 존재할 수 있습니다.
이 점 양해해 주시며 본 블로그의 게시글을 읽어주시면 감사하겠습니다.
안녕하세요 버스트캐넌입니다.
90%도 막히는 게 없어서 (자뻑은.. 아닙니다ㅎ) 정답률 마지노선을 80 퍼로 낮췄습니다.
오늘은 프로그래머스 lv0 정답률 80% 영어가 싫어요 문제를 풀어보겠습니다.
(저도 영어가 싫어서 고른건... 아닐 겁니다.)
문제
문제 설명
- 영어가 싫은 머쓱이는 영어로 표기되어 있는 숫자를 수로 바꾸려고 합니다.
- 문자열 numbers가 매개변수로 주어질 때, numbers를 정수로 바꿔 return 하도록 solution 함수를 완성해 주세요.
제한사항
- numbers는 소문자로만 구성되어 있습니다.
- numbers는 "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" 들이 공백 없이 조합되어 있습니다.
- 1 ≤ numbers의 길이 ≤ 50
- "zero"는 numbers의 맨 앞에 올 수 없습니다.
입출력 예
- numbers = "onetwothreefourfivesixseveneightnine", return = 123456789
- "onetwothreefourfivesixseveneightnine"를 숫자로 바꾼 123456789를 return 합니다.
풀이
import Foundation
func solution(_ numbers:String) -> Int64 {
var result: String = ""
var num = numbers
var a = true
while(a == true) {
if num.prefix(1) == "o" {
result += "1"
let substring = num.dropFirst(3)
num = String(substring)
} else if num.prefix(2) == "tw" {
result += "2"
let substring = num.dropFirst(3)
num = String(substring)
} else if num.prefix(2) == "th" {
result += "3"
let substring = num.dropFirst(5)
num = String(substring)
} else if num.prefix(2) == "fo" {
result += "4"
let substring = num.dropFirst(4)
num = String(substring)
} else if num.prefix(2) == "fi" {
result += "5"
let substring = num.dropFirst(4)
num = String(substring)
} else if num.prefix(2) == "si" {
result += "6"
let substring = num.dropFirst(3)
num = String(substring)
} else if num.prefix(2) == "se" {
result += "7"
let substring = num.dropFirst(5)
num = String(substring)
} else if num.prefix(1) == "e" {
result += "8"
let substring = num.dropFirst(5)
num = String(substring)
} else if num.prefix(1) == "n" {
result += "9"
let substring = num.dropFirst(4)
num = String(substring)
} else if num.prefix(1) == "z" {
result += "0"
let substring = num.dropFirst(4)
num = String(substring)
}
if num == "" {
a = false
}
}
return Int64(result)!
}
기본 개념
prefix(_:)
func prefix(_ maxLength: Int) -> Publishers.Output<Self>
Swift에서 String의 특정 자릿수까지의 문자만 뽑아내는 메서드입니다.
여기서 나온 값은 SubString 타입으로 반환되어, String으로 쓸려면 String()으로 감싸야합니다.
var n: String = "hello"
n.prefix(2) // 문자열 n의 2번째자리까지만 출력
간단한 예시를 들고 왔습니다.
n.prefix(2)를 하게 되면 문자열 n의 첫 번째와 두 번째 문자인 he가 반환됩니다.
SubString
Sub + String이 합쳐진 단어로, 부분 문자열이라고 합니다.
SubString은 String과 같은 String protocol을 준수하고 있지만, 장기저장에는 적합하지 않아, SubString을 이용하고 싶다면, 위에서 언급했듯이 String()으로 감싸주어 String 인스턴스로 변환 후 사용해야 합니다.
dropFirst(_:)
func dropFirst(_ count: Int = 1) -> Publishers.Drop<Self>
주어진 Int 값만큼 앞에서부터 요소(Element)를 제거하고 그 뒤 요소를 반환하는 메서드입니다.
var n: String = "hello"
n.dropFirst(2) // 처음부터 시작해서 두자리 삭제 후 나머지 반환
또 간단한 예시를 들고 왔습니다.
처음 두 글자인 he가 날아가고 llo가 반환되겠네요.
간단히 이론 공부를 하면서 더 알아본 것이 있습니다.
removeFirst(_:)
mutating func removeFirst(_ k: Int)
dropFirst와 비슷하게, Int 값만큼 앞에서부터 요소를 제거합니다.
dropFirst와의 차이점은 removeFirst는 반환을 하지 않습니다.
정확하진 않지만 간단하게 설명하자면, n.dropFist()는 n과, n.dropFirst() 둘 다 자체의 값을 가지고 있지만,
n.removeFirst()는 n값에서 빠지기 때문에, n만 값을 가지고 있다고 생각하시면 편합니다. (다시 한번 말하지만 정확한 비유는 아닙니다)
여담이지만, removeFirst()를 제 풀이에 가져다 쓴다면,
// dropFirst
if num.prefix(1) == "o" {
result += "1"
let substring = num.dropFirst(3)
num = String(substring)
}
// removeFirst
if num.prefix(1) == "o" {
result += "1"
num.removeFirst(3)
}
이렇게 됩니다.
자세한 설명은 밑에서 하겠습니다.
코드 풀이
우선 저는, String을 Int로 변환? 하는 함수를 몰라서 직접 알고리즘을 짜서 풀어보려고 했습니다.
Dictionary를 이용하여 ["one": 1, "two": 2 ...]를 선언하고, Dictionary의 keys 값과 입력된 변수의 문자열과 같다면 Values로 바꿔주려고 했는데... 그랬는데... 결국에는 실패했습니다.
구현을 해보려 하는데 제가 Dictionary를 깊숙이 해본 적이 없어서 계속 알 수 없는 문법에러가 뜨더라고요.
그래서 생각해 본 것이 입력받은 String을 저장하고 앞자리의 단어가 특정 단어면, 예를 들어 "o"로 시작하는 영어 단어 같은 경우는 one이 유일하니 "o"로 시작한다면, "one"으로 인식하고, 아까 이론에서 살짝 배운 메서드를 사용해서 o, n, e 3글자를 없애고 result에 "1"이라고 집어넣고 마지막에 Int64로 강제 변환해서 반환할 생각이었습니다.
입력된 문자열이 끝날 때까지 while문으로 돌리고, 문자열이 다 끝났으면 while문을 종료시키려고 저렇게 짰습니다 하하
다른 사람 코드 뜯어볼 차례네요.
다른 사람 코드 탐구
import Foundation
var dic = ["zero" : "0", "one": "1", "two": "2", "three": "3", "four": "4", "five": "5",
"six": "6", "seven": "7", "eight": "8", "nine": "9"]
func solution(_ numbers:String) -> Int64 {
var answer = numbers
for (k, v) in dic {
answer = String(answer.replacingOccurrences(of: k, with: v))
}
return Int64(answer)!
}
깔끔하게 Dictonary를 사용하여 코드를 푼 모습입니다.
Dictonary를 다시 따로 공부를 해봐야겠습니다....
그리고 여기서 replacingOccurrences라는 게 쓰였는데 이것도 한번 알아보죠.
기본 개념
replacingOccurrences(of: A, with: B)
String의 제거, 변경을 위한 메서드입니다.
예시를 통해 이해하는 것이 빠를 겁니다.
let num = "onetwo"
let numstr = num.replacingOccurrences(of: "one", with: "1")
print(numstr) // "1two"
"one"이라는 String이 "1"로 변경된 걸 볼 수 있습니다.
let num = "onetwo"
let number = num.replacingOccurrences(of: "one", with: "")
print(number) // "two"
with 부분을 공백으로 두어 삭제하는 것도 가능합니다.
이상 영어가 싫어요 문제를 풀어보았습니다.
포스팅 읽어주셔서 감사합니다.
좋은 하루 보내세요~
궁금한 점이나 지적해야 할 부분이 있으시면 댓글 남겨주세요. 블로그 주인의 상황에 따라 답변이 없을 수 있으나, 최대한 피드백해 드리겠습니다.
'Algorithm > 프로그래머스' 카테고리의 다른 글
[프로그래머스 : 코딩테스트 연습 - Swift] 평균 구하기 (0) | 2023.12.08 |
---|---|
[프로그래머스 : 코딩테스트 연습 - Swift] 원소들의 곱과 합 (0) | 2023.10.25 |
[프로그래머스 : 코딩테스트 연습 - Swift] 문자열안에 문자열 (0) | 2023.10.25 |
[프로그래머스 : 코딩테스트 연습 - Swift] 아이스 아메리카노 (0) | 2023.10.18 |
[프로그래머스 : 코딩테스트 연습 - Swift] 순서쌍의 개수 (2) | 2023.10.13 |