[Python] 54-Poker hands

링크

결과

답은 적지 않지만 풀면서 중복된 값을 찾고 정렬해서 스트레이트 카드인지 여부를 판별하는데 어려움이 있었던것 같다.

소스 코드는 많이 지저분 하지만 나름대로 한번에 풀이한 성과가 있는거 같다.

문제 풀이

  1. CARD 인덱싱할 수 있는 배열을 선언
  2. 승리 여부를 판별할 수 있는 배열 선언
  3. 각 카드를 승리 여부를 판별 할 수 있는 문자로 변환
  4. 플레이어 2명의 카드가 동일한 경우 두번째로 높은 카드를 판별

** collections.Counter 클래스를 이용 **

collections.Counter 클래스는 배열의 중복되는 값을 찾아 Key-Value 형태로 리턴해주기 때문에 One-Pair, Two-Pairs, Full House, Four Card 등과 같은 값을 판별하기 적합하다.

[풀이코드]

import collections
import logging

CARD_INDEX = ['A', 'T','J','Q','K']
WIN_ORDER = ['None', 'HIGH', 'ONE_PAIR', 'TWO_PAIR', 'THREE_OF_KIND'
             , 'STRAIGHT', 'FLUSH', 'FULL_HOUSE', 'FOUR_OF_A_KIND', 'S_FLUSH', 'R_FLUSH']
for i in range(2, 10):
  CARD_INDEX.insert(i-1, str(i))

logging.basicConfig(filename='D:/result.log',level=logging.DEBUG)



def flushCheck(nums):
  nums = sorted(nums)
  R_FLUSH_CARDS = [CARD_INDEX.index('A'), CARD_INDEX.index('T'), CARD_INDEX.index('J'), CARD_INDEX.index('Q'), CARD_INDEX.index('K')]
  if (len(set(nums).intersection(R_FLUSH_CARDS)) == 5):
    return 'R_FLUSH', nums

  if not isStraight(nums):
    return 'FLUSH', nums  
  return 'S_FLUSH', nums


def isStraight(nums):
  nums = sorted(nums)
  for i in range(0, len(nums)-1):    
    if (nums[i]+1 != nums[i+1]):      
      return False
  return True


def getResult(nums, suits):   

  if (len(set(suits)) == 1):
    return flushCheck(nums)

  cardCounters = collections.Counter(nums).values()  
  if 4 in cardCounters:
    return 'FOUR_OF_A_KIND', nums

  if len(cardCounters) == 2 and (3 in cardCounters) and (2 in cardCounters):
    return 'FULL_HOUSE', nums

  if isStraight(nums):
    return 'STRAIGHT', nums

  if len(cardCounters) == 3 and 3 in cardCounters:
    return 'THREE_OF_KIND', nums

  if len(cardCounters) == 3 and 2 in collections.Counter(cardCounters).values():
    return 'TWO_PAIR', nums

  if len(cardCounters) == 4 and 2 in cardCounters:
    return "ONE_PAIR", nums

  return "None", 'None'


def sperateNumSuit(s):  
  cards = s.split(" ")
  nums = []
  suits = []
  for c in cards:
    num = c[:1]
    suit = c[1:]    
    nums.append(CARD_INDEX.index(num))
    suits.append(suit)
  return nums, suits


def getHighestNum(num1, num2):
  # Ace is highest number
  while True:
    if 0 not in num1:
      break
    num1[num1.index(0)] = 14  

  while True:
    if 0 not in num2:
      break
    num2[num2.index(0)] = 14  

  collectNum1 = collections.Counter(num1)
  collectNum2 = collections.Counter(num2)

  if (len(collectNum1) == 5):
    if 0 in num1:
      return "PLAYER#1 WIN"
    elif 0 in num2:
      return "PLAYER#2 WIN"    
    return (max(num1) > max(num2)) and "PLAYER#1 WIN" or "PLAYER#2 WIN"

  for i in range(1, len(collectNum1)):
    p1Max = max(collectNum1, key=collectNum1.get)
    p2Max = max(collectNum2, key=collectNum2.get)

    if (collectNum1[p1Max] == 1 and collectNum2[p2Max] == 1):
      return max(collectNum1) > max(collectNum2) and "PLAYER#1 WIN" or "PLAYER#2 WIN"            

    if (p1Max == p2Max):
      print collectNum1, collectNum2
      del collectNum1[p1Max]
      del collectNum2[p2Max]      
      print 'DELETE %s' % CARD_INDEX[p1Max]

    else:      
      if (p1Max > p2Max):
        return "PLAYER#1 WIN"
      else: 
        return "PLAYER#2 WIN"


if __name__ == '__main__':
  f = open("C:/Users/coozplz/Downloads/p054_poker.txt")
  lines = f.readlines()  
  p1WinCount = 0
  for s in lines:      
    p1, p2 = s[:14], s[15:len(s)-1]
    logging.info("P1=%s, P2=%s" % (p1, p2))
    nums1, suits1 = sperateNumSuit(p1)    
    pr1, n1 = getResult(nums1, suits1)  
    nums2, suits2 = sperateNumSuit(p2)    
    pr2, n2 = getResult(nums2, suits2)
    if pr1 == None:
      pr1 = 'None'
    if pr2 == None:
      pr2 = 'None'

    logging.info("%s,%s / %s, %s" % (pr1, str(n1), pr2, str(n2)))
    if pr1 == pr2:      
      result = getHighestNum(nums1, nums2)
    else:
      if (WIN_ORDER.index(pr1) > WIN_ORDER.index(pr2)):
        result = "PLAYER#1 WIN"
      else:
        result = "PLAYER#2 WIN"
    if (result == "PLAYER#1 WIN"):
      p1WinCount += 1
      logging.info("Player1 Won!!")
    else:
      logging.info("Player2 Won!!")    
    logging.info( "-" * 80)
  logging.info("Total Win Count=%d" % p1WinCount)    

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

%s에 연결하는 중