プログラマー2018 KAKAO BLIND RECRUITMENT-友人4枚


https://programmers.co.kr/learn/courses/30/lessons/17679

問題の説明


四つのレンズ


ブラインド公債を通じた新入社員のライアンが新しいゲームの開発を担当する.今回発売されるタイトルは「友達4ブロック」
同じ形状のカメラレンズブロック2×これは2つの形で4つ貼ってあると、消えていくにつれて点数が得られるゲームです.

プレートが上に示されている場合、ライアンは2を得ることができます.×2ブロック×7、コンソール×2×2で配置された4つのブロックはクリアされます.同じブロックに複数の2を含む×2に含めることができ、消去条件を満たす2×2複数の形があれば、一気に消すことができます.

ブロックがクリアされると、上のブロックが下に落ち、空白を埋めます.

空白のスペースを埋めたら、再び2×2つの同じ形の塊が集まると、再び消され、繰り返し落下します.

上の初期レイアウトは以下のように文字で表されています.
TTTANT
RRFACC
RRRFCC
TRRRAA
TTMMMF
TMMTTJ
各文字は、ライアン(R)、ムージ(M)、アピチ(A)、フロド(F)、ニオ(N)、トゥゲン(T)、ジェシー(J)、コン(C)を表す.
指定されたブロックの最初の配置を入力すると、削除されたブロックが全部で何個あるかを判断するプログラムを作成します.

入力フォーマット


進入板の高さm,幅n,板の配置情報板を入力する.
2 ≦ n, m ≦ 30
boardは、m個の長さnの文字列の配列で与えられる.ブロックを表す文字は、大文字AにZを使用します.

出力フォーマット


指定したレイアウト情報を入力し、消去するブロックを出力します.

に答える


久しぶりに解釈して、一人で解いた.
長い時間をかけてクイズで解いていましたが、嬉しかったです^^
まずfindという関数を作成し,現在のブロックの右下角と右下角が同じであれば二重砲口で走査する.
boomsetという名前のコレクションに追加(重複するコレクションがある可能性があるため)
スキャンが終わったら.
BoomSetを利用して爆発したブロックにXマークをつけ、その数字を数えます
このとき、爆発がなければboomはfalseに戻り、爆発が山ほどある場合はtrueに戻ります.
次に、中間部分が爆発し、上に浮かぶブロックが分離される関数を作成します.
下部から巡回を開始し、現在のブロックがxである場合、そのブロックの上まで検査し、非xブロックと交換するように実現する.
そしてメイン関数ではwhileゲートでスキャンし、落下を繰り返し、爆弾が爆発しなければループを離れる.
cnt = 0
def find(m, n, board): # 스캔하여 찾은 다음 터트린 블럭을 x로 표시하는 함수
    global cnt
    boom = False # 폭발이 일어나는지 안 일어나는지 판단
    boomSet = set() # 터진 블럭들의 좌표를 저장함. 겹치는게 있을 수 있으므로 set으로 선언
    for i in range(m-1):
        for j in range(n-1):
            if board[i][j] == board[i][j+1] and board[i][j] != 'x': # 만약에 현재 블럭이 다음 블럭과 같고 x가 아니라면
                if board[i][j] == board[i+1][j]: # 근데 또 밑에 블럭도 같으면
                    if board[i][j] == board[i+1][j+1]: # 오른쪽 대각선 밑의 블럭과도 같으면
                        boomSet.add((i, j)) # 4개 블럭 모두 터진블럭 리스트에 추가하자
                        boomSet.add((i+1, j))
                        boomSet.add((i, j+1))
                        boomSet.add((i+1, j+1))
                        boom = True # 폭탄 터졌다고 체크
    for b in boomSet: # 터진 블럭들에다가 x표시하고 count 셈
        board[b[0]][b[1]] = 'x'
        cnt += 1
    return boom


def slideDown(m, n, board): # 중간에 폭탄이 터졌으면 위에 있는 블럭들을 밑으로 내려 주는 함수
    for i in range(m-1, 0, -1): # 밑에서 부터 순회하면서
        for j in range(n): # 하나씩 순회하며
            if board[i][j] == 'x': # 만약에 x이면 
                for k in range(i-1, -1, -1): # 그 위로 쭉 검사해서 x가 아닌것 나타나면 자리를 바꿈
                    if board[k][j] != 'x':
                        temp = board[k][j]
                        board[k][j] = board[i][j]
                        board[i][j] = temp
                        break


def makeBoard(board): # 입력값을 list로 만들어 주는 함수
    temp = []
    for b in board:
        temp.append(list(b))
    return temp


def solution(m, n, board):
    board = makeBoard(board) # map으로 만들어 주고
    global cnt
    boom = False 
    while 1: 
        boom = find(m, n, board) # 스캔한뒤 터진블럭들 세고 x표시함
        if not boom: # 터지지 않았다면 루프 빠져나감
            break
        slideDown(m, n, board) # 밑으로 다 떨궈줌
    return cnt