본문 바로가기
알고리즘/문제풀이

[백준](Swift) 반복문

by venniek 2022. 5. 28.

세 번째 단계인 반복문이다.

2739 구구단

1…9N을 받아서 N단을 출력하는 문제다.

9번 반복하고, print 함수가 인수를 자동으로 공백으로 나눠주니 출력할 것들을 나열하기만 하면 된다.

let n = Int(readLine()!)!
for i in 1...9 {
    print(n, "*", i, "=", n * i)
}

10950 A+B - 3

숫자를 두 개 입력받아 합을 출력한다.

숫자가 작으므로 오버플로우는 신경쓰지 않아도 되고, T를 받아 반복하니 그 부분만 주의한다.

import Foundation

let t = Int(readLine()!)!
for _ in 1...t {
    let nums = readLine()!.components(separatedBy: " ").map{ Int($0)! }
    print(nums[0] + nums[1])
}

8393 합

n을 입력받아 n까지의 합을 구한다.

가우스 합을 사용해도 되지만 반복문을 써보는 단계라서 일일이 더해주었다.

let n = Int(readLine()!)!
var sum = 0
for i in 1...n { sum += i }
print(sum)

15552 빠른 A+B

입출력 방식을 빠르게 해 두 수의 합을 구하는 문제다.

각 언어별로 빠르게 입출력을 할 수 있는 방법이 있는데 스위프트의 경우 readLine()의 속도가 느려 fread의 스위프트 버전을 만들어 사용한다. 라이노님이 작성하신 코드를 이용하는데 정확한 원리는 모르겠지만… 사용하니 시간초과 뜨던 문제가 바로 통과됐다.

// 라이노님이 만드신 FileIO 클래스

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)])
    }
}

// 사용할 때
let fIO = FileIO()     // 입력받는 인스턴스 생성
let n = fIO.readInt()  // Int로 입력받기
// 15552 정답 코드
// 위 코드의 클래스 부분 + 아래 코드

let fio = FileIO()
let n = fio.readInt()
for _ in 0..<n {
    var a = fio.readInt() + fio.readInt()
    print(a)
}

2741 N 찍기

N을 입력받아 1…N을 출력한다.

let n = Int(readLine()!)!
for i in 1...n { print(i) }

2742 기찍 N

N을 입력받아 N…1 을 출력한다.

세 가지 방법이 있다.

  1. 1…N 으로 범위를 주면 1부터 커지기만 한다. 거꾸로 쓰고 싶을 때는 stride 함수를 이용해서시작점, 도착점, 더해갈 수 를 정해주면 된다.
stirde(from: N, to: 0, by: -1) { //실행 구문 }

// 아래와 같이 작동된다. to 미만인 점을 주의하자.
while (from < to) {
    // 실행 구문
    from += by
}
// 정답코드 1
let n = Int(readLine()!)!
for i in stride(from: n, to: 0, by: -1) { print(i) }
  1. 거꾸로 쓰는 법이 하나 더 있다. 정방향의 범위를 써준 후 reversed() 함수를 적용한다. reversed() 함수는 범위를 반대로 뒤집어준다.
// 정답코드 2
let n = Int(readLine()!)!
for i in (1...n).reversed() { print(i) }
  1. 0..<N 을 사용하고, 출력할 때 N - i 를 사용한다.
// 정답코드 3
let n = Int(readLine()!)!
for i in 0..<n { print(n - i) }

11021 A+B - 7

입력받은 두 수의 합을 예쁘게 출력한다. 출력문에 몇 번째 케이스인지 보여줘야 한다.

문자열 보간법을 사용해 StringInt들을 한 번에 출력해준다.

import Foundation

let t = Int(readLine()!)!
for i in 1...t {
let nums = readLine()!.components(separatedBy: " ").map{ Int($0)! }
    print("Case #(i): (nums[0] + nums[1])")
}

11022 A+B - 8

위 문제와 거의 비슷하지만 이번에는 입력받은 숫자까지 같이 써준다.

import Foundation

let t = Int(readLine()!)!
for i in 1...t {
let nums = readLine()!.components(separatedBy: " ").map{ Int($0)! }
    print("Case #(i): (nums[0]) + (nums[1]) = (nums[0] + nums[1])")
}

2438 별 찍기 - 1

n번째 줄에 별을 n개 찍는 문제다.

한 줄에 한 문자를 여러 번 적고, 여러 줄 반복하니 이중 for문을 써야 한다.

문자를 반복할 때는 줄바꿈을 하지 않으니까 terminator를 다시 설정해준다.

let n = Int(readLine()!)!

for i in 1...n {
    for _ in 1...i {
        print("*", terminator: "")
    }
    print("")
}

2439 별 찍기 - 2

위 문제와 거의 비슷하지만 이번에는 왼쪽에 공백을 둬 오른쪽 정렬한다.

공백의 개수와 별의 개수의 합이 n임을 이용한다.

let n = Int(readLine()!)!

for i in 0..<n {
    for _ in 1..<(n - i) { print(" ", terminator: "") }
        for _ in 0...i { print("*", terminator: "") }
        print("")
}

10871 X보다 작은 수

숫자 목록을 받아서 주어진 X보다 작은 수들만 출력한다.

반복문을 돌 때 print가 자동 개행을 하므로 terminator를 다시 설정해주자.

import Foundation

// nums[0] = N, nums[1] = X
let nums = readLine()!.components(separatedBy: " ").map{ Int($0)! }
let a = readLine()!.components(separatedBy: " ").map{ Int($0)! }
for i in 0..<nums[0] {
    if a[i] < nums[1] {
        print(a[i], terminator: " ")
    }
}

10952 A+B - 5

두 수의 합을 출력하는데, 입력으로 (0, 0) 이 들어올 때까지 계속 입력을 받는다.

무한 반복문을 돌면서 입력을 받고, 특정 입력이 들어오면 break 하게 했다.

while 의 조건식에는 bool 값이 들어가야 되는데, c++ 에서 했던 거처럼 1을 쓰니 오류가 나서 true를 넣어주었다.

import Foundation

while true {
    let nums = readLine()!.components(separatedBy: " ").map{ Int($0)! }
    if nums[0] + nums[1] == 0 { break }
    print(nums[0] + nums[1])
}

10951 A+B - 4

이번에는 입력이 없을 때까지 입력을 받는다.

readLine()이 옵셔널 값이니 let 문을 사용해 입력이 정상적으로 들어왔는지를 판단한다.

제출 전 실행해서 테스트 입력을 넣으면 다음 입력을 기다리는데, 아마 채점할 때는 EOF를 줘서 입력을 끝낼 것이다. ctrl+DEOF를 주고 잘 종료된다면 제출하자.

import Foundation

while let input = readLine() {
    let ns = input.components(separatedBy: " ").map{ Int($0)! }
    print(ns[0] + ns[1])
}

1110 더하기 사이클

입력받은 수의 각 자리수를 더하고(한 자리 수면 자기 자신), 원래 숫자의 1의 자리 수더한 수의 1의 자리 수 를 이어 새로운 수를 만든다. 이렇게 계속 진행하다가 처음에 입력받은 수가 되면 사이클이 된 것이고, 그 사이클의 길이를 구하면 된다.

처음 숫자로 돌아왔는지 검사해야되니 nc(n copy)라는 상수에 저장해두고, 적어도 한 번은 진행할 것이니 repeat while 문을 사용한다. 각 자리수를 따로 계속 사용하니 상수에 저장해둔다.

var n = Int(readLine()!)!
let nc = n
var cnt: Int = 0

repeat {
    let a = n / 10
    let b = n % 10
    n = b * 10 + (a + b) % 10 // (원래 수 1의 자리를 10의 자리로) + (더한 수의 1의 자리)
    cnt += 1
} while n != nc
print(cnt)

'알고리즘 > 문제풀이' 카테고리의 다른 글

[백준] (Swift) 2675 문자열 반복  (0) 2022.07.11
[백준](Swift) 1차원 배열  (0) 2022.06.04
[백준](Swift) 조건문  (0) 2022.05.13
[백준](Swift) 입출력과 사칙연산  (2) 2022.05.10
[백준] (C++) 5567 - 결혼식  (0) 2022.01.12

댓글