백준, 프로그래머스

[프로그래머스] swift 코딩 기초 트레이닝(0레벨) 3회차

퐁스팡스 2024. 5. 23. 23:52

✅ 1. 주사위 게임2

https://school.programmers.co.kr/learn/courses/30/lessons/181930

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

🎃 나의 풀이

func solution(_ a:Int, _ b:Int, _ c:Int) -> Int {
    var result : Int = 0
    if(a == b && b == c){
        let sum1 = a + b + c
        let sum2 = a * a + b * b + c * c
        let sum3 = a * a * a + b * b * b + c * c * c
        result = sum1 * sum2 * sum3
    }
    else if(a == b || a == c || b == c){
        let sum1 = a + b + c
        let sum2 = a * a + b * b + c * c
        result = sum1 * sum2
    }
    else{
        result = a + b + c
    }
    return result
}

3개의 케이스를 모두 조건문으로 작성하였다.

처음에는 한 줄에 계산식을 같이 작성하였는데 오류가 생겼다.

result = (a + b + c) * (a * a + b * b + c * c) * (a * a * a + b * b * b + c * c * c)
// 너무 긴 계산식은 오류가 생길 수 있음
//The compiler is unable to type-check this expression in reasonable time;
//try breaking up the expression into distinct sub-expressions

 

sum1, 2, 3 으로 나눠서 계산하는 이유는 아래의 오류가 나와서 그렇게 하였는데

The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions

뜻을 해석하면, 계산식이 너무 긴 경우 처리하는 시간이 오래 걸리기 때문에 짧게 여러개로 나눠서 계산해야 한다고한다!

그리고 조건문을 더 간결히 할수 있는 방법이 있을거라 생각했는데 역시나 유용한 함수가 있었다..!

 

🏆 모범 풀이

func solution(_ a:Int, _ b:Int, _ c:Int) -> Int {
    let count = Set([a, b, c]).count
    if count == 3 {
        return a + b + c
    } else if count == 2 {
        return (a + b + c) * (a * a + b * b + c * c)
    } else {
        return (a + b + c) * (a * a + b * b + c * c) * (a * a * a + b * b * b + c * c * c)
    }
}

Set함수를 사용하여 중복여부를 판단할 수 있었다.

Set함수는 배열을 집어 넣으면 중복을 제외한 컬렉션을 반환해준다.

 

✅ 2. 원소들의 곱과 합

https://school.programmers.co.kr/learn/courses/30/lessons/181929

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

🎃 나의 풀이

func solution(_ num_list:[Int]) -> Int {
    var sum1 = num_list.reduce(1){ (accumulater, num) in return accumulater * num }
    var sum2 = num_list.reduce(0){(accumulater, num) in return accumulater + num}
    return sum1 < sum2 * sum2 ? 1 : 0
}

reduce를 사용하면 간단하게 구현이 가능했다. 간결하게 잘 작성했다고 생각했지만, 더 좋은 코드는 항상 존재한다.

 

🏆 모범 풀이

func solution(_ num_list:[Int]) -> Int {
    return num_list.reduce(1, *) < Int(pow(Double(num_list.reduce(0, +)), 2)) ? 1 : 0
}

reduce의 클로저 구현하는 부분을 더 짧게 생략이 가능한 거 같다..?

다음에 클로저 경량 문법에 대해 포스팅을 해야겠다.

 

✅ 3. 이어 붙인 수

https://school.programmers.co.kr/learn/courses/30/lessons/181928

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

🎃 나의 풀이

func solution(_ num_list:[Int]) -> Int {
    let (resultEven, resultOdd) = num_list.reduce(("",""))
    {
        result, num in
        if (num % 2 == 0) {
            return (result.0 + String(num), result.1)
        }
        else{
            return (result.0 , result.1 + String(num))
        }
    }
    
    let evenSum = Int((resultEven)) ?? 0
    let oddSum = Int((resultOdd)) ?? 0
    
    return evenSum + oddSum
}

reduce 함수를 연습하기 위해서 reduce를 이용해 풀어보았다. reduce의 인자 값을 튜플로 받으면 복수의 인자값을 반환 받을 수 있다.

쓰면 쓸수록 쓰임새가 대단한 친구

 

🏆 모범 풀이

func solution(_ num_list:[Int]) -> Int {
    let even = Int(num_list.filter { $0 % 2 == 0 }.map { String($0) }.joined())!
    let odd = Int(num_list.filter { $0 % 2 != 0 }.map { String($0) }.joined())!
    return even + odd
}

모범 풀이에서는 filter map을 사용하여 더욱 간결하게 풀어낸 모습이다.

filter 함수는 컬랙션 타입에서 특정 조건을 만족하는 원소들만 추출하는데 사용되는 고차함수이다.

원래 컬렉션을 수정하지 않고 새로운 컬랙션을 반환한다고 한다. 굉장히 유용해 보인다!

 

✅ 4. 마지막 두 원소

https://school.programmers.co.kr/learn/courses/30/lessons/181927

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

🎃 나의 풀이

func solution(_ num_list:[Int]) -> [Int] {
    var result = num_list
    
    let lastElement = num_list[num_list.count - 1]
    let secondElement = num_list[num_list.count - 2]
    
    if(lastElement > secondElement){
        result.append(lastElement - secondElement)
    }
    else{
        result.append(lastElement * 2)
    }
    return result
}

어렵지 않은 문제였지만 알게된것이 많다.

 

1. 함수의 매개변수는 let(상수)처리 되기 때문에 값을 바꿀 수 없다.

    var(변수)로 받아서 처리를 해주어야 한다.

 

2. swift에서는 배열이 가변 배열이다.

   c#에서는 배열은 불변 배열이기 때문에 크기가 정해지면 늘리거나 줄일 수 없었다.

   swift는 가변 배열이기 때문에 append함수를 사용하여 추가, 제거가 가능했다..! (*제거는 Remove함수 사용)

 

🏆 모범 풀이

func solution(_ num_list:[Int]) -> [Int] {
    let prev = num_list[num_list.count-2]
    let last = num_list[num_list.count-1]
    return num_list + [last > prev ? last-prev : last * 2]
}

오잉? 모범 풀이에서 또 알게된 것은 +연산자로도 배열에 원소를 추가할 수 있다는 것이다. 정말 신기하다.

 

✅ 4. 수 조작하기 1

https://school.programmers.co.kr/learn/courses/30/lessons/181926

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

🎃 나의 풀이

func solution(_ n:Int, _ control:String) -> Int {
    var result = n
    
    for i in control{
        switch i{
        case "w":
            result += 1
        case "s":
            result -= 1
        case "d":
            result += 10
        case "a":
            result -= 10
        default: break
        }
    }
    return result
}

평범하게 switch문으로 풀었다.

 

🏆 모범 풀이

unc solution(_ n:Int, _ control:String) -> Int {
    let op: [Character: Int] = ["w": 1, "s": -1, "d": 10, "a": -10]
    return n + control.reduce(0) { $0 + op[$1]! }
}

dictionary와 reduce를 사용하여 간단하게 해결한 모습.. 대단하다.

func solution(_ n: Int, _ control: String) -> Int {
    return control.reduce(n) { acc, c in
        acc + (c == "w" ? 1 : c == "s" ? -1 : c == "d" ? 10 : -10)
    }
}

삼항연산자를 사용할 때 조건을 여러개 사용할 수 있는 거였어..? 더이상 '삼항'연산자 아니잖아요 선생님 ...

 

✅ 5. 수 조작하기 2

https://school.programmers.co.kr/learn/courses/30/lessons/181925

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

🎃 나의 풀이

func solution(_ numLog:[Int]) -> String {
    let dic : [Int: String] = [1:"w",-1:"s",10:"d", -10:"a"]
    
    let result = numLog.enumerated().map{ (index, value) in
        let differce = index > 0 ? value - numLog[index-1] : 0
         return dic[differce] ?? ""
    }.joined()
    
    return result
}

현 기준으로 할 수 있는 최고 복잡함으로 풀어낸 거 같다.

우선 enumerated로 index와 value값을 가져온다.

튜플 배열 값을 map으로 차례로 처리한다.

(현재값 - 이전값)을 딕셔너리에서 문자열로 가져온다.

* 인덱스가 0인 경우에는 예외 처리하여 ""값으로 가져온다.

map으로 반환된 문자 배열을 joined 함수로 하나의 문자열로 가져온다.

 

🏆 모범 풀이

func solution(_ numLog:[Int]) -> String {
    let log: [Int: String] = [1: "w", -1: "s", 10: "d", -10: "a"]
    return (1..<numLog.count).map { log[numLog[$0] - numLog[$0 - 1]]! }.joined()
}

(1..<numLog.count) 범위 연산자map을 조합하여 간결하게 해결된 모습이다.