_ 9421 소수상근수

Zion·2021년 12월 29일
0

실버단계 도달... 부끄럽지만 처음이라 기록
문제링크

sol)

1) 범위안의 소수 찾기
2) 소수 중 상근수 찾기

1) 소수 소수 소수

그대이름 소수 소수
[에라토스테네스의 체]

이렇게 구하는 방법을 안다.
그래서

func primeNum(_ range: Int) {
    var numSet: [Bool] = Array(repeating: false, count: range + 1)
    
    numSet.enumerated().forEach{ set in
        
        let index = set.offset
        let element = set.element
        
        if index == 1 || index == 0 {
            return
        }
        
        if element == false {
            for i in 2... {
                if index * i <= range {
                    if numSet[index * i] == false {
                        numSet[index * i] = true
                    }
                } else {
                    return
                }
            }
        }
    }

절씨구 이렇게 구했다.
여기서 배운건 그간 forEach쓸 때 index를 알아야하는 경우가 별로 없었다.(있었던 적도 있었지만 그땐 그냥 깔끔하게(?) for문 돌렸다.) enumerate() 메소드를 이용해서

offset : index
element : value

index와 value에 접근이 가능해졌다.
코드가 그닥 깔끔해 보이진 않아보이는데 더 효율적인 방법으로 에라토스테네스의 체를 구하는 방법이 있으면 적어놓겠다!
위키백과 - 에라토스테네스의 체

2) 상근수

    var primeSet = numSet.enumerated().filter{ $0.element == false }.map{ $0.offset }
    primeSet.removeSubrange(0...1)
    primeSet.forEach{ num in
        var dict: [Int: Bool] = [:]
        let stringNum = String(num)
        var arr = stringNum.compactMap{ Int(String($0)) }
        
        var sum = 0
        while sum != 1 {
            arr.forEach {
                sum += ($0)*($0)
            }
            if dict[sum] == nil {
                dict[sum] = true
                arr = String(sum).compactMap{ Int(String($0)) }
                sum = 0
                
            } else if sum == 1 {
                print(num)
                return
            } else {
                return
            }
        }
        
    }

딕셔너리 사용해서 primeSet.forEachnum이 반복되는지 체크한다.
반복된다면, 상근수가 아니다.

알게된것.

enumerated()
소수 구하기

+ 소수판별 O(√n)

위에 적어놓은 primeNum함수 보다 더 나은 방법이 있어서 적어놓겠다.

func isPrime(_ num: Int) -> Bool {
    if num <= 1 { return false }
    if num == 2 { return true }
    
    if num % 2 == 0 { return false }
    let sqrtn = Int(sqrt(Double(num)))
    for div in stride(from: 3, through: sqrtn, by: 2) {
        if num % div == 0 {
            return false
        }
    }
    return true
}
//출처 : 종만북 - 정수론
profile
어제보다만 나아지는

0개의 댓글