[Swift] [27일차] 시소 짝꿍

·2025년 1월 3일
0

SwiftAlgorithm

목록 보기
30/105
post-thumbnail

programmers-시소짝꿍

문제 설명

  1. 2m,3m,4m 거리에 시소가 설치해져있다
  2. weights배열에서 2명씩 뽑아서 균형이 잘 이루어지게끔 해라
  3. m랑 몸무게의 비율이 일치하면된다.
    아래 사진과 같은 느낌이라 보시면 될 것 같다 !

문제 접근

  1. 일단 두개씩 짝 지어줘야하는 상황이고, 나올 수 있는 비율이 1:1을 제외하고는 2:3, 3:4, 2:4 이거 3개라고 생각했다. 3:2, 4:3 처럼 뒤집어진 상황도 있겠지만 이거는 배열을 처음에 정렬하고 들어가면 해결되는 문제라고 생각했다.
  2. 1:1도 제외한 이유는 같은 원소는 그냥 SET으로 만들면서 처음에 그 값을 최종 방법론에 더해줬다. 그러면 1:1해서 없어진거랑 같은효과이기 때문 !

제출 코드

import Foundation

func solution(_ weights: [Int]) -> Int64 {
    let TMP: [Float] = [2, 3, 4]
    let SET: Set<Float> = [TMP[0] / TMP[1], TMP[1] / TMP[2], TMP[0] / TMP[2]]

    var answer = 0
    var arr_weights = Array(Set(weights)).sorted()
    answer += weights.count - arr_weights.count // 중복 날려주기 , 이러면 1:1 안봐도됨
    // 1:2, 2:3 , 3:4 ,
    while arr_weights.count > 1 {
        let current_target = arr_weights.removeLast() // 마지막애를 뽑아줬음(큰친구)
        for item in arr_weights {
            let tmp: Float = (Float(item) / Float(current_target))
            if SET.contains(tmp) {
                answer += 1
            }
        }
    }
    return Int64(answer)
}

Float로 큰값에서 작은값을 나눈 애를 미리 정해놓은 SET배열에서 찾아주는 형태로 수행을 했고, 예제가 잘나와서 한 번에 잘 통과되나했는데..

꽥☠️

채점 결과

정확성: 17.6
합계: 17.6 / 100.0
3개맞고 나머지를 다 틀렸다. 오류는 아니고 틀린거로 찍혀서 어딘가 로직에 결함이 있는 것 같았다.


코드 수정

질문게시판을 통해서 반례들을 보니 일단 같은 친구가 여러개 있을 때를 생각하지 못했다.

중복부분을 없애고 SET배열에서 1:1비율을 추가를 해주도록 하겠다.

채점 결과

정확성: 35.3
합계: 35.3 / 100.0
조금 오르긴했는데, 이제 나머지 친구들이 시간초과가 나오는 것으로 바뀌었다...

결국 야무지게 질문게시판 뒤적거린 결과

100 ≤ weights[i] ≤ 1,000라는 점을 잘 고려하라는 이야기를 듣고 이걸 딕셔너리형태로 바꿔주기로 했다.

var dict: [Float: Int] = [:]
    for item in weights {
        dict[Float(item), default: 0] += 1
    }

그리고 1:1일때는 nC2니까 이를 dict를 한 번 순회해주면서 수행했다.

for item in dict {
        answer += (item.1 * (item.1 - 1) / 2)
    }

이렇게 해주면 5개 같은게 있을 때 5*4에 순서 고려하지 않으니 /2 해서 10이 나올 것이다.


그리고 코드는 원래 있던 구조 SET을 다시 살려서 차용하되, 비율이 있을 때 dict를 참조해서 각각의 중복되는 값을 곱해주면서 경우의 수를 챙겼다.

import Foundation

func solution(_ weights: [Int]) -> Int64 {
    let TMP: [Float] = [2, 3, 4]
    let SET: Set<Float> = [TMP[0] / TMP[0], TMP[0] / TMP[1], TMP[1] / TMP[2], TMP[0] / TMP[2]]

    var answer = 0
    var dict: [Float: Int] = [:]
    for item in weights {
        dict[Float(item), default: 0] += 1
    }

    for item in dict {
        answer += (item.1 * (item.1 - 1) / 2)
    }

    var arr_weights = Array(Set(weights)).sorted().map { Float($0) }

    while arr_weights.count > 1 {
        let current_target = arr_weights.removeLast() // 마지막애를 뽑아줬음(큰친구)
        for item in arr_weights {
            let tmp: Float = (item / current_target)
            if SET.contains(tmp) {
                answer += 1 * dict[item]! * dict[current_target]!
            }
        }
    }
    return Int64(answer)
}

아직 문제를 풀 때 시간이 오래 걸리기는 하는데, 그래도 점점 나아지고 있는게 느껴져서 뿌듯했다.

채점 결과

정확성: 100.0
합계: 100.0 / 100.0


타인의 코드

import Foundation

func solution(_ weights:[Int]) -> Int64 {
    var result = 0
    var counter: [Double: Int] = [:]

    for w in weights {
        counter[Double(w), default: 0] += 1
    }

    let candis: [Double] = [2/3, 2/4, 3/2, 3/4, 4/2, 4/3]
    for (key, value) in counter {
        result += value * (value - 1)
        for c in candis {
            if let oppo = counter[key * c] {
                result += value * oppo
            }
        }
    }
    return Int64(result) / 2
}
  1. candis를 찾아줄 생각만했는데, 반대로 candis에 있는 애를 곱해서 dict의 값과 비교하는데에서 좀 더 깊게 생각하지 못했음을 반성했다. 괜히 값끼리 곱해주고 하느라 억지로 float해주고 형태 맞춰주느라 고생했는데, 결과값을 중간으로 끌어와서 값을 도출하는게 너무 좋다고 느꼈다.
  2. 그리고 나는 sorted()를 해줘서 2/3을 챙기고 3/2는 안챙기는 방식으로했는데, 순서상관없이 다해주고 맨마지막에 /2 해줘서 까끔한 코드가 된 것 같다.
profile
기억보단 기록을

0개의 댓글