[Python 2.x] print without newline

파이썬 2.X 에서 줄바꿈 없이 출력하기

파이썬 2.x를 사용하다 보니 출력 결과가 줄바꿈이 되서 표시되는 현상이 발생하였습니다.
그래서 그걸 해결하기위해 검색하다보니 역시나…

from __future__ import print_function

위와 같이 선언하고 python3 에 있는 print 함수를 동일하게 사용하면 되는 편리함이…

data = ['hello', 'world']
for d in data:
    print(d, end=' ')

# 출력결과
# hello world

다른 방법은 sys 모듈을 사용하는 방법입니다.

sys.stdout.write('a')

위와 같이 사용하면 되는데 sys 모듈을 사용하는 것 보다는 __future__print_function 을 사용하는게 보다 유용하게 사용할 수 있을 것 같습니다.

이상입니다.

[Python] 크리스마스트리

제작 의도

어제 다음 카페 게시글을 보다 보니 각 학과별 크리스마스트리를 그리는 방법이라는 글이 올라와 있어 Python을 이용하여 크리스마스 트리를 제작해봤습니다.

모두 즐거운 성탄절 되세요..!!

소스 코드

ROW = 9


def printTree(maxCountOfSpaceNStart):
    for i in range(1, maxCountOfSpaceNStart):
        print '%*s%*s' % (ROW-i, ' ', 0, '*' * (i * 2 -1))

if __name__ == '__main__':
    print '=' * 20
    print '%2s%s' % (' ', 'Merry Christmas!!!')
    print '=' * 20
    trees = [5, 7, 9]
    for i in trees:
       printTree(i)

실행 결과

====================
  Merry Christmas!!!
====================
        *
       ***
      *****
     *******
        *
       ***
      *****
     *******
    *********
   ***********
        *
       ***
      *****
     *******
    *********
   ***********
  *************
 ***************

[Python] netstat

개발 내용

네트워크 프로그래밍을 하다 보면 서버에서 어떤 클라이언트가 접속했는지 확인을 해야 하는데 Windows 환경에서 제공하는 netstat 으로 목록을 출력하고 findstr command를 이용하여 필터링하는 과정을 주기적으로 하는 프로그램을 Python 으로 구현

개발 및 동작 환경

  • OS: Windows 7 64Bit
  • Python: 2.7.10

소스 코드

# -*- coding: utf-8 -*-
# ===================================================================
# Author: coozplz@gmail.com
# File: netstat.py
# Date: 2015. 10. 16
# Desc: Windows command "netstat -anp tcp | findstr [PORT]" 를 주기적으로 하는 프로그램
# ===================================================================

import subprocess
import time
from time import localtime, strftime
import datetime

PORT = '12084'
SLEEP_SEC = 5


class NetstatInfo:
    def __init__(self, protocol, local_addr, remote_addr, status):
        self.protocal = protocol
        self.local_addr = local_addr
        self.remote_addr = remote_addr
        self.status = status

    def __str__(self):
        return '%s %s %s %s' % (self.protocal, self.local_addr, self.remote_addr, self.status)


if __name__ == '__main__':
    while True:
        print '-' * 70
        print '%40s' % strftime('%Y-%m-%d, %H:%M:%S', localtime())
        print '-' * 70
        out, err = subprocess.Popen("netstat -anp tcp", stdout=subprocess.PIPE).communicate()
        result = out.splitlines()
        filtered_line = []
        for line in result:
            if PORT in line:
               splitted_value = filter(lambda x: len(x) > 0, line.split(' '))
               n = NetstatInfo(splitted_value[0], splitted_value[1], splitted_value[2], splitted_value[3])
               print n
        time.sleep(SLEEP_SEC) 

[Python] 018/067 Maximum Path Sum

밤에 잠이 안와서 시작한 문제 풀이가 어느덧 3시간이 지났다.
그래서 풀어서 기분은 좋다..^^

문제를 보고 잘못 생각해서 위에서 아래로 큰 수를 찾아가는 거로 계산을 하고 제출을 했는데 오답 표시.

문제를 다시 읽어보니 어떻게 풀어야 할지 조금 막막하다.. 구글신의 도움을 받아 다른 사람이 어떻게 풀었는지를 찾아보았다.

http://www.mathblog.dk/project-euler-18/

위의 링크에 보면 Dynamic Programming 이라는 섹션에 어떤식으로 풀어야 되는지 표시가 되어 있다.

풀이과정

[초기값]

8 5 9 3
2 4 6
7 4
3

[가공값]

  1. 8+2 와 5+2 를 비교하여 큰값을 2행 1열(2)위치에 입력
  2. 5+4 와 9+4 를 비교하여 큰값을 2행 2열(4)위치에 입력
  3. 9+6 과 3+6 을 비교하여 큰값을 2행 3열(6)위치에 입력
  4. 1~3의 스텝을 반복한다.

[소스코드]

import unittest


class TestMaximumPathSumClass(unittest.TestCase):

    def testExample(self):
        input_str = '''
                    3
                    7 4
                    2 4 6
                    8 5 9 3'''
        value = self.maximum_path_sum(input_str)
        self.assertEqual(value, 23)

    def testPE67(self):
        f = open("/Users/p/Downloads/p067_triangle.txt")
        lines = f.readlines()
        value = self.maximum_path_sum(''.join(lines))
        print(value)
        f.close()

    def testPE18(self):
        input_str = '''
                    75
                    95 64
                    17 47 82
                    18 35 87 10
                    20 04 82 47 65
                    19 01 23 75 03 34
                    88 02 77 73 07 63 67
                    99 65 04 28 06 16 70 92
                    41 41 26 56 83 40 80 70 33
                    41 48 72 33 47 32 37 16 94 29
                    53 71 44 65 25 43 91 52 97 51 14
                    70 11 33 28 77 73 17 78 39 68 17 57
                    91 71 52 38 17 14 91 43 58 50 27 29 48
                    63 66 04 68 89 53 67 30 73 16 69 87 40 31
                    04 62 98 27 23 09 70 98 73 93 38 53 60 04 23'''
        value = self.maximum_path_sum(input_str)
        print("Maximum path sum = ", value)

    def maximum_path_sum(self, input_str):
        input_str = input_str.strip()
        lines = input_str.split('n')
        array = []
        for line in lines:
            if len(line) == 0:
                continue
            nums_array = line.strip().split(" ")
            array.insert(0, nums_array)

        for i in range(0, len(array) - 1):
            nums_array = array[i]
            changed_array = []
            for j in range(0, len(nums_array)-1):
                v1 = int(array[i][j]) + int(array[i+1][j])
                v2 = int(array[i][j+1]) + int(array[i+1][j])
                changed_array.append(max(v1, v2))
            array[i+1] = changed_array
            print(changed_array)

        return array[len(array)-1][0]

if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(TestMaximumPathSumClass)
    unittest.TextTestRunner(verbosity=2).run(suite)

[Python] 53_combinatoric_selections

문제링크

문제풀이

  1. 조합을 구하는 함수를 정의한다
  2. 팩토리얼을 구하는 함수를 정의한다. (팩토리얼을 lambda를 이용한다)
  3. 조합의 공식에 따라 구해진 값이 1,000,000이 넘는 값을 카운팅 한다.
import unittest
import functools


class TestCombination(unittest.TestCase):

    def testCombination(self):
        value = self.combination(5, 3)
        self.assertEqual(value, 10)

        value = self.combination(23, 10)
        self.assertEqual(value, 1144066)

    def combination(self, a, b):
        v1 = self.fact(a)
        v2 = (a == b and 1 or (self.fact(b) * (self.fact(a - b))))
        return v1 / v2

    def fact(self, a):
        if a == 0:
            return 0
        fact_value = functools.reduce(lambda x, y: x * y, range(1, a + 1))
        return fact_value

    def testOverMillionCount(self):
        count = 0
        for i in range(1, 101):
            for j in range(1, i):
                combi_value = self.combination(i, j)
                if combi_value > 1000000:
                    # print("%d, %d, combi_value=%d" % (i, j, combi_value))
                    count += 1
        print("Over 1million counts = ", count)

if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(TestCombination)
    unittest.TextTestRunner(verbosity=2).run(suite)

[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)    

[Python] 56-Powerful digit sum

A googol (10100) is a massive number: one followed by one-hundred zeros; 100100 is almost unimaginably large: one followed by two-hundred zeros. Despite their size, the sum of the digits in each number is only 1.

Considering natural numbers of the form, ab, where a, b < 100, what is the maximum digital sum?


문제 해결 전략

  1. 제곱을 문자열로 변환하여 문자열을 한자씩 더해 간다.
  2. 문자열을 더하기 위해서 reduce 와 lambda를 활용한다.
def sumOfDigit(i, j):
  powValue = str(i**j)
  result = reduce(lambda x, y: int(x)+int(y), powValue)
  return int(result)


if __name__ == '__main__':
  maxValue = iVal = jVal = 0    
  for i in range(1, 101):      
    for j in range(1, 101):        
      result = sumOfDigit(i, j)
      if (result > maxValue):          
        maxValue, iVal, jVal = result, i, j          
  print "i=%d, j=%d, maximum=%d" % (iVal, jVal, maxValue)