카테고리 보관물: python

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

PythonMagick과 PIL을 이용한 PDF에서 이미지 추출

테스트 환경

  • 운영체제: Windows 7 64Bit
  • PythonVersion: 2.7

ImageMagick 설치

  1. ImageMagick 다운로드 [링크]
  2. ImageMagick 설치
  3. 중요 환경 변수 등록 (IMAGEMAGICK_HOME)

PythonMagick 설치

PIP 또는 easy_install 을 이용하여 설치 할 수 없기 때문에 수동으로 설치를 해야 하는 부분이 있습니다.

  1. PythonMagick‑0.9.10‑cp27‑none‑win32.whl 파일 다운로드 [링크] (운영체제가 64Bit여도 32Bit 파일을 다운로드)
  2. pip 를 이용하여 설치
C:UserscoozplzDownloads>pip install PythonMagick-0.9.10-cp27-none-win32.whl

테스트
파이썬 명령 프롬프트에서 import를 했을때 Module Not Found 가 표시되지 않으면 정상적으로 설치된 것입니다.

>>> import PythonMagick

GhostScript 설치

GhostScript가 없는 경우 Windows에서 실행하면 파일의 저장경로를 찾을 수 없다는 오류가 발생됩니다.

  1. GhostScript 32Bit 다운로드 [링크] (운영체제가 64Bit여도 32Bit 파일을 다운로드)
  2. GhostScript 설치
  3. 환경변수 등록 (GHOSTSCRIPT_HOME)

PIL 설치

> easy_install PIL

테스트
파이썬 명령 프롬프트에서 import를 했을때 Module Not Found 가 표시되지 않으면 정상적으로 설치된 것입니다.

>>> import Image

소스

import PythonMagick
import Image
import time

def loadPDFImage(pdfPath, outputFile):
    """
    PDF 파일을 로딩하여 이미지 파일로 저장한다.
    :param pdfPath  PDF 파일 경로
    :param outputFile   추출한 이미지 저장 경로
    """
    pdfImage = PythonMagick.Image()
    pdfImage.density("300")
    pdfImage.read(pdfPath)
    pdfImage.write(outputFile)


def splitImage(imageFileName, splittedImageSavingDir):
    """
    이미지 파일을 원하는 크기로 Split한 후 저장한다.
    :param imageFileName    원본 이미지의 경로
    :param splittedImageSavingDir   잘린 이미지를 저장할 상위 디렉토리
    """
    loadedImage = Image.open(imageFileName)
    for i in range(3):
        left = 256 + (952 * i) + (15 * i)
        right = 1212 + (952 * i) + (15 * i)
        cropImage = loadedImage.crop((left, 278, right, 1800))
        savingFileName = "%s_%d.jpg" % (time.strftime('%Y%m%d%H%M'), i)
        cropImage.save("%s/%s" % (splittedImageSavingDir, savingFileName))
        print "Successfully saved, %s" % savingFileName


if __name__ == '__main__':
    pdfPath = "D:/test.pdf"
    outputPath = "D:/test.jpg"
    splittedImageSavingDir = "D:/"
    loadPDFImage(pdfPath, outputPath)
    splitImage(outputPath, splittedImageSavingDir)

결과

원본 PDF
ORIGIN_IMAGE

잘린 이미지
SPLIT_IMAGE{max-width:320px}

Python 스크립트파일을 Exe로 변경

Install py2exe

> pip install py2exe

실행 스크립트

#execute_test.py
print 'HelloWorld'

Setup.py 스크립트

#setup.py
from distutils.core import setup
import py2exe, sys, os

sys.argv.append('py2exe')

options = {
    "bundle_files": 1,                    # create singlefile exe
    "compressed"  : 1,                    # compress the library archive
    "excludes"    : ["w9xpopen.exe"]    # we don't need this
}

setup(
    options = {'py2exe' : options},
    windows = [{'script': "merge_swf_helper.py"}],
    zipfile = None,
)

Cmd 창에서 빌드 명령 실행

> python setup.py install

결과 확인

명령을 실행한 폴더의 dist 디렉토리에 들어가면 생성된 exe 파일을 볼 수 있다.

[Python] Read excel(xlsx)

xlrd 를 이용한 엑셀 파일 읽기


기능

xlsx 파일에서 cell에 입력된 Text 데이터를 모두 출력한다. 출력 포맷은 excel 데이터와 동일하게 출력하도록 한다. (ROW별로 출력)

리소스정보

  • 입력: 컨텐츠가 포함된 xlsx 파일(resource.xlsx)

소스코드
#-*- coding: utf-8 -*-
# ================================================
# Author: coozplz@gmail.com
# Date: 2015. 08. 11
# Desc: 토플 앱 개발에 필요한 엑셀 파일 분석
# ================================================

import xlrd

def open_excel(path):
    '''
    엑셀 파일에 포함된 내용을 system.out으로 출력한다. 
    '''
    workbook = xlrd.open_workbook(path)

    # 엑셀 시트 개수 정보 출력
    print workbook.nsheets
    # 0번 시트정보를 조회한다.
    sheet = workbook.sheet_by_index(0)
    for row_num in range(sheet.nrows):
        row = sheet.row(row_num)
        cols = []
        for cell in row:
            if (cell.ctype == 1):
                cols.append(cell.value)
        print ','.join(cols)

#
# Main
#
if __name__ == '__main__':
    path = './word_end_0811.xlsx'
    open_excel(path)