문제 설명

XX게임에는 피로도 시스템(0 이상의 정수로 표현합니다)이 있으며, 일정 피로도를 사용해서 던전을 탐험할 수 있습니다. 이때, 각 던전마다 탐험을 시작하기 위해 필요한 "최소 필요 피로도"와 던전 탐험을 마쳤을 때 소모되는 "소모 피로도"가 있습니다. "최소 필요 피로도"는 해당 던전을 탐험하기 위해 가지고 있어야 하는 최소한의 피로도를 나타내며, "소모 피로도"는 던전을 탐험한 후 소모되는 피로도를 나타냅니다. 예를 들어 "최소 필요 피로도"가 80, "소모 피로도"가 20인 던전을 탐험하기 위해서는 유저의 현재 남은 피로도는 80 이상 이어야 하며, 던전을 탐험한 후에는 피로도 20이 소모됩니다.

이 게임에는 하루에 한 번씩 탐험할 수 있는 던전이 여러개 있는데, 한 유저가 오늘 이 던전들을 최대한 많이 탐험하려 합니다. 유저의 현재 피로도 k와 각 던전별 "최소 필요 피로도", "소모 피로도"가 담긴 2차원 배열 dungeons 가 매개변수로 주어질 때, 유저가 탐험할수 있는 최대 던전 수를 return 하도록 solution 함수를 완성해주세요.

제한사항
  • k는 1 이상 5,000 이하인 자연수입니다.
  • dungeons의 세로(행) 길이(즉, 던전의 개수)는 1 이상 8 이하입니다.
    • dungeons의 가로(열) 길이는 2 입니다.
    • dungeons의 각 행은 각 던전의 ["최소 필요 피로도", "소모 피로도"] 입니다.
    • "최소 필요 피로도"는 항상 "소모 피로도"보다 크거나 같습니다.
    • "최소 필요 피로도"와 "소모 피로도"는 1 이상 1,000 이하인 자연수입니다.
    • 서로 다른 던전의 ["최소 필요 피로도", "소모 피로도"]가 서로 같을 수 있습니다.

내가 푼 풀이

[1...던전의크기] 만큼 던전루트 조합을 구한뒤 갈 수 있는 던전루트인지 확인하고 최댓값 출력

이 문제의 주어지는 던전수는 최대 8이라서 완전탐색으로 해도 시간이 넉넉하다.

 

 

import Foundation

func solution(_ k:Int, _ dungeons:[[Int]]) -> Int {
    var result = [Int]()
    for i in 1...dungeons.count {
        var arr = find(i)
        arr.forEach {
            var hp = k
            var count = 0
            for j in $0 {
                if hp >= dungeons[j][0] {
                    hp -= dungeons[j][1]
                    count += 1
                }
            }
            result.append(count)
        }
    }
    return result.max()!
}
func find(_ n: Int) -> [[Int]] {
    var result = [[Int]]()
    
    func comb(_ arr: [Int]) {
        if arr.count == n {
            result.append(arr)
            return
        } else {
            for i in 0..<n {
                if !arr.contains(i) {
                    comb(arr + [i])
                }
            }
        }
    }
    comb([])
    return result
}

 

 

 

문제 설명

문제 설명

양의 정수 n이 주어집니다. 이 숫자를 k진수로 바꿨을 때, 변환된 수 안에 아래 조건에 맞는 소수(Prime number)가 몇 개인지 알아보려 합니다.

  • 0P0처럼 소수 양쪽에 0이 있는 경우
  • P0처럼 소수 오른쪽에만 0이 있고 왼쪽에는 아무것도 없는 경우
  • 0P처럼 소수 왼쪽에만 0이 있고 오른쪽에는 아무것도 없는 경우
  • P처럼 소수 양쪽에 아무것도 없는 경우
  • 단, P는 각 자릿수에 0을 포함하지 않는 소수입니다.
    • 예를 들어, 101은 P가 될 수 없습니다.

예를 들어, 437674을 3진수로 바꾸면 211020101011입니다. 여기서 찾을 수 있는 조건에 맞는 소수는 왼쪽부터 순서대로 211, 2, 11이 있으며, 총 3개입니다. (211, 2, 11을 k진법으로 보았을 때가 아닌, 10진법으로 보았을 때 소수여야 한다는 점에 주의합니다.) 211은 P0 형태에서 찾을 수 있으며, 2는 0P0에서, 11은 0P에서 찾을 수 있습니다.

정수 n과 k가 매개변수로 주어집니다. n을 k진수로 바꿨을 때, 변환된 수 안에서 찾을 수 있는 위 조건에 맞는 소수의 개수를 return 하도록 solution 함수를 완성해 주세요.


제한사항
  • 1 ≤ n ≤ 1,000,000
  • 3 ≤ k ≤ 10

내가 푼 풀이

위 조건을 자세히 보면,

두번째 조건은 0을 경계로 가장 왼쪽에 있는 숫자가 소수인 경우이고

세번째 조건은 0을 경계로 가장 오른쪽에 있는 숫자가 소수인 경우이다.

네번째 조건은 변환된숫자의 자리수가 1이고, 그게 소수인 경우다.

따라서 숫자를 k진수로 변환시키고, 변환시킨 숫자를 문자열로 변경해서 0을 기준으로 나눈 값들중 소수의 갯수를 출력한다.

 

소수인지 판별할땐, 판별할 정수 n의 제곱근까지만 검사한다.

 

 

import Foundation

func solution(_ n:Int, _ k:Int) -> Int {
    var num = n
    var numString = ""
    var changeKnum = [String]()
    var result = 0
    
    if k == 10 {
        numString = String(num)
    } else {
        while num >= 1 {
            changeKnum.append(String(num % k))
            num = num / k
        }
        numString = changeKnum.reversed().joined(separator: "")
    }
    var arr = numString.split(separator: "0").map{Int($0)!}
    for i in arr {
        var checkNum = Int(i)
        if checkNum == 1 {
            continue
        } else {
            var rangeNum = 1
            var isntPrime = false
            while rangeNum * rangeNum <= checkNum {
                if rangeNum == 1 {
                    rangeNum += 1
                    continue
                }
                if checkNum % rangeNum == 0 {
                    isntPrime = true
                    break
                }
                rangeNum += 1
            }
            if !isntPrime {
                result += 1
            }
        }

    }

    return result
}

'코딩테스트 > 프로그래머스' 카테고리의 다른 글

[프로그래머스] 할인 행사 Swift  (0) 2023.04.13
피로도 Swift  (0) 2023.04.13
[1차] 뉴스 클러스터링 Swift  (0) 2023.04.12
연속 부분 수열 합의 개수 Swift  (0) 2023.04.12
위장 Swift  (0) 2023.04.12

문제 설명

뉴스 클러스터링

여러 언론사에서 쏟아지는 뉴스, 특히 속보성 뉴스를 보면 비슷비슷한 제목의 기사가 많아 정작 필요한 기사를 찾기가 어렵다. Daum 뉴스의 개발 업무를 맡게 된 신입사원 튜브는 사용자들이 편리하게 다양한 뉴스를 찾아볼 수 있도록 문제점을 개선하는 업무를 맡게 되었다.

개발의 방향을 잡기 위해 튜브는 우선 최근 화제가 되고 있는 "카카오 신입 개발자 공채" 관련 기사를 검색해보았다.

  • 카카오 첫 공채..'블라인드' 방식 채용
  • 카카오, 합병 후 첫 공채.. 블라인드 전형으로 개발자 채용
  • 카카오, 블라인드 전형으로 신입 개발자 공채
  • 카카오 공채, 신입 개발자 코딩 능력만 본다
  • 카카오, 신입 공채.. "코딩 실력만 본다"
  • 카카오 "코딩 능력만으로 2018 신입 개발자 뽑는다"

기사의 제목을 기준으로 "블라인드 전형"에 주목하는 기사와 "코딩 테스트"에 주목하는 기사로 나뉘는 걸 발견했다. 튜브는 이들을 각각 묶어서 보여주면 카카오 공채 관련 기사를 찾아보는 사용자에게 유용할 듯싶었다.

유사한 기사를 묶는 기준을 정하기 위해서 논문과 자료를 조사하던 튜브는 "자카드 유사도"라는 방법을 찾아냈다.

자카드 유사도는 집합 간의 유사도를 검사하는 여러 방법 중의 하나로 알려져 있다. 두 집합 A, B 사이의 자카드 유사도 J(A, B)는 두 집합의 교집합 크기를 두 집합의 합집합 크기로 나눈 값으로 정의된다.

예를 들어 집합 A = {1, 2, 3}, 집합 B = {2, 3, 4}라고 할 때, 교집합 A ∩ B = {2, 3}, 합집합 A ∪ B = {1, 2, 3, 4}이 되므로, 집합 A, B 사이의 자카드 유사도 J(A, B) = 2/4 = 0.5가 된다. 집합 A와 집합 B가 모두 공집합일 경우에는 나눗셈이 정의되지 않으니 따로 J(A, B) = 1로 정의한다.

자카드 유사도는 원소의 중복을 허용하는 다중집합에 대해서 확장할 수 있다. 다중집합 A는 원소 "1"을 3개 가지고 있고, 다중집합 B는 원소 "1"을 5개 가지고 있다고 하자. 이 다중집합의 교집합 A ∩ B는 원소 "1"을 min(3, 5)인 3개, 합집합 A ∪ B는 원소 "1"을 max(3, 5)인 5개 가지게 된다. 다중집합 A = {1, 1, 2, 2, 3}, 다중집합 B = {1, 2, 2, 4, 5}라고 하면, 교집합 A ∩ B = {1, 2, 2}, 합집합 A ∪ B = {1, 1, 2, 2, 3, 4, 5}가 되므로, 자카드 유사도 J(A, B) = 3/7, 약 0.42가 된다.

이를 이용하여 문자열 사이의 유사도를 계산하는데 이용할 수 있다. 문자열 "FRANCE"와 "FRENCH"가 주어졌을 때, 이를 두 글자씩 끊어서 다중집합을 만들 수 있다. 각각 {FR, RA, AN, NC, CE}, {FR, RE, EN, NC, CH}가 되며, 교집합은 {FR, NC}, 합집합은 {FR, RA, AN, NC, CE, RE, EN, CH}가 되므로, 두 문자열 사이의 자카드 유사도 J("FRANCE", "FRENCH") = 2/8 = 0.25가 된다.

입력 형식

  • 입력으로는 str1과 str2의 두 문자열이 들어온다. 각 문자열의 길이는 2 이상, 1,000 이하이다.
  • 입력으로 들어온 문자열은 두 글자씩 끊어서 다중집합의 원소로 만든다. 이때 영문자로 된 글자 쌍만 유효하고, 기타 공백이나 숫자, 특수 문자가 들어있는 경우는 그 글자 쌍을 버린다. 예를 들어 "ab+"가 입력으로 들어오면, "ab"만 다중집합의 원소로 삼고, "b+"는 버린다.
  • 다중집합 원소 사이를 비교할 때, 대문자와 소문자의 차이는 무시한다. "AB"와 "Ab", "ab"는 같은 원소로 취급한다.

출력 형식

입력으로 들어온 두 문자열의 자카드 유사도를 출력한다. 유사도 값은 0에서 1 사이의 실수이므로, 이를 다루기 쉽도록 65536을 곱한 후에 소수점 아래를 버리고 정수부만 출력한다.

내가 푼 풀이

아주 차근차근 입력해가서 규칙대로 소거해나갔다.

1. str1 , str2 개별로 크기가 2인 문자열을 뽑아냈다.

2. 뽑아낸 문자열중 영문자가 아니면 pass , 영문자라면 결과배열에 추가

      (전부 대문자로 만들고 UnicodeScalar의 코드가 65 이상 90이하)

3. 문자열을 추가한 str1의 배열 A, str2의 배열 B에서  A ∩ B , A ∪ B 를 구한다.

4. 문자 A와 B를 순회하면서 다음 조건에 맞는 배열을 따로 저장한다.

Set을 이용해서 교집합 합집합을 쉽게 구할 수 있지만, 문제의 집합은 중복집합을 허용하므로 Set을 사용하지 않는다.

중복집합인경우 교집합은 한 배열의 a의 갯수 최솟값, 합집합은 한 배열의 a갯수 최댓값 이다.

ex) A = ["1", "1", "1", "1", "1"] , B = ["1", "1"] 일때

A ∩ B = min(5,2) = 2 , A ∪ B = max(5,2) = 5 

A B 모두 중복집합 일수도 있고, 아닐수도있고 하나만 중복일 수 있으므로 아래 방법으로 구한다.

두가지 배열을 준비한다. A - B  = Z , B - A = Y

  • A배열을 순회한다.
  • A[i] == B[i] -> A ∩ B ,  B에서 B[i] 제거 (B - A)
  • A[i] != B[i] -> A[i] 를 배열에 저장 ( A - B )

모두 순회하면 세가지 배열이 생성된다. A ∩ B , A - B, B - A

A ∩ B 는 이미 구해졌고, A ∪ B = (A ∩ B) + (A - B) + (B - A) 이다.

유사도 J 는 교집합 / 합집합으로

결과는 Int( Double(A ∩ B / A ∪ B) * 65536) 이다.

 

 

func solution(_ str1:String, _ str2:String) -> Int {
    var str1Arr = [String]()
    var str2Arr = [String]()
    
    for i in 0..<str1.count-1 {
        var s1 = str1[str1.index(str1.startIndex, offsetBy: i)].uppercased()
        var s2 = str1[str1.index(str1.startIndex, offsetBy: i+1)].uppercased()
        var s1code = UnicodeScalar(s1)!.value
        var s2code = UnicodeScalar(s2)!.value
        if s1code >= 65 && s1code <= 90 {
            if s2code >= 65 && s2code <= 90 {
                str1Arr.append("\(s1)" + "\(s2)")
            }
        }
    }
    for i in 0..<str2.count-1 {
        var s1 = str2[str2.index(str2.startIndex, offsetBy: i)].uppercased()
        var s2 = str2[str2.index(str2.startIndex, offsetBy: i+1)].uppercased()
        var s1code = UnicodeScalar(s1)!.value
        var s2code = UnicodeScalar(s2)!.value
        if s1code >= 65 && s1code <= 90 {
            if s2code >= 65 && s2code <= 90 {
                str2Arr.append("\(s1)" + "\(s2)")
            }
        }
    }
    
    var exArr = [String]()
    var nArr = [String]()
    for i in 0..<str1Arr.count {
        var idx = -1
        var s1 = str1Arr[i]
        for j in 0..<str2Arr.count{
            if s1 == str2Arr[j] {
                nArr.append(s1)                
                idx = j
                break
            }
        }
        if idx >= 0 {
            str2Arr.remove(at: idx)
        } else {
            exArr.append(s1)
        }
        
    }
    var num1: Double = Double(nArr.count)
    var num2: Double = Double(nArr.count + exArr.count + str2Arr.count)
    if num1 == 0 && num2 == 0 {
        return 65536
    } else {
        return Int(num1 / num2 * 65536)
    }
    
}

'코딩테스트 > 프로그래머스' 카테고리의 다른 글

피로도 Swift  (0) 2023.04.13
k진수에서 소수 개수 구하기 Swift  (0) 2023.04.12
연속 부분 수열 합의 개수 Swift  (0) 2023.04.12
위장 Swift  (0) 2023.04.12
n^2 배열 자르기 Swift  (0) 2023.04.12

문제 설명

철호는 수열을 가지고 놀기 좋아합니다. 어느 날 철호는 어떤 자연수로 이루어진 원형 수열의 연속하는 부분 수열의 합으로 만들 수 있는 수가 모두 몇 가지인지 알아보고 싶어졌습니다. 원형 수열이란 일반적인 수열에서 처음과 끝이 연결된 형태의 수열을 말합니다. 예를 들어 수열 [7, 9, 1, 1, 4] 로 원형 수열을 만들면 다음과 같습니다.


원형 수열은 처음과 끝이 연결되어 끊기는 부분이 없기 때문에 연속하는 부분 수열도 일반적인 수열보다 많아집니다.
원형 수열의 모든 원소 elements가 순서대로 주어질 때, 원형 수열의 연속 부분 수열 합으로 만들 수 있는 수의 개수를 return 하도록 solution 함수를 완성해주세요.


제한사항
  • 3 ≤ elements의 길이 ≤ 1,000
  • 1 ≤ elements의 원소 ≤ 1,000

내가 푼 풀이

원형 수열의 연속 부분 수열 합은 각 자리에서 본인을 제외한 나머지 인접한 원소들끼리 더해가는 부분 수열 합이다.

[7, 9, 1, 1, 4] 에서 7 일때 (7) (7, 9) (7, 9, 1) (7, 9, 1, 1) (7, 9, 1, 1, 4) 이다

남은 자리도 똑같은 방법으로 구하고 인덱스가 배열을 초과 하면 0으로 초기화해서 구한다

구한 부분집합의 합들을 중복없이 저장한 후 갯수 출력

 

import Foundation

func solution(_ elements:[Int]) -> Int {
    var sumSet = Set<Int>()
    for i in 0..<elements.count {
        var sum = 0
        for j in 0..<elements.count {
            
            var idx = i+j
            if idx >= elements.count {
                idx = idx - elements.count
            }
            sum += elements[idx]
            sumSet.insert(sum)
        }
    }
    return sumSet.count
}

'코딩테스트 > 프로그래머스' 카테고리의 다른 글

k진수에서 소수 개수 구하기 Swift  (0) 2023.04.12
[1차] 뉴스 클러스터링 Swift  (0) 2023.04.12
위장 Swift  (0) 2023.04.12
n^2 배열 자르기 Swift  (0) 2023.04.12
튜플 Swift  (0) 2023.04.12

문제 설명

스파이들은 매일 다른 옷을 조합하여 입어 자신을 위장합니다.

예를 들어 스파이가 가진 옷이 아래와 같고 오늘 스파이가 동그란 안경, 긴 코트, 파란색 티셔츠를 입었다면 다음날은 청바지를 추가로 입거나 동그란 안경 대신 검정 선글라스를 착용하거나 해야 합니다.

 


스파이가 가진 의상들이 담긴 2차원 배열 clothes가 주어질 때 서로 다른 옷의 조합의 수를 return 하도록 solution 함수를 작성해주세요.

제한사항
  • clothes의 각 행은 [의상의 이름, 의상의 종류]로 이루어져 있습니다.
  • 스파이가 가진 의상의 수는 1개 이상 30개 이하입니다.
  • 같은 이름을 가진 의상은 존재하지 않습니다.
  • clothes의 모든 원소는 문자열로 이루어져 있습니다.
  • 모든 문자열의 길이는 1 이상 20 이하인 자연수이고 알파벳 소문자 또는 '_' 로만 이루어져 있습니다.
  • 스파이는 하루에 최소 한 개의 의상은 입습니다.

 

내가 푼 풀이

간단하게 2개의 a, b를 나열하는 경우의 수는 a , b , ab 이다.

이 문제도 똑같이 의상의 종류를 모두 구한후, 갯수만큼 입는경우 + 입지않는 경우 를 계산해서 

아무것도 입지않은 경우의 수 1 을 뺀 결과를 출력하면 된다.

 

 

import Foundation

func solution(_ clothes:[[String]]) -> Int {
    var dict = [String: Int]()
    var result = 1
    
    for i in 0..<clothes.count {
        let name = clothes[i][1]
        if dict[name] == nil {
            dict[name] = 1
        } else {
            dict[name]! += 1
        }
    }
    for i in dict {
        result = result * (i.value + 1)
    }
    
    return result-1
}

'코딩테스트 > 프로그래머스' 카테고리의 다른 글

[1차] 뉴스 클러스터링 Swift  (0) 2023.04.12
연속 부분 수열 합의 개수 Swift  (0) 2023.04.12
n^2 배열 자르기 Swift  (0) 2023.04.12
튜플 Swift  (0) 2023.04.12
[1차] 캐시 Swift  (0) 2023.04.12

문제 설명

정수 n, left, right가 주어집니다. 다음 과정을 거쳐서 1차원 배열을 만들고자 합니다.

  1. n행 n열 크기의 비어있는 2차원 배열을 만듭니다.
  2. i = 1, 2, 3, ..., n에 대해서, 다음 과정을 반복합니다.
    • 1행 1열부터 i행 i열까지의 영역 내의 모든 빈 칸을 숫자 i로 채웁니다.
  3. 1행, 2행, ..., n행을 잘라내어 모두 이어붙인 새로운 1차원 배열을 만듭니다.
  4. 새로운 1차원 배열을 arr이라 할 때, arr[left], arr[left+1], ..., arr[right]만 남기고 나머지는 지웁니다.

정수 n, left, right가 매개변수로 주어집니다. 주어진 과정대로 만들어진 1차원 배열을 return 하도록 solution 함수를 완성해주세요.


제한사항
  • 1 ≤ n ≤ 10^7
  • 0 ≤ left  right < n^2
  • right - left < 10^5

내가 푼 풀이

처음에는 그냥 2차원 배열을 구해서 1차원배열로 만들고 그에 해당하는 인덱스의 범위를 출력하려고 했는데

주어지는 n의 최대크기가 10^7 이라서, 2중 for문을 이용하면 무조건 시간초과가 뜨겠다 싶어서 해당하는 인덱스의 범위만 구하고

해당 배열이 만들어지는 규칙을 적용해서 정답을 출력하기로 했다.

이 문제에 적용한 배열이 만들어지는 규칙은 i행 1열부터 i열까지의 원소는 전부 i, i행 i+1열부터는 i+1, i+2 ... 이다.

ex) n = 3 일때 3x3 행렬 3행 1열 부터 3열까지는 전부 3이다.

ex) n = 5 일때 5x5 행렬 3행 1열 부터 3열까지는 전부 3이다. 3행 4열은 3+1 = 4, 3행 5열은 3+2 = 5 이다.

 

구하고자하는 범위 [left...right] 의 배열

전부 n으로 나눈 나머지 그 행의 순서가 나온다. 

전부 n으로 나눈 몫으로 바꾸면 그 행의 번호가 나온다. 

해당하는 위치의 순서가 행의 번호 보다 작거나 같으면 그 위치의 원소는 행의번호

해당하는 위치의 순서가 행의 번호 보다 크다면 그 위치의 원소는 행의번호 + (행의순서 - 행의번호 )

배열의 원소는 인덱스로 구성되어있으니 출력할때 +1을 해준다.

글로만 봐서는 헷갈리니까 예제문제로 예시를 들어본다.

 

ex) n = 3 , 3x3 행렬, left = 2, right = 5 

[[1,2,3],

 [2,2,3],

 [3,3,3]]

  • 구하고자 하는 범위의 인덱스를 배열로 만든다. :  [2,3,4,5]
  • 인덱스 배열을 3로 나눈 나머지 :  [2, 0, 1, 2] ( 행의 순서)
  • 인덱스 배열을 2으로 나눈 몫 : [0, 1, 1, 1] (행의 번호)

인덱스배열 첫번째 2

행의 번호: 0 ,행의 순서: 2

행의 순서가 행의번호보다 크다. 결과는 행의번호 + 행의순서 - 행의번호 = 2 

위에 숫자는 전부 배열의 인덱스 이므로 +1 해서 출력한다 -> 3

 

인덱스배열 두번째 3

행의번호: 1, 행의순서: 0

행의번호가 더 크다. 결과는 행의번호

숫자는 배열의 인덱스이므로 +1을 해서 출력한다 -> 2

 

인덱스배열 세번째 4

행의번호: 1, 행의순서: 1

행의번호와 행의순서가 같다. 결과는 행의번호

숫자는 배열의 인덱스이므로 +1을 해서 출력한다 -> 2

 

인덱스배열 세번째 5

행의번호: 1, 행의순서: 2

행의순서가 행의번호 보다 크다. 결과는 행의번호 + 행의순서 - 행의번호 = 2

숫자는 배열의 인덱스이므로 +1을 해서 출력한다 -> 3

 

이런 규칙을 적용하여 풀었다.

 

import Foundation

func solution(_ n:Int, _ left:Int64, _ right:Int64) -> [Int] {
    var arr = Array(left...right)
    var rows: [Int64] = arr.map{ $0 % Int64(n)}
    var cols: [Int64] = arr.map{ $0 / Int64(n)}
    var result = [Int]()
    
    for i in 0..<rows.count {
        var num = cols[i] + 1
        if rows[i] <= cols[i] {
            result.append(Int(num))
        }  else {
            result.append(Int(num + (rows[i] - cols[i])))
        }
    }
    return result
}

'코딩테스트 > 프로그래머스' 카테고리의 다른 글

연속 부분 수열 합의 개수 Swift  (0) 2023.04.12
위장 Swift  (0) 2023.04.12
튜플 Swift  (0) 2023.04.12
[1차] 캐시 Swift  (0) 2023.04.12
괄호 회전하기 Swift  (0) 2023.04.12

문제 설명

셀수있는 수량의 순서있는 열거 또는 어떤 순서를 따르는 요소들의 모음을 튜플(tuple)이라고 합니다. n개의 요소를 가진 튜플을 n-튜플(n-tuple)이라고 하며, 다음과 같이 표현할 수 있습니다.

  • (a1, a2, a3, ..., an)

튜플은 다음과 같은 성질을 가지고 있습니다.

  1. 중복된 원소가 있을 수 있습니다. ex : (2, 3, 1, 2)
  2. 원소에 정해진 순서가 있으며, 원소의 순서가 다르면 서로 다른 튜플입니다. ex : (1, 2, 3) ≠ (1, 3, 2)
  3. 튜플의 원소 개수는 유한합니다.

원소의 개수가 n개이고, 중복되는 원소가 없는 튜플 (a1, a2, a3, ..., an)이 주어질 때(단, a1, a2, ..., an은 자연수), 이는 다음과 같이 집합 기호 '{', '}'를 이용해 표현할 수 있습니다.

  • {{a1}, {a1, a2}, {a1, a2, a3}, {a1, a2, a3, a4}, ... {a1, a2, a3, a4, ..., an}}

예를 들어 튜플이 (2, 1, 3, 4)인 경우 이는

  • {{2}, {2, 1}, {2, 1, 3}, {2, 1, 3, 4}}

와 같이 표현할 수 있습니다. 이때, 집합은 원소의 순서가 바뀌어도 상관없으므로

  • {{2}, {2, 1}, {2, 1, 3}, {2, 1, 3, 4}}
  • {{2, 1, 3, 4}, {2}, {2, 1, 3}, {2, 1}}
  • {{1, 2, 3}, {2, 1}, {1, 2, 4, 3}, {2}}

는 모두 같은 튜플 (2, 1, 3, 4)를 나타냅니다.

특정 튜플을 표현하는 집합이 담긴 문자열 s가 매개변수로 주어질 때, s가 표현하는 튜플을 배열에 담아 return 하도록 solution 함수를 완성해주세요.

[제한사항]

  • s의 길이는 5 이상 1,000,000 이하입니다.
  • s는 숫자와 '{', '}', ',' 로만 이루어져 있습니다.
  • 숫자가 0으로 시작하는 경우는 없습니다.
  • s는 항상 중복되는 원소가 없는 튜플을 올바르게 표현하고 있습니다.
  • s가 표현하는 튜플의 원소는 1 이상 100,000 이하인 자연수입니다.
  • return 하는 배열의 길이가 1 이상 500 이하인 경우만 입력으로 주어집니다.

내가 푼 풀이

주어진 문자열을 2차원 배열로 만들고, 배열의 크기순으로 정렬한 다음 중복되는 값들을 소거하고 출력한다.

 

replacingOccurrences

split

subtracting

import Foundation

func solution(_ s:String) -> [Int] {
    var arr = s.split(separator: "{").map{String($0)}
    var nums = [[Int]]()
    var result = [Int]()
    arr = arr.map{ $0.replacingOccurrences(of: "}", with: "")}.sorted{$0.count < $1.count}
    for i in 0..<arr.count {
        nums.append(arr[i].split(separator: ",").map{Int(String($0))! })
    }
    result.append(nums[0][0])
    for i in 1..<nums.count {
        var set1 = Set(nums[i])
        var set2 = Set(nums[i-1])
        result += Array(set1.subtracting(set2))
        
    }
    return result
}

 

'코딩테스트 > 프로그래머스' 카테고리의 다른 글

위장 Swift  (0) 2023.04.12
n^2 배열 자르기 Swift  (0) 2023.04.12
[1차] 캐시 Swift  (0) 2023.04.12
괄호 회전하기 Swift  (0) 2023.04.12
귤 고르기 Swift  (0) 2023.04.12

캐시

지도개발팀에서 근무하는 제이지는 지도에서 도시 이름을 검색하면 해당 도시와 관련된 맛집 게시물들을 데이터베이스에서 읽어 보여주는 서비스를 개발하고 있다.
이 프로그램의 테스팅 업무를 담당하고 있는 어피치는 서비스를 오픈하기 전 각 로직에 대한 성능 측정을 수행하였는데, 제이지가 작성한 부분 중 데이터베이스에서 게시물을 가져오는 부분의 실행시간이 너무 오래 걸린다는 것을 알게 되었다.
어피치는 제이지에게 해당 로직을 개선하라고 닦달하기 시작하였고, 제이지는 DB 캐시를 적용하여 성능 개선을 시도하고 있지만 캐시 크기를 얼마로 해야 효율적인지 몰라 난감한 상황이다.

어피치에게 시달리는 제이지를 도와, DB 캐시를 적용할 때 캐시 크기에 따른 실행시간 측정 프로그램을 작성하시오.

입력 형식

  • 캐시 크기(cacheSize)와 도시이름 배열(cities)을 입력받는다.
  • cacheSize는 정수이며, 범위는 0 ≦ cacheSize ≦ 30 이다.
  • cities는 도시 이름으로 이뤄진 문자열 배열로, 최대 도시 수는 100,000개이다.
  • 각 도시 이름은 공백, 숫자, 특수문자 등이 없는 영문자로 구성되며, 대소문자 구분을 하지 않는다. 도시 이름은 최대 20자로 이루어져 있다.

출력 형식

  • 입력된 도시이름 배열을 순서대로 처리할 때, "총 실행시간"을 출력한다.

조건

  • 캐시 교체 알고리즘은 LRU(Least Recently Used)를 사용한다.
  • cache hit일 경우 실행시간은 1이다.
  • cache miss일 경우 실행시간은 5이다.

내가 푼 풀이

LRU 알고리즘을 모르고 가장 최근에 사용된 캐시가 있다면 hit 없으면 miss 인 줄 알았다.

그래서 캐시의 크기만큼 배열을 만들어서 주어진 도시들을 순회하면서 밀어내기식으로 검사했는데 틀렸다

이 문제의 핵심은 LRU 알고리즘을 알고 있는지 이다.

 

LRU : Least Recently Used 로 가장 오랫동안 참조하지 않은 원소를 교체하는 방식이다.

 

여기서 문제풀이의 핵심은 검사배열에 없다면 추가해주고 있으면 순서를 앞으로 당겨줘야한다.

배열에 추가하기 쉽게 배열의 마지막인덱스가 가장 최근에 추가된 원소로 한다.

 

배열안에 존재할때

  • array.contains(city)  = true  -> array.remove(at: city.index) , array.append(city)

배열안에 존재하지 않을때

  • array.contains(city)  = false -> array.append(city)
  • array.count > cache.count   -> array.removeFirst() , array.append(city)

 

func solution(_ cacheSize:Int, _ cities:[String]) -> Int {
    var cache = [String]()
    var result = 0
    
    
    for i in 0..<cities.count {
        var city = cities[i].uppercased()
        if !cache.contains(city) {
            result += 5
            cache.append(city)
            if cache.count > cacheSize {
                cache.removeFirst()
            }
        } else {
            for j in 0..<cache.count {
                if cache[j] == city {
                    cache.remove(at: j)
                    cache.append(city)
                    break
                }
            }
            result += 1
        }
    }
    return result
}

'코딩테스트 > 프로그래머스' 카테고리의 다른 글

n^2 배열 자르기 Swift  (0) 2023.04.12
튜플 Swift  (0) 2023.04.12
괄호 회전하기 Swift  (0) 2023.04.12
귤 고르기 Swift  (0) 2023.04.12
멀리 뛰기 Swift  (0) 2023.04.11

+ Recent posts