본문 바로가기
🐣 알고리즘

[프로그래머스] Swift - 두수의 합(LV.0)

by @Eddy 2023. 5. 31.
728x90

👆문제풀러 가기👆

문제 설명

0 이상의 두 정수가 문자열 a, b로 주어질 때, a + b의 값을 문자열로 return 하는 solution 함수를 작성해 주세요.

 

제한 사항

  • 1 ≤ a의 길이 ≤ 100,000
  • 1 ≤ b의 길이 ≤ 100,000
  • a와 b는 숫자로만 이루어져 있습니다.
  • a와 b는 정수 0이 아니라면 0으로 시작하지 않습니다.

 

입출력 예

a b return
"582" "734" "1316"
"18446744073709551615" "287346502836570928366" "305793246910280479981"
"0" "0" "0"

 


풀이 [ 메모리: 17,817kb, 최대시간: 277.94ms ] - 거친 풀이

import Foundation

func solution(_ a:String, _ b:String) -> String {
    var long = "", short = ""
    
    // 문자열의 길이가 긴 값과 짧은 값 비교
    if a.count >= b.count {
        long = a
        short = b
    } else {
        long = b
        short = a
    }
    
    var sum = 0
    var ten = 0
    var result = ""
    
    for _ in 0..<long.count {       
        if short != "" {
            // 길이가 짧은 문자열과 긴 문자열 합
            sum = Int(String(long.last!))! + Int(String(short.last!))! + ten
            short.removeLast() // 가장 마지막 문자 삭제
        } else {
            // 길이가 긴 문자열
            sum = Int(String(long.last!))! + ten
        }
        long.removeLast() // 가장 마지막 문자 삭제
        
        // 추가 10의자리 수 초기화
        ten = 0
        
        // 문자열의 합이 10이상일 때,
        // 다음 숫자(ten) + 1,
        // 1의 자리 수(sum % 10) 만들기
        if sum >= 10 {
            ten = sum / 10
            sum = sum % 10
        }
        // 현재 자릿수의 값 + 지금까지 계산한 값 
        result = String(sum) + result
    }
    
    // 다음자릿수가 있으면 추가
    if ten != 0 {
        result = String(ten) + result
    }
    
    return result
}

문제는 어렵지 않은데, 다소 귀찮은(?) 문제였다.

Swift라서 LV.0으로 안 느껴지는건지 잘 모르겠지만, 파이썬이라면 그냥 정수로 바꿔서 더하기하면 끝인 것 같은데,(사실 잘 모름)

Swift이기에 문자열 마지막 값을 더해주고, 10의 자리가 생성되면 다음 자릿수에 더해주는 작업을 해줘야했다.

더하기 문제이지만 Int로 표현가능한 수를 넘긴 값을 계산하기 위해 문자열로 계산해야했던 문제.

 

다른 풀이 - 다듬어진 풀이

import Foundation

func solution(_ a:String, _ b:String) -> String {
    var a = a, b = b
    var temp = 0
    var result = ""
    
    while true {
        var sum = temp
        
        // a가 빈문자열이 아니면, 
        // 마지막 숫자를 더하고, 
        // 마지막 숫자 제거
        if a != "" {
            sum += Int(String(a.last!))!
            a.removeLast()
        }
        
        // a와 동일
        if b != "" {
            sum += Int(String(b.last!))!
            b.removeLast()
        }
        
        // 1의 자리의 합의 1의 자리(현재 자릿수) + 이전 계산값 
        result = String(sum % 10) + result
        // 10의 자릿수(다음 자릿수 + 1)
        temp = sum / 10   
        
        // 모든 문자열이 비워지면 종료
        if a == "" && b == "" {
            break
        }
    }
    
    // temp가 남아있으면 추가
    if temp != 0 {
        result = String(temp) + result
    }
    
    return result
}

기존 코드에서 조금 더 다듬어진 코드이다.

a와 b를 한번에 처리하다보니 코드가 지저분했었는데, 분리해서 작성하니 훨씬 깔끔해졌다.

removeLast와 last!를 사용해서 시간이 오래걸린다고 생각할 수 있으나, 두 코드 모두 시간복잡도는 O(1)이라서 큰 영향을 주지 않는다.

다만 강제언래핑이 조금 불편할 수 있는데,

 

단순히 옵셔널 바인딩을 사용하면 된다.

import Foundation

func solution(_ a:String, _ b:String) -> String {
    var a = a, b = b
    var temp = 0
    var result = ""
    
    while true {
        var sum = temp
        
        if a != "" {
            guard let aLast = a.last, 
                  let intA = Int(String(aLast)) else { break }
            sum += intA
            a.removeLast()
        }
        
        if b != "" {
            guard let bLast = b.last,
                  let intB = Int(String(bLast)) else { break }
            sum += intB
            b.removeLast()
        }
        
        result = String(sum % 10) + result
        temp = sum / 10   
        
        if a == "" && b == "" {
            break
        }
    }
    
    if temp != 0 {
        result = String(temp) + result
    }
    
    return result
}

하지만 논리적으로 nil여부를 확인하고 있고, 제시되는 값도 문자열(숫자)만 들어오도록 되어 있기에,

별도의 바인딩은 필요없다는 점만 알아두고 가면 될 것 같다.

반응형

댓글