정의 (소수와 합성수)
    1보다 큰 양의 정수 n에 대하여
    (i) n = a * b 를 만족하고 1보다 큰 두 양의 정수 a와 b가 존재하면,
        n을 합성수(合成數, composite number)라고 한다. 참고로 이 경우,
        a, b 중에 적어도 하나는 sqrt(n) 보다 작거나 같다.
        합성수의 예로는 4, 6, 9, 24, 143 등이 있다.
    (ii) n = a * b 를 만족하고 1보다 큰 두 양의 정수 a와 b가 존재하지 않으면,
         즉 n을 두 양의 정수의 곱으로 표현하는 방법이 1*n과 n*1 두 가지 뿐이면,
         n을 소수(素數, prime number)라고 한다.  소수의 예로는 2, 3, 5, 7, 11 등이 있다.
         n이 소수인지 아닌지 확인하려면, 
         n을 2 보다 크거나 같고 sqrt(n) 보다 작거나 같은 모든 정수로 나누어 본다.
         이 경우 언제나 나누어 떨어지지  않으면 n은 소수이고, 그렇지 않으면 n은 합성수이다.
    

우선 다음의 Python 소스 코드는 명령행 인자로 전달 받은 양의 정수 n을
2 및 3, 5, 7, ... , sqrt(n) 이하의 홀수들로 나누어 보아 n이 합성수인지 아닌지
확인하는 애플리케이션 소스이다. 확인하는데 걸린 경과 시간도 알려준다.


#  Filename: divideEach.py
#
#  Purpose:  Determine whether the given integer is a prime or not.
#
#  Execute: python divideEach.py [integer]
#
#     Date:  2009/03/23
#   Author:  PH Kim   [ pkim ((AT)) scripts.pe.kr ]

"""
  Execution Examples:
      Prompt> python divideEach.py 1234567812343
      1234567812343 = 1 * 1234567812343
      1234567812343 is a prime
      Elapsed time: 0.562000 sec
 
      Prompt> python divideEach.py 9999994200000841
      9999994200000841 = 99999971 * 99999971
      9999994200000841 is a not prime
      Elapsed time: 51.437000 sec
 
      Prompt> python divideEach.py 18446744073709551617
      18446744073709551617 = 274177 * 67280421310721
      18446744073709551617 is a not prime
      Elapsed time: 0.141000 sec

      Prompt> python divideEach.py 10023859281455311421
      10023859281455311421 = 1308520867 * 7660450463
      10023859281455311421 is a not prime
      Elapsed time: 705.016000 sec
 """

import sys
import math
from time import *

n = 10006099720301
if len(sys.argv) > 1:
    n = int(sys.argv[1])

z = int(n / 2)
if n == 2*z:
    print "%d = %d * %d" % (n, 2, z)

time1 = time()

d = 1
k = 3
while k*k <= n:
    z = n // k
    if n == k*z:
        d = k
        break
    k = k + 2

time2 = time()

print "%d = %d * %d" % (n, d, n/d)
if d == 1:
    print "%d is a prime" % n
else:
    print "%d is a not prime" % n

print "Elapsed time: %f sec" % (time2 - time1)




이제 다음은 정수의 인수분해 능력이 뛰어난  Pollard의 rho 방법(일명 거북이와 토끼 알고리즘, tortoise-hair algorithm)을 구현한  Python 소스 코드이다. 이 알고리즘은 소수에 대해서는 시간이 많이 걸리지만, 합성수에 대해서는 시간이 매우 적게 걸린다는 것이 특징이다.

 

#  Filename: pollardRho.py
#
#  Purpose:  By using the pollard rho method,
#            determine whether the given integer is a prime or not.
#
#      See:  http://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm
#            http://en.wikipedia.org/wiki/Floyd%27s_cycle-finding_algorithm#Tortoise_and_hare#
#
#  Execute: python pollardRho.py [integer]
#
#     Date:  2009/03/23
#   Author:  PH Kim   [ pkim ((AT)) scripts.pe.kr ]

"""
  Execution Examples:
      Prompt> python pollardRho.py 1234567812343
      Try first the Pollard rho algorithm with c = 2
      d = 1234567812343, count = 466951
      Try second the Pollard rho algorithm with c = 3
      d = 1, count = 1111112
      Try third the Pollard rho algorithm with c = 1
      d = 1234567812343, count = 799441
      1234567812343 = 1234567812343 * 1
      Elapsed time: 28.656000 sec

      Prompt> python pollardRho.py 9999994200000841
      Try first the Pollard rho algorithm with c = 2
      d = 99999971, count = 3593
      9999994200000841 = 99999971 * 99999971
      Elapsed time: 0.062000 sec

      Prompt> python pollardRho.py 18446744073709551617
      Try first the Pollard rho algorithm with c = 2
      d = 274177, count = 1028
      18446744073709551617 = 274177 * 67280421310721
      Elapsed time: 0.016000 sec

      Prompt> python pollardRho.py 10023859281455311421
      Try first the Pollard rho algorithm with c = 2
      d = 1308520867, count = 20350
      10023859281455311421 = 1308520867 * 7660450463
      Elapsed time: 0.375000 sec
"""

import sys
from time import *

def f(x, c, n):
    return (x*x + c) % n

def g(x, c, n):
    return f(f(x, c, n), c, n)

def gcd(x, y):
    a = abs(x)
    b = abs(y)
    if b == 0:
        return a
    while b != 0:
        t = a % b
        a = b
        b = t
    return a

def pollardRho(n):
    c = 2
    x = 1
    y = 1
    d = 1
    savedX = x
    count = 0
    print "Try first the Pollard rho algorithm with c = %d" % c
    while d == 1 and count*count <= n:
        x = f(x, c, n)
        if x == savedX:
         print "It is cyclic.  x = %d" % x
         break
        y = g(y, c, n)
        d = gcd(abs(x - y), n)
        count = count + 1
        # if count % 5000 == 0:
        #  print "  count = %d" % count

    print "d = %d, count = %d" % (d, count)
    if d > 1 and d < n:
        return d

    c = 3
    x = 1
    y = 1
    d = 1
    savedX = x
    count = 0
    print "Try second the Pollard rho algorithm with c = %d" % c
    while d == 1 and count*count <= n:
        x = f(x, c, n)
        if x == savedX:
         print "It is cyclic.  x = %d" % x
         break
        y = g(y, c, n)
        d = gcd(abs(x - y), n)
        count = count + 1
        # if count % 5000 == 0:
        #  print "  : count = %d" % count

    print "d = %d, count = %d" % (d, count)
    if d > 1 and d < n:
        return d

    c = 1
    x = 1
    y = 1
    d = 1
    savedX = x
    count = 0
    print "Try third the Pollard rho algorithm with c = %d" % c
    while d == 1 and count*count <= n:
        x = f(x, c, n)
        if x == savedX:
         print "It is cyclic.  x = %d" % x
         break
        y = g(y, c, n)
        d = gcd(abs(x - y), n)
        count = count + 1
        # if count % 5000 == 0:
        #  print "  : count = %d" % count

    print "d = %d, count = %d" % (d, count)

    return d


n = 9991
if len(sys.argv) > 1:
    n = int(sys.argv[1])

time1 = time()

k = pollardRho(n)

time2 = time()

z = n/k
if n == k*z:
    print "%d = %d * %d" % (n, k, z)

print "Elapsed time: %f sec" % (time2 - time1)


 

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Scripter
,


초등학교 때 배우는 두 정수의 곱셈표를 만들어 주는 Python 소스이다.
(이 소스는 Jython이나 IronPython에서도 수정없이 그대로 실행된다.)

이항 연산자 // 는 Python의 정수나눗셈 연산자이다.


# Filename: makeMultTable.py
#
#     Print a multiplication table.
#
#     Execute: python makeMultTable.py 230 5100
#
# Date: 2009/03/06
#
#

import sys

def printUsing():
    print "Using: python makeMultTable.py [number1] [number2]"
    print "Print a multiplication table for the given two integers."

def printMultTable(x, y):
    nx = x
    if nx < 0:
        nx = -nx
    ny = y
    if ny < 0:
        ny = -ny
    ntail1 = 0
    ntail2 = 0
    while nx % 10 == 0:
        nx = nx // 10
        ntail1 = ntail1 + 1
    while ny % 10 == 0:
        ny = ny // 10
        ntail2 = ntail2 + 1
    z = nx * ny
    strZ = "%d" % z
    strX = "%d" % nx
    strY = "%d" % ny
    n = len(strY)
    zeros  = "0000000000000000000000000000000000000000"
    whites = "                                        "
    bars   = "----------------------------------------"
    loffset = "       "
    line4 = loffset + strZ
    line1 = loffset + whites[0: len(strZ) - len(strX)] + strX
    line2 = "   x ) " +  whites[0: len(strZ) - len(strY)] + strY
    line3 = "     --" +  bars[0: len(strZ)]
    print line1 + zeros[0: ntail1]
    print line2 + zeros[0: ntail2]
    print line3
    if len(strY) > 1:
        for i in range(0, len(strY)):
            y1 = int(strY[len(strY) - i - 1: len(strY) - i])
            if y1 != 0:
                strT = "%d" % (nx * y1)
                print loffset + whites[0: len(strZ) - len(strT) - i] + strT
        print line3
    print line4 + zeros[0: ntail1] + zeros[0: ntail2]

if len(sys.argv) >= 3:
    x = long(sys.argv[1])
    y = long(sys.argv[2])
    print
    printMultTable(x, y)
else:
    printUsing()



실행> python makeMultTable.py 230 5100
결과>

         230
   x )   5100
     ------
         23
       115
     ------
       1173000

 

크리에이티브 커먼즈 라이선스
Creative Commons License

 

Posted by Scripter
,
▒ Python  소스:  testStringReverse.py

#!/usr/bin/python
# -*- coding: cp949 -*-

s = "Hello, world!"
s2 = "안녕하세요?"

#########################################
t = s[::-1]      # 문자열 거꾸로 하기
t2 = s2[::-1]    # 문자열 거꾸로 하기

#########################################
u = ''.join(reversed(s))     # reversed(string) 함수 사용(Python 2.4 이상 가능)
u2 = ''.join(reversed(s2))   # reversed(string) 함수 사용(Python 2.4 이상 가능)

print( "s = " + s )
print( " ---> " + "s[::-1] = " + t )
print( "      " + "''.join(reversed(s)) = " + t )
print( "s2 = " + s2 )
print( " ---> " + "s2[::-1] = " + t2 )
print( "      " + "''.join(reversed(s2)) = " + t2 )
#########################################
# 출력 결과(Python 2.5의 경우):
# s = Hello, world!
#  ---> s[::-1] = !dlrow ,olleH
#       ''.join(reversed(s)) = !dlrow ,olleH
# s2 = 안녕하세요?
#  ---> s2[::-1] = ?岳세逑楹횡
#       ''.join(reversed(s2)) = ?岳세逑楹횡
#########################################
# 출력 결과(Python 3.0의 경우):
# s = Hello, world!
#  ---> s[::-1] = !dlrow ,olleH
#       ''.join(reversed(s)) = !dlrow ,olleH
# s2 = 안녕하세요?
#  ---> s2[::-1] = ?요세하녕안
#       ''.join(reversed(s2)) = ?요세하녕안




위의 예제에서 보듯이
멀티바이트 유니코드의 문자열을 거꾸로 하기가 Python 3.0의 경우에는 잘 동작하지만,
Python 2.5의 경우에는 잘 동작하지 않는다.
이를 대화형 모드(inttractive mode) 파이썬에서 다시 한번 확인해 보자.

[Python 3,0의 경우]---------------------
명령 프롬프트> python
Python 3.0 (r30:67507, Dec  3 2008, 20:14:27) [MSC v.1500 32 bit (Intel)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> s = "한글"
>>> print( s[::-1] )
글한
>>> ^Z
----------------------------------------



[Python 2,5의 경우]---------------------
명령 프롬프트> python
Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> s = "한글"
>>> print( s[::-1] )
旁饑
>>> ^Z
----------------------------------------


[참고]
IronPython에서 실행시킬 경우 첫줄의 유닉스 shebang(#!) 줄을 제거하여 인코딩 선언

# -*- encoding: cp949 -*-

이 첫 줄에 오도록 고치면 한글도 (정상적으로) 역순으로 변환되어 출력된다.





Creative Commons License

이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.


Posted by Scripter
,

다음은 초등학교에서 배우는 나눗셈 계산표를 만들어주는 Python 소스 코드이다.
나눗셈 계산표를 완성하고 나서 약수, 배수 관계를 알려준다.

아래의 소스는 Jython에서는 수정없이 그대로 실행되지만,
IronPython에서는 인코딩 선언 부분을

        # -*- encoding: ms949 -*-

대신

        # -*- encoding: cp949 -*-
        # -*- encoding: CP949 -*-
        # -*- encoding: euc-kr -*-
        # -*- encoding: EUC-KR -*-

중 하나로 수정해야 실행된다.

  1. # -*- encoding: ms949 -*-
  2. #  Filename: makeDivisionTable.py
  3. #
  4. #  Purpose:  Make a division table in a handy written form.
  5. #
  6. #  Execute: python makeDivisionTable.py 12345 32
  7. #           python makeDivisionTable.py 500210 61
  8. #
  9. #     Date:  2008/05/15
  10. #   Author:  PH Kim   [ pkim ((AT)) scripts.pe.kr ]
  11. import sys
  12. def printUsage():
  13.     # print("Using: python makeDivisionTable.py [numerator] [denominator]")
  14.     # print("Make a division table in a handy written form.")
  15.     print("사용법: python makeDivisionTable.py [피제수] [제수]")
  16.     print("손으로 작성한 형태의 나눗셈 표를 만들어준다.")
  17. def simplify(v, width):
  18.     t = "%ld" % v
  19.     if t[-2:] == ".0":
  20.         t = t[0:len(t) - 2]
  21.     slen = len(t)
  22.     if slen < width:
  23.         t = " " * (width - slen) + t
  24.     return t
  25. def getSuffix(v):
  26.     t = v % 10L
  27.     suffix = "은"
  28.     if "2459".find("%d" % t) >= 0:
  29.         suffix = "는"
  30.     return suffix
  31. def makeTable(numer, denom, quotient):
  32.     strNumer = "%ld" % numer
  33.     strDenom = "%ld" % denom
  34.     strQuotient = "%ld" % quotient
  35.     lenN = len(strNumer)
  36.     lenD = len(strDenom)
  37.     lenQ = len(strQuotient)
  38.     offsetLeft = 3 + lenD + 3
  39.     spaces = "                                                                                 "
  40.     uline  = "_" * (lenN + 2)
  41.     sline  = "-" * lenN
  42.     bias = lenN - lenQ
  43.     print(spaces[0:offsetLeft] + spaces[0:bias] + "%ld" % quotient)
  44.     print(spaces[0:offsetLeft - 2] + uline)
  45.     sys.stdout.write("   " + strDenom + " ) " + strNumer)
  46.     strTmpR = strNumer[0: bias + 1]
  47.     tmpR = long(strTmpR)
  48.     tmpSub = 0L
  49.     oneDigit = None
  50.     for i in range(0, lenQ):
  51.         if strQuotient[i: i + 1] == "0":
  52.             if i + 1 < lenQ:
  53.                 oneDigit = strNumer[bias + i + 1: bias + i + 2]
  54.                 sys.stdout.write(oneDigit)
  55.                 strTmpR = strTmpR + oneDigit
  56.                 tmpR = long(strTmpR)
  57.         else:
  58.             print
  59.             tmpSub = long(strQuotient[i: i + 1]) * denom
  60.             print(spaces[0: offsetLeft] + simplify(tmpSub, bias + i + 1))
  61.             print(spaces[0: offsetLeft] + sline)
  62.             tmpR = tmpR - tmpSub
  63.             if tmpR == 0L and i + 1 < lenQ:
  64.                 sys.stdout.write(spaces[0: offsetLeft] + spaces[0: bias + i + 1])
  65.             else:
  66.                 sys.stdout.write(spaces[0: offsetLeft] + simplify(tmpR, bias + i + 1))
  67.             strTmpR = "%ld" % tmpR
  68.             if i + 1 < lenQ:
  69.                 oneDigit = strNumer[bias + i + 1: bias + i + 2]
  70.                 if oneDigit != None:
  71.                     sys.stdout.write(oneDigit)
  72.                     strTmpR = strTmpR + oneDigit
  73.                 tmpR = long(strTmpR)
  74.     print
  75.     return tmpR
  76. if len(sys.argv) < 3:
  77.     printUsage()
  78.     exit(1)
  79. a = None
  80. b = None
  81. try:
  82.     a = long(sys.argv[1])
  83.     b = long(sys.argv[2])
  84. except ValueError:
  85.     print("피제수: %s, 제수: %s" % (sys.argv[1], sys.argv[2]))
  86.     print("숫자 입력에 오류가 있습니다.")
  87.     sys.exit(1)
  88. if a <= 0L:
  89.     print("피제수: %ld" % a)
  90.     print("피제수는 양의 정수라야 합니다.")
  91.     sys.exit(1)
  92. elif b <= 0L:
  93.     print("제수: %ld" % b)
  94.     print("제수는 양의 정수라야 합니다.");
  95.     sys.exit(1)
  96. q = a / b
  97. r = a % b
  98. sys.stdout.write("나눗셈 %ld ÷ %ld 의 결과: " % (a, b))
  99. sys.stdout.write("몫: %ld, " % q)
  100. print("나머지: %ld" % r)
  101. print
  102. k = makeTable(a, b, q)
  103. if k == r:
  104.     print("\n나머지: %ld" % k)
  105. if k == 0L:
  106.     print("%ld = %ld x %ld" % (a, b, q))
  107.     print("%ld%s %ld의 배수(mupltiple)이다." % (a, getSuffix(a), b))
  108.     print("%ld%s %ld의 약수(divisor)이다." % (b, getSuffix(b), a))
  109. else:
  110.     print("%ld = %ld x %ld + %ld" % (a, b, q, r))
  111.     print("%ld%s %ld의 배수(mupltiple)가 아니다." % (a, getSuffix(a), b))




실행> python makeDivisionTable.py 500210 61

나눗셈 500210 ÷ 61 의 결과: 몫: 8200, 나머지: 10

          8200
      ________
   61 ) 500210
        488
        ------
         122
         122
        ------
            10

나머지: 10
500210 = 61 x 8200 + 10
500210은 61의 배수(mupltiple)가 아니다.




Creative Commons License

이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.

Posted by Scripter
,

Python 언어에서도 한 개의 소스 파일에 여러 개의 클래스가 존재해도 된다. 또 클래스명과 다른 파일명으로 저장해도 된다. Python 언어도 Java 언어 처럼 대소문자 구별을 엄격히 하므로 클래스를 선언하고 그 클래스로 객체 생성할 때 대소문자 구별을 꼭 지켜야 한다.

다음은 두 개의 클래스로 구성되어 있다.
Parent는 부모 클래스이고 Child는 Parent에서 상속 받은 자식 클래스이다.


# Filename: testSubclassing.py

class Parent:
    def __init__(self, name):       # 클래스 생성자
        self.name =  name
    def sayName(self):
        print("I am Parent, " + self.name)

class Child(Parent):        # 부모 클래스 상속
    def __init__(self, name):
        self.name =  name
    def sayName(self):
        print("I am a child, named as " + self.name)

obj = Child("Dooly")        # 클래스 생성
obj.sayName()




실행> python testSubclassing.py
I am a child, named as Dooly


Jython에서도 수정없이 그대로 실행된다.

실행> jython testSubclassing.py
I am a child, named as Dooly


IronPython에서도 수정없이 그대로 실행된다.

실행> ipy testSubclassing.py
I am a child, named as Dooly



크리에이티브 커먼즈 라이선스
Creative Commons License

 

Posted by Scripter
,

콘솔에 삼각형

         *
       * *
      *   *
     *     *
    *       *
   *         *
  *           *
 *             *
*****************


을 출력하는 Python 소스 코드를 작성해 보자. 이런 소스 코드의 작성은 학원이나 학교에서 프로그래밍 입문자에게 과제로 많이 주어지는 것 중의 하나이다. 코끼리를 보거나 만진 사람들이 저마다 그 생김새를 말할 때 제각기 다르게 표현할 수 있듯이 이런 소스 코드의 작성도 알고 보면 얼마든지 많은 방법이 있을 것이다. 여기서는 쉬운 코드 부터 작성해 보고 차츰차츰 소스를 바꾸어 가면서 Python 프로그래밍의 기초부분을 터득해 보기로 한다.

모든 소스 코드에서는 삼각형 출력 부분 담당 함수 printTriange()를 별도로 구현하였다.

우선 첫번 째 예제는 Python의 컨솔 출력 함수 print의 사용법만 알면 누구나 코딩할 수 있는 매우 단순한 소스 코드이다.


삼각형 출력 예제 1
#  Filename: printTriangle1.py
#            Print a triangle on console.
#
#  Execute: python printTriangle1.py
#
#      Date:  2008/04/02
#    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]

def printTriange():
    print "        *        "
    print "       * *       "
    print "      *   *      "
    print "     *     *     "
    print "    *       *    "
    print "   *         *   "
    print "  *           *  "
    print " *             * "
    print "*****************"

printTriange()




위의 소스 코드는 아무 알고리즘도 없는 너무 단순한 코드이다. 이런 코드를 작성했다간 출력 모양이나 크기를 변경해야 하는 상황을 맞이하면 워드프로세서로 문서 만드는 것 이상으로 많은 수작업을 하거나 아니면 포기하는 지경에 이를 수도 있다. 그래서 다음 처럼 좀 더 나은 소스 코드를 작성하였다. 그런데 Python 언어의 출력 함수 print 의 언어 간 호환성에 문제가 있다. print 문은 Groovy 언어의 println처럼 스트링을 출력 후 새 줄 문자(newline, '\n')을 추가한다. 그리고 끝에 콤마를 추가한

        print string,

문은 출력 후 차후 print 구문을 만날 시 빈간 문자(' ')를 하나 추가한다. 자바 언어의 System.out.print 나 Groovy 언어의 print 에 해당하는 Python의 출력 구문이나 출력 함수는 없을끼? 이 질문에 대한 대답은

        import sys
        sys.stdout.write(string)

이다. 이 경우 print 구문과 달리 string을 반드시 괄호 속에 넣어야 한다. 아래의 소스 코드에서는 아예 write() 함수를 작성하여 이의 사용을 더 편하게 하였다.




삼각형 출력 예제 2
#  Filename: printTriangle2.py
#            Print a triangle on console.
#
#  Execute: python printTriangle2.py
#
#      Date:  2008/04/02
#    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]

import sys

def write(s):
    sys.stdout.write(s)

def printTriange():
    for i in range(0, 8):
        for k in range(0, 8-i):
            write(" ")
        for k in range(0, 2*i+1):
            if k == 0 or k == 2*i:
                write("*")
            else:
                write(" ")
        for k in range(0, 8-i):
            write(" ")
        print

    for i in range(0, 17):
        write("*")
    print

printTriange()



위의 소스 코드는 Python의 컨솔 출력 함수 print 와 sys.std.write() 그리고 for 반복 구문을 적절히 사용하여 구현되었다. 숫자 몇 곳만 수정하면 출력되는 삼각형의 크기를 바꿀 수 있다. 한 줄에 출력될 문자를 구성하는 알고리즘은 위의 예제와 근본적으로 같지만 print, sys.std.write 를 사용하지 않고, 그대신 문자의 리스트를 만들어 한 즐씩 출력하는 소스 코드를 다음 예제와 같이 작성해 보았다.
또 빈칸 17개의 문자로 구성된 리스트를 생성하기 위한 구문은

        whites = [" "]*17

이다. (string*number 또는 list*number 의 구문은 Groovy, Ruby 언어에서도 지원된다.)



삼각형 출력 예제 3
#  Filename: printTriangle3.py
#            Print a triangle on console.
#
#  Execute: python printTriangle3.py
#
#      Date:  2008/04/02
#    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]

def printTriange():
    line2 = [" "]*17
    for i in range(0, 8):
        line2 = [" "]*17
        line2[8-i] =  '*'
        line2[8+i] =  '*'
        print "".join(line2)

    line2 = [" "]*17
    for i in range(0, 17):
        line2[i] =  '*'
    print "".join(line2)

printTriange()




별(*) 문자를 이용하여 삼각형을 출력하는 일은 빈칸 문자와 별 문자를 적당한 좌표(위치)에 촐력하는 일이다. 출력될 한 줄의 스트링을 완성한 후 하나의 print 구문으로 출력하는 기법으로 소스 코드를 작성해 보았다. 소스 코드 중에

        whites = " "*17
        stars = "*"*17

은 지정된 개수(여기서는 17) 만큼 string을 중복 연결하는 구문이다.




삼각형 출력 예제 4
#  Filename: printTriangle4.py
#            Print a triangle on console.
#
#  Execute: python printTriangle4.py
#
#      Date:  2008/04/02
#    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]

def printTriange():
    whites = " "*17
    stars  = "*"*17
    line2 = "%s%s%s" % (whites[0:8], "*", whites[0:7])
    print line2
    for i in range(1, 8):
        line2 = "%s%s%s%s%s" % (whites[:8-i], "*", whites[8-i:7+i], "*", whites[7+i:])
        print line2
    print stars

printTriange()




string은 immutable이라 그 내용을 변경할 수 없지만, 리스트는 그 요소(item)를 아무 때 나 변경할 수 있다. 한줄에 출력될 각 문자를 리스트 타입의 변수 line2에 저장한 다음 print 문으로 출력 시

    "".join(line2)

로 그 리스트의 모든 요소(item)가 모두 연결되어 출력되게 하였다.



삼각형 출력 예제 5
#  Filename: printTriangle5.py
#            Print a triangle on console.
#
#  Execute: python printTriangle5.py
#
#      Date:  2008/04/02
#    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]

def printTriange():
    whites = " "*17
    stars  = "*"*17
    start = 8
    line2 = [" "]*17
    line2[start] = "*"
    print "".join(line2)
    for i in range(1, 8):
        line2 = [" "]*17
        line2[start - i] = stars[start - i]
        line2[start + i] = stars[start + i]
        print "".join(line2)
    print stars

printTriange()




출력되는 삼각형이 좌우 대칭이라는 사실에 착안하여, 다음 소스 코드에서는  각 줄을 처음 8자, 중앙 한 문자, 끝 8자(처음 8자의 역순)로 string을 만들어 출력하였다.



삼각형 출력 예제 6
#  Filename: printTriangle6.py
#            Print a triangle on console.
#
#  Execute: python printTriangle6.py
#
#      Date:  2008/04/02
#    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]

import array

def reverse(chars):
    aa = array.array('c', chars)
    aa.reverse()
    return aa.tostring()
   
def printTriange():
    whites = " "*8
    stars  = "*"*8
    start = 8
    line = whites + '*' + whites
    print line
    for i in range(1, 8):
        line = whites[:-i] + '*' + whites[-i:-1]
        print line + ' ' + reverse(line)
    line = stars + '*' + stars
    print line

printTriange()




다음 소스 코드는 한 줄에 출력될 문자열의 데이터를 17비트 이진법 수로 구성하고, 이 이진법수의 비트가 0인 곳에는 빈칸을, 1인 곳에는 별(*)을 출력하는 기법으로 작성되었다.



삼각형 출력 예제 7
#  Filename: printTriangle7.py
#            Print a triangle on console.
#
#  Execute: python printTriangle7.py
#
#      Date:  2008/04/02
#    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]

BASE36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

def itoa(num, radix=10):
   isNegative = False
   if num < 0:
      isNegative = True
      num = -num
   arr = []
   q, r = num, 0
   while q >= radix:
      q, r = divmod(q, radix)
      arr.append(BASE36[r])
   arr.append(BASE36[q])
   if isNegative:
      arr.append("-")
   arr.reverse()
   return ''.join(arr)

def printTriange():
    start = 0x100
    total = 0
    val = start
    data = ""
    for k in range(0, 8):
        val = (start << k) | (start >> k)
        data = itoa(val, 2)
        s = ""
        for i in range(0, 17 - len(data)):
            s += " "
        for i in range(0, len(data)):
            if data[i] == '0':
                s += " "
            else:
                s += "*"
        print s
        total += val

    val = (start << 8) | (start >> 8)
    total += val
    data = itoa(total, 2)
    s = ""
    for i in range(0, 17 - len(data)):
        s += " "
    for i in range(0, len(data)):
        if data[i] == '0':
            s += " "
        else:
            s += "*"
    print s

printTriange()




기본적인 원리는 위의 소스 코드와 같지만 이진법수의 한 비트 마다 한 문자씩 츨력하는 대신에 출력될 한 줄의 string을 완성하여 이를 print 구문으로 출력하는 기법으로 재작성한 것이 다음의 소스 코드이다. anotherString = string.replace(원본, 타겟) 을 이용하여 모든 0을 빈칸으로, 모든 1을 별(*) 문자로 바꾸었으며, 별(*) 문자만으로 이루어진 마지막 줄 출력을 위해 변수 total을 준비하였다. for 반복 구문의 블럭 내에서 구문

            total |= val

이 하는 일이 무엇인지 이해할 수 있으면 좋겠다.




삼각형 출력 예제 8
#  Filename: printTriangle8.py
#            Print a triangle on console.
#
#  Execute: python printTriangle8.py
#
#      Date:  2008/04/02
#    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]

import array

def reverse(chars):
    aa = array.array('c', chars)
    aa.reverse()
    return aa.tostring()
   
BASE36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

def itoa(num, radix=10):
   isNegative = False
   if num < 0:
      isNegative = True
      num = -num
   arr = []
   q, r = num, 0
   while q >= radix:
      q, r = divmod(q, radix)
      arr.append(BASE36[r])
   arr.append(BASE36[q])
   if isNegative:
      arr.append("-")
   arr.reverse()
   return ''.join(arr)

def printTriange():
    zeros  = "00000000"
    start = 0x100
    total = 0
    val = start
    line = ""
    data = ""
    for k in range(0, 8):
        val = (start << k) | (start >> k)
        data = itoa(val, 2)
        line = zeros[0:17-len(data)] + data
        line = line.replace("0", " ")
        line = line.replace("1", "*")
        print line
        total |= val

    val = (start << 8) | (start >> 8)
    total |= val
    line = itoa(total, 2)
    line = line.replace("0", " ")
    line = line.replace("1", "*")
    print line

printTriange()




소스 코드가 처음 것 보다 매우 복잡해졌지만, Python의 리스트를 이용해서 구현해 보았다. Python 언어 외에 Groovy, Ruby 언어 같은 스크립팅 언어에서도 리스트와 맵은 매우 중요하게 취급되며, 구문에서도 이를 위한 문법을 제공하고 있다. 별(*) 문자만으로 구성된 마지막 줄 출력을 위해 리스트 타입의 변수 last를 준비하였다. 또 리스트에 속한 모든 item을 출력하는 Python 코드

        print "".join(data)

는 음미해볼 만한 부분이다.



삼각형 출력 예제 9
#  Filename: printTriangle9.py
#            Print a triangle on console.
#
#  Execute: python printTriangle9.py
#
#      Date:  2008/04/02
#    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]

def printTriange():
    start = 8
    data = [" "]*17
    last = [" "]*17

    data[start] = "*"
    last[start] = "*"
    print "".join(data)
    data[start] = " "

    for k in range(1, 8):
        data[start - k] = "*"
        last[start - k] = "*"
        data[start + k] = "*"
        last[start + k] = "*"
        print "".join(data)
        data[start - k] = " "
        data[start + k] = " "

    last[start - 8] = "*"
    last[start + 8] = "*"
    print "".join(last)

printTriange()





다음 예제는 수학에서 xy-좌표평면에 점을 찍듯이 논리 구문

             (x + y - 8 == 0) or (y - x + 8 == 0) or (y - 8 == 0)

가 참이 되는 위치에 별(*) 문자를 표시하는 기법으로 작성된 소스 코드이다.




삼각형 출력 예제 10
#  Filename: printTriangle10.py
#            Print a triangle on console.
#
#  Execute: python printTriangle10.py
#
#      Date:  2008/04/02
#    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]

import sys

def printTriange():
    for y in range(0, 9):
        for x in range(0, 17):
            if (x + y - 8 == 0) or (y - x + 8 == 0) or (y - 8 == 0):
                a = '*'
            else:
                a = ' '
            sys.stdout.write(a)
        print

printTriange()






Creative Commons License

이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.

Posted by Scripter
,
파이썬 언어에서 주로 쓰이는  컨솔 출력 구문은

         print  something

         print  something,

이다. 첫번 째 것은  출력 후 새 줄 문자(newline code, '\n')도 같이 내 보내는 것이고,
둘 째 것은 출력 후 다음에 만나는 print 구문은 선두에 공백문자(' ')를 먼저 내보내라는 의미이다.

즉, 파이썬 소스 코드

        for i in range(10): print "*",
        print

        * * * * * * * * * *

을 출력한다. 그렇다면 연속적으로 출력되는 별(*) 문자 사이의 공백문자가 출력되지 않게 할 수는 없을까?  이 질문에 대한 답은 당연히 "있다"이다.  sys 모듈의  sys.stdout.write(string) 함수를 사용하면 된다. 예를 들어, 파이썬 소스 코드

        import sys
        for i in range(10): sys.stdout.write("*")
        sys.stdout.write("\n")

        **********

를 출력한다.


참고 자료:  Python Gotchas




Creative Commons Licence This work is licensed under the Creative Commons Attribution 2.0 License


Posted by Scripter
,

ASCII(애스키)란 American Standard Code for Information Interchange의 줄임글로서, 영문자에 기초한 문자 인코딩이다.  이 문자 인코딩에는 C0 제어문자(C0 control character)도 포함되어 있다.  ( 참고:  ASCII - Wikipedia, the free encyclopedia )

다음은  7bit ASCII 코드표를 만들어 보여주는 Python 소스 코드이다. 소스 코드 중에 진법변환에 필요한 함수

        convertAtoI(string, radix)
        convertItoA(number, radix)

의 구현도 포함되어 있다.

(아래의 소스는 Jython이나 IronPython에서도 수정없이 그대로 실행된다.)



  1. #  Filename: makeAsciiTable.py
  2. #            Make a table of ascii codes.
  3. #
  4. #  Execute: python makeAsciiTable.py
  5. #
  6. #      Date:  2008/03/28
  7. #    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
  8. import sys
  9. BASE36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  10. def println(s=None):
  11.     if s == None:
  12.         print
  13.     else:
  14.         print(s)
  15. def printUsage():
  16.     println("Usage: python makeAsciiTable.py")
  17.     println("Make a table of ascii codes.")
  18. def convertItoA(num, radix):
  19.     isNegative = False
  20.     if num < 0:
  21.         isNegative = True
  22.         num = -num
  23.     arr = ""
  24.     q = num
  25.     r = 0
  26.     while q >= radix:
  27.         r = q % radix
  28.         q = q / radix
  29.         arr += BASE36[r]
  30.     arr += BASE36[q]
  31.     if isNegative:
  32.         arr += "-"
  33.     n = len(arr)
  34.     ret = ""
  35.     for i in range(0, n):
  36.         ret += arr[n - i - 1]
  37.     return ret
  38. def convertAtoI(srcStr, radix):
  39.     isNegative = False
  40.     ret = 0
  41.     m = len(srcStr)
  42.     val = 0
  43.     c = srcStr[0]
  44.     if c == '-':
  45.         isNegative = True
  46.     elif c >= '0' and c <= '9':
  47.         ret = ord(c) - ord('0')
  48.     elif c >= 'A' and c <= 'Z':
  49.         ret = (ord(c) - ord('A')) + 10
  50.     elif c >= 'a' and c <= 'z':
  51.         ret = (ord(c) - ord('a')) + 10
  52.     if ret >= radix:
  53.         println("        Invalid character!")
  54.         return ret
  55.     for i in range(1, m):
  56.         c = srcStr[i]
  57.         ret *= radix
  58.         if c >= '0' and c <= '9':
  59.             val = ord(c) - ord('0')
  60.         elif c >= 'A' and c <= 'Z':
  61.             val = (ord(c) - ord('A')) + 10
  62.         elif c >= 'a' and c <= 'z':
  63.             val = (ord(c) - ord('a')) + 10
  64.         if val >= radix:
  65.             println("        Invalid character!")
  66.             return ret
  67.         ret += val
  68.     return ret
  69. asc = [
  70.     "NUL", "SOH", "STX", "ETX", "EOT",
  71.     "ENQ", "ACK", "BEL", "BS", "HT",
  72.     "LF", "VT", "FF", "CR", "SO",
  73.     "SI", "DLE", "DC1", "DC2", "DC3",
  74.     "DC4", "NAK", "SYN", "ETB", "CAN",
  75.     "EM", "SUB", "ESC", "FS", "GS",
  76.     "RS", "US", "Spc"
  77. ]
  78. control  = [
  79.     "NUL (null)",
  80.     "SOH (start of heading)",
  81.     "STX (start of text)",
  82.     "ETX (end of text)",
  83.     "EOT (end of transmission)",
  84.     "ENQ (enquiry)",
  85.     "ACK (acknowledge)",
  86.     "BEL (bell)",
  87.     "BS  (backspace)",
  88.     "TAB (horizontal tab)",
  89.     "LF  (line feed, NL new line)",
  90.     "VT  (vertical tab)",
  91.     "FF  (form feed, NP new page)",
  92.     "CR  (carriage return)",
  93.     "SO  (shift out)",
  94.     "SI  (shift in)",
  95.     "DLE (data link escape)",
  96.     "DC1 (device control 1)",
  97.     "DC2 (device control 2)",
  98.     "DC3 (device control 3)",
  99.     "DC4 (device control 4)",
  100.     "NAK (negative acknowledge)",
  101.     "SYN (synchronous idle)",
  102.     "ETB (end of trans. block)",
  103.     "CAN (cancel)",
  104.     "EM  (end of medium)",
  105.     "SUB (substitute, EOF end of file)",
  106.     "ESC (escape)",
  107.     "FS  (file separator)",
  108.     "GS  (group separator)",
  109.     "RS  (record separator)",
  110.     "US  (unit separator)",
  111. ]
  112. def makeTable():
  113.     sbuf = ""
  114.     abuf = ""
  115.     tbuf = ""
  116.     sbuf = "    "
  117.     for i in range(0, 8):
  118.         sbuf += "+----"
  119.     sbuf += "+"
  120.     println(sbuf)
  121.     sbuf = "    "
  122.     sbuf += "| 0- "
  123.     sbuf += "| 1- "
  124.     sbuf += "| 2- "
  125.     sbuf += "| 3- "
  126.     sbuf += "| 4- "
  127.     sbuf += "| 5- "
  128.     sbuf += "| 6- "
  129.     sbuf += "| 7- "
  130.     sbuf += "|"
  131.     println(sbuf)
  132.     sbuf = "+---"
  133.     for i in range(0, 8):
  134.         sbuf += "+----"
  135.     sbuf += "+"
  136.     println(sbuf)
  137.     for i in range(0, 16):
  138.         tbuf = ""
  139.         sbuf = convertItoA(i, 16)
  140.         tbuf += "| " + sbuf + " "
  141.         for j in range(0, 8):
  142.             if j*16 + i <= 32:
  143.                 abuf = "| %-3s" % asc[j*16 + i]
  144.             elif j*16 + i == 127:
  145.                 abuf = "| %-3s" % "DEL"
  146.             else:
  147.                 c = chr(j*16 + i)
  148.                 abuf = "| %2c " % c
  149.             tbuf += abuf
  150.         tbuf += "|"
  151.         println(tbuf)
  152.     sbuf = "+---"
  153.     for i in range(0, 8):
  154.         sbuf += "+----"
  155.     sbuf += "+"
  156.     println(sbuf)
  157.     println("")
  158.     for i in range(0, 16):
  159.         tbuf = "%-30s  %-34s" % (control[i], control[i+16])
  160.         println(tbuf)
  161. if len(sys.argv) > 1 and "-h" == sys.argv[1]:
  162.     printUsage()
  163.     sys.exit(1)
  164. makeTable()




실행> python makeAsciiTable.py

   
    +----+----+----+----+----+----+----+----+
    | 0- | 1- | 2- | 3- | 4- | 5- | 6- | 7- |
+---+----+----+----+----+----+----+----+----+
| 0 | NUL| DLE| Spc|  0 |  @ |  P |  ` |  p |
| 1 | SOH| DC1|  ! |  1 |  A |  Q |  a |  q |
| 2 | STX| DC2|  " |  2 |  B |  R |  b |  r |
| 3 | ETX| DC3|  # |  3 |  C |  S |  c |  s |
| 4 | EOT| DC4|  $ |  4 |  D |  T |  d |  t |
| 5 | ENQ| NAK|  % |  5 |  E |  U |  e |  u |
| 6 | ACK| SYN|  & |  6 |  F |  V |  f |  v |
| 7 | BEL| ETB|  ' |  7 |  G |  W |  g |  w |
| 8 | BS | CAN|  ( |  8 |  H |  X |  h |  x |
| 9 | HT | EM |  ) |  9 |  I |  Y |  i |  y |
| A | LF | SUB|  * |  : |  J |  Z |  j |  z |
| B | VT | ESC|  + |  ; |  K |  [ |  k |  { |
| C | FF | FS |  , |  < |  L |  \ |  l |  | |
| D | CR | GS |  - |  = |  M |  ] |  m |  } |
| E | SO | RS |  . |  > |  N |  ^ |  n |  ~ |
| F | SI | US |  / |  ? |  O |  _ |  o | DEL|
+---+----+----+----+----+----+----+----+----+

NUL (null)                      DLE (data link escape)
SOH (start of heading)          DC1 (device control 1)
STX (start of text)             DC2 (device control 2)
ETX (end of text)               DC3 (device control 3)
EOT (end of transmission)       DC4 (device control 4)
ENQ (enquiry)                   NAK (negative acknowledge)
ACK (acknowledge)               SYN (synchronous idle)
BEL (bell)                      ETB (end of trans. block)
BS  (backspace)                 CAN (cancel)
TAB (horizontal tab)            EM  (end of medium)
LF  (line feed, NL new line)    SUB (substitute, EOF end of file)
VT  (vertical tab)              ESC (escape)
FF  (form feed, NP new page)    FS  (file separator)
CR  (carriage return)           GS  (group separator)
SO  (shift out)                 RS  (record separator)
SI  (shift in)                  US  (unit separator)



Creative Commons License

이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
Posted by Scripter
,

컴퓨터 프로그래밍에서 꼭 알아두어야 할 주요 진법은 당연히 10진법, 2진법, 8진법, 16진법이다.
다음은  0 에서 15 까지의 정수를 10진법, 2진법, 8진법, 16진법의 표로 만들어 보여주는 Python 소스 코드이다. 진법 변환에 필요한 함수

        convertAtoI(string, radix)
        convertItoA(number, radix)

를 Python 코드로 자체 작성하여 사용하였다.

(아래의 소스는 Jython이나 IronPython에서도 수정없이 그대로 실행된다.)



  1. #  Filename: makeRadixTable.py
  2. #            Show the radix table with 10-, 2-, 8-, 16-radices.
  3. #
  4. #  Execute: python makeRadixTable.py
  5. #
  6. #      Date:  2008/03/28
  7. #    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
  8. import sys
  9. BASE36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  10. def println(s=None):
  11.     if s == None:
  12.         print
  13.     else:
  14.         print(s)
  15. def printUsage():
  16.     println("Usage: python makeRadixTable.py")
  17.     println("Show the radix table with 10-, 2-, 8-, 16-radices.")
  18. def convertItoA(num, radix):
  19.     isNegative = False
  20.     if num < 0:
  21.         isNegative = True
  22.         num = -num
  23.     arr = ""
  24.     q = num
  25.     r = 0
  26.     while q >= radix:
  27.         r = q % radix
  28.         q = q / radix
  29.         arr += BASE36[r]
  30.     arr += BASE36[q]
  31.     if isNegative:
  32.         arr += "-"
  33.     n = len(arr)
  34.     ret = ""
  35.     for i in range(0, n):
  36.         ret += arr[n - i - 1]
  37.     return ret
  38. def convertAtoI(srcStr, radix):
  39.     isNegative = False
  40.     ret = 0
  41.     m = len(srcStr)
  42.     val = 0
  43.     c = srcStr[0]
  44.     if c == '-':
  45.         isNegative = True
  46.     elif c >= '0' and c <= '9':
  47.         ret = ord(c) - ord('0')
  48.     elif c >= 'A' and c <= 'Z':
  49.         ret = (ord(c) - ord('A')) + 10
  50.     elif c >= 'a' and c <= 'z':
  51.         ret = (ord(c) - ord('a')) + 10
  52.     if ret >= radix:
  53.         println("        Invalid character!")
  54.         return ret
  55.     for i in range(1, m):
  56.         c = srcStr[i]
  57.         ret *= radix
  58.         if c >= '0' and c <= '9':
  59.             val = ord(c) - ord('0')
  60.         elif c >= 'A' and c <= 'Z':
  61.             val = (ord(c) - ord('A')) + 10
  62.         elif c >= 'a' and c <= 'z':
  63.             val = (ord(c) - ord('a')) + 10
  64.         if val >= radix:
  65.             println("        Invalid character!")
  66.             return ret
  67.         ret += val
  68.     return ret
  69. def makeTable():
  70.     sbuf = ""
  71.     abuf = ""
  72.     tbuf = ""
  73.     for i in range(0, 4):
  74.         sbuf += "+-------"
  75.     sbuf += "+"
  76.     println(sbuf)
  77.     sbuf = "|  Dec"
  78.     sbuf += "\t|   Bin"
  79.     sbuf += "\t|  Oct"
  80.     sbuf += "\t|  Hex  |"
  81.     println(sbuf)
  82.     sbuf = ""
  83.     for i in range(0, 4):
  84.         sbuf += "+-------"
  85.     sbuf += "+"
  86.     println(sbuf)
  87.     for i in range(0, 16):
  88.         sbuf = "|   %2d" % i
  89.         abuf = convertItoA(i, 2)
  90.         tbuf = "\t|  %4s" % abuf
  91.         sbuf += tbuf
  92.         abuf = convertItoA(i, 8)
  93.         tbuf = "\t|   %2s" % abuf
  94.         sbuf += tbuf
  95.         abuf = convertItoA(i, 16)
  96.         tbuf = "\t|    %-2s |" % abuf
  97.         sbuf += tbuf
  98.         println(sbuf)
  99.     sbuf = ""
  100.     for i in range(0, 4):
  101.         sbuf += "+-------"
  102.     sbuf += "+"
  103.     println(sbuf)
  104. if len(sys.argv) > 1 and "-h" == sys.argv[1]:
  105.     printUsage()
  106.     sys.exit(1)
  107. makeTable()



실행> python makeRadixTable.py

+-------+-------+-------+-------+
|  Dec  |   Bin |  Oct  |  Hex  |
+-------+-------+-------+-------+
|    0  |     0 |    0  |    0  |
|    1  |     1 |    1  |    1  |
|    2  |    10 |    2  |    2  |
|    3  |    11 |    3  |    3  |
|    4  |   100 |    4  |    4  |
|    5  |   101 |    5  |    5  |
|    6  |   110 |    6  |    6  |
|    7  |   111 |    7  |    7  |
|    8  |  1000 |   10  |    8  |
|    9  |  1001 |   11  |    9  |
|   10  |  1010 |   12  |    A  |
|   11  |  1011 |   13  |    B  |
|   12  |  1100 |   14  |    C  |
|   13  |  1101 |   15  |    D  |
|   14  |  1110 |   16  |    E  |
|   15  |  1111 |   17  |    F  |
+-------+-------+-------+-------+




Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
Posted by Scripter
,

다음은  대화형 모드(interactive mode)에서 진법 변환(radix conversion)하는 Python 소스 코드이다.
메뉴는 주메뉴 Command: (S)et radix, (A)bout, (Q)uit or E(x)it
와 부메뉴 SubCommand: 'main()' to goto Main menu, 'exit()' or 'quit()' to exit
로 구성되어 있으며, 진법 변환의 핵심은 Python의 빌트인 함수 int(string, radix)와 소스 코드에 자체 작성된 함수 itoa(number, radix)의 사용이다.

         val = int(s, srcRdx)
         ret = itoa(val, destRdx)

지원되는 진법은 2진법에서 36진법까지이다.
(Jython으로는 finally: 구문 때문에 실행이 안된다.)



  1. #  Filename: convertRadix.py
  2. #            Convert radix in a interactive mode.
  3. #
  4. #  Execute: python convertRadix.py
  5. #
  6. #      Date:  2008/03/25
  7. #    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
  8. import sys
  9. def println(s=None):
  10.     if s != None:
  11.         print(s)
  12.     else:
  13.         print
  14. def printUsage():
  15.     println("Usage: python convertRadix.py")
  16.     println("Convert radix in a interactive mode, where the maximum radix is 36.")
  17. def printAbout():
  18.     println("    About: Convert radix in a interactive mode.")
  19. def printMainMenu():
  20.     println("  Command: (S)et radix, (A)bout, (Q)uit or E(x)it")
  21. def printMainPrompt():
  22.     print("  Prompt>"),
  23. def printSubMenu(srcRadix, destRadix):
  24.     println("    Convert Radix_" + str(srcRadix) + " to Radix_" + str(destRadix))
  25.     println("    SubCommand: 'main()' to goto Main menu, 'exit()' or 'quit()' to exit")
  26. def printSubPrompt():
  27.     print("    Input Value>>"),
  28. BASE36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  29. def itoa(num, radix=10):
  30.    isNegative = False
  31.    if num < 0:
  32.       isNegative = True
  33.       num = -num
  34.    arr = []
  35.    q, r = num, 0
  36.    while q >= radix:
  37.       q, r = divmod(q, radix)
  38.       arr.append(BASE36[r])
  39.    arr.append(BASE36[q])
  40.    if isNegative:
  41.       arr.append("-")
  42.    arr.reverse()
  43.    return ''.join(arr)
  44. def convertRadix(s, srcRdx, destRdx):
  45.     ret = ""
  46.     try:
  47.         val = int(s, srcRdx)
  48.         ret = itoa(val, destRdx)
  49.         return ret.upper()
  50.     except ValueError:
  51.         println("    Error: Cannot convert radix " + str(srcRdx))
  52.         ret = "????"
  53.     finally:
  54.         return ret.upper()
  55. def doConvert(srcRadix, destRadix):
  56.     line = ""
  57.     cmd = ""
  58.     srcStr = ""
  59.     destStr = ""
  60.     println("")
  61.     printSubMenu(srcRadix, destRadix)
  62.     try:
  63.         while True:
  64.             printSubPrompt()
  65.             cmd = raw_input()
  66.             while cmd == None:
  67.                 cmd = raw_input()
  68.             if "main()" == cmd:
  69.                 return
  70.             elif "exit()" == cmd or "quit()" == cmd:
  71.                 sys.exit(0)
  72.             try:
  73.                 int(cmd, srcRadix)
  74.                 srcStr = cmd
  75.                 destStr = convertRadix(srcStr, srcRadix, destRadix)
  76.                 println("        ( " + srcStr + " )_" + str(srcRadix) +  "   --->   ( " + destStr + " )_" + str(destRadix))
  77.                 println("")
  78.             except ValueError:
  79.                  pass
  80.     except RuntimeError:
  81.         print sys.exc_value
  82. def doStart():
  83.     line = ""
  84.     cmd = ""
  85.     srcRadix = 10
  86.     destRadix = 10
  87.     srcStr = ""
  88.     destStr = ""
  89.     onlyOnce = True
  90.     try:
  91.         while True:
  92.             println()
  93.             if onlyOnce:
  94.                 println("  The supported maximum radix is 36.")
  95.                 onlyOnce = False
  96.             printMainMenu()
  97.             printMainPrompt()
  98.             cmd = raw_input()
  99.             while cmd == None:
  100.                 cmd = raw_input()
  101.             if "qQxX".find(cmd) >= 0 and len(cmd) == 1:
  102.                 sys.exit(0)
  103.             elif "aA".find(cmd) >= 0 and len(cmd) == 1:
  104.                 printAbout()
  105.             elif "sS".find(cmd) >= 0 and len(cmd) == 1:
  106.                 line = raw_input("  Input the source and target radices (say, 16 2): ")
  107.                 st = line.split(" ")
  108.                 while len(st) < 2:
  109.                     line = raw_input("  Input the source and target radices (say, 16 2): ")
  110.                     st = line.split(" ")
  111.                 srcRadix = int(st[0])
  112.                 destRadix = int(st[1])
  113.                 doConvert(srcRadix, destRadix)
  114.     except RuntimeError:
  115.         print sys.exc_value
  116. # Begin here
  117. if len(sys.argv) > 1 and "-h" == sys.argv[1]:
  118.     printUsage()
  119.     sys.exit(1)
  120. doStart()



실행> python convertRadix.py

  The supported maximum radix is 36.
  Command: (S)et radix, (A)bout, (Q)uit or E(x)it
  Prompt> s
  Input the source and target radices (say, 16 2): 10 8

    Convert Radix_10 to Radix_8
    SubCommand: 'main()' to goto Main menu, 'exit()' or 'quit()' to exit
    Input Value>> 200
        ( 200 )_10   --->   ( 310 )_8

    Input Value>> main()

  Command: (S)et radix, (A)bout, (Q)uit or E(x)it
  Prompt> S
  Input the source and target radices (say, 16 2): 8 10

    Convert Radix_8 to Radix_10
    SubCommand: 'main()' to goto Main menu, 'exit()' or 'quit()' to exit
    Input Value>> 2666
        ( 2666 )_8   --->   ( 1462 )_10

    Input Value>> main()

  Command: (S)et radix, (A)bout, (Q)uit or E(x)it
  Prompt> x




IronPython의 경우에는 구문

    print 스트링,

이 Python과 달리 끝에 빈칸을 곧 바로 추가하지 않고, 빈칸 출력을 유보하고 있다가 다음 print 문을 만날 때 이 빈칸을 먼저 출력한 후 주어진 스트링을 출력한다. raw_input()과 함께 쓰일 때는 이 빈칸 하나 때문에 신경이 쓰이기도 한다. 그래서 프롬프트를 출력하는 함수를

def printMainPrompt(): 
     print("  Prompt> "),

def printSubPrompt(): 
     print("    Input Value>> "),

로 수정해야 한다.




Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
Posted by Scripter
,