본문 바로가기
Algorithm/문제풀이_백준

[Swift][비트마스킹] 백준 11723번 (집합)

by Joahnee 2022. 3. 14.

요구능력 : 비트연산

 

코드설명 : 

 

이론적으로 어려운 문제는 아닌데 Swift로는 난이도가 상당한문제이다.

 

이 문제는 wapas님의 IO을 줄여주는 코드가 없으면 풀 수 없는것같다.

아래 코드의 경우 Int는 그냥 readInt()로 받아주면 되지만, String의 경우에는 Byte의 합으로 출력을 해주므로 "add" -> 297 이런식으로 String -> 10진수로 변환해서 모든 값을 더한 값을 알아내야하는 노가다를 해줘야한다.

class FileIO {
    @inline(__always) private var buffer: [UInt8] = Array(FileHandle.standardInput.readDataToEndOfFile()) + [0], byteIdx = 0
    
    @inline(__always) private func readByte() -> UInt8 {
        defer { byteIdx += 1 }
        return buffer.withUnsafeBufferPointer { $0[byteIdx] }
    }
    
    @inline(__always) func readInt() -> Int {
        var number = 0, byte = readByte(), isNegative = false
        while byte == 10 || byte == 32 { byte = readByte() }
        if byte == 45 { byte = readByte(); isNegative = true }
        while 48...57 ~= byte { number = number * 10 + Int(byte - 48); byte = readByte() }
        return number * (isNegative ? -1 : 1)
    }
    
    @inline(__always) func readStirngSum() -> Int {
        var byte = readByte()
        while byte == 10 || byte == 32 { byte = readByte() }
        var sum = Int(byte)
        while byte != 10 && byte != 32 && byte != 0 { byte = readByte(); sum += Int(byte) }
        return sum - Int(byte)
    }
    
    @inline(__always) private func write(_ output: String) {
        FileHandle.standardOutput.write(output.data(using: .utf8)!)
    }
}

 

하나만 예시를 들어 설명하자면,

case 297:

|=연산의 경우에는 bit에 |=의 오른쪽에 있는 값과 or연산을 해서 bit에 집어넣는다는 의미이다.

1 << file.readInt()는 만약 입력을 3으로 받았다면 1 << 3이 될 것이고,

1비트를 3만큼 이동시킨다는 의미이다.

bit의 현재 값이 0이라면 나머지 비트는 그대로이고 3 + 1번째 비트만 1로 바뀌게 된다.

만약 00000이 있다면, 01000 이 된다.

switch file.readStirngSum(){
    case 297:
        bit |= (1 << file.readInt())
    case 654:
        bit &= ~(1 << file.readInt())
    case 510:
        
        if (bit & (1 << file.readInt()) != 0){
            result.append("1\n")
        }else{
            result.append("0\n")
        }
    case 642:
        bit ^= (1 << file.readInt())
    case 313:
        bit |= (~0)
    case 559:
        bit &= 0
    default:
        break
    }

 

 

요약하자면, 비트마스킹으로 집합을 관리하였다.

1은 1번째비트 2는 2번째비트 3은 3번째비트 ... 이런식으로 관리한것이다.

만약 1번째 비트가 1이라면 1이 존재하는것이고,

1번째 비트가 0이라면 1이 존재하지 않는것이다.

 

후기 : 이해는 빨리했는데,, 입출력 때문에 고생한문제

import Foundation

class FileIO {
    @inline(__always) private var buffer: [UInt8] = Array(FileHandle.standardInput.readDataToEndOfFile()) + [0], byteIdx = 0
    
    @inline(__always) private func readByte() -> UInt8 {
        defer { byteIdx += 1 }
        return buffer.withUnsafeBufferPointer { $0[byteIdx] }
    }
    
    @inline(__always) func readInt() -> Int {
        var number = 0, byte = readByte(), isNegative = false
        while byte == 10 || byte == 32 { byte = readByte() }
        if byte == 45 { byte = readByte(); isNegative = true }
        while 48...57 ~= byte { number = number * 10 + Int(byte - 48); byte = readByte() }
        return number * (isNegative ? -1 : 1)
    }
    
    @inline(__always) func readStirngSum() -> Int {
        var byte = readByte()
        while byte == 10 || byte == 32 { byte = readByte() }
        var sum = Int(byte)
        while byte != 10 && byte != 32 && byte != 0 { byte = readByte(); sum += Int(byte) }
        return sum - Int(byte)
    }
    
    @inline(__always) private func write(_ output: String) {
        FileHandle.standardOutput.write(output.data(using: .utf8)!)
    }
}
//시간 줄인요소
//1. Wapas님 입출력
//2. print() result에 모아서 한번에 출력

let file = FileIO()
var m = file.readInt()

var bit = 0
var result = ""
while m != 0{
//    let oper = file.readStirngSum()
//    let x = file.readInt()
    switch file.readStirngSum(){
    case 297:
        bit |= (1 << file.readInt())
    case 654:
        bit &= ~(1 << file.readInt())
    case 510:
        
        if (bit & (1 << file.readInt()) != 0){
            result.append("1\n")
        }else{
            result.append("0\n")
        }
    case 642:
        bit ^= (1 << file.readInt())
    case 313:
        bit |= (~0)
    case 559:
        bit &= 0
    default:
        break
    }
    m -= 1
}
print(result)

댓글