μ•Œκ³ λ¦¬μ¦˜/κ΅¬ν˜„

[λ°±μ€€ 7682 πŸ₯‡] 틱택토

1eehyunji 2023. 8. 3. 00:49

문제

틱택토 κ²Œμž„μ€ 두 λͺ…μ˜ μ‚¬λžŒμ΄ λ²ˆκ°ˆμ•„κ°€λ©° 말을 λ†“λŠ” κ²Œμž„μ΄λ‹€. κ²Œμž„νŒμ€ 3×3 격자판이며, μ²˜μŒμ—λŠ” λΉ„μ–΄ μžˆλ‹€. 두 μ‚¬λžŒμ€ 각각 X λ˜λŠ” O 말을 λ²ˆκ°ˆμ•„κ°€λ©° λ†“λŠ”λ°, λ°˜λ“œμ‹œ 첫 번째 μ‚¬λžŒμ΄ Xλ₯Ό 놓고 두 번째 μ‚¬λžŒμ΄ Oλ₯Ό λ†“λŠ”λ‹€. μ–΄λŠ λ•Œλ“ μ§€ ν•œ μ‚¬λžŒμ˜ 말이 κ°€λ‘œ, μ„Έλ‘œ, λŒ€κ°μ„  λ°©ν–₯으둜 3칸을 μž‡λŠ” 데 μ„±κ³΅ν•˜λ©΄ κ²Œμž„μ€ μ¦‰μ‹œ λλ‚œλ‹€. κ²Œμž„νŒμ΄ 가득 차도 κ²Œμž„μ€ λλ‚œλ‹€.

κ²Œμž„νŒμ˜ μƒνƒœκ°€ μ£Όμ–΄μ§€λ©΄, κ·Έ μƒνƒœκ°€ 틱택토 κ²Œμž„μ—μ„œ λ°œμƒν•  수 μžˆλŠ” μ΅œμ’… μƒνƒœμΈμ§€λ₯Ό νŒλ³„ν•˜μ‹œμ˜€.

μž…λ ₯

μž…λ ₯은 μ—¬λŸ¬ 개의 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ‘œ 이루어져 μžˆλ‹€. 각 쀄은 9개의 문자λ₯Ό ν¬ν•¨ν•˜λ©°, 'X', 'O', '.' 쀑 ν•˜λ‚˜μ΄λ‹€. '.'은 λΉˆμΉΈμ„ μ˜λ―Έν•˜λ©°, 9개의 λ¬ΈμžλŠ” κ²Œμž„νŒμ—μ„œ 제일 μœ— 쀄 μ™Όμͺ½λΆ€ν„°μ˜ μˆœμ„œμ΄λ‹€. μž…λ ₯의 λ§ˆμ§€λ§‰μ—λŠ” λ¬Έμžμ—΄ "end"κ°€ μ£Όμ–΄μ§„λ‹€.

좜λ ₯

각 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ§ˆλ‹€ ν•œ 쀄에 정닡을 좜λ ₯ν•œλ‹€. κ°€λŠ₯ν•  경우 "valid", λΆˆκ°€λŠ₯ν•  경우 "invalid"λ₯Ό 좜λ ₯ν•œλ‹€.

λ¬Έμ œν’€μ΄

import sys


# μ΅œμ’… μƒνƒœκ°€ κ°€λŠ₯ν•œ 경우
# 1) X의 개수 = 5, O의 개수 =4 μ΄λ©΄μ„œ κ²Œμž„νŒμ΄ λͺ¨λ‘ 차있음(단, X,0 λͺ¨λ‘ 3칸을 μ±„μš΄ μƒνƒœκ°€ μ•„λ‹˜)
# 2) X의 개수 = O의 κ°œμˆ˜μ΄λ©΄μ„œ Oκ°€ 3칸을 이은 경우
# 3) X의 개수 = O의 개수+1 μ΄λ©΄μ„œ Xκ°€ 3칸을 이은 경우
# Xκ°€ μŒλŒ€κ°μ„ μ„ μ΄λ£¨λŠ” 경우λ₯Ό μ œμ™Έν•˜κ³ , ν•œ μ€„λ§Œ λ§Œμ‘±ν•΄μ•Ό 함.

def success(tictactoe, xoro):
    # λŒ€κ°μ„  λ§Œμ‘±ν•˜λŠ” 라인 개수
    dia_line=0
    # 평행선 λ§Œμ‘±ν•˜λŠ” 라인 개수
    pal_line=0
    # 3쀄을 λ§Œμ‘±ν•˜λŠ” 경우 μ°ΎκΈ°
    # 1쀄 이상 만쑱히면 λΆˆκ°€λŠ₯ν•œ 경우이기 λ•Œλ¬Έμ— line λ³€μˆ˜μ— λ§Œμ‘±ν•˜λŠ” μ€„μ˜ 개수λ₯Ό μ €μž₯함.
    # λŒ€κ°μ„ μœΌλ‘œ λ§Œμ‘±ν•˜λŠ” 경우
    if tictactoe[0][0]==xoro and tictactoe[1][1]==xoro and tictactoe[2][2]==xoro:
        dia_line+=1
    if tictactoe[0][2]==xoro and tictactoe[1][1]==xoro and tictactoe[2][0]==xoro:
        dia_line+=1
    for i in range(3):
        if tictactoe[i][0]==xoro and tictactoe[i][1]==xoro and tictactoe[i][2]==xoro:
            pal_line+=1
        if tictactoe[0][i]==xoro and tictactoe[1][i]==xoro and tictactoe[2][i]==xoro:
            pal_line+=1
    # 1μ€„λ§Œ λ§Œμ‘±ν•˜λŠ” 경우
    if dia_line+pal_line==1:
        return True
    elif dia_line==2:
        return True
    else:
        return False



while True:
    tictactoe=sys.stdin.readline().strip()
    if tictactoe=='end':
        sys.exit(0)
    tictactoe2d=[list(tictactoe[:3]),list(tictactoe[3:6]),list(tictactoe[6:])]
    # X의 개수
    numX=tictactoe.count('X')
    # O의 개수
    numY=tictactoe.count('O')
    # X의 개수 = O의 개수 +1 인 경우
    if numX==numY+1:
        # 꽉 μ±„μ›Œμ Έ μžˆλŠ”λ° λˆ„κ΅¬λ„ 이기지 λͺ»ν•˜κ³  μ’…λ£Œλ˜λŠ” 경우
        if numX==5 and numY==4 and not success(tictactoe2d,'X') and not success(tictactoe2d, 'O'):
            print('valid')
        # Xκ°€ μ΄κΈ°λŠ” 경우(ν•œ μ€„λ§Œ λ§Œμ‘±ν•˜λ©΄μ„œ 'O'λŠ” ν•œμ€„λ„ λ§Œμ‘±ν•˜λ©΄ μ•ˆλ¨)
        elif success(tictactoe2d,'X') and not success(tictactoe2d, 'O'):
            print('valid')
        # 두 경우 λͺ¨λ‘ μ•„λ‹ˆλ©΄ μ΅œμ’… μƒνƒœμ— 도달할 수 μžˆλŠ” μƒνƒœκ°€ μ•„λ‹˜
        else:
            print('invalid')
    elif numX==numY:
        # Oκ°€ μ΄κΈ°λŠ” 경우
        if success(tictactoe2d,'O') and not success(tictactoe2d,'X'):
            print('valid')
        else:
            print('invalid')
    else:
        print('invalid')

κ·œμΉ™μ„ μ°Ύμ•„μ„œ κ΅¬ν˜„ν•˜λŠ” λ¬Έμ œμ˜€λ‹€. μ²˜μŒμ— μƒκ°ν•˜μ§€ λͺ»ν–ˆλ˜ λ°˜λ‘€κ°€ μžˆμ–΄μ„œ ν‹€λ Έλ‹€κ°€ 질문 κ²Œμ‹œνŒμ„ 보고 μ•Œμ•˜λ‹€!

 

μ²˜μŒμ— μƒκ°ν–ˆλ˜ μ΅œμ’… μƒνƒœκ°€ 될 수 μžˆλŠ” κ·œμΉ™μ€

  1. λͺ¨λ‘ 꽉 μ±„μ›Œμ Έμ„œ μ΅œμ’… μƒνƒœκΉŒμ§€ 온 경우 : Xκ°€ 5개, Oκ°€ 4κ°œμ΄λ©΄μ„œ X,O λͺ¨λ‘ ν•œ 쀄을 μ±„μš°μ§€ λͺ»ν•œ μƒνƒœ
  2. O둜 이긴 경우 : X와 O의 κ°œμˆ˜κ°€ λ™μΌν•˜κ³  Oκ°€ ν•œ 쀄을 μ±„μš΄ 경우
  3. X둜 이긴 경우 : X의 κ°œμˆ˜κ°€ O의 κ°œμˆ˜λ³΄λ‹€ ν•œ 개 더 많고 Xκ°€ ν•œ 쀄을 μ±„μš΄ 경우

κ΅¬ν˜„μ„ μ‰½κ²Œ ν•˜λ €κ³  μž…λ ₯받은 κ²Œμž„νŒ tictactoe λ¬Έμžμ—΄μ„ 2차원 λ°°μ—΄λ‘œ λ³€κ²½ν•΄μ„œ tictactoe2d 배열에 μ €μž₯ν–ˆλ‹€.

그리고 numX에 X의 개수λ₯Ό μ €μž₯ν•˜κ³ , numY에 O의 개수λ₯Ό μ €μž₯ν–ˆλ‹€.

(λ³€μˆ˜λͺ…을 numO둜 ν–ˆμ–΄μ•Ό ν–ˆλŠ”λ° Xκ°€ λ‚˜μ˜€λ‹€λ³΄λ‹ˆ λ¬΄μ˜μ‹μ μœΌλ‘œ numY둜 μ„€μ •ν–ˆλ‹€πŸ™ƒ..)

 

이후 μ°¨λ‘€λ‘œ μœ„μ—μ„œ μƒκ°ν–ˆλ˜ κ·œμΉ™μ— λ§Œμ‘±ν•˜λŠ”μ§€ ν™•μΈν•œλ‹€. 

 

numX=numY+1인 κ²½μš°λŠ” μœ„μ—μ„œ μ˜ˆμƒν–ˆλ˜ κ·œμΉ™ 1번과 3λ²ˆμ„ λ§Œμ‘±ν•  κ°€λŠ₯성이 μžˆλ‹€. 

λ¨Όμ € numX=5이고, numY=4인 κ²½μš°μ—” κ²Œμž„νŒμ΄ 꽉 μ±„μ›Œμ§„ μƒνƒœμΈλ° X, O λͺ¨λ‘ ν•œ 쀄을 λ§Œλ“€μ§€ λͺ»ν•˜λŠ”μ§€ success ν•¨μˆ˜λ‘œ ν™•μΈν–ˆλ‹€.

(success ν•¨μˆ˜ μ½”λ“œ μ„€λͺ…은 밑에 μžˆλ‹€)

 

그리고 Xκ°€ μ΄κΈ°λŠ” κ²½μš°μΈμ§€ ν™•μΈν–ˆλŠ”λ°, 이 κ²½μš°μ—” XλŠ” ν•œ μ€„λ§Œ λ§Œμ‘±ν•˜λ©΄μ„œ OλŠ” ν•œ 쀄도 λ§Œμ‘±ν•΄μ„œλŠ” μ•ˆλœλ‹€.

μ—¬κΈ°μ„œ Xκ°€ ν•œ μ€„λ§Œ λ§Œμ‘±ν•˜λŠ”μ§€ ν™•μΈν•˜λŠ” 것 뿐만 μ•„λ‹ˆλΌ Oκ°€ ν•œ 쀄도 λ§Œμ‘±ν•˜μ§€ λͺ»ν•˜λŠ”μ§€ ν™•μΈν•˜λŠ” 것도 μ€‘μš”ν•˜λ‹€.

μ™œλƒν•˜λ©΄ Oκ°€ ν•œ 쀄을 λ§Œλ“œλŠ”μ§€ ν™•μΈν•˜μ§€ μ•ŠμœΌλ©΄ μ•„λž˜μ™€ 같은 κ²½μš°λŠ” ν•„ν„°λ§ν•˜μ§€ λͺ»ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€. 

O X X
O O O
X X X

λ‹€μŒμœΌλ‘œ numX==numY+1을 λ§Œμ‘±ν•˜μ§€λ§Œ μœ„ 두 κ°€μ§€ κ²½μš°κ°€ μ•„λ‹Œ κ²½μš°λŠ” μ΅œμ’… μƒνƒœκ°€ μ•„λ‹ˆλ―€λ‘œ invalidλ₯Ό 좜λ ₯ν•œλ‹€.

 

λ‹€μŒμœΌλ‘œ, numX==numY인 κ²½μš°λŠ” Oκ°€ μ΄κΈ°λŠ” κ²½μš°μΈμ§€ ν™•μΈν•˜κΈ° μœ„ν•΄μ„œ Oκ°€ ν•œ 쀄을 λ§Œλ“€λ©΄μ„œ Xκ°€ ν•œ 쀄을 λ§Œλ“€μ§€ λͺ»ν•˜λŠ”μ§€ 확인해야 ν•œλ‹€. 

예λ₯Ό λ“€μ–΄ μ•„λž˜μ˜ 경우, Xκ°€ λ¨Όμ € ν•œ 쀄을 μ±„μš°κ³  κ²Œμž„μ΄ λλ‚˜κΈ° λ•Œλ¬Έμ— Oκ°€ λ‹€μŒ ν•œ 쀄을 μ±„μšΈ 수 μ—†λ‹€. 

X O .
X O .
X O .

그런데 λ‹¨μˆœνžˆ success(tictactoe2d, 'O')λ₯Ό ν†΅ν•΄μ„œ Oκ°€ ν•œ 쀄을 μ±„μš°λŠ”μ§€λ§Œ ν™•μΈν•˜λŠ” μ½”λ“œλ₯Ό μ œμΆœν•˜κ³  톡과λ₯Ό λ°›μ•˜μ—ˆλŠ”λ° λ‹€μ‹œ μƒκ°ν•΄λ³΄λ‹ˆ μœ„μ˜ κ²½μš°λŠ” λΆˆκ°€λŠ₯ν•˜μ§€λ§Œ validν•œ 경우라고 좜λ ₯ν•˜λŠ”λ°λ„ λΆˆκ΅¬ν•˜κ³  톡과가 됐닀. κ·Έλž˜μ„œ 질문 κ²Œμ‹œνŒμ— μœ„ μΌ€μ΄μŠ€μ— λŒ€ν•΄μ„œ μ§ˆλ¬Έμ„ 남겨둔 μƒνƒœμ΄λ‹€!

닡변이 λ‹¬λ¦¬κ±°λ‚˜ 이유λ₯Ό 찾으면 이 글에 μ—…λ°μ΄νŠΈ ν•˜κ² μŠ΅λ‹ˆλ‹€

이제 success ν•¨μˆ˜μ— λŒ€ν•΄μ„œ μ½”λ“œ μ„€λͺ…을 ν•΄λ³΄μžλ©΄ λ‹€μŒκ³Ό κ°™λ‹€.

def success(tictactoe, xoro):
    # λŒ€κ°μ„  λ§Œμ‘±ν•˜λŠ” 라인 개수
    dia_line=0
    # 평행선 λ§Œμ‘±ν•˜λŠ” 라인 개수
    pal_line=0
    # 3쀄을 λ§Œμ‘±ν•˜λŠ” 경우 μ°ΎκΈ°
    # 1쀄 이상 만쑱히면 λΆˆκ°€λŠ₯ν•œ 경우이기 λ•Œλ¬Έμ— line λ³€μˆ˜μ— λ§Œμ‘±ν•˜λŠ” μ€„μ˜ 개수λ₯Ό μ €μž₯함.
    # λŒ€κ°μ„ μœΌλ‘œ λ§Œμ‘±ν•˜λŠ” 경우
    if tictactoe[0][0]==xoro and tictactoe[1][1]==xoro and tictactoe[2][2]==xoro:
        dia_line+=1
    if tictactoe[0][2]==xoro and tictactoe[1][1]==xoro and tictactoe[2][0]==xoro:
        dia_line+=1
    for i in range(3):
        if tictactoe[i][0]==xoro and tictactoe[i][1]==xoro and tictactoe[i][2]==xoro:
            pal_line+=1
        if tictactoe[0][i]==xoro and tictactoe[1][i]==xoro and tictactoe[2][i]==xoro:
            pal_line+=1
    # 1μ€„λ§Œ λ§Œμ‘±ν•˜λŠ” 경우
    if dia_line+pal_line==1:
        return True
    elif dia_line==2:
        return True
    else:
        return False

λ¨Όμ € λŒ€κ°μ„ μ„ λ§Œμ‘±ν•˜λŠ” 경우 dia_line에 +1을 ν•œλ‹€. 

그리고 for문을 λŒλ©΄μ„œ ν–‰ λ˜λŠ” 열을 κΈ°μ€€μœΌλ‘œ λ§Œμ‘±ν•˜λŠ”μ§€ pal_line에 +1을 ν•œλ‹€.

μ΄λ ‡κ²Œ λ§Œμ‘±ν•˜λŠ” μ€„μ˜ 수λ₯Ό λͺ¨λ‘ κ΅¬ν•œ λ‹€μŒμ—, dia_lineκ³Ό pal_line을 λ”ν•΄μ„œ 1μ€„λ§Œ λ§Œμ‘±ν•˜λŠ”μ§€ ν™•μΈν•˜κ³ , 1μ€„λ§Œ λ§Œμ‘±ν•œλ‹€λ©΄ Trueλ₯Ό λ¦¬ν„΄ν•œλ‹€.

그리고 dia_line의 2쀄일 λ•Œλ„ Trueλ₯Ό 리턴해야 ν•œλ‹€.

이 뢀뢄이 μ•žμ„œ μ–ΈκΈ‰ν–ˆλ˜ μƒκ°ν•˜μ§€ λͺ»ν–ˆλ˜ λ°˜λ‘€μ΄λ‹€!

X O X
O X O
X O X

이 κ²½μš°λŠ” Xκ°€ λŒ€κ°μ„  ν•œ 쀄을 μ±„μš°λ©΄ μ’…λ£Œλ˜κΈ° λ•Œλ¬Έμ— λΆˆκ°€λŠ₯ν•œ 경우라고 μƒκ°ν–ˆλŠ”λ°, κ°€μž₯ λ¨Όμ € Xλ₯Ό λ‘˜ λ•Œ, κ°€μš΄λ° 뢀뢄에 두고 μ‹œμž‘ν•˜λ©΄ κ°€λŠ₯ν•œ μΌ€μ΄μŠ€μ˜€λ‹€.

이 외에 λ§Œμ‘±ν•˜λŠ” 쀄이 μ—¬λŸ¬ μ€„μ΄κ±°λ‚˜ μ—†λŠ” κ²½μš°μ—” Falseλ₯Ό λ¦¬ν„΄ν•œλ‹€.