Today I Learned

20210930 백준 swift - 1차원 배열

돌맹이시터 2021. 9. 30. 00:55

1~7단계 (10818, 2562, 2577, 3052, 1546, 8958, 4344)

 

 

 

10818 최소, 최대

 

let caseNum = Int(readLine()!)!
let num = readLine()!.split(separator: " ").map{Int(String($0))!}
print(num.min()!, num.max()!)

 

arrayName.min() & arrayName.max() 사용해서 해결

 

 

문제는 시간초과였는데,

스위프트로 백준 알고리즘을 풀 때 시간초과 문제가 많이 발생한다고 한다.

https://velog.io/@ryan-son/Swift-10818-%EC%B5%9C%EC%86%8C-%EC%B5%9C%EB%8C%80-%EB%B0%B1%EC%A4%80-B3

글을 참조했다.

 

split을 사용해 문자열을 나누어 배열에 넣을 때 [String.SubSequence] 타입으로 반환된다.

일반적인 [String]타입과는 다르며,

map을 사용해 Int 타입으로 각 요소를 변환하는 경우,

String.SubSequence -> Int 로 수행하는 것보다

String.SubSequence -> String -> Int 로 수행했을 때 속도가 더 빠르다.

map{Int($0)!} 을 사용했을 때 시간 초과로 정답판정을 받지 못했지만,

map{Int(String($0))!}을 사용했을 때 정답으로 인정받았다.

 

 


 

 

2562 최댓값

 

 

var num:[Int] = []
for _ in 1...9 {
	num.append(Int(readLine()!)!)
}
let index = num.firstIndex(of: num.max()!)!+1
print(num.max()!)
print(index)

 

firstIndex를 사용했다.

https://developer.apple.com/documentation/swift/array/2994720-firstindex

 

 

 


 

 

2577 숫자의 개수

 

 

 

var num:[Int] = []
var nums:[Int] = []

for _ in 1...3 {
	num.append(Int(readLine()!)!)
}

let multiplied = num.reduce(1,{$0*$1})

let splitNum = String(multiplied).map {Int(String($0))!}

for i in 0...9 {
	let countNum = splitNum.filter{$0 == i}.count
	nums.append(countNum)
}
nums.forEach {
	print($0)
}

 

 

reduce

filter

forEach

을 새로 사용했다.

 

 

reduce는 내부의 값들을 하나로 합쳐줄 수 있다. 첫 번째 매개변수는 초기값을 의미한다.

filter는 조건에 대해 true인 값들만 리턴한다.

forEach 의 경우 for-in 처럼 각각의 element를 호출할 수 있다.

 

 

 

 


 

3052 나머지

 

 

 

두 가지 방법으로 풀었다.

 

 

 

1. Dictionary를 사용하는 방법

 

var numDict:[Int:Int] = [:]
for _ in 1...10 {
	let num = Int(readLine()!)! % 42
	if numDict[num] == nil {
		numDict[num] = 1
	}
}
print(numDict.count)

 

Dictionary를 하나 만들고, 

입력받은 값을 42로 나눈 나머지를 키 값으로 사용한다.

딕셔너리의 해당 인덱스 값이 비어있는 경우, 특정 값을 value로 입력한 다음

딕셔너리의 갯수를 카운트하여 출력한다.

 

코드에서는 1을 넣었지만 사실 어떤 값이 들어가든 상관없다.

value의 타입을 Character나 String으로 설정하여 임의의 값을 넣어도 상관없고, Int를 쓰더라도 1이 아닌 어떤 값을 넣어도 무방하다.

 

 

 

 

2. Set을 사용하는 방법

 

 

var numDict: Set<Int> = []
for _ in 1...10 {
	numDict.insert(Int(readLine()!)! % 42)
}
print(numDict.count)

 

 

swift에서 Set는 배열과 유사하기는 하지만, 고유한 값들을 갖는 컬렉션 타입의 하나이다.

https://developer.apple.com/documentation/swift/set

 

변수를 Set타입으로 만들어주고,

입력받은 값을 42로 나눈 나머지값을 Set에 넣어주면,

자동적으로 중복되는 값들은 배제되어 들어가게 된다.

 

 

 

*****

위의 두 가지 방법으로 코드를 실행했을 때 

코드의 길이는 두 번째 경우가 더 짧지만

차지하는 메모리나, 시간은 동일했다.

 

 

 

 


 

 

1546 평균

 

 

두 가지 코드를 작성해봤다.

 

// 1546 평균 - 첫번째
let count = Int(readLine()!)!
var score = readLine()!.split(separator: " ").map{Float(String($0))!}
let maxScore = score.max()!
var fakeScore:[Float] = []
for i in 0...count-1 {
	fakeScore.append(score[i]/maxScore*100)
}
let fakeAvarage = fakeScore.reduce(0,{$0+$1})/Float(count)
print(fakeAvarage)

 

 

// 1546 평균 - 두번째
let count = Int(readLine()!)!
var score = readLine()!.split(separator: " ").map{Float(String($0))!}
let maxScore = score.max()!
let fakeScore = score.map{$0/maxScore*100}
let fakeAvarage = fakeScore.reduce(0,+)/Float(count)
print(fakeAvarage)

 

 

첫 번째 방법에서 for-in을 사용하여 fakeScore 배열에 각각의 값을 append를 해줬고,

두 번째 방법에서는 map을 사용하여 score 배열을 계산한 결과로 fakeScore 배열을 만들었는데

두 가지 방법에서 차지하는 메모리는 동일했고, 시간은 map을 사용한 두 번째 방법이 더 짧게 걸렸다.

 

 

 

 


 

 

8958 OX퀴즈

 

 

세 가지 방법으로 풀었다.

 

 

 

// 8958 OX퀴즈 - 첫번째

let qNum = Int(readLine()!)!
for _ in 1...qNum {
	var answer = readLine()!.map{String($0)}
	var aNum = answer.count
	var score:[Int] = []
	for i in 0...aNum-1 {
		if i == 0 {
			if answer[i] == "O" {
				score.append(1)
			} else {
				score.append(0)
			}
		} else if i > 0 {
			if answer[i] == "O" && answer[i-1] == "O" {
				score.append(score[i-1]+1)
			} else if answer[i] == "O" && answer[i-1] != "O" {
				score.append(1)
			} else {
				score.append(0)
			}
		} 
	}
	let sum = score.reduce(0,+)
	print(sum)
}

 

// 8958 OX퀴즈 - 두번째
let qNum = Int(readLine()!)!
for _ in 1...qNum {
	var sum = 0
	var score = 0
	let answer = readLine()!
	for i in answer {
		if i == "O" {
			sum += score + 1
			score += 1
		} else {
			score = 0
		}
	}
	print(sum)
}

 

// 8958 ox퀴즈 - 세번째 (가우스)
let qNum = Int(readLine()!)!
for _ in 0...qNum-1 {
	var sum = readLine()!.split(separator : "X").map{$0.count * (1 + $0.count) / 2}.reduce(0, +)
	print(sum)
}

 

 

첫 번째 방법이 코드가 가장 길다.

입력받은 OX문을 배열의 형태로 저장하여 각각의 인덱스 값을 사용하여 점수를 계산하는 방식이었는데

코드가 길고, 약간 지저분하다.

 

 

두 번째 방법은 조금 더 간단하게 작성했는데,

OX문을 배열로 만들지 않고 하나의 String으로 두어 for 문 자체에서 하나씩 비교해가면서 주어진 조건에 맞게 점수를 계산했다.

세 가지 방법 중 메모리를 가장 적게 차지했다 (4KB 차이)

 

 

세 번째 방법은 가우스 공식을 사용했다. == 갯수 n * (첫번째 수 + 마지막 수) / 2

split으로 X가 나오는 부분을 기준으로 나누어주면서, 나누어진 부분 내에서의 합을 각각 구해서 배열에 저장하고, 

모든 값을 더해주었다.

코드의 양이 매우 많이 줄어든다.

 

 

 

세 가지 방법 모두 실행에 동일한 시간이 소모되었다.

 

 

 

 


 

 

4344 평균은 넘겠지

 

 

 

// 4344 평균은 넘겠지
import Foundation
let caseNum = Int(readLine()!)!
for _ in 1...caseNum {
	var inputArr = readLine()!.split(separator: " ").map{Double(String($0))!}
	let studentNum = inputArr[0]
	inputArr.removeFirst()
	let average = inputArr.reduce(0,+)/studentNum
	let highStudent = inputArr.filter{$0>average}
	let result = Double(highStudent.count)/studentNum*100
	print(String(format: "%.3f", result),"%", separator: "")
	}

 

'Today I Learned' 카테고리의 다른 글

백준 swift - 문자열  (0) 2021.10.21
20211006 - 백준 swift - 함수  (0) 2021.10.06
20210831 백준 swift - while문  (0) 2021.09.01
20210830 백준 swift - for문 -2  (0) 2021.08.31
20210826~20210829 백준 swift - for문 -1  (0) 2021.08.30