이 세계에선 내가 개발자?
[1292/Swift] 쉽게 푸는 문제 본문
*** 언어는 Swift! ***
요번의 문제는 1292번의 쉽게 푸는 문제 라는 제목을 가진 문제이다.
자세한 내용은 아래와 같다.
이번에는 문제가 이야기를 가지고 있다. 그래서 또 이해하기가 힘들 수도 있으니 하나 씩 천천히 문단을 나눠서 생각해보자!
1. 1을 한번, 2를 두번 숫자에 따라 나열되는 수열을 만든다.
2. 일정한 구간을 정한다.
3. 해당 구간의 합을 구한다.
여기서 예제 입력과 예제 출력에 대해 조금 고민이 있었다. 처음에 이해했던 건 3 숫자의 구간부터 7 숫자의 구간까지의 합을 구하라는 건 줄 알았는데 예제출력의 값이 터무니없이 부족했기 때문이다.
그래서 문제를 다시 한번 자세히 읽어보니 예제 입력 부분의 숫자들은 말 그대로 그냥 index 값에 지나지 않는다는 걸 깨달았다.
말 그대로 수열에서 3번째 위치에 있는 값부터 7번째 위치에 까지 있는 값들의 합을 구하는 것이다.
자 그럼 하나씩 코딩을 시작해보자
1. 첫째 줄에 구간의 시작과 끝을 나태내는 정수 A, B( 1 <= A <= B <= 1,000)가 주어진다.
마찬가지로 readLine으로 입력을 받아보자, 그런데 여기서 예제 입력이 처음 시작 위치와 끝 위치가 띄어쓰기로 구분되어 있으니 그 친구들을 나눠주는 부분도 같이 입력해주자
guard let input = readLine() else { return }
let inputArray = input.components(separatedBy: " ")
guard let startNumber = Int(inputArray[0]),
let endNumber = Int(inputArray[inputArray.count - 1])
else { return }
input을 readLine으로 입력받고 입력받은 input을 " " 기준으로 나눈 뒤 startNumber와 endNumber에 각각의 숫자를 넣어준다.
그럼 startNumber에는 3, endNumber에는 7이 들어간다.
이번에도 입력값에 대한 조건이 있길래 if 문으로 조건에 대한 내용도 추가해주었다.
if startNumber < 1 || startNumber > endNumber {
print("시작 숫자가 조건에 맞지 않습니다.")
return
} else if endNumber > 1000 {
print("끝 숫자가 조건에 맞지 않습니다.")
return
}
startNumber가 1보다 작거나 endNumber 보다 크면 return 시키고
endNumber가 1000보다 크면 return 시키도록 했다.
2. 1을 한 번, 2를 두 번, 3을 세 번 이러한 규칙을 가진 수열을 만든다.
여기서 수열을 만드는 것에 대해 조금 고민을 했다. 문제가 startNumber 부터 endNumber 까지 숫자들의 합을 구하는 것인데 어디까지 수열을 만들어 놓고 그 사이 합을 구하느냐에 대한 고민이 조금 있었다.
그래서 나는 간단하게 endNumber 기준으로 수열을 만들기로 했다.
var numberArray: [Int] = []
for i in 1...endNumber {
for _ in 1...i {
numberArray.append(i)
}
}
numberArray이라는 Int 형 배열을 만들고 (Int인 이유는 합해야 하니까) for문으로 endNumber까지 돌린다.
그리고 두번째 for 문으로 i 까지 돌린 후 i를 numberArray 배열에 append 한다.
쉽게 말하면 i가 1일 경우 안의 for 문은 1 부터 i 까지 한 번 돌고 i(1) 가 numberArray이 append 되니까 1 하나만 들어가게 된다.
마찬기지로 i가 2일 경우 안의 for 문은 1부터 i 까지 두 번 돌고 i(2) 가 numberArray에 append 되어서 1 2 2 요렇게 배열이 만들어지게 된다.
뒤 숫자들도 마찬가지가 이 for 문을 endNumber 가 될 때까지 돌린다.
3. A 구간부터 B 구간까지의 합을 구한다.
자 이제 합을 구해보자 나는 두 가지 방법으로 해보았다.
첫 번째 방법은 for 문으로 index를 체크해서 더해주는 방법이다.
var sumNumber = 0
for i in 1...numberArray.count {
if i >= startNumber {
sumNumber += numberArray[i - 1]
}
if i == endNumber {
break
}
}
sumNumber 라는 변수를 하나 만들어 주고 초기화해준다.
for문은 1부터 numberArray의 갯수 만큼 돈다.
이제 i가 startNumber 보다 크거나 같을 경우 부터 sumNumber 에 더해주기 시작한다.
(numberArray[i - 1] 인 경우는 for 문이 1부터 시작하기 때문이다.)
endNumber 위치의 숫자도 더해주어야 하니까 위에 더해준 다음에 i가 endNumber 인지 확인 한 후 맞으면 for 문을 break 해준다.
두 번째 방법은 map 과 reduce 를 이용하는 방법이다.
let sumNumber2 = numberArray[(startNumber - 1)..<endNumber].map { $0 }.reduce(0) { $0 + $1 }
확실히 위에 코드보다 짧긴 하다.
swift 에 있는 array의 특정 인덱스부터 특정 인덱스까지 값을 가져오는 방법을 사용했다.
(startNumber에 -1을 해 준 이유는 배열이 0부터 시작하기 때문이다.)
자 이렇게 startNumber 와 endNumber 사이의 array를 구했다면 map으로 돌리며 꺼내준다.
그리고 reduce를 이용해서 더해준다. 그럼 쉽게 답이 나오게 된다.
여기서 reduce를 조금 살펴보자면
reduce는 고차함수이다. 고차함수는 다른 함수를 전달인자로 받거나 함수 실행의 결과를 함수를 반환하는 함수를 뜻한다고 한다.
reduce (결합) 은 주로 데이터를 합쳐주기 위해 사용한다고 한다.
기존 컨테이너에서 내부의 값들을 결합하여 새로운 값을 만들 때 사용한다.
reduce에는 파라메터가 두 가지가 있는데 initialResult와 nextPartialResult이다.
initialResult : 초기값으로 사용할 값을 넣으면 클로저가 처음 실행될 때. nextPartialResult에 전달된다.
nextPartialResult : 컨테이너의 요소를 새로운 누적값으로 결합하는 클로저이다.
내가 썼던 내용 중 reduce(0) 이 말은 초기값을 0으로 설정해주겠다는 말이다.
요렇게 이번 문제도 완료!🔥🔥
'알록리즘 > BAEKLOG' 카테고리의 다른 글
[1457/Swift] 방 번호 (0) | 2023.04.28 |
---|---|
[11656/Swift] 접미사 배열 (0) | 2023.04.24 |
[9093/Swift] 단어 뒤집기 (0) | 2023.04.24 |
[1427/Swift] 소트인사이드 (1) | 2023.04.18 |
[9086/Swift] 문자열 (1) | 2023.04.17 |