내가 푼 풀이

- 두 원이 주어졌을때 교차하는 경우의수를 알고 있으면 된다.

- 두 원과의 거리를 dist, 각각 원의 반지름을 r1 ,r2라고 할때

 

d

1. dist > r1 + r2 : 원이 서로 만나지 않는 경우

 

2. dist = r1 + r2: 두 원이 교차하는 점이 한개 인 경우

 

3. dist < r1 + r2, dist > |r1 - r2| : 두 원이 교차하여 접점이 두개인 경우

-> 원이 교차하는 시점부터는 모든 경우의 수는 dist < r1 + r2가 성립하므로 반지름의 차로 경우의수를 구해야한다.

 

4. dist < r1 + r2 , dist == |r1 - r2|: 한개의 작은 원이 큰원 안에 들어가있고 접점이 한개인 경우

 

5. dist < r1 + r2 , dist < |r1 - r2|: 원이 내부에 있지만, 접점이 없는 경우

 

 

6. dist == 0, r1 == r2: 두 원이 일치하는경우

 

--> 위의 6가지 경우의수를 코드로 구현하면 된다.

 

import Foundation

let T = Int(readLine()!)!

for i in 0..<T {
    let arr = readLine()!.split(separator: " ").map{Double(String($0))!}
    let x1: Double = arr[0], y1 = arr[1], dist1 = arr[2]
    let x2: Double = arr[3], y2 = arr[4], dist2 = arr[5]
    var totalDist: Double {
        return sqrt(pow((abs(x1 - x2)), 2) + pow(abs(y1 - y2), 2))
    }
    if totalDist == 0 && dist1 == dist2{
        print(-1)
        continue
    }
    if totalDist > dist1 + dist2 {
        print(0)
    } else if totalDist == dist1 + dist2 {
        print(1)
    } else if totalDist < dist1 + dist2 {
        if totalDist > abs(dist1 - dist2) {
            print(2)
        } else if totalDist == abs(dist1 - dist2) {
            print(1)
        } else {
            print(0)
        }
    }
}

 

원의 성질 사진 출처:

https://kg-m-s-a-k-mol-cd.tistory.com/242

 

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-1654 랜선 자르기 Swift  (0) 2024.04.05
BOJ-1920 수 찾기 Swift  (0) 2024.04.05
BOJ-11286 절댓값 힙 Swift  (0) 2024.04.04
BOJ-11279 최대 힙 Swift  (0) 2024.04.04
BOJ-28279 덱 2 Swift  (0) 2024.04.03

문제

절댓값 힙은 다음과 같은 연산을 지원하는 자료구조이다.

  1. 배열에 정수 x (x ≠ 0)를 넣는다.
  2. 배열에서 절댓값이 가장 작은 값을 출력하고, 그 값을 배열에서 제거한다. 절댓값이 가장 작은 값이 여러개일 때는, 가장 작은 수를 출력하고, 그 값을 배열에서 제거한다.

프로그램은 처음에 비어있는 배열에서 시작하게 된다.

입력

첫째 줄에 연산의 개수 N(1≤N≤100,000)이 주어진다. 다음 N개의 줄에는 연산에 대한 정보를 나타내는 정수 x가 주어진다. 만약 x가 0이 아니라면 배열에 x라는 값을 넣는(추가하는) 연산이고, x가 0이라면 배열에서 절댓값이 가장 작은 값을 출력하고 그 값을 배열에서 제거하는 경우이다. 입력되는 정수는 -231보다 크고, 231보다 작다.

출력

입력에서 0이 주어진 회수만큼 답을 출력한다. 만약 배열이 비어 있는 경우인데 절댓값이 가장 작은 값을 출력하라고 한 경우에는 0을 출력하면 된다.

내가 푼 풀이

- 최소힙 기반으로 정렬기준을 좀 바꾸면 된다.

- 절댓값이 같다면, 값이 작은게 우선인 힙을 만들면 된다.

 

import Foundation

struct Heap<T: Comparable> {
    var elements: [T] = []
    var sortFunction: (T,T) -> Bool
    var isEmpty: Bool {
        return elements.isEmpty || elements.count == 1
    }
    var peek: T? {
        if elements.isEmpty {
            return nil
        } else {
            return elements[1]
        }
    }
    var count: Int {
        if elements.isEmpty {
            return 0
        } else {
            return elements.count - 1
        }
    }
    init(elements: [T] = [], sortFunction: @escaping (T,T) -> Bool) {
        if !elements.isEmpty {
            self.elements = [elements.first!] + elements
        } else {
            self.elements = elements
        }
        self.sortFunction = sortFunction
        if elements.count > 1 {
            self.buildHeap()
        }
    }
    func leftChild(of index: Int) -> Int {
        return index * 2
    }
    func rightChild(of index: Int) -> Int {
        return index * 2 + 1
    }
    func parent(of index: Int) -> Int {
        return index / 2
    }

    mutating func swimUp(from index: Int) {
        var idx = index
        while idx != 1 && self.sortFunction(self.elements[idx], self.elements[parent(of: idx)]) {
            self.elements.swapAt(idx, self.parent(of: idx))
            idx = self.parent(of: idx)
        }
    }
    mutating func insert(element: T) {
        if self.elements.isEmpty {
            self.elements.append(element)
            self.elements.append(element)
            return
        }
        self.elements.append(element)
        self.swimUp(from: self.elements.endIndex - 1)
    }
    mutating func diveDown(from index: Int) {
        var higherPriority = index
        let leftIndex = self.leftChild(of: index)
        let rightIndex = self.rightChild(of: index)

        if leftIndex < self.elements.endIndex && self.sortFunction(self.elements[leftIndex], self.elements[higherPriority]) {
            higherPriority = leftIndex
        }
        if rightIndex < self.elements.endIndex && self.sortFunction(self.elements[rightIndex], self.elements[higherPriority]) {
            higherPriority = rightIndex
        }
        if higherPriority != index {
            self.elements.swapAt(index, higherPriority)
            self.diveDown(from: higherPriority)
        }
    }
    
    mutating func buildHeap() {
        for i in (1...(self.elements.count / 2)).reversed() {
            self.diveDown(from: i)
        }
    }
    mutating func remove() -> T? {
        if self.isEmpty {
            return nil
        }
        self.elements.swapAt(1, self.elements.endIndex - 1)
        var returnValue = self.elements.removeLast()
        self.diveDown(from: 1)
        
        return returnValue
    }
}

let N = Int(readLine()!)!
var heap = Heap(elements: [Int](),sortFunction: { if abs($0) == abs($1) {
    return $0 < $1
} else {
    return abs($0) < abs($1)
}})

for i in 0..<N {
    let num = Int(readLine()!)!
    if num == 0 {
        if let poped = heap.remove() {
            print(poped)
        } else {
            print(0)
        }
    } else {
        heap.insert(element: num)
    }
}

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-1920 수 찾기 Swift  (0) 2024.04.05
BOJ-1002 터렛 Swift  (0) 2024.04.04
BOJ-11279 최대 힙 Swift  (0) 2024.04.04
BOJ-28279 덱 2 Swift  (0) 2024.04.03
BOJ-24511 queuestack Swift  (1) 2024.04.03

문제

널리 잘 알려진 자료구조 중 최대 힙이 있다. 최대 힙을 이용하여 다음과 같은 연산을 지원하는 프로그램을 작성하시오.

  1. 배열에 자연수 x를 넣는다.
  2. 배열에서 가장 큰 값을 출력하고, 그 값을 배열에서 제거한다.

프로그램은 처음에 비어있는 배열에서 시작하게 된다.

입력

첫째 줄에 연산의 개수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 N개의 줄에는 연산에 대한 정보를 나타내는 정수 x가 주어진다. 만약 x가 자연수라면 배열에 x라는 값을 넣는(추가하는) 연산이고, x가 0이라면 배열에서 가장 큰 값을 출력하고 그 값을 배열에서 제거하는 경우이다. 입력되는 자연수는 231보다 작다.

출력

입력에서 0이 주어진 횟수만큼 답을 출력한다. 만약 배열이 비어 있는 경우인데 가장 큰 값을 출력하라고 한 경우에는 0을 출력하면 된다.

 

내가 푼 풀이

- 힙을 구현한 후 문제의 연산을 해주면 된다.

import Foundation

struct Heap<T: Comparable> {
    var elements: [T] = []
    var sortFunction: (T,T) -> Bool
    var isEmpty: Bool {
        return elements.isEmpty || elements.count == 1
    }
    var peek: T? {
        if elements.isEmpty {
            return nil
        } else {
            return elements[1]
        }
    }
    var count: Int {
        if elements.isEmpty {
            return 0
        } else {
            return elements.count - 1
        }
    }
    init(elements: [T] = [], sortFunction: @escaping (T,T) -> Bool) {
        if !elements.isEmpty {
            self.elements = [elements.first!] + elements
        } else {
            self.elements = elements
        }
        self.sortFunction = sortFunction
        if elements.count > 1 {
            self.buildHeap()
        }
    }
    func leftChild(of index: Int) -> Int {
        return index * 2
    }
    func rightChild(of index: Int) -> Int {
        return index * 2 + 1
    }
    func parent(of index: Int) -> Int {
        return index / 2
    }

    mutating func swimUp(from index: Int) {
        var idx = index
        while idx != 1 && self.sortFunction(self.elements[idx], self.elements[parent(of: idx)]) {
            self.elements.swapAt(idx, self.parent(of: idx))
            idx = self.parent(of: idx)
        }
    }
    mutating func insert(element: T) {
        if self.elements.isEmpty {
            self.elements.append(element)
            self.elements.append(element)
            return
        }
        self.elements.append(element)
        self.swimUp(from: self.elements.endIndex - 1)
    }
    mutating func diveDown(from index: Int) {
        var higherPriority = index
        let leftIndex = self.leftChild(of: index)
        let rightIndex = self.rightChild(of: index)

        if leftIndex < self.elements.endIndex && self.sortFunction(self.elements[leftIndex], self.elements[higherPriority]) {
            higherPriority = leftIndex
        }
        if rightIndex < self.elements.endIndex && self.sortFunction(self.elements[rightIndex], self.elements[higherPriority]) {
            higherPriority = rightIndex
        }
        if higherPriority != index {
            self.elements.swapAt(index, higherPriority)
            self.diveDown(from: higherPriority)
        }
    }
    
    mutating func buildHeap() {
        for i in (1...(self.elements.count / 2)).reversed() {
            self.diveDown(from: i)
        }
    }
    mutating func remove() -> T? {
        if self.isEmpty {
            return nil
        }
        self.elements.swapAt(1, self.elements.endIndex - 1)
        var returnValue = self.elements.removeLast()
        self.diveDown(from: 1)
        
        return returnValue
    }
}

let N = Int(readLine()!)!
var heap = Heap(elements: [Int](),sortFunction: { $0 > $1})

for i in 0..<N {
    let num = Int(readLine()!)!
    if num == 0 {
        if let poped = heap.remove() {
            print(poped)
        } else {
            print(0)
        }
    } else {
        heap.insert(element: num)
    }
}

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-1002 터렛 Swift  (0) 2024.04.04
BOJ-11286 절댓값 힙 Swift  (0) 2024.04.04
BOJ-28279 덱 2 Swift  (0) 2024.04.03
BOJ-24511 queuestack Swift  (1) 2024.04.03
BOJ-2346 풍선 터트리기 Swift  (0) 2024.04.03

문제

정수를 저장하는 덱을 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.

명령은 총 여덟 가지이다.

  1. 1 X: 정수 X를 덱의 앞에 넣는다. (1 ≤ X ≤ 100,000)
  2. 2 X: 정수 X를 덱의 뒤에 넣는다. (1 ≤ X ≤ 100,000)
  3. 3: 덱에 정수가 있다면 맨 앞의 정수를 빼고 출력한다. 없다면 -1을 대신 출력한다.
  4. 4: 덱에 정수가 있다면 맨 뒤의 정수를 빼고 출력한다. 없다면 -1을 대신 출력한다.
  5. 5: 덱에 들어있는 정수의 개수를 출력한다.
  6. 6: 덱이 비어있으면 1, 아니면 0을 출력한다.
  7. 7: 덱에 정수가 있다면 맨 앞의 정수를 출력한다. 없다면 -1을 대신 출력한다.
  8. 8: 덱에 정수가 있다면 맨 뒤의 정수를 출력한다. 없다면 -1을 대신 출력한다.

입력

첫째 줄에 명령의 수 N이 주어진다. (1 ≤ N ≤ 1,000,000)

둘째 줄부터 N개 줄에 명령이 하나씩 주어진다.

출력을 요구하는 명령은 하나 이상 주어진다.

출력

출력을 요구하는 명령이 주어질 때마다 명령의 결과를 한 줄에 하나씩 출력한다.

내가 푼 풀이

- 덱을 구현해서 해당 명령어를 실행하면 된다.

- 명령수가 많아서 입출력코드를 이용했다

 

import Foundation

final class FileIO {
    private let buffer:[UInt8]
    private var index: Int = 0

    init(fileHandle: FileHandle = FileHandle.standardInput) {
        
        buffer = Array(try! fileHandle.readToEnd()!)+[UInt8(0)] // 인덱스 범위 넘어가는 것 방지
    }

    @inline(__always) private func read() -> UInt8 {
        defer { index += 1 }

        return buffer[index]
    }

    @inline(__always) func readInt() -> Int {
        var sum = 0
        var now = read()
        var isPositive = true

        while now == 10
                || now == 32 { now = read() } // 공백과 줄바꿈 무시
        if now == 45 { isPositive.toggle(); now = read() } // 음수 처리
        while now >= 48, now <= 57 {
            sum = sum * 10 + Int(now-48)
            now = read()
        }

        return sum * (isPositive ? 1:-1)
    }

    @inline(__always) func readString() -> String {
        var now = read()

        while now == 10 || now == 32 { now = read() } // 공백과 줄바꿈 무시

        let beginIndex = index-1

        while now != 10,
              now != 32,
              now != 0 { now = read() }

        return String(bytes: Array(buffer[beginIndex..<(index-1)]), encoding: .ascii)!
    }

    @inline(__always) func readByteSequenceWithoutSpaceAndLineFeed() -> [UInt8] {
        var now = read()

        while now == 10 || now == 32 { now = read() } // 공백과 줄바꿈 무시

        let beginIndex = index-1

        while now != 10,
              now != 32,
              now != 0 { now = read() }

        return Array(buffer[beginIndex..<(index-1)])
    }
}

// 덱
struct Deque<T> {
    var enqueue: [T]
    var dequeue: [T] = []

    init(enqueue: [T]) {
        self.enqueue = enqueue
    }
    var count: Int {
        return enqueue.count + dequeue.count
    }
    var isEmpty: Bool {
        return enqueue.isEmpty && dequeue.isEmpty
    }

    mutating func first() -> T? {
        if dequeue.isEmpty {
            dequeue = enqueue.reversed()
            enqueue.removeAll()
        }
        return dequeue.last
    }
    mutating func last() -> T? {
        if enqueue.isEmpty {
            if dequeue.isEmpty {
                return nil
            } else {
                return dequeue[0]
            }
        } else {
            return enqueue.last
        }
    }
    mutating func pushFront(_ element: T) {
        dequeue.append(element)
    }
    mutating func pushRear(_ element: T) {
        enqueue.append(element)
    }
    mutating func popFront() -> T? {
        if dequeue.isEmpty {
            dequeue = enqueue.reversed()
            enqueue.removeAll()
        }
        return dequeue.popLast()
    }
    mutating func popRear() -> T? {
        if enqueue.isEmpty {
            enqueue = dequeue.reversed()
            dequeue.removeAll()
        }
        return enqueue.popLast()
    }
}
let fIO = FileIO()
let N = fIO.readInt()
var dq = Deque(enqueue: [Int]())

for i in 0..<N {
    let op = fIO.readInt()
    
    switch op {
    case 1:
        let element = fIO.readInt()
        dq.pushFront(element)
    case 2:
        let element = fIO.readInt()
        dq.pushRear(element)
    case 3:
        if let popFir = dq.popFront() {
            print(popFir)
        } else {
            print(-1)
        }
    case 4:
        if let popLas = dq.popRear() {
            print(popLas)
        } else {
            print(-1)
        }
    case 5:
        print(dq.count)
    case 6:
        print(dq.isEmpty ? 1 : 0)
    case 7:
        if let fir = dq.first() {
            print(fir)
        } else {
            print(-1)
        }
    case 8:
        if let las = dq.last() {
            print(las)
        } else {
            print(-1)
        }
    default: continue
    }
}

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-11286 절댓값 힙 Swift  (0) 2024.04.04
BOJ-11279 최대 힙 Swift  (0) 2024.04.04
BOJ-24511 queuestack Swift  (1) 2024.04.03
BOJ-2346 풍선 터트리기 Swift  (0) 2024.04.03
BOJ-2164 카드2 Swift  (0) 2024.04.02

 

내가 푼 풀이

- 이문제는 Swift한테 너무 가혹하다..

- 최대 10만개의 입력값들로 인해 입출력(라이노님)코드를 사용해야하고, 시간복잡도 O(n^2)는 무조건 시간초과가 뜬다.
- 문제를 곰곰히 생각해보면 한가지 알수있다.
- 원소를 queuestack에 넣으면 스택형 자료구조는 원소값에 영향을 주지않는다. ( push한 값이 pop되므로)
- 이 말은 queuestack의 스택구조인 원소들은 제외시켜도 결과값에 영향을 주지않는다는 것이다.
- 큐 구조의 원소들만 남겨놓고 이를 붙이면 하나의 큰 큐 배열이 된다.
- 만들어진 큐 배열에 원소를 push / pop 하면 정답값이 나온다.
- 시간초과에 너무 가혹해서 출력도 문자열 출력을 이용했다.

 

 

 

import Foundation

final class FileIO {
    private let buffer:[UInt8]
    private var index: Int = 0

    init(fileHandle: FileHandle = FileHandle.standardInput) {
        
        buffer = Array(try! fileHandle.readToEnd()!)+[UInt8(0)] // 인덱스 범위 넘어가는 것 방지
    }

    @inline(__always) private func read() -> UInt8 {
        defer { index += 1 }

        return buffer[index]
    }

    @inline(__always) func readInt() -> Int {
        var sum = 0
        var now = read()
        var isPositive = true

        while now == 10
                || now == 32 { now = read() } // 공백과 줄바꿈 무시
        if now == 45 { isPositive.toggle(); now = read() } // 음수 처리
        while now >= 48, now <= 57 {
            sum = sum * 10 + Int(now-48)
            now = read()
        }

        return sum * (isPositive ? 1:-1)
    }

    @inline(__always) func readString() -> String {
        var now = read()

        while now == 10 || now == 32 { now = read() } // 공백과 줄바꿈 무시

        let beginIndex = index-1

        while now != 10,
              now != 32,
              now != 0 { now = read() }

        return String(bytes: Array(buffer[beginIndex..<(index-1)]), encoding: .ascii)!
    }

    @inline(__always) func readByteSequenceWithoutSpaceAndLineFeed() -> [UInt8] {
        var now = read()

        while now == 10 || now == 32 { now = read() } // 공백과 줄바꿈 무시

        let beginIndex = index-1

        while now != 10,
              now != 32,
              now != 0 { now = read() }

        return Array(buffer[beginIndex..<(index-1)])
    }
}
// 큐
struct Queue<T> {
    var elements: [T]
    var idx = 0
    
    init(elements: [T]) {
        self.elements = elements
    }
    var isEmpty: Bool {
        return elements.isEmpty
    }
    mutating func push(element: T) {
        elements.append(element)
    }
    mutating func pop() -> T? {
        if elements.isEmpty || idx >= elements.count { return nil }
        let value = elements[idx]
        idx += 1
        return value
    }
}
// 입력
let fIO = FileIO()
let N = fIO.readInt()
var dataStruct = [Int]()
var elements = [Int]()
var inputElements = [Int]()
var queueIndexArr = [Bool]()
// 스택구조는 패스하고, 큐 구조의 원소만 받는다. 나중에 원소도 넣기위해 인덱스를 저장
for i in 0..<N {
    let input = fIO.readInt()
    if input == 0 {
        dataStruct.append(input)
        queueIndexArr.append(true)
    } else {
        queueIndexArr.append(false)
    }

}
// 저장해둔 인덱스에 따라 큐구조의 원소만 넣는다.
for i in 0..<N {
    let input = fIO.readInt()
    if queueIndexArr[i] {
        elements.append(input)
    }
}
let M = fIO.readInt()
for i in 0..<M {
    inputElements.append(fIO.readInt())
}
// 큐 구조만 가려서 만든 원소들을 하나의 큰 큐 배열로 만든다.
var queue = Queue(elements: elements.reversed())
var answer = ""

// queuestack에 넣을 원소들을 차례로 넣고 결과 출력
if queue.isEmpty {
    for i in 0..<inputElements.count {
        if i == inputElements.count-1 {
            answer += "\(inputElements[i])"
        } else {
            answer += "\(inputElements[i]) "
        }
    }
} else {
    for i in 0..<inputElements.count {
        queue.push(element: inputElements[i])
        if i == inputElements.count - 1 {
            answer += "\(queue.pop()!)"
        } else {
            answer += "\(queue.pop()!) "
        }
    }
}
print(answer)

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-11279 최대 힙 Swift  (0) 2024.04.04
BOJ-28279 덱 2 Swift  (0) 2024.04.03
BOJ-2346 풍선 터트리기 Swift  (0) 2024.04.03
BOJ-2164 카드2 Swift  (0) 2024.04.02
BOJ-18258 큐 2 Swift  (0) 2024.04.02

문제

1번부터 N번까지 N개의 풍선이 원형으로 놓여 있고. i번 풍선의 오른쪽에는 i+1번 풍선이 있고, 왼쪽에는 i-1번 풍선이 있다. 단, 1번 풍선의 왼쪽에 N번 풍선이 있고, N번 풍선의 오른쪽에 1번 풍선이 있다. 각 풍선 안에는 종이가 하나 들어있고, 종이에는 -N보다 크거나 같고, N보다 작거나 같은 정수가 하나 적혀있다. 이 풍선들을 다음과 같은 규칙으로 터뜨린다.

우선, 제일 처음에는 1번 풍선을 터뜨린다. 다음에는 풍선 안에 있는 종이를 꺼내어 그 종이에 적혀있는 값만큼 이동하여 다음 풍선을 터뜨린다. 양수가 적혀 있을 경우에는 오른쪽으로, 음수가 적혀 있을 때는 왼쪽으로 이동한다. 이동할 때에는 이미 터진 풍선은 빼고 이동한다.

예를 들어 다섯 개의 풍선 안에 차례로 3, 2, 1, -3, -1이 적혀 있었다고 하자. 이 경우 3이 적혀 있는 1번 풍선, -3이 적혀 있는 4번 풍선, -1이 적혀 있는 5번 풍선, 1이 적혀 있는 3번 풍선, 2가 적혀 있는 2번 풍선의 순서대로 터지게 된다.

입력

첫째 줄에 자연수 N(1 ≤ N ≤ 1,000)이 주어진다. 다음 줄에는 차례로 각 풍선 안의 종이에 적혀 있는 수가 주어진다. 종이에 0은 적혀있지 않다.

출력

첫째 줄에 터진 풍선의 번호를 차례로 나열한다.

내가 푼 풀이

- 처음에 인덱스만으로 풀려고 했다가 너무 복잡해져서 다른 방법을 찾았다.

- 이 문제는 자료구조 중 Deque의 성질인 양방향 Pop,push기능을 사용하여 풀었다.

- 코드와 알고리즘에 대한 설명은 주석처리해두었다.

 

import Foundation

// Deque
struct Deque<T> {
    var enqueue: [T]
    var dequeue: [T] = []

    init(enqueue: [T]) {
        self.enqueue = enqueue
    }
    var count: Int {
        return enqueue.count + dequeue.count
    }
    var isEmpty: Bool {
        return enqueue.isEmpty && dequeue.isEmpty
    }

    mutating func first() -> T? {
        if dequeue.isEmpty {
            dequeue = enqueue.reversed()
            enqueue.removeAll()
        }
        return dequeue.last
    }
    mutating func pushFront(_ element: T) {
        dequeue.append(element)
    }
    mutating func pushRear(_ element: T) {
        enqueue.append(element)
    }
    mutating func popFront() -> T? {
        if dequeue.isEmpty {
            dequeue = enqueue.reversed()
            enqueue.removeAll()
        }
        return dequeue.popLast()
    }
    mutating func popRear() -> T? {
        if enqueue.isEmpty {
            enqueue = dequeue.reversed()
            dequeue.removeAll()
        }
        return enqueue.popLast()
    }
}
// 입력
let N = Int(readLine()!)!
let booms = readLine()!.split(separator: " ").map{Int(String($0))!}
// Deque에 입력받은 정수 크기의 배열 넣는다
var dq = Deque(enqueue: Array(1...N))
// 결과를 저장할 배열
var result = [Int]()

// 처음에 첫번째 풍선을 터트리고 해당 인덱스에 있는 요소만큼 이동하여 다음 풍선을 터트린다.
// 인덱스를 사용하여 풍선을 터트릴 수 있지만, Deque 성질을 활용한다.
// 오른쪽으로(양수) 이동한다는 것은 가장 왼쪽 원소를 떼서 오른쪽으로 붙여넣는것이랑 같다.
// 반대로 왼쪽으로(음수) 이동한다는 것은 가장 오른쪽 원소를 떼서 왼쪽으로 붙여넣는것이랑 같다.
// push(pop)을 움직여야할 수만큼 움직였다면, 가장 왼쪽에는 문제에 나온대로 터트려야할 풍선이 위치하게 된다.
// 주의할점: 터트려야 할 풍선을 뻈다면, 자료형이 배열이라서 이미 오른쪽으로 한번 이동한 것과 같다.
// 따라서 오른쪽(양수)으로 이동은 1 적게 가고, 왼쪽(음수)이동은 이동해야 할 만큼 가야한다.
while true {
    let balloon = dq.popFront()!
    result.append(balloon)
    if result.count == N { break }
    var move = booms[balloon-1]
    if move > 0 {
        for i in 0..<move-1 {
            dq.pushRear(dq.popFront()!)
        }
    } else {
        for i in 0..<abs(move) {
            dq.pushFront(dq.popRear()!)
        }
    }
    
}
print(result.map{String($0)}.joined(separator: " "))

 

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-28279 덱 2 Swift  (0) 2024.04.03
BOJ-24511 queuestack Swift  (1) 2024.04.03
BOJ-2164 카드2 Swift  (0) 2024.04.02
BOJ-18258 큐 2 Swift  (0) 2024.04.02
BOJ-9012 괄호 Swift  (0) 2024.04.02

문제

N장의 카드가 있다. 각각의 카드는 차례로 1부터 N까지의 번호가 붙어 있으며, 1번 카드가 제일 위에, N번 카드가 제일 아래인 상태로 순서대로 카드가 놓여 있다.

이제 다음과 같은 동작을 카드가 한 장 남을 때까지 반복하게 된다. 우선, 제일 위에 있는 카드를 바닥에 버린다. 그 다음, 제일 위에 있는 카드를 제일 아래에 있는 카드 밑으로 옮긴다.

예를 들어 N=4인 경우를 생각해 보자. 카드는 제일 위에서부터 1234 의 순서로 놓여있다. 1을 버리면 234가 남는다. 여기서 2를 제일 아래로 옮기면 342가 된다. 3을 버리면 42가 되고, 4를 밑으로 옮기면 24가 된다. 마지막으로 2를 버리고 나면, 남는 카드는 4가 된다.

N이 주어졌을 때, 제일 마지막에 남게 되는 카드를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 정수 N(1 ≤ N ≤ 500,000)이 주어진다.

출력

첫째 줄에 남게 되는 카드의 번호를 출력한다.

내가 푼 풀이

- 큐를 간단히 구현한 후 해당 동작들을 메소드로 선언한다.

- 큐는 선입선출이기 때문에 Swift에서 큐를 배열로 선언해서 removeFirst() 식으로 하면 시간초과가 날것으로 예상했다.

- 그래서 index로 접근하여 push / pop 한다.

 

import Foundation
// 큐 구현 (index를 통한 pop)
struct Queue {
    var elements = [Int]()
    var idx = 0
    var count: Int {
        return elements.count
    }
    var top: Int {
        if elements.isEmpty || idx >= elements.count {
            return -1
        } else {
            return elements[idx]
        }
    }
    mutating func pop() -> Int {
        if elements.isEmpty || idx >= elements.count {
            return -1
        } else {
            let num = elements[idx]
            idx += 1
            return num
        }
    }
    
    mutating func moveToBack(element: Int) {
        if idx <= elements.count {
            elements.append(element)
        }
    }
}

let N = Int(readLine()!)!
var queue = Queue()
queue.elements = Array(1...N)
// index로 접근하기 때문에, 모든 동작이 완료될때까지
// 1번동작: pop, 2번동작: pop and move to back
// pop을 한 원소가 마지막인경우 출력, pop을 한 다음 원소 한개가 남은경우 2번동작 후 출력
// 마지막 순서로 옮기면 앞 원소가 pop되는거라 index가 증가해야 하지만 pop에서 이미 증가시키므로 추가로 증가하지않는다
while queue.idx < queue.count {
    let num = queue.pop()
    if queue.top == -1 {
        print(num)
        break
    }
    queue.moveToBack(element: queue.pop())
}

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-24511 queuestack Swift  (1) 2024.04.03
BOJ-2346 풍선 터트리기 Swift  (0) 2024.04.03
BOJ-18258 큐 2 Swift  (0) 2024.04.02
BOJ-9012 괄호 Swift  (0) 2024.04.02
BOJ-10773 제로 Swift  (1) 2024.04.02

문제

정수를 저장하는 큐를 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.

명령은 총 여섯 가지이다.

  • push X: 정수 X를 큐에 넣는 연산이다.
  • pop: 큐에서 가장 앞에 있는 정수를 빼고, 그 수를 출력한다. 만약 큐에 들어있는 정수가 없는 경우에는 -1을 출력한다.
  • size: 큐에 들어있는 정수의 개수를 출력한다.
  • empty: 큐가 비어있으면 1, 아니면 0을 출력한다.
  • front: 큐의 가장 앞에 있는 정수를 출력한다. 만약 큐에 들어있는 정수가 없는 경우에는 -1을 출력한다.
  • back: 큐의 가장 뒤에 있는 정수를 출력한다. 만약 큐에 들어있는 정수가 없는 경우에는 -1을 출력한다.

입력

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 2,000,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지 않은 명령이 주어지는 경우는 없다.

출력

출력해야하는 명령이 주어질 때마다, 한 줄에 하나씩 출력한다.

내가 푼 풀이

- 큐 구현자체는 어렵지않다. 해당 명령어만 메소드와 속성으로 만든 구조체 하나 만들면된다.

- 문제는 엄청 많은 입력값과 그에 준하는 출력이다.

- swift에 내장된 readLine() 과 print는 너무 느려서 시간초과가 난다.

- 이 문제는 Swift 파일 입출력, 큐의 index를 이용한 pop, 입력된 명령어를 byte로 바꿔 풀어야 겨우 시간초과를 면할 수 있었다.

- 추가로 출력은 문자열출력이 print 보다 더 빠르다

 

 

import Foundation

final class FileIO {
    private let buffer:[UInt8]
    private var index: Int = 0

    init(fileHandle: FileHandle = FileHandle.standardInput) {
        
        buffer = Array(try! fileHandle.readToEnd()!)+[UInt8(0)] // 인덱스 범위 넘어가는 것 방지
    }

    @inline(__always) private func read() -> UInt8 {
        defer { index += 1 }

        return buffer[index]
    }

    @inline(__always) func readInt() -> Int {
        var sum = 0
        var now = read()
        var isPositive = true

        while now == 10
                || now == 32 { now = read() } // 공백과 줄바꿈 무시
        if now == 45 { isPositive.toggle(); now = read() } // 음수 처리
        while now >= 48, now <= 57 {
            sum = sum * 10 + Int(now-48)
            now = read()
        }

        return sum * (isPositive ? 1:-1)
    }

    @inline(__always) func readString() -> Int {
        var str = 0
        var now = read()

        while now == 10 || now == 32 { now = read() } // 공백과 줄바꿈 무시

        let beginIndex = index-1

        while now != 10,
              now != 32,
              now != 0 {
            str += Int(now)
            now = read()
        }

        return str
    }

    @inline(__always) func readByteSequenceWithoutSpaceAndLineFeed() -> [UInt8] {
        var now = read()

        while now == 10 || now == 32 { now = read() } // 공백과 줄바꿈 무시

        let beginIndex = index-1

        while now != 10,
              now != 32,
              now != 0 { now = read() }

        return Array(buffer[beginIndex..<(index-1)])
    }
}

struct Queue {
    var elements = [Int]()
    var idx = 0
    var count: Int {
        return elements.count - idx
    }
    var front: Int {
        if elements.isEmpty || idx >= elements.count {
            return -1
        } else {
            return elements[idx]
        }
    }
    var back: Int {
        if elements.isEmpty || idx >= elements.count {
            return -1
        } else {
            return elements[elements.count - 1]
        }
    }
    var isEmpty: Int {
        if elements.isEmpty || idx >= elements.count {
            return 1
        } else {
            return 0
        }
    }
    
    mutating func push(element: Int) {
        elements.append(element)
    }
    
    mutating func pop() -> Int {
        if elements.isEmpty || idx >= elements.count  {
            return -1
        } else {
           let output = elements[idx]
            idx += 1
            
            return output
        }
    }
    
}
let fIO = FileIO()
let N = fIO.readInt()
var queue = Queue()
var answer = ""

for i in 0..<N {
    let operation = fIO.readString()
    switch operation {
    case 448:
        //push
        queue.push(element: fIO.readInt())
    case 335:
        //pop
        answer += "\(queue.pop())\n"
    case 443:
        //size
        answer += "\(queue.count)\n"
    case 559:
        //empty
        answer += "\(queue.isEmpty)\n"
    case 553:
        //front
        answer += "\(queue.front)\n"
    case 401:
        //back
        answer += "\(queue.back)\n"
    default:
        continue
    }
}

print(answer)

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-2346 풍선 터트리기 Swift  (0) 2024.04.03
BOJ-2164 카드2 Swift  (0) 2024.04.02
BOJ-9012 괄호 Swift  (0) 2024.04.02
BOJ-10773 제로 Swift  (1) 2024.04.02
BOJ-28278 스택 2 Swift  (0) 2024.04.02

+ Recent posts