Skip to content

Conversation

@MuchanKim
Copy link
Collaborator

@MuchanKim MuchanKim commented Apr 11, 2025

🔗 문제 링크

소-난다

✔️ 소요된 시간

3시간 + @

✨ 수도 코드

에라토스테네스의체 + 백트래킹으로 풀려고 했으나...?? 수 시간 사투(시간초과) 끝에 지피티 선생의 조언을 받아 비트마스킹으로 풀었습니다.(구글링 해도 잘 안나오더라고요)

혹시나해서 이전 코드도 첨부해봅니다. 어디서 터졌는지 조금 파악해보고 글 추가 할 예정이에요. 제출 코드는 커밋메시지에!

import Foundation

// 에라토스테네스의 체
func getPrimes(_ maxNum: Int) -> [Bool] {
    var isPrime = Array(repeating: true, count: maxNum + 1)
    isPrime[0] = false
    isPrime[1] = false
    
    for i in 2...Int(Double(maxNum).squareRoot()) {
        if isPrime[i] {
            for j in stride(from: i * i, through: maxNum, by: i) {
                isPrime[j] = false
            }
        }
    }
    
    return isPrime
}

func solution(_ n: Int, _ m: Int, _ cowsWeight: [Int]) -> String {
    if m > n || n <= 0 || m <= 0 {
        return "-1"
    }
    
    // 조합에서 가장 큰 수 찾기
    let sortedWeights = cowsWeight.sorted(by: >)
    var maxSum = 0
    for i in 0..<min(m, sortedWeights.count) {
        maxSum += sortedWeights[i]
    }
    
    let isPrime = getPrimes(maxSum)
    
    // 가능한 소수 합을 저장할 집합
    var possiblePrimes: Set<Int> = []
    var visited = Array(repeating: false, count: n)
    
    func backtrack(_ start: Int, _ count: Int, _ sum: Int) {
        if count == m {
            if sum >= 2 && isPrime[sum] {
                possiblePrimes.insert(sum)
            }
            return
        }
        
        if n - start < m - count {
            return
        }
        
        for i in start..<n {
            visited[i] = true
            backtrack(i + 1, count + 1, sum + cowsWeight[i])
            visited[i] = false
        }
    }
    
    backtrack(0, 0, 0)
    
    let res = Array(possiblePrimes).sorted()
    
    return res.isEmpty ? "-1" : res.map { String($0) }.joined(separator: " ")
}

let input = readLine()!.split(separator: " ").map { Int($0)! }
let n = input[0]
let m = input[1]
let cowWeightArray = readLine()!.split(separator: " ").map { Int($0)! }

let res = solution(n, m, cowWeightArray)
print(res)
image

<기존 제가 생각한 풀이>

  1. M가지 조합 중 가장 큰 수를 찾는다.
  2. 에라토스테네스의 체를 활용하여 가장 큰 수안의 소수를 찾는다.
  3. M마리의 소를 선택하는 모든 경우의 수(백트래킹)를 찾으면서 합이 소수인지 확인한다.

<변경된 풀이 by gpt쌤>

  1. 소의 무게 배열에서 모든 무게의 합을 구하여 최대 가능한 합을 찾는다. -> 굳이 정렬해서 할 필요 x
  2. 에라토스테네스의 체를 활용하여 총합까지의 모든 소수를 찾는다.
  3. 비트마스킹을 사용하여 모든 가능한 M개의 조합을 찾는다.
    • 총 조합 수는 2^N개
    • 각 마스크(0 ~ 2^N-1)에 대해:
      a. 마스크에서 1의 개수(선택된 소의 수)를 센다
      b. 선택된 소들의 무게 합을 계산한다
      c. 선택된 소의 수가 M이고 무게 합이 소수인 경우, 결과에 추가한다
  4. 결과를 오름차순으로 정렬하여 반환

📚 새롭게 알게된 내용

(런타임 오류 난 내용 돌아보고 글 추가 예정 + 비트마스킹에 대한 이해)

기억 되살리는용으로 쇼츠하나 봤는데 이거 하나면 이해 뚝딱입니다.
에라토스테네스의 체 간단이해 쇼츠

또 제곱근 지원하는 함수가 있나 검색해봤는데 2개있더라구요.
sqrt() vs squareRoot()
결론부터 말하자면 성능적인 차이는 없다고합니다.
구글링 해보니 대부분은 sqrt를 쓰더군요. sqrt가 파이썬에도 있어서 익숙하다고 느껴졌습니다.
그냥 sqrt는 Foundation 라이브러리를 필요로하고 squareRoot는 기본 지원한다! 요정도만 알아도 될 것 같습니다.
sqrt는 함수 방식

import Foundation

sqrt(50.0)

squareRoot는 객체지향방식?

let n = 50.0
n.squareRoot()

전 squareRoot 썼어요!

Comment on lines +59 to +62
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

백준은 진짜 항상 입력받는게 번거롭네요.. 코드완성한다음에 MOO의 입력받는부분 야무지게 가져왔습니닷

  • 이전에 개미에서 배운 solution()묶어주는거 같이 쓰고 있어요

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

약간 이 부분 보고 있으면 프로그래머스식의 문제로 바꿔서 푸는 느낌이 있는 것 같아요 ㅋㅋㅋㅋ..

Comment on lines +4 to +18
Copy link
Collaborator

@bishoe01 bishoe01 Apr 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 어처피 소수 판단하겠구나해서 그냥 엄청 간단한 소수 판별 함수 짜주고 시작했어요!

그래서 무꺼보고, 아 이거 에라토스테네스하는게 훨씬 효율적이었나해서 좀 더 알아보니까

소수를 많이 판별해야 하거나 범위가 좁을 경우에는
에라토스테네스의 체를 사용하는 게 재활용도 가능하니까 훨씬 효율적이라네요 !

근데 저는 이 문제는 소가 최대 9마리밖에 안돼서 조합의 개수가 엄청 적고,
근데 9라는 작은 수에 비해서는 각 마리당 무게가 1000 이하라서 (이 수도 충분히 작을 수 있지만 소의 수에 비해서는 좀 큰느낌) 메모리 면에서 좀 비효율적일수도 있을것같다는 생각을 해봤습니다 !
사실 마리수나, 무게나 그렇게 큰 효율을 요구하는 문제는 아닌 것 같지만 혹시나 나중에 도움이 될까해서 말씀드려봐요!

그래서 이렇게 되게 적은 수 정도는 직접 판단해도 충분히 괜찮겠다는 생각이 들었어요!
짜는데도 훨씬 쉬우니까 시간 절약에 좀 도움이 될 수 있을까해서 공유드립니다 !

에라토스 테네스 채 : O(n log log n)
isPrime : O(√n) (대신 얘는 큰 수에 대해서 나눗셈 연산이 많이 들어감)

알아낸 것

  • 수가 적을수록 간단하게 만든 함수가 더 빠름
  • 수가 높아질수록 에라토스 압승 (대신에 수가 클지라도, 범위가 엄청 넓은데, 판단해야하는 개수는 적고 엄청 듬성 듬성 있다면 비효율적-메모리)
    사실 이렇게 효율따질 정도가 오면 무조건 체가 좋은 것 같아요
func isPrime(_ n: Int) -> Bool { // 소수 판단 함수
    guard n > 1 else { return false }
    if n == 2 {
        return true
    }
    for i in 2 ... Int(sqrt(Double(n)))+1 {
        if n % i == 0 {
            return false
        }
    }
    return true
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그렇네요! 소수 판별 문제에서는 그냥 에라토스테네스체가 정답이다라고 생각했는데 위 문제처럼 판별 할 수가 많지 않은 경우에는 불필요 할 수도 있겠네요.
핀은 에라토스테네스체를 염두하지 않고 바로 소수 판별로 들어간 걸까요? 아니면 구분 할 케이스가 별로 없다고 판단하고 간단하게 구현하신걸까요?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 깊게 생각은하지않고, 그냥 소수판별하는구나!해서 일단 간단하게 구현해놓고 시작했어요!
제출하면서 시간초과뜨면 그때 체를 써야겠다 했습니다 !

Comment on lines +37 to +53
Copy link
Collaborator

@bishoe01 bishoe01 Apr 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

비트마스킹 미쳤네요...
비트에서 선택된 인덱스로 하는건 알겠는데, 지피티쌤한테 계속 물어봐서 감 정도만 잡았습니다..
나중에 블로그 같은데에 정리하면서 한 번 제대로 다듬어봐야겠네요..!

아래는 짱피티쌤한테 하나하나 다 달라해서 한번 흐름따라가봤던 표입니다!
다른 PR하시는분들께 도움이 되길바라며..

1 << 4 = 16 → 총 16개의 부분집합(0부터 15까지 mask 순회)

mask (10진수) mask (2진수) 선택된 인덱스 선택된 값들 count sum
0 0000 [] [] 0 0
1 0001 [0] [2] 1 2
2 0010 [1] [4] 1 4
3 0011 [0, 1] [2, 4] 2 6
4 0100 [2] [5] 1 5
5 0101 [0, 2] [2, 5] 2 7
6 0110 [1, 2] [4, 5] 2 9
7 0111 [0, 1, 2] [2, 4, 5] 3 11
8 1000 [3] [7] 1 7
9 1001 [0, 3] [2, 7] 2 9
10 1010 [1, 3] [4, 7] 2 11
11 1011 [0, 1, 3] [2, 4, 7] 3 13
12 1100 [2, 3] [5, 7] 2 12
13 1101 [0, 2, 3] [2, 5, 7] 3 14
14 1110 [1, 2, 3] [4, 5, 7] 3 16
15 1111 [0, 1, 2, 3] [2, 4, 5, 7] 4 18

예를 들어 mask = 5 (0101)일 때

  • 인덱스 0번과 2번이 선택됨 → [2, 5]
  • sum = 7
  • count = 2
  • count == m이면 sum이 소수인지 검사

Copy link
Collaborator Author

@MuchanKim MuchanKim Apr 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 이해가 어렵더라고요... 거의 피티 선생님이 풀어줬다고봐도 무방합니다. 그래서 다른분들 코드가 기다려지는 부분... 핀 열심히 하는 모습보니까 동기부여되고 좋네요! 항상 정성 피드백 굿쟙입니다. 리뷰 다 달고 이 문제는 꼭 다시 보려구요.,!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아래도 얘기하지만 비트마스킹은 생각도 못했네요 ㄷㄷ
위에 표로 올려주신 핀도 감사합니다 이해가 쉽네요.

그런데 코드를 보다 보니, count 값이 이미 m과 같아졌다면 이후에도 계속 반복문을 돌면서 sum을 계산하는 것이 없어도 되지 않을까요?? (제가 잘못 이해했을 수도 있씁니다.ㅎㅎ)

지금은 아래코드처럼 루프를 무조건 0부터 n-1까지 끝까지 도는 구조인 것 같습니다!
결론적으로 count가 m을 초과해도 끝까지 다 도는 것 같습니다.

for i in 0..<n {
    if (mask & (1 << i)) != 0 {
        count += 1
        sum += cowsWeight[i]
    }
}

문제에서 원하는 건 정확히 m개의 소를 선택했을 때의 합이니깐
아래처럼 if count > m { break }로 반복을 미리 종료하면 성능 개선이 좀 더 될 것 같슴다!!

for i in 0..<n {
    if (mask & (1 << i)) != 0 {
        count += 1
        if count > m { break } 
        sum += cowsWeight[i]
    }
}

특히 N이 커지면 영향이 클 수 있을 것 같슴다...!
놓친게 있다면 알려주십셔,,,

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호 저도 비트마스킹으로 할 생각은 못했어요!! (사실 비트마스킹을 아직 잘 모르기도 하고)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

핀이 적어주신 비트마스킹이 이해 하는데 도움이 많이 됏네요 감사합니다!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

세션시간에 리뷰하는 개고수 장님..!

Copy link
Collaborator

@bishoe01 bishoe01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JPEG 이미지-41CE-BE36-C9-0

입력받는 부분은 제외하고 올릴게요 !

수도코드

  • 처음 문제 파악단계에서는 1000개 중에 9개를 고르는 건지 알고 위처럼 적었던 것 같아요
  • M개를 다 더한 시점만 판단해주고, 겹쳤을때만 생략해도 괜찮을 것 같다는 생각에서 출발했습니다.
    그래서 이미 계산된 것을 생략할 선택안이 3개였는데,
  1. 방문배열처럼 관리
  2. Dictionary로 관리
  3. Set으로 관리 (성공Set, 실패Set 나눈채로 코드를 짰는데, 어처피제가 )
    조건문으로 성공Set에도 없고, 실패Set에도 없을 때를 조건으로 쓰고 있더라구요, 그래서 이럴거면 그냥 방문Set느낌으로 통일하자 했고, 완성된걸 따로 answer을 만들어줬습니다.

그래서 막상이제 다 기획은 끝난것같은데, 어떻게 이걸 순환할 것이냐? 가 걸리더라구요

포문을 무슨 9개 만들어줄것도아니다보니,, 그래서 어처피 인덱스로 관리할 수 있으니까 재귀쓰면서 그냥 인덱스만 옮겨가게끔 해줬습니다.

import Foundation

func solution(_ n: Int, _ m: Int, weights: [Int]) {
    let LEN = weights.count

    // 이미 된놈 안된놈 구분하면 좀 낫지않나?
    var visitedSet = Set<Int>()
    var resultArr = Set<Int>()
    // 어떻게 순환을 해줄것인가? M개 포문돌릴 수는 없으니 ..
    func recursive(_ idx: Int, _ cnt: Int, _ sum: Int) { // 재귀 돌리기
        if cnt == m { // 길이충족
            if !visitedSet.contains(sum) { // 첨보는애
                visitedSet.insert(sum) // 방문에 추가
                if isPrime(sum) {
                    resultArr.insert(sum)
                }
            }
            return
        }
        for i in idx ..< LEN {
            recursive(i+1, cnt+1, sum+weights[i])
        }
    }
    recursive(0, 0, 0)
    var result = Array(resultArr)
    if result.isEmpty {
        print(-1)
    } else {
        result.sort()
//        print(resultArr)
        print(result.map { String($0) }.joined(separator: " ")) // 백준 걍 배열로 주니까 뱉어버리네요.. 🤬
    }
}
func isPrime(_ n: Int) -> Bool { // 소수 판단 함수
    guard n > 1 else { return false }
    if n == 2 {
        return true
    }
    for i in 2 ... Int(sqrt(Double(n))) {
        if n % i == 0 {
            return false
        }
    }
    return true
}

solution(n, m, weights: cowWeightArray)

재귀 설명

0부터 시작하면

  1. 0이 일단 담기고 1마리
  2. 1이 추가로 담겨서 2마리
  3. 2가 추가로 담겨서 3마리가 되는 순간이제 소수 판단해서 아웃하고 ,
  4. 지금까지 담긴게 (0,1,2)였다면이제, 거기서 또 반복문이 돌아서 (0,1,3) , (0,1,4)이런식으로
    첫번째 소가 0번째 소일때 이렇게 쭉 훑어지고,
    그다음 소로 넘어가면이제 1번째소를 시작으로 쭉 오른쪽으로 훑어지는 구조가 나옵니다.

결국 3마리 완성댈때마다 이미 계산했는지를 판단해주고 그게 아니면 판단해서 방문Set에 넣어주면서 관리해주면 끝 !

--- 틀리던거 고치고 시간초과 뜨겠지..하면서 풀다가
타임 에러 를 걍 뇌없이 아 시간초과가 뜨는구나!해서 계속 바꿔줬는데, 진짜로 그냥 오류였더라구요..

스크린샷 2025-04-12 오후 6 43 48

해당 아래 isPrime범위에서 + 1 추가주니까 해결이 됐습니다.
2 ... Int(sqrt(Double(n)))범위때문에 그런 것 같더라구요 2가 더 커지는 경우인지.. 아니면 다른 변수가 있나..

func isPrime(_ n: Int) -> Bool { // 소수 판단 함수
    guard n > 1 else { return false }
    if n == 2 {
        return true
    }
    for i in 2 ... Int(sqrt(Double(n))) {
        if n % i == 0 {
            return false
        }
    }
    return true
}

Copy link
Member

@giljihun giljihun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

>> 소들은 항의했지만 소들의 항의는 받아들여지지 않았다.

문제 설명 진짜 넘웃김요 제작자 천재

일단 위에서도 말씀드렸지만, 저는 조합을 구함에 있어서 비트마스킹은 생각도 못했는데
좋은 인사이트 감사합니다!!

저는 입력의 수가 적다고 생각해서 단순하게 아래 로직으로 구현해봤어요

1. 입력
2. 만들 수 있는 조합 배열 구하기
3. 소수판정
4. 출력

image

아마 메모리나 시간효율이 훨씬 떨어질 것 같네요
그리고 이 문제는 함수 단위로 쪼개는게 직관적이기도하고 무처럼 함수단위로 나눠보려고 노력했슴다

/* MARK: - SOLUTION
 
 // INPUT
 소들은 항의했지만 소들의 항의는 받아들여지지 않았다.
5 3
2 4 10 5 8
 
 1. 입력
 2. 조합 배열 구하기(시간 괜찮을듯?)
 3. 소수판정
 4. 출력
 
 */

import Foundation


// MARK: - Funcs
// "앞에서부터 하나씩 뽑고, 그 다음 나머지에서 뽑자."
func comb(_ arr: [Int], _ k: Int) -> [[Int]] {
    if k == 0 { return [[]] }
    
    var result = [[Int]]()
    
    for i in 0...(arr.count - k) {
        let currentNum = arr[i]
        let remainingNums = Array(arr[(i+1)...])
        let remainingCombs = comb(remainingNums, k - 1)
        
        for comb in remainingCombs {
            result.append([currentNum] + comb)
        }
    }
    return result
}

func isPrime(_ num: Int) -> Bool {
    if num < 2 { return false }
    
    for i in 2..<num {
        if num % i == 0 {
            return false
        }
    }
    return true
}

func getPrimes(_ cows: [Int]) {
    let sum = cows.reduce(0, +)
    
    if isPrime(sum) && !primes.contains(sum) {
        primes.append(sum)
    }
}

// MARK: - Input & Output

guard let input = readLine(),
      let N = Int(input.split(separator: " ")[0]),
      let M = Int(input.split(separator: " ")[1]) else { exit(0) }

guard let cowArray = readLine()?.split(separator: " ").compactMap({ Int($0) }) else { exit(0) }

let combinations = comb(cowArray, M)
var primes = [Int]()

combinations.forEach { getPrimes($0) }

if primes.count == 0 {
    print(-1)
} else {
    primes.sort()
    print(primes.map {String($0)}.joined(separator: " "))
}

image

.forEach 열심히 연습도했는데 이거때매 많이 틀렷네요 하하..

추가적으로 정렬도 안해줘서 문제 다시 읽어보기도하고 삽질 많이 했네요.. 하하


참고문헌

swift 순열, 조합 구현

저는 도저히 제 머리로는 조합 함수를 못짜겠더라고요,,..
사실 매우 근접했지만 너무 비효율적으로 짠 것 같아서
순열, 조합 함수 직접 구현 블로그를 참고했어요.

추가적으로 앱에 이런 순열, 조합이 필요하다면 직접 구현말고 아래 공식 라이브러리를 넣는 것도 방법이겠습니다.
https://github.com/apple/swift-algorithms

Comment on lines +37 to +53
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아래도 얘기하지만 비트마스킹은 생각도 못했네요 ㄷㄷ
위에 표로 올려주신 핀도 감사합니다 이해가 쉽네요.

그런데 코드를 보다 보니, count 값이 이미 m과 같아졌다면 이후에도 계속 반복문을 돌면서 sum을 계산하는 것이 없어도 되지 않을까요?? (제가 잘못 이해했을 수도 있씁니다.ㅎㅎ)

지금은 아래코드처럼 루프를 무조건 0부터 n-1까지 끝까지 도는 구조인 것 같습니다!
결론적으로 count가 m을 초과해도 끝까지 다 도는 것 같습니다.

for i in 0..<n {
    if (mask & (1 << i)) != 0 {
        count += 1
        sum += cowsWeight[i]
    }
}

문제에서 원하는 건 정확히 m개의 소를 선택했을 때의 합이니깐
아래처럼 if count > m { break }로 반복을 미리 종료하면 성능 개선이 좀 더 될 것 같슴다!!

for i in 0..<n {
    if (mask & (1 << i)) != 0 {
        count += 1
        if count > m { break } 
        sum += cowsWeight[i]
    }
}

특히 N이 커지면 영향이 클 수 있을 것 같슴다...!
놓친게 있다면 알려주십셔,,,

Copy link
Member

@alstjr7437 alstjr7437 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 우선 생각한게 그냥 소수 판별로 간단하게 되고 시간 초과도 안날 것 같았습니다!!

그런데 오래만에 체의 개념도 다시 알아가고 코드도 짜볼겸 체를 사용한 것 같아요

  1. 최대 조합 수를 구한다
  2. 최대 조합 수까지 체를 돌린다.
  3. 소들의 조합을 구한다(dfs)
  4. 조합과 체 두개의 배열을 이용해서 result에 넣는다
  5. 출력한다

이런식으로 진행 한 것 같습니다!!

저도 소들의 조합을 찾는 곳에서 많이 막혔었는데 저는 DFS를 이용해서 했습니다!

let NM = readLine()!.split(separator: " ").map{ Int(String($0))! }
let N = NM[0]
let M = NM[1]
let H = readLine()!.split(separator: " ").map { Int(String($0))! }

// 에라토스테네스의 체 부분
let maxValue = H.reduce(0, +) + 1
var sosu = Array(repeating: true, count: maxValue)
sosu[0] = false
sosu[1] = false

for i in 2..<maxValue {
    if sosu[i] {
        var j = 2
        while i * j < maxValue {
            sosu[i * j] = false
            j += 1
        }
    }
}

// 소들의 조합 찾는 dfs
func dfs(_ idx: Int, _ count: Int, _ total: Int) {
    if count == M {
        cows.insert(total)
        return
    }
    if idx == N { return }

    dfs(idx + 1, count + 1, total + H[idx])
    dfs(idx + 1, count, total)
}
var cows = Set<Int>()
dfs(0, 0, 0)

// 결과를 넣을 부분
var result: [Int] = []
for cow in cows {
    if cow < maxValue && sosu[cow] {
        result.append(cow)
    }
}

// 결과 출력하기
if result.isEmpty {
    print(-1)
} else {
    print(result.sorted().map { String($0) }.joined(separator: " "))
}

Comment on lines +37 to +53
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호 저도 비트마스킹으로 할 생각은 못했어요!! (사실 비트마스킹을 아직 잘 모르기도 하고)

Comment on lines +59 to +62
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

약간 이 부분 보고 있으면 프로그래머스식의 문제로 바꿔서 푸는 느낌이 있는 것 같아요 ㅋㅋㅋㅋ..

Copy link
Collaborator

@YooGyeongMo YooGyeongMo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

비트 마스킹이라니 ... 와 진짜 .... 생각치도 못했습니다.... 머리 터질꺼같은데 이것은 주말에 비트마스킹으로 풀어보도록하겠습니다 무센세...

Copy link
Collaborator

@YooGyeongMo YooGyeongMo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

approve테스트용

@MuchanKim MuchanKim merged commit 64ae784 into main Apr 27, 2025
16 checks passed
@alstjr7437 alstjr7437 deleted the 2-MuchanKim branch May 23, 2025 06:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants