https://www.acmicpc.net/problem/1244
문제접근
문제가 조금 길어 보이긴 하지만 천천히 읽어보면 조건에 맞게 하나하나 구현해 주면 되는 문제임!!
잘 고려해주어야 하는 점은 남학생일 때와 여학생일 때 스위치를 조작하는 방식이 달라지는 점임!!
남학생은 자기가 받은 수의 배수이면 -> 스위치 상태 변경 (ex. 켜짐 -> 꺼짐, 꺼짐 -> 켜짐)
여학생은 자기가 받은 수와 같은 번호가 붙은 스위치를 중심으로 좌우 대칭이면서 가장 많은 스위치를 포함하는 구간을 찾아서, 그 구간에 속한 스위치 상태를 모두 바꿈.

예를 들어 <그림 2>에서 여학생이 3을 받았다면, 3번 스위치를 중심으로 2번, 4번 스위치의 상태가 같고 1번, 5번 스위치의 상태가 같으므로, <그림 3>과 같이 1번부터 5번까지 스위치의 상태를 모두 바꿈. 만약 <그림 2>에서 여학생이 4를 받았다면, 3번, 5번 스위치의 상태가 서로 다르므로 4번 스위치의 상태만 바꿈.
주의❗️
정답을 출력할 때 스위치의 상태를 1번 스위치에서 시작하여 마지막 스위치까지 한 줄에 20개씩 출력해야 함!!!
정답풀이
import Foundation
// 첫째 줄에는 스위치 개수가 주어진다. 스위치 개수는 100 이하인 양의 정수이다
let switchCount = Int(readLine()!)!
// 둘째 줄에는 각 스위치의 상태가 주어진다. 켜져 있으면 1, 꺼져있으면 0이라고 표시하고 사이에 빈칸이 하나씩 있다.
var switchs:[Int] = [0]
// i가 1부터로 이용하기 위해서 배열의 0번에 0을 넣어줌
let switchInput = readLine()!.split(separator: " ").map { Int(String($0))!}
switchs.append(contentsOf:switchInput)
// 셋째 줄에는 학생수가 주어진다. 학생수는 100 이하인 양의 정수이다
let studentsCount = Int(readLine()!)!
// 넷째 줄부터 마지막 줄까지 한 줄에 한 학생의 성별, 학생이 받은 수가 주어진다.
// 남학생은 1 여학생은 2
for _ in 0..<studentsCount {
let input = readLine()!.split(separator: " ").map { Int(String($0))!}
let (gender, number) = (input[0], input[1])
// 남학생이 받은 수의 배수이면 스위치 상태를 바꿈 ex3 3 6을 바꿈
if gender == 1 {
// 배수를 구해야 함
for i in number..<switchs.count {
if i % number == 0 {
if switchs[i] == 1 {
switchs[i] = 0
} else {
switchs[i] = 1
}
}
}
}
// 여자부분
else {
// 우선 자기 스위치 부터 변화
if switchs[number] == 1 {
switchs[number] = 0
} else {
switchs[number] = 1
}
var j = 1
while switchs[number-j] == switchs[number+j] {
if switchs[number-j] == switchs[number+j] {
if switchs[number-j] == 0 && switchs[number+j] == 0 {
switchs[number-j] = 1
switchs[number+j] = 1
j += 1
} else {
switchs[number-j] = 0
switchs[number+j] = 0
j += 1
}
}
}
}
}
// a맨 앞 0 빼고
for i in 1...switchCount {
print(switchs[i], terminator: " ")
if i % 20 == 0 {
print() // 20개마다 줄 바꿈
}
}
var switchs:[Int] = [0]
let switchInput = readLine()!.split(separator: " ").map { Int(String($0))!}
switchs.append(contentsOf:switchInput)
우선 스위치의 상태를 넣어줄 switchs 배열의 0번에 0을 넣어주었음!
문제를 보면 스위치 번호가 1번부터 시작하기 때문에 switchs 배열에 1번으로 사용하기 위해서임.

배열의 끝에 시퀀스의 요소를 추가합니다.라고 함.
switchs 배열이 빈 배열이 아니기 때문에 append(contentsOf:)를 사용해 배열에 추가해 주었음!!
남학생 부분! 💁♂️
for _ in 0..<studentsCount {
let input = readLine()!.split(separator: " ").map { Int(String($0))!}
let (gender, number) = (input[0], input[1])
// 남학생이 받은 수의 배수이면 스위치 상태를 바꿈 ex3 3 6을 바꿈
if gender == 1 {
// 배수를 구해야 함
for i in number..<switchs.count {
if i % number == 0 {
if switchs[i] == 1 {
switchs[i] = 0
} else {
switchs[i] = 1
}
}
}
}
gender가 1이면 남학생을 의미함!
주어진 스위치 번호부터 반복문을 이용해서 스위치 상태를 변경해 주었음!!
여학생 부분! 💁♀️
else {
// 우선 자기 스위치 부터 변화
if switchs[number] == 1 {
switchs[number] = 0
} else {
switchs[number] = 1
}
var j = 1
while switchs[number-j] == switchs[number+j] {
if switchs[number-j] == switchs[number+j] {
if switchs[number-j] == 0 && switchs[number+j] == 0 {
switchs[number-j] = 1
switchs[number+j] = 1
j += 1
} else {
switchs[number-j] = 0
switchs[number+j] = 0
j += 1
}
}
}
}
}
자기가 받은 수와 같은 번호가 붙은 스위치가 좌우 대칭이거나 아니더라도 자기 받은 번호의 스위치 상태가 바뀌어야 하기 때문에 우선 받은 번호의 스위치를 바꿔줌!!
그 후 while문을 이용해서
while switchs[number-j] == switchs[number+j] {
}
자기가 받은 수와 같은 번호가 붙은 스위치를 중심으로 좌우가 대칭이지 확인해 주었음!!
대칭이 맞다면 좌우 스위치 상태를 변경해 주었음!!
변경될 때마다 j값을 증가시켜서 범위를 늘려갔음~
for i in 1...switchCount {
print(switchs[i], terminator: " ")
if i % 20 == 0 {
print() // 20개마다 줄 바꿈
}
}
마지막으로 switchs 배열을 20개마다 줄을 바꿔서 출력해 주었음!!
맨 처음에 배열에 0번에 0을 추가해 주었기 때문에 switchs[1] 번부터 출력을 해줌!!!
예시 입력을 넣어주니깐

잘 나온다!!!

하지만 제출을 하였을 땐 계속 런타임 에러가 떴음!!! 😂
무엇이 문제일까????? 🤔
while switchs[number-j] == switchs[number+j] {
}
while문을 사용할 때 배열의 범위를 벗어났기 때문임!!!
그래서 다시 범위를 정해주었음!
while (number - j > 0 && number + j <= switchCount) {
}
switch 배열을 확인할 때 1번부터 마지막 배열까지만 확인할 수 있도록 범위를 제한해 주었음!!
이제는 과연!!!

시간초과네......😭
코드가 많이 지저분한 거 같았는데... 결국...
그럼 코드를 다시 정리하고 다듬어 보자!!
남학생 부분! 💁♂️
// 남학생이 받은 수의 배수이면 스위치 상태를 바꿈 ex3 3 6을 바꿈
if gender == 1 {
// 배수를 구해야 함
for i in number..<switchs.count {
if i % number == 0 {
if switchs[i] == 1 {
switchs[i] = 0
} else {
switchs[i] = 1
}
}
}
우선 남학생이 받은 수의 배수인 스위치 위치를 찾기 위한 코드를 stride(from:through:by:)를 사용하고 삼항연산자를 사용하여 변경해 주었음!!

시작 값부터 종료 값까지(가능한 경우 포함) 시퀀스를 지정된 양만큼 단계별로 반환합니다.라고 함!!
- 매개변수
시작
시퀀스에 사용할 시작 값입니다. 시퀀스에 값이 포함되어 있으면 첫 번째 값은 start입니다.
끝
시퀀스를 제한하는 종료 값입니다. end는 stride 단계를 사용하여 시작부터 생성될 수 있는 경우에만 결과 시퀀스의 요소입니다.
보폭
각 반복마다 단계별로 수행할 양입니다. 긍정적인 보폭은 위쪽으로 반복됩니다. 음의 보폭은 아래쪽으로 반복됩니다.
만약 남학생이 받은 번호가 3이고 스위치 개수가 8개이면
각 반복마다 3만큼 보폭을 주게 됨
for i in stride(from: 3, through: 8, by: 3) {
print(i)
}
// 3
// 6
if gender == 1 {
// 남학생이 받은 수의 배수이면 스위치 상태를 바꿈
for i in stride(from: number, through: switchCount, by: number) {
switchs[i] = switchs[i] == 1 ? 0 : 1
}
}
이렇게 변경!!
여학생 부분! 💁♀️
else if gender == 2 {
// 여학생의 경우, 좌우 대칭 구간을 찾아 스위치 상태를 바꿈
switchs[number] = switchs[number] == 1 ? 0 : 1
var j = 1
while (number - j > 0 && number + j <= switchCount) {
if switchs[number - j] == switchs[number + j] {
switchs[number - j] = switchs[number - j] == 1 ? 0 : 1
switchs[number + j] = switchs[number + j] == 1 ? 0 : 1
j += 1
} else {
break
}
}
}
그전에는 쓸데없이 이중으로 if문을 작성했는데 지금은 한 번만 사용하고 삼항연사자를 사용했음!!
import Foundation
// 첫째 줄에는 스위치 개수가 주어진다. 스위치 개수는 100 이하인 양의 정수이다
let switchCount = Int(readLine()!)!
// 둘째 줄에는 각 스위치의 상태가 주어진다. 켜져 있으면 1, 꺼져있으면 0이라고 표시하고 사이에 빈칸이 하나씩 있다.
var switchs: [Int] = [0]
// i가 1부터로 이용하기 위해서 배열의 0번에 0을 넣어줌
let switchInput = readLine()!.split(separator: " ").map { Int(String($0))! }
switchs.append(contentsOf: switchInput)
// 셋째 줄에는 학생수가 주어진다. 학생수는 100 이하인 양의 정수이다
let studentsCount = Int(readLine()!)!
// 넷째 줄부터 마지막 줄까지 한 줄에 한 학생의 성별, 학생이 받은 수가 주어진다.
// 남학생은 1 여학생은 2
for _ in 0..<studentsCount {
let input = readLine()!.split(separator: " ").map { Int(String($0))! }
let (gender, number) = (input[0], input[1])
if gender == 1 {
// 남학생이 받은 수의 배수이면 스위치 상태를 바꿈
for i in stride(from: number, through: switchCount, by: number) {
switchs[i] = switchs[i] == 1 ? 0 : 1
}
} else if gender == 2 {
// 여학생의 경우, 좌우 대칭 구간을 찾아 스위치 상태를 바꿈
switchs[number] = switchs[number] == 1 ? 0 : 1
var j = 1
while (number - j > 0 && number + j <= switchCount) {
if switchs[number - j] == switchs[number + j] {
switchs[number - j] = switchs[number - j] == 1 ? 0 : 1
switchs[number + j] = switchs[number + j] == 1 ? 0 : 1
j += 1
} else {
break
}
}
}
}
// 스위치 상태 출력 (20개씩 줄 바꿈)
for i in 1...switchCount {
print(switchs[i], terminator: " ")
if i % 20 == 0 {
print() // 20개마다 줄 바꿈
}
}
위와 같이 정리를 해보았다!!

드디어 정답!!! 😭
배열의 범위가 넘지 않게 주의해서 설계를 해주어야 할 거 같음!!
그리고 계속 문제 구현만 집중하다 보니 코드가 지저분해지는 느낌.. ,,
최대한 간단하고 가독성이 좋게 구현할 수 있도록 고민을 많이 해봐야 할 거 같음!!
참고 및 인용
https://developer.apple.com/documentation/swift/stride(from:through:by:)
'Algorithm' 카테고리의 다른 글
| [Algorithm] Swift 프로그래머스 달리기경주(178871번) (2) | 2024.05.31 |
|---|---|
| [Algorithm] Swift 백준 2167번 (0) | 2024.05.24 |
| [Algorithm] Swift 1차원, 2차원 배열의 합 (1) | 2024.05.24 |
| [Algorithm] Swift 백준 2563번 (3) | 2024.05.19 |
| [Algorithm] Swift 백준 1002번 (0) | 2024.05.06 |