programmers.co.kr/learn/courses/30/lessons/17679
안녕하세요! 후르륵짭짭 입니다.
이 문제는 백준의 뽀요뽀요 문제랑 비슷합니다.
그냥 빡!! 구현 문제 입니다.
그럼 바로 알아 가보도록 하겠습니다.
** 저의 풀이 **
// 1 : 22
var check : [[Bool]] = []
var breakBlock : Int = 0
func solution(_ m:Int, _ n:Int, _ board:[String]) -> Int {
var map : [[String]] = []
for element in board {
let temp = element.map { (char) -> String in
return String(char)
}
map.append(temp)
}
var flag = true
while flag == true {
flag = false
check = Array(repeating: Array(repeating: true , count: n), count: m)
for y in 0..<m{
for x in 0..<n {
if checkIs4(map, x, y) {
flag = true
}
}
}
moveItme(&map)
for element in map{
print(element)
}
print(flag)
}
return breakBlock
}
func checkIs4(_ map : [[String]],_ x : Int, _ y: Int) -> Bool{
let start = map[y][x]
let LR = [1,1,0,0]
let UD = [1,0,1,0]
if start != " " {
if x >= 0 && x < map[0].count - 1 && y >= 0 && y < map.count - 1{
if map[y + 1][x + 1] == start && map[y][x + 1] == start && map[y + 1][x] == start {
for go in 0..<4{
if check[y + UD[go]][x + LR[go]] == true {
breakBlock += 1
}
check[y + UD[go]][x + LR[go]] = false
}
return true
}
}
}
return false
}
func moveItme(_ map : inout [[String]]){
for x in 0..<map[0].count {
var down = map.count - 1
var cnt = 0
while down >= 0 {
if !check[down][x]{
cnt += 1
}
else if check[down][x] && cnt > 0 {
let item = map[down][x]
map[down + cnt][x] = item
check[down + cnt][x] = true
for start in down..<(down+cnt) {
check[start][x] = false
map[start][x] = " "
}
}
down -= 1
}
for start in 0..<cnt {
// print(start, x)
check[start][x] = false
map[start][x] = " "
}
}
}
코드가 너무 길어서 줄이도록 하겠습니다.
var map : [[String]] = []
for element in board {
let temp = element.map { (char) -> String in
return String(char)
}
map.append(temp)
}
일단 이렇게 문자열로 된 지도를 2차원 배열로 만들어 줍니다.
func checkIs4(_ map : [[String]],_ x : Int, _ y: Int) -> Bool{
let start = map[y][x]
let LR = [1,1,0,0]
let UD = [1,0,1,0]
if start != " " {
if x >= 0 && x < map[0].count - 1 && y >= 0 && y < map.count - 1{
if map[y + 1][x + 1] == start && map[y][x + 1] == start && map[y + 1][x] == start {
for go in 0..<4{
if check[y + UD[go]][x + LR[go]] == true {
breakBlock += 1
}
check[y + UD[go]][x + LR[go]] = false
}
return true
}
}
}
return false
}
그리고 이렇게 4개가 동일한 모양인지 확인을 해줍니다.
그런데 여기서 주의 해야할 것은
라이언 라이언 라이언
라이언 라이언 라이언
이렇게 가운데 라이언이 중복 될 경우에는 부수는 벽돌을 계산 해주면 안되기 때문에
경우를 나눠주고 check를 false로 바꿔 줍니다. check 배열은 파괴 됐는지 안됐는지 확인용 입니다.
func moveItme(_ map : inout [[String]]){
for x in 0..<map[0].count {
var down = map.count - 1
var cnt = 0
while down >= 0 {
if !check[down][x]{
cnt += 1
}
else if check[down][x] && cnt > 0 {
let item = map[down][x]
map[down + cnt][x] = item
check[down + cnt][x] = true
for start in down..<(down+cnt) {
check[start][x] = false
map[start][x] = " "
}
}
down -= 1
}
for start in 0..<cnt {
// print(start, x)
check[start][x] = false
map[start][x] = " "
}
}
}
이 방법은 위에서 그린 것 처럼
세로줄 맨 마지막 부터 확인 해서 올라가는 방식 입니다. 그래서 check가 false인 곳 파괴된 곳이라면 파괴 안된 것을 몇칸 아래로 내려 줄지
알려주는 cnt 갯수를 증가시켜주고 파괴 안된 것을 만나면 그 파괴 안 된 것을 올라온 갯수 만큼 내려주게 됩니다.
그리고 당연히 내려줬으니 기존에 있던 장난감을 false로 만들어줘야합니다.
이러한 과정이 끝났는데, 만약에 파괴 되지 않는 것을 만나지 않고 끝나면 과정을 마무리를 마치고 끝나기 때문에
마지막에도 " " 로 만들어주는 과정을 해줍니다.
예를 들어
let m = 2
let n = 2
var board = ["AA", "AA"]
이런 경우를 말하는 겁니다.
while flag == true {
flag = false
check = Array(repeating: Array(repeating: true , count: n), count: m)
for y in 0..<m{
for x in 0..<n {
if checkIs4(map, x, y) {
flag = true
}
}
}
moveItme(&map)
}
이제 마지막으로 파괴가 되지 않을 경우가 나올 때 까지 이 과정을 반복 해줍니다.
나름 처리해줘야할게 많은 빡구현 문제 였습니다....
예전에 현대카드에서도 이런 문제가 나왔는데,,,
'Xcode > Swift - Algorithm' 카테고리의 다른 글
Swift ) 프로그래머스(Lv2) - [3차] 파일명 정렬 (RegularExpression) (0) | 2020.09.10 |
---|---|
Swift ) 프로그래머스(Lv2) - [3차] 압축 (Hash) (0) | 2020.09.10 |
Swift ) 프로그래머스(Lv2) - [3차] 방금 그곡 (String) (1) | 2020.09.08 |
Swift ) 프로그래머스(Lv2) - 후보키 (DFS&Set) (0) | 2020.09.08 |
Swift ) 프로그래머스(Lv2) - 오픈 채팅방 (Hash) (0) | 2020.09.08 |
댓글