다트 게임
문제 설명
- 다트 3게임에 해당하는 표시를 전달해줄테니 이걸 점수를 계산하라 (ex.1S2D*3T -> 37)
*
이 나오면 지금꺼랑 이전꺼에 X2 , #이 나오면 해당 라운드점수를-
로 수정
문제 풀이
- 이거
import Foundation
func solution(_ dartResult: String) -> Int {
var calcu: [Character: Int] = ["S": 1, "D": 2, "T": 3]
var operator_calcu: [Character: Int] = ["#": -1, "*": 2]
var cur_score = -1
var operator_arr = Array(repeating: 1, count: 3)
var round = [Int]()
var PRIZE = Set(["#", "*"])
var answer = 0
for item in dartResult {
let LEN = round.count // 현재까지 나온 라운드 수
if let num = Int(String(item)) {
cur_score = num
} else {
if PRIZE.contains(String(item)) { // #,* 상일 때
operator_arr[LEN - 1] = operator_calcu[item]!
if item == "*" {
if LEN - 1 > 0 {
operator_arr[LEN - 2] *= 2
}
}
} else { // S , D , T
round.append(Int(pow(Float(cur_score), Float(calcu[item]!))))
}
}
}
print(operator_arr)
print(round)
for i in 0 ..< 3 {
print(round[i] * operator_arr[i])
answer += round[i] * operator_arr[i]
}
return answer
}
// print(solution("1S2D*3T"))
print(solution("1D2S#10S"))
// 1S*2T*3S -> 1 * 2^2 + 2^3 * 2 + 3 = 4+16+3
이거보니까 최대숫자 10일대에 대한 고려가 되지않아서 1, 0 으로 초기화돼서 세번째 라운드 점수가 0이 되어버리는 사태가 발생했다. 이걸 해결하기 위해서는 cur_score 를 문자열로서 붙여줘야할 것 같았다.
먼저 cur_score를 ""로 변경
var cur_score = ""
그리고 숫자가 확정되는 시기에 cur_score를 다시 리셋해주는 로지긍ㄹ 추가했다. 물론 계산할때도 Int()로 씌워줘서 에러뜨지 않게 수정해줬다.
else { // S , D , T round.append(Int(pow(Float(Int(cur_score)!), Float(calcu[item]!)))) cur_score = "" }
최종 제출
import Foundation
func solution(_ dartResult: String) -> Int {
var calcu: [Character: Int] = ["S": 1, "D": 2, "T": 3]
var operator_calcu: [Character: Int] = ["#": -1, "*": 2]
var cur_score = "" as String
var operator_arr = Array(repeating: 1, count: 3)
var round = [Int]()
var PRIZE = Set(["#", "*"])
var answer = 0
for item in dartResult {
let LEN = round.count // 현재까지 나온 라운드 수
if let num = Int(String(item)) {
cur_score += String(num)
} else {
if PRIZE.contains(String(item)) { // #,* 상일 때
operator_arr[LEN - 1] = operator_calcu[item]!
if item == "*" {
if LEN - 1 > 0 {
operator_arr[LEN - 2] *= 2
}
}
} else { // S , D , T
round.append(Int(pow(Float(Int(cur_score)!), Float(calcu[item]!))))
cur_score = ""
}
}
}
for i in 0 ..< 3 {
answer += round[i] * operator_arr[i]
}
return answer
}
채점 결과
정확성: 100.0
합계: 100.0 / 100.0
타인의 코드
스스로 코드가 좀 난잡해진것 같다고 느꼈고, 기존에 없었던
import foundation
까지 작성해서pow()
를 사용했는데, 이걸 사용하지 않고는 어떻게 진행했을까도 궁금해서 모범코드들을 좀 살펴보았다.
func solution(_ dartResult:String) -> Int {
let numberList = dartResult.split(whereSeparator: {$0.isLetter || $0 == "#" || $0 == "*"})
let letterList = dartResult.split(whereSeparator: {$0.isNumber})
var totalScore = 0
for (i, (number, letter)) in zip(numberList, letterList).enumerated() {
var score = 0
if let number = Int(number) {
score = letter.contains("D") ? number * number : letter.contains("T") ? number * number * number : number
}
if letter.contains("*") {
score *= 2
} else if letter.contains("#") {
score = -score
}
if i != 2 {
if letterList[i + 1].contains("*") {
score *= 2
}
}
totalScore += score
}
return totalScore
}
난잡한 코드는 여기서 어떻게 다른가 ?
let numberList = dartResult.split(whereSeparator: {$0.isLetter || $0 == "#" || $0 == "*"}) let letterList = dartResult.split(whereSeparator: {$0.isNumber})
보시다시피 split을 사용했는데, 나는 이게 split하게 되면 원래 마크가 사라지는 것을 걱정했는데, 여기서는 그것대신에
어떻게 pow를 사용하지 않고 풀었나?
최대제곱이 세제곱이라 그냥
number * number * number
까지는 정직하게 작성을 해준 것을 확인했다.
if let number = Int(number) {
score = letter.contains("D") ? number * number : letter.contains("T") ? number * number * number : number
}
예를들어 1D2S#10S
가 들어왔을 때는 다음과 같이 정리가 되는 것이다.
["1", "2", "10"]
["D", "S#", "S"]
숫자+S,D,T
/ #,*
로 구분하려했었는데, 그게 아니라 이렇게 쪼개주면 깔끔하게 상이 없는 곳도 처리가 쉬워진다는 것이다.