본문 바로가기

Develop/Coding Test

코딩테스트 입문 (feat. Day 10 수학, 문자열, 해시, 완전탐색, 조건문)

10일차 스탬프

1.  점의 위치 구하기

Q. 사분면은 한 평면을 x축과 y축을 기준으로 나눈 네 부분입니다. 사분면은 아래와 같이 1부터 4까지 번호를매깁니다. x 좌표 (x, y)를 차례대로 담은 정수 배열 dot이 매개변수로 주어집니다. 좌표 dot이 사분면 중 어디에 속하는지 1, 2, 3, 4 중 하나를 return 하도록 solution 함수를 완성해주세요.

func solution(_ dot:[Int]) -> Int {
    return dot[0] > 0 ? dot[1] > 0 ? 1 : 4 : dot[1] > 0 ? 2 : 3
}

 

A. 전달 받은 dot의 x 좌표를 먼저 0보다 큰 지 비교한 후,

크면 y 좌표를 0보다 큰 지 비교하여 크면 1 작으면 4를 반환하고

작으면 y 좌표를 0보다 큰 지 비교하여 크면 2를 작으면 3을 반환하여 해결했다.

2. 2차원으로 만들기

Q. 정수 배열 num_list와 정수 n이 매개변수로 주어집니다. num_list를 다음 설명과 같이 2차원 배열로 바꿔 return하도록 solution 함수를 완성해주세요. num_list가 [1, 2, 3, 4, 5, 6, 7, 8] 로 길이가 8이고 n이 2이므로 num_list를 2 * 4 배열로 다음과 같이 변경합니다. 2차원으로 바꿀 때에는 num_list의 원소들을 앞에서부터 n개씩 나눠 2차원 배열로 변경합니다. 

(num_list의 길이는 n의 배 수개입니다.)

func solution(_ num_list:[Int], _ n:Int) -> [[Int]] {
    var result: [[Int]] = []
    for cnt in 1...num_list.count / n {
        var array: [Int] = []
        for i in 0...n - 1 {
            array.append(num_list[i + ((cnt - 1) * n)])
        }
        result.append(array)
    }
    return result
}

 

A. 전달 받은 num_list를 num_list의 길이를 n으로 나눈 몫만큼 순회하는 반복문 내부에서

0부터 n-1까지 for문으로 순회하면서 num_list의 i + (cnt - 1) * n 번째 값을 array에 추가한 후,

result에 array를 추가하는 작업을 반복한 후 result를 반환하여 해결했다.

3. 공 던지기

Q. 머쓱이는 친구들과 동그랗게 서서 공 던지기 게임을 하고 있습니다. 공은 1번부터 던지며 오른쪽으로 한 명을 건너뛰고 그다음 사람에게만 던질 수 있습니다. 친구들의 번호가 들어있는 정수 배열 numbers와 정수 K가 주어질 때, k번째로 공을 던지는 사람의 번호는 무엇인지 return 하도록 solution 함수를 완성해보세요.

func solution(_ numbers:[Int], _ k:Int) -> Int {
    var result: Int = 0
    (1...k - 1).forEach { _ in
        switch result {
            case numbers.count - 1:
                result = 1
            case numbers.count - 2:
                result = 0
            default:
                result += 2
        }
    }    
    return numbers[result]
}

 

A. 1부터 k - 1까지 forEach로 순회하면서 switch문 안에서

전달 받은 배열의 길이를 활용하여

result의 값이 배열의 마지막 index인지,

마지막에서 두번째 index인지 비교하여

result의 값을 관리한 후, result를 반환하여 해결했다.

 

feat.

func solution(_ numbers:[Int], _ k:Int) -> Int {
    return numbers[((k-1)*2) % numbers.count]
}

 

다른 풀이를 참고했을 때, 위 해결법은 조건문 없이 단순 수식으로만 해결한 방법인데

풀이를 수학적으로 최적화하여 효율적인 코드를 작성할 수 있는 방법인 것 같다.

 

두 코드를 ChatGPT를 통해 비교해 본 결과,

기존의 반복문과 조건문을 사용하여 순회하는 방식보다는

수학적 계산으로 바로 결과를 도출하는 것이 훨씬 효율적인 코드라고 한다.

특징 첫 번째 코드 두 번째 코드
동작 방식 반복적으로 순회하며 인덱스를 계산 수학적 계산으로 인덱스를 바로 구함
복잡도 O(k): k 값이 커지면 수행 시간이 길어짐 O(1): 항상 일정한 시간이 소요됨
가독성 복잡도가 높아지는 대신 코드 흐름을 명확히 확인 가능 매우 간결하며 읽기 쉬움

4. 배열 회전시키기

Q. 정수가 담긴 배열 numbers와 문자열 direction가 매개변수로 주어집니다. 배열 numbers의 원소를 direction방향으로 한 칸씩 회전시킨 배열을 return하도록 solution 함수를 완성해주세요.

func solution(_ numbers:[Int], _ direction:String) -> [Int] {
    var result = numbers
    if direction == "right" {
        result.insert(result.last!, at: 0)
        result.removeLast()
    } else {
        result.append(result.first!)
        result.removeFirst()
    }
    return result
}

func secondSolution(_ numbers:[Int], _ direction:String) -> [Int] {
    var result: [Int] = []
    (0...numbers.count - 1).forEach {
        if direction == "right" {
            result.append($0 == 0 ? numbers.last! : numbers[$0 - 1]) 
        } else {
            result.append($0 == numbers.count - 1 ? numbers.first! : numbers[$0 + 1])
        }

    }
    return result
}

 

A. 위 문제는 두 가지 방법으로 코드를 작성하여 해결했다.

 

첫 번째 코드는 조건문을 통해 방향을 비교한 후,

오른쪽일 경우, result의 첫번째에 마지막 원소를 삽입한 후, removeLast()로 마지막 원소를 제거하고

왼쪽일 경우, result의 마지막에 첫번째 원소를 추가한 후, removeFirst()로 첫번째 원소를 제거한 후

result를 반환하여 해결하였다.

 

두 번째 코드는 반복문을 활용해 문제를 해결해보고 싶어서 작성한 코드이다.

빈 Int배열 result를 생성하고 0부터 전달 받은 numbers의 길이 - 1 까지 순회하면서

오른쪽일 경우, result에 첫번 째 index에 값을 추가하는 경우 numbers의 마지막 값을 추가하고

아닐 때는 numbers[$0 - 1] 값을 추가한다.

왼쪽일 경우, result의 마지막 index에 값을 추가하는 경우 numbers의 첫번째 값을 추가하고

아닐 때는 numbers]$0 + 1] 값을추가한다.

그리고 result를 반환하여 해결하였다.  

 

feat.

func solution(_ numbers:[Int], _ direction:String) -> [Int] {
    var nums = numbers
    direction == "right" ? nums.insert(nums.removeLast(), at: 0) : nums.append(nums.removeFirst())
    return nums
}

 

다른 풀이를 참고했을 때, 위 코드는 내가 작성한 첫 번째 해결 코드를

더욱 효율적으로 작성할 수 있게 하는 방법이라 느꼈다.

 

나는 removeFirst()와 removeLast ()가 값을 반환하지 않고 제거하는 동작만 수행하는 메서드인 줄 알았는데,

공식문서에 따르면 다음과 같이 제거한 요소를 반환까지 해주는 메서드였던 것이었다.

- mutating func removeFirst() -> Self.Element

- mutating func removeLast() -> Self.Element

 

따라서 내가 작성한 코드에선 insert, append와 remove 동작을 따로 해주고 있었는데,

위 코드에서는 insert와 append에 파라미터를 넘길 때 remove 동작을 같이 수행할 수 있던 것이다!


오늘도 어김 없이 코드를 어떻게 하면 효율적으로 작성할 수 있을지에 대한 고민을 하게 되는 날이었다.

다른 이들의 풀이를 보면서 이렇게도 해결할 수 있구나를 느끼게 되면

아직 갈 길이 멀다는 게 느껴지는 상황인데 꾸준히 생각하고 해결하다 보면

좋은 결과가 있지 않을까 생각한다.

 

그리고 ChatGPT를 통해 해결한 코드를 분석하는 방법이

내가 생각하지 못한 수학적 접근법으로 코드의 효율성을 극대화 시켜줄 수 있다는 걸 깨닫고

앞으로도 문제를 해결하고 피드백 하는 과정에서 자주 사용할 것 같다.

내일도 화이팅!