[파일명:  testSort.lsp]------------------------------------------------
(defun printArray(a)
    (format t "[")
    (loop for i from 0 below (1- (length a)) do
        (format t "~A, " (nth i a))
    )
    (if (plusp (length a))
        (format t "~A" (nth (1- (length a)) a))
    )
    (format t "]~%")
)


(setf list ext:*args*)
(sort list #'string<)
(printArray list)
------------------------------------------------


실행> clisp testSort.lsp one two three four five
[five, four, one, three, two]

실행> clisp testSort.lsp 하나 둘 셋 넷 다섯
[넷, 다섯, 둘, 셋, 하나]




Posted by Scripter
,

정의 (소수와 합성수)
    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은 합성수이다.
    

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

;;  Filename: divideEach.lsp
;;
;;  Purpose:  Determine whether the given integer is a prime or not.
;;
;;  Execute: clisp divideEach.lsp [integer]
;;
;;     Date:  2013. 9. 6.

#|
  Execution Examples:
      Prompt> clisp divideEach.lsp 1234567812343
      1234567812343 = 1 * 1234567812343
      1234567812343 is a prime.
      Elapsed time: 3 secs
 
      Prompt> clisp divideEach.lsp 9999994200000841
      9999994200000841 = 99999971 * 99999971
      9999994200000841 is a not prime
      Elapsed time: 51.437000 sec
 
      Prompt> clisp divideEach.lsp 18446744073709551617
      18446744073709551617 = 274177 * 67280421310721
      18446744073709551617 is a not prime
      Elapsed time: 0.141000 sec

      Prompt> clisp divideEach.lsp 10023859281455311421
      10023859281455311421 = 1308520867 * 7660450463
      10023859281455311421 is a not prime
      Elapsed time: 705.016000 sec
|#


(setf n 10006099720301)
(if (> (length ext:*args*) 0)
    (setf n (parse-integer (nth 0 ext:*args*)))
)

(setf z (floor (/ n 2)))
(if (= n (* 2 z))
    (progn
        (format t "~A = ~A * ~A~d" n 2 z)
        (quit)
    )
)

(setf time1 (get-universal-time))

(setf d 1)
(setf k 3)

(loop while (<= (* k k) n) do
    (setf z (floor (/ n k)))
    (if (= n (* k z))
        (progn
            (set d k)
            (return)
        )
    )
    (setf k (+ k 2))
)

(setf z (floor (/ n d)))

(setf time2 (get-universal-time))

(format t "~A = ~A * ~A~%" n d (floor (/ n d)))

(if (= d 1)
    (format t "~A is a prime.~%" n)
    (format t "~A is a not prime.~%" n)
)

(format t "Elapsed time: ~A secs" (- time2 time1))

 




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

 

;;  Filename: pollardRho.lsp
;;
;;  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: clisp pollardRho.lsp [integer]
;;
;;     Date:  2013. 9. 6.

#|
  Execution Examples:
      Prompt> clisp pollardRho.lsp 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 = 1 * 1234567812343
      Elapsed time: 104 secs      Try first the Pollard rho algorithm with c = 2

      Prompt> clisp pollardRho.lsp 9999994200000841
      Try first the Pollard rho algorithm with c = 2
      d = 99999971, count = 3593
      9999994200000841 = 99999971 * 99999971
      Elapsed time: 0 secs

      Prompt> clisp pollardRho.lsp 18446744073709551617
      Try first the Pollard rho algorithm with c = 2
      d = 274177, count = 1028
      18446744073709551617 = 274177 * 67280421310721
      Elapsed time: 0 secs

      Prompt> clisp pollardRho.lsp 10023859281455311421
      Try first the Pollard rho algorithm with c = 2
      d = 1308520867, count = 20350
      10023859281455311421 = 1308520867 * 7660450463
      Elapsed time: 1 secs
|#


(defun f(x c n)
    (floor (mod (+ (* x x) c) n))
)

(defun g(x c n)
    (f (f x c n) c n)
)

(defun  my-gcd(x y):
 (let* ((a (abs x))
        (b (abs y))
        (tt 0))
        (if (zerop b) a)
        (loop while (not (zerop b)) do
            (setf tt (floor (mod a b)))
            (setf a b)
            (setf b tt)
        )
        a
    )
)

(defun pollardRho(n)
 (let* ((c 2)
        (x 1)
        (y 1)
        (d 1)
        (savedX x)
        (count 0)
        (tt 0))

     (setf c 2)
     (setf x 1)
        (setf y 1)
     (setf d 1)
     (setf savedX x)
     (setf count 0)

        (format t "Try first the Pollard rho algorithm with c = ~A~%" c)
        (loop while (and (= d 1) (<= (* count count) n)) do
            (setf x (f x c n))
            (if (= x savedX)
                (progn
                    (format t "It is cyclic.  x = ~A~%" x)
                    (return)   ;; break loop
                )
            )
            (setf y (g y c n))
            (setf d (my-gcd (abs (- x y)) n))
            (setf count (1+ count))
        )

        (format t "d = ~A, count = ~A~%" d count)
        (if (and (> d 1) (< d n))
                d
      (progn
     (setf c 3)
     (setf x 1)
        (setf y 1)
     (setf d 1)
     (setf savedX x)
     (setf count 0)

        (format t "Try second the Pollard rho algorithm with c = ~A~%" c)
        (loop while (and (= d 1) (<= (* count count) n)) do
            (setf x (f x c n))
            (if (= x savedX)
                (progn
                    (format t "It is cyclic.  x = ~A~%" x)
                    (return)   ;; break loop
                )
            )
            (setf y (g y c n))
            (setf d (my-gcd (abs (- x y)) n))
            (setf count (1+ count))
        )

        (format t "d = ~A, count = ~A~%" d count)
        (if (and (> d 1) (< d n))
                d

      (progn
     (setf c 1)
     (setf x 1)
        (setf y 1)
     (setf d 1)
     (setf savedX x)
     (setf count 0)

        (format t "Try third the Pollard rho algorithm with c = ~A~%" c)
        (loop while (and (= d 1) (<= (* count count) n)) do
            (setf x (f x c n))
            ; (format t "  x = ~A~%" x)
            (if (= x savedX)
                (progn
                    (format t "It is cyclic.  x = ~A~%" x)
                    (return)   ;; break loop
                )
            )
            (setf y (g y c n))
            (setf d (my-gcd (abs (- x y)) n))
            (setf count (1+ count))
        )

        (format t "d = ~A, count = ~A~%" d count)
        (if (and (> d 1) (< d n))
                d

         1  )
      ))
      ))
    )
)


(setf n 9991)
(if (> (length ext:*args*) 0)
    (setf n (parse-integer (nth 0 ext:*args*)))
)

(setf time1 (get-universal-time))

(setf k (pollardRho n))

(setf time2 (get-universal-time))

(setf z (floor (/ n k)))
(if (= n (* k z))
    (format t "~A = ~A * ~A~%" n k z)
)

(format t "Elapsed time: ~A secs" (- time2 time1))

 

 

 

Posted by Scripter
,

초등학교 때 배우는 두 정수의 곱셈표를 만들어 주는 Common Lisp 소스이다.
(이 소스는 CLisp으로 잘 실행됨을 확인하였다.)

Common Lisp 언어로, 양의 정수 a를 양의 정수 b로 나는 몫을 구하려면

        (setf q (floor (/ a b)))

한다. 그 몫은 변수 q에 저장된다. 이렇게 하는 이유는

        (setf q (/ a b))

로 한 경우 q에는 분수 a/b가 저장되기 때문이다.

 

;;  Filename: makeMultTable.lsp
;;
;;     Print a multiplication table.
;;
;;     Execute: clisp makeMultTable.lsp 230 5100
;;
;;  Date: 2013, 9. 6.


(defun printUsing()
    (format t "Using: clisp makeMultTable.lsp [number1] [number2]~%")
    (format t "Print a multiplication table for the given two integers.~%")
)

(defun printMultTable(x y)
    (let* ((nx x)
           (ny y)
           (nz 0)
           (n  0)
           (y1  0)
           (ntail1 0)
           (ntail2 0)
           (strX "")
           (strY "")
           (strZ "")
           (strT "")
           (zeros  "0000000000000000000000000000000000000000")
           (whites "                                        ")
           (bars   "----------------------------------------")
           (loffset "       ")
           (line1 "")
           (line2 "")
           (line3 "")
           (line4 ""))
           
        (if  (minusp nx) (setf nx (- nx)))
        (if  (minusp ny) (setf ny (- ny)))

        (setf ntail1 0)
        (setf ntail2 0)
        (loop while (zerop (mod nx 10)) do
            (setf nx (floor (/ nx 10)))
            (setf ntail1 (1+ ntail1))
        )
        (loop while (zerop (mod ny 10)) do
            (setf ny (floor (/ ny 10)))
            (setf ntail2 (1+ ntail2))
        )

        (setf z (* nx ny))
        (setf strZ (format nil "~D" z))
        (setf strX (format nil "~D" nx))
        (setf strY (format nil "~D" ny))
        (setf n (length strY))

        (setf line4 (concatenate 'string loffset strZ))
        (setf line1 (concatenate 'string loffset (substring whites 0 (- (length strZ) (length strX))) strX))
        (setf line2 (concatenate 'string "   x ) " (substring whites 0 (- (length strZ) (length strY))) strY))
        (setf line3 (concatenate 'string "     --" (substring bars 0 (length strZ))))
        
        (format t "~A~A~%" line1 (substring zeros 0 ntail1))
        (format t "~A~A~%" line2 (substring zeros 0 ntail2))
        (format t "~A~%" line3)
        (if (> (length strY) 1)
            (progn
                (loop for i from 0 below (length strY) do
                    (setf y1 (parse-integer (substring strY (- (length strY) i 1) (- (length strY) i))))
                    (if (not (zerop y1))
                        (progn
                            (setf strT (format nil "~D" (* nx y1)))
                            (format t "~A~A~A~%" loffset (substring whites 0  (- (length strZ) (length strT) i)) strT)
                        )
                    )
                )
                (format t "~A~%" line3)
            )
        )

        (format t "~A~A~A~%" line4 (substring zeros 0 ntail1) (substring zeros 0 ntail2))
    )
)


(if (>= (length ext:*args*) 2)
    (progn
        (setf x (parse-integer (nth 0 ext:*args*)))
        (setf y (parse-integer (nth 1 ext:*args*)))
        (format t "~%")
        (printMultTable x y)
    )
    (printUsing)
)

 


실행> clisp makeMultTable.lsp 230 5100
결과>

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

 

Posted by Scripter
,
▒ Common Lips 소스:  testStringReverse.lsp

#!/usr/bin/env clisp

(defun my-string-reverse (s)
    (let* ((arr (concatenate 'list s))
           (arr2 (reverse arr)))
        (format nil "~{~A~^~}" arr2)
    )
)

(setf s "Hello, world!")
(setf s2 "안녕하세요?")


(format t "s = ~A~%" s)
(format t "(reverse s) = ~A~%" (reverse s))
(format t "(my-string-reverse s) = ~A~%" (my-string-reverse s))
(format t "s2 = ~A~%" s2)
(format t "(reverse s2) = ~A~%" (reverse s2))
(format t "(my-string-reverse s2) = ~A~%" (my-string-reverse s2))

;; --------------------------------------------------------------
;; 출력 결과(CLisp 에서  MS949 인코딩으로 소스를 저장한 경우):
;;    s = Hello, world!
;;    (reverse s) = !dlrow ,olleH
;;    (my-string-reverse s) = !dlrow ,olleH
;;    s2 = 안녕하세요?
;;    (reverse s2) = ?요세하녕안
;;    (my-string-reverse s2) = ?요세하녕안




위의 예제에서 보듯이 CP949 한글의 문자열을 거꾸로 하기가 CLisp의 경우에는 잘 동작함이 확인되었다.
이를 대화형 모드(inttractive mode) CLisp에서 다시 한번 확인해 보자.

[CLisp의 대화형 모드에서 실행한 경우]---------------------
명령 프롬프트> clisp
 i i i i i i i       ooooo    o        ooooooo   ooooo   ooooo
  I I I I I I I      8     8   8           8     8     o  8    8
  I  \ `+' /  I      8         8           8     8        8    8
   \  `-+-'  /       8         8           8      ooooo   8oooo
    `-__|__-'        8         8           8           8  8
        |            8     o   8           8     o     8  8
  ------+------       ooooo    8oooooo  ooo8ooo   ooooo   8

Welcome to GNU CLISP 2.49 (2010-07-07) <http://clisp.cons.org/>

Copyright (c) Bruno Haible, Michael Stoll 1992, 1993
Copyright (c) Bruno Haible, Marcus Daniels 1994-1997
Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998
Copyright (c) Bruno Haible, Sam Steingold 1999-2000
Copyright (c) Sam Steingold, Bruno Haible 2001-2010

Type :h and hit Enter for context help.

[1]> (setf s "Hello, world!")
"Hello, world!"
[2]> (setf s2 "안녕하세요?")
"안녕하세요?"
[3]> (defun my-string-reverse (s)
    (let* ((arr (concatenate 'list s))
           (arr2 (reverse arr)))
        (format nil "~{~A~^~}" arr2)
    )
)
MY-STRING-REVERSE

Break 1 [7]> (format t "s = ~A~%" s)
s = Hello, world!
NIL
Break 1 [7]> (format t "(reverse s) = ~A~%" (reverse s))
(reverse s) = !dlrow ,olleH
NIL
Break 1 [7]> (format t "(my-string-reverse s) = ~A~%" (my-string-reverse s))
(my-string-reverse s) = !dlrow ,olleH
NIL
Break 1 [7]> (format t "s2 = ~A~%" s2)
s2 = 안녕하세요?
NIL
Break 1 [7]> (format t "(reverse s2) = ~A~%" (reverse s2))
(reverse s2) = ?요세하녕안
NIL
<-string-reverse s2) = ~A~%" (my-string-reverse s2))
(my-string-reverse s2) = ?요세하녕안
NIL
Break 1 [7]> (quit)
Bye.
----------------------------------------




Posted by Scripter
,

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

아래의 소스는 CLisp으로 실행되도록 작성되었다.

  1. #!/usr/bin/env clisp
  2. ;;  Filename: makeDivisionTable.lsp
  3. ;;
  4. ;;  Purpose:  Make a division table in a handy written form.
  5. ;;
  6. ;;  Execute: clisp makeDivisionTable.lsp 12345 32
  7. ;;           clisp makeDivisionTable.lsp 500210 61
  8. ;;           ./makeDivisionTable.lsp 500210 61
  9. ;;
  10. ;;     Date:  2013, 9. 5.
  11. (defun printUsage()
  12.     (format t "사용법: clisp makeDivisionTable.lsp [피제수] [제수]~%")
  13.     (format t "손으로 작성한 형태의 나눗셈 표를 만들어준다.~%") )
  14. (defun simplify(v &optional width)
  15.     (let* ((tt "")
  16.            (slen 0))
  17.         (setf tt (format nil "~A" v))
  18.         (setf slen (length tt))
  19.         (if (and (>= slen 2) (string= (substring tt (- slen 2) slen) ".0"))
  20.             (setf tt (substring tt 0 (- slen 2))) )
  21.         (setf slen (length tt))
  22.         (if width
  23.             (if (< slen width)
  24.                 (setf tt (concatenate 'string (make-string (- width slen) :initial-element #\Space) tt)) ))
  25.         tt
  26.     )
  27. )
  28. (defun getSuffix(v)
  29.     (let* ((tt (mod (abs v) 10))
  30.            (suffix "은"))
  31.         (if (search (format nil "~A" tt) "2459")
  32.             (setf suffix "는") )
  33.         suffix
  34.     )
  35. )
  36. (defun makeTable(numer denom quotient)
  37.     (let* ((strNumer (format nil "~A" numer))
  38.            (strDenom (format nil "~A" denom))
  39.            (strQuotient (format nil "~A" quotient))
  40.            (lenN (length strNumer))
  41.            (lenD (length strDenom))
  42.            (lenQ (length strQuotient))
  43.            (offsetLeft (+ 3 lenD 3))
  44.            (spaces (make-string 100 :initial-element #\Space))
  45.            (uline (make-string (+ lenN 2) :initial-element #\_))
  46.            (sline (make-string lenN :initial-element #\-))
  47.            (bias (- lenN lenQ))
  48.            (strTmpR (substring strNumer 0 (+ bias 1)))
  49.            (tmpR (parse-integer strTmpR))
  50.            (tmpSub 0)
  51.            (oneDigit nil) )
  52.         (format t "~A~A~A~%" (substring spaces 0 offsetLeft) (substring spaces 0 bias) (format nil "~D" quotient))
  53.         (format t "~A~A~%" (substring spaces 0 (- offsetLeft 2)) uline)
  54.         (format t "~A~A~A~A" "   " strDenom " ) " strNumer)
  55.         (loop for i from 0 below lenQ do
  56.             (if (string= (substring strQuotient i (1+ i)) "0")
  57.                 (progn
  58.                     (if (< (1+ i) lenQ)
  59.                         (progn
  60.                            (setf oneDigit (substring strNumer (+ bias i 1) (+ bias i 2)))
  61.                            (format t "~A" oneDigit)
  62.                            (setf strTmpR (concatenate 'string strTmpR oneDigit))
  63.                            (setf tmpR (parse-integer strTmpR))
  64.                         )
  65.                     )
  66.                 )
  67.                 (progn
  68.                     (format t "~%")
  69.                     (setf tmpSub (* (parse-integer (substring strQuotient i (1+ i))) denom))
  70.                     (format t "~A~A~%" (substring spaces 0 offsetLeft) (simplify tmpSub (+ bias i 1)))
  71.                     (format t "~A~A~%" (substring spaces 0 offsetLeft) sline)
  72.                     (setf tmpR (- tmpR tmpSub))
  73.                     (if (and (= tmpR 0) (< (+ i 1) lenQ))
  74.                         (format t "~A~A" (substring spaces 0 offsetLeft) (substring spaces 0 (+ bias i 1)))
  75.                         (format t "~A~A" (substring spaces 0 offsetLeft) (simplify tmpR (+ bias i 1)))
  76.                     ) 
  77.                     (setf strTmpR (format nil "~D" tmpR)) 
  78.                     (if (< (+ i 1) lenQ)
  79.                         (progn
  80.                             (setf oneDigit (substring strNumer (+ bias i 1) (+ bias i 2)))
  81.                             (if (plusp (length oneDigit))
  82.                                 (progn
  83.                                     (format t "~A" oneDigit)
  84.                                     (setf strTmpR (concatenate 'string strTmpR oneDigit))
  85.                                 )
  86.                             )
  87.                             (setf tmpR (parse-integer strTmpR))
  88.                         )
  89.                     )
  90.                 )
  91.             )
  92.         )
  93.         tmpR
  94.     )
  95. )
  96. ;; Begin here
  97. (if (< (length ext:*args*) 2)
  98.     (progn
  99.         (printUsage)
  100.         (quit)
  101.     )
  102. )
  103. (setf a nil)
  104. (setf b nil)
  105. (handler-case
  106.     (progn
  107.         (setf a (parse-integer (nth 0 ext:*args*)))
  108.         (setf b (parse-integer (nth 1 ext:*args*)))
  109.         (if (minusp a)
  110.             (progn
  111.                 (format t "피제수: ~A~%" a)
  112.                 (format t "피제수는 양의 정수라야 합니다.~%")
  113.                 (quit)
  114.             )
  115.             (if (minusp b)
  116.                 (progn
  117.                     (format t "제수: ~A~%" b)
  118.                     (format t "제수는 양의 정수라야 합니다.~%")
  119.                     (quit)
  120.                 )
  121.             )
  122.         )
  123.         (setf q (floor (/ a b)))
  124.         (setf r (mod a b))
  125.         (format t "나눗셈 ~A ÷ ~A 의 결과: " a b)
  126.         (format t "몫:  ~A, " q)
  127.         (format t "나머지: ~A~%" r)
  128.         (format t "~%")
  129.         (setf k (makeTable a  b q))
  130.         (format t "~%")
  131.         (if (= k r)
  132.             (format t "~%나머지: ~A~%" k)
  133.         )
  134.         (if (= k 0)
  135.             (progn
  136.                 (format t "~A = ~A x ~A~%" a b q)
  137.                 (format t "~A~A ~A의 배수(mupltiple)이다.~%" a (getSuffix a) b)
  138.                 (format t "~A~A ~A의 약수(divisor)이다.~%" b (getSuffix b) a)
  139.                 (format t "~%")
  140.             )
  141.             (progn
  142.                 (format t "~A = ~A x ~A + ~A~%" a b q r)
  143.                 (format t "~A~A ~A의 배수(mupltiple)가 아니다.~%" a (getSuffix a) b)
  144.                 (format t "~%")
  145.             )
  146.         )
  147.     )
  148.     (parse-error (c)
  149.         (format t "예외상황: ~A" c)
  150.         (format t "이 발생였음. 다시 하시오,~%~%")
  151.     )
  152. )




실행> clisp makeDivisionTable.lsp 500210 61

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

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

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




Posted by Scripter
,

콘솔에 삼각형

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


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

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

우선 첫번 째 예제는 Common Lisp의 컨솔 출력 함수 format t 의 사용법만 알면 누구나 코딩할 수 있는 매우 단순한 소스 코드이다. 문자열 상수 내에서 ~%는 C, C++, Java, C#, Python 같은 대부분의 절차형 언어에서 사용하는 메타문자 \n에 해당한다.

아래의 모든 소스는 CLisp으로 실행되도록 작성되었다.


삼각형 출력 예제 1
;;  Filename: printTriangle1.lsp
;;            Print a triangle on console.
;;
;;  Execute: clisp printTriangle1.lsp
;;
;;      Date:  2013. 9. 5.

(defun printTriange()
    (format t "        *        ~%")
    (format t "       * *       ~%")
    (format t "      *   *      ~%")
    (format t "     *     *     ~%")
    (format t "    *       *    ~%")
    (format t "   *         *   ~%")
    (format t "  *           *  ~%")
    (format t " *             * ~%")
    (format t "*****************~%") )

(printTriange)




위의 소스 코드는 아무 알고리즘도 없는 너무 단순한 코드이다. 이런 코드를 작성했다간 출력 모양이나 크기를 변경해야 하는 상황을 맞이하면 워드프로세서로 문서 만드는 것 이상으로 많은 수작업을 하거나 아니면 포기하는 지경에 이를 수도 있다. 그래서 다음 처럼 좀 더 나은 소스 코드를 작성하였다.  문자를 하나씩 출력하는 함수 my-write를 정의하여 이를 사용하였다. (write는 Common Lisp에서 이미 정의되어 있으므오 다른 이름 my-write으로 하였다.) C, C++, Java, C#, Python, Ruby 등의 대부분의 언어에서는 특수문자 +, -, * 등을 함수명이나 변수명에 사용하지 못하지만, Common Lisp 언어에서는 이들을 사용해도 된다.  특히 *variable-name* 처럼 변수명의 처음과 끝에 *를 사용하는 것은 (Common Lisp 소스 코드 작상 관습상) 전역변수인 것으로 본다.



삼각형 출력 예제 2
;;  Filename: printTriangle2.lsp
;;            Print a triangle on console.
;;
;;  Execute: clisp printTriangle2.lsp
;;
;;      Date:  2013. 9. 5.

(defun my-write(s)
    (format t "~A" s) )

(defun printTriange()
    (loop for i from 0 below 8 do
        (loop for k from 0 below (- 8 i) do
            (my-write " ") )
        (loop for k from 0 below (+ (* 2 i) 1) do
            (if (or (zerop k) (= k (* 2 i)))
                (my-write "*")
                (my-write " ") ))
        (loop for k from 0 below (- 8 i) do
            (my-write " ") )
        (format t "~%") )

    (loop for i from 0 below 17 do
        (my-write "*") )
    (format t "~%")
)

(printTriange)



위의 소스 코드는 my-write 함수와 format t "~%"  를 적절히 사용하여 구현되었다. 숫자 몇 곳만 수정하면 출력되는 삼각형의 크기를 쉽게 바꿀 수 있다. 한 줄에 출력될 문자를 구성하는 알고리즘은 위의 예제와 근본적으로 같지만 한 문자식 출력하는 대신에 한 줄에 출력될 문자열을 만들어서 출력하는 소스 코드를 다음 예제와 같이 작성해 보았다.
또 빈칸 17개의 문자로 구성된 리스트를 생성하기 위한 구문은

        (setf line2 (make-list 17 :initial-element " "))

이다.


삼각형 출력 예제 3
;;  Filename: printTriangle3.lsp
;;            Print a triangle on console.
;;
;;  Execute: clisp printTriangle3.lsp
;;
;;      Date:  2013. 9. 5.

(defun join-string-list (string-list)
    (format nil "~{~A~^~}" string-list))

(defun printTriange()
    (let ((line2 (list)))
        (setf line2 (make-list 17 :initial-element " "))
        (loop for i from 0 below 8 do
            (setf line2 (make-list 17 :initial-element " "))
            (setf (nth (- 8 i) line2) #\*)
            (setf (nth (+ 8 i) line2) #\*)
            (format t "~A~%" (join-string-list line2)) )

        (setf line2 (make-list 17 :initial-element " "))
        (loop for i from 0 below 17 do
            (setf (nth i line2) #\*) )
        (format t "~A~%" (join-string-list line2))
    )
)

(printTriange)




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

           (whites (make-string 17 :initial-element #\Space))
           (stars (make-string 17 :initial-element #\*))

은 지정된 개수(여기서는 17) 만큼 :initial-element 옵션에 주어진 character를 중복 연결하는 구문이다.




삼각형 출력 예제 4
;;  Filename: printTriangle4.lsp
;;            Print a triangle on console.
;;
;;  Execute: clisp printTriangle4.lsp
;;
;;      Date:  2008/04/02

(defun printTriange()
    (let* ((whites (make-string 17 :initial-element #\Space))
           (stars (make-string 17 :initial-element #\*))
           (line2 (concatenate 'string (substring whites 0 8) "*" (substring whites 0 7))) )
   
        (format t "~A~%" line2)
        (loop for i from 1 below 8 do
            (setf line2 (concatenate 'string (substring whites 0 (- 8 i)) "*" (substring whites (- 8 i) (+ 7 i)) "*" (substring whites (+ 7 i) 17)))
            (format t "~A~%" line2))
        (format t "~A~%" stars)
    )
)

(printTriange)




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

    (join-string-list line2)

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



삼각형 출력 예제 5
;;  Filename: printTriangle5.lsp
;;            Print a triangle on console.
;;
;;  Execute: clisp printTriangle5.lsp
;;
;;      Date:  2013. 9. 5.

(defun join-string-list (string-list)
    (format nil "~{~A~^~}" string-list))

(defun printTriange()
    (let* ((whites (make-string 17 :initial-element #\Space))
           (stars (make-string 17 :initial-element #\*))
           (start 8)
           (line2 (make-list 17 :initial-element " ")))

        (setf (nth start line2) "*")
        (format t "~A~%" (join-string-list line2))

        (loop for i from 1 below 8 do
            (setf line2 (make-list 17 :initial-element " "))
            (setf (nth (- start i) line2) (format nil "~A" (aref stars (- start i))))
            (setf (nth (+ start i) line2) (format nil "~A" (aref stars (+ start i))))
            (format t "~A~%" (join-string-list line2)) )

        (format t "~A~%" stars)
    )
)


(printTriange)



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



삼각형 출력 예제 6
;;  Filename: printTriangle6.lsp
;;            Print a triangle on console.
;;
;;  Execute: clisp printTriangle6.lsp
;;
;;      Date:  2013. 9. 5.

(defun printTriange()
    (let* ((whites (make-string 8 :initial-element #\Space))
           (stars (make-string 8 :initial-element #\*))
           (start 8)
           (line (concatenate 'string whites "*" whites)))

        (format t "~A~%" line)

        (loop for i from 1 below 8 do
            (setf line (concatenate 'string (substring whites 0 (- 8 i)) "*" (substring whites (- 8 i) (1- 8))))
            (format t "~A ~A~%" line (reverse line)) )

        (setf line (concatenate 'string stars "*" stars))
        (format t "~A~%" line)
    )
)

(printTriange)




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



삼각형 출력 예제 7
;;  Filename: printTriangle7.lsp
;;            Print a triangle on console.
;;
;;  Execute: clisp printTriangle7.lsp
;;
;;      Date:  2013. 9. 5.

(setf *BASE36* "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")

(defun itoa(num radix)
    (let* ((isNegative nil)
           (a 0)
           (arr (list))
           (q 0)
           (r 0))

        (if (equal radix nil) (setf radix 10))
  
        (if (minusp num) (progn
            (setf isNegative t)
            (setf inum (- num)) ))

        (setf q num)
      
        (loop while (>= q radix) do
            (setf r (mod q radix))
            (setf q (floor (/ q radix)))
            (setf arr (nconc arr (list (substring *BASE36* r (1+ r)))))
        )

       (setf arr (nconc arr (list (substring *BASE36* q (1+ q)))))
       (if isNegative (nconc (ncons arr (list "-"))) )

       (setf arr (reverse arr))
       (join-string-list arr)
    )
)

(defun join-string-list (string-list)
    (format nil "~{~A~^~}" string-list))

(defun printTriange()
    (let* ((start #x100)
           (total 0)
           (val start)
           (s "")
           (data ""))
        (loop for k from 0 below 8 do
            (setf val (logior (ash start k) (ash start (- k))))
            (setf data (itoa val 2))
            (setf s "")
            (loop for i from 0 below (- 17 (length data)) do
                (setf s (concatenate 'string s " ")) )
            (loop for i from 0 below (length data) do
                (if (equal (aref data i) #\0)
                   (setf s (concatenate 'string s " "))
                   (setf s (concatenate 'string s "*")) ))
            (format t "~A~%" s)
            (setf total (+ total val)) )

        (setf val (logior (ash start 8) (ash start -8)))
        (setf total (+ total val))
        (setf data (itoa total 2))
        (setf s "")
        (loop for i from 0 below (- 17 (length data)) do
            (setf s (concatenate 'string s " ")) )
        (loop for i from 0 below (length data) do
            (if (equal (aref data i) #\0)
                (setf s (concatenate 'string s " "))
                (setf s (concatenate 'string s "*")) ))
        (format t "~A~%" s)
    )
)

(printTriange)




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

            (setf total (+ total val))

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




삼각형 출력 예제 8
;;  Filename: printTriangle8.lsp
;;            Print a triangle on console.
;;
;;  Execute: clisp printTriangle8.lsp
;;
;;      Date:  2013. 9. 5.

   
(setf *BASE36* "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")

(defun itoa(num radix)
    (let* ((isNegative nil)
           (a 0)
           (arr (list))
           (q 0)
           (r 0))

        (if (equal radix nil) (setf radix 10))
  
        (if (minusp num) (progn
            (setf isNegative t)
            (setf inum (- num)) ))

        (setf q num)
      
        (loop while (>= q radix) do
            (setf r (mod q radix))
            (setf q (floor (/ q radix)))
            (setf arr (nconc arr (list (substring *BASE36* r (1+ r)))))
        )

       (setf arr (nconc arr (list (substring *BASE36* q (1+ q)))))
       (if isNegative (nconc (ncons arr (list "-"))) )

       (setf arr (reverse arr))
       (join-string-list arr)
    )
)

(defun join-string-list (string-list)
    (format nil "~{~A~^~}" string-list))

(defun char-replace (a b c)
    (if (= (char-code a) (char-code b))
          c
          a ))

(defun string-to-list (s)
    (loop for char across s
            collect char) )

(defun list-to-string (a)
    (format nil "~{~A~^~}" a))

(defun replacer(b c) #'(lambda (x) (char-replace x b c)))

(defun string-replace-char (s a b)
    (let* ((arr (string-to-list s))
           (arr2 (mapcar (replacer a b) arr)))
       (list-to-string arr2) ))

(defun printTriange()
    (let* ((zeros "00000000")
           (start #x100)
           (total 0)
           (val start)
           (line ""))

        (loop for k from 0 below 8 do
            (setf val (logior (ash start k) (ash start (- k))))
            (setf line (itoa val 2))
            (setf line (concatenate 'string (substring zeros 0 (- 17 (length line))) line))
            (setf line (string-replace-char line #\0 #\Space))
            (setf line (string-replace-char line #\1 #\*))
            (format t "~A~%" line)
            (setf total (+ total val)) )

        (setf val (logior (ash start 8) (ash start -8)))
        (setf total (+ total val))
        (setf line (itoa total 2))
        (setf line (string-replace-char line #\0 #\Space))
        (setf line (string-replace-char line #\1 #\*))
        (format t "~A~%" line)
    )
)

(printTriange)




소스 코드가 처음 것 보다 매우 복잡해졌지만, Common Lisp의 리스트를 이용해서 구현해 보았다. Common Lisp 언어 처럼 함수형 언어에서는 리스트가 매우 중요한 지료형(타입)이다. 별(*) 문자만으로 구성된 마지막 줄 출력을 위해 리스트 타입의 변수 last를 준비하였다. 또 리스트에 속한 모든 item을 출력하도록 구현된 Common Lisp 함수의 정의

    (defun join-string-list (data sep)
        (format nil (concatenate 'string "~{~A" sep "~^~}") data))

과 이의 사용

            (format t "~A~%" (join-string-list 리스트 구분자))

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



삼각형 출력 예제 9
;;  Filename: printTriangle9.lsp
;;            Print a triangle on console.
;;
;;  Execute: clisp printTriangle9.lsp
;;
;;      Date:  2013. 9. 6.

#|
(setf *BASE36* "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")

(defun itoa(num radix)
    (let* ((isNegative nil)
           (a 0)
           (arr (list))
           (q 0)
           (r 0))

        (if (equal radix nil) (setf radix 10))
  
        (if (minusp num) (progn
            (setf isNegative t)
            (setf inum (- num)) ))

        (setf q num)
      
        (loop while (>= q radix) do
            (setf r (mod q radix))
            (setf q (floor (/ q radix)))
            (setf arr (nconc arr (list (substring *BASE36* r (1+ r)))))
        )

       (setf arr (nconc arr (list (substring *BASE36* q (1+ q)))))
       (if isNegative (nconc (ncons arr (list "-"))) )

       (setf arr (reverse arr))
       (join-string-list arr)
    )
)

(defun char-replace (a b c)
    (if (= (char-code a) (char-code b))
          c
          a ))

(defun string-to-list (s)
    (loop for char across s
            collect char) )

(defun list-to-string (a)
    (format nil "~{~A~^~}" a))

(defun replacer(b c) #'(lambda (x) (char-replace x b c)))

(defun string-replace-char (s a b)
    (let* ((arr (string-to-list s))
           (arr2 (mapcar (replacer a b) arr)))
       (list-to-string arr2) ))
|#

(defun join-string-list (data sep)
    (format nil (concatenate 'string "~{~A" sep "~^~}") data))

(defun printTriange()
    (let* ((data (make-list 17 :initial-element " "))
           (last (make-list 17 :initial-element " "))
           (start 8))

        (setf (nth start data) "*")
        (setf (nth start last) "*")
        (format t "~A~%" (join-string-list data ""))

        (setf (nth start data) " ")

        (loop for k from 1 below 8 do
            (setf (nth (- start k) data) "*")
            (setf (nth (- start k) last) "*")
            (setf (nth (+ start k) data) "*")
            (setf (nth (+ start k) last) "*")
            (format t "~A~%" (join-string-list data ""))
            (setf (nth (- start k) data) " ")
            (setf (nth (+ start k) data) " ")
        )

        (setf (nth (- start 8) last) "*")
        (setf (nth (+ start 8) last) "*")
        (format t "~A~%" (join-string-list las ""t))
    )
)

(printTriange)





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

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

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




삼각형 출력 예제 10
;;  Filename: printTriangle10.lsp
;;            Print a triangle on console.
;;
;;  Execute: clisp printTriangle10.lsp
;;
;;      Date:  2013. 9. 6.

(defun printTriange()
    (let* ((x 0)
           (y 0)
           (a ""))
          
        (loop for y from 0 below 9 do
            (loop for x from 0 below 17 do
                (if (or (zerop (- (+ x y) 8)) (zerop (+ (- y x) 8)) (zerop (- y 8)))
                    (setf a "*")
                    (setf a " "))
                (format t "~A" a)
            )
            (format t "~%")
        )
    )
)

(printTriange)





Posted by Scripter
,

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

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

        ()convertItoA number  radix)

의 구현도 포함되어 있다.

(아래의 소스는 CLisp으로 실행된다.)


  1. ;;  Filename: makeAsciiTable.lsp
  2. ;;            Make a table of ascii codes.
  3. ;;
  4. ;;  Execute: clisp makeAsciiTable.lsp
  5. ;;
  6. ;;      Date:  2013.9. 5.
  7. (setf *BASE36* "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")
  8. (defun printUsage()
  9.     (format t "Usage: lisp makeAsciiTable.lsp~%")
  10.     (format t "Make a table of ascii codes.~%") )
  11. (defun join-string-list (string-list)
  12.     ; (format nil "~{~A~^ ~}" string-list))
  13.     (format nil "~{~A~^~}" string-list))
  14. (defun to-right-align(s)
  15.     (let* ((n (length s))
  16.            (a (get-token s))
  17.            (k (length a)))
  18.          (if (= n 0) s)
  19.          (concatenate 'string (substring s k n) a) ))
  20. (defun get-token (s)
  21.   (let* ((i (if (find (elt s 0) "+-") 1 0))
  22.          (d (position-if 'nonwhite-char-p s :start i))
  23.          (f 0))
  24.     (if (equal d nil) s
  25.            (progn
  26.                (setf f (position-if 'white-char-p s :start (1+ d)))
  27.                (if (equal f nil) s
  28.                    (progn 
  29.                         (substring s d f) )) )) ))
  30. (defun nonwhite-char-p (c)
  31.     (> (char-code c) (char-code #\Space)))
  32. (defun white-char-p (c)
  33.     (<= (char-code c) (char-code #\Space)))
  34. (defun convertItoA(num radix)
  35.     (let* ((isNegative nil)
  36.            (a 0)
  37.            (arr (list))
  38.            (q 0)
  39.            (r 0))
  40.         (if (equal radix nil) (setf radix 10))
  41.         (if (minusp num) (progn
  42.             (setf isNegative t)
  43.             (setf inum (- num)) ))
  44.         (setf q num)
  45.         (loop while (>= q radix) do
  46.             (setf r (mod q radix))
  47.             (setf q (floor (/ q radix))) 
  48.             (setf arr (nconc arr (list (substring *BASE36* r (1+ r)))))
  49.         )
  50.        (setf arr (nconc arr (list (substring *BASE36* q (1+ q)))))
  51.        (if isNegative (nconc (ncons arr (list "-"))) )
  52.        (setf arr (reverse arr))
  53.        (join-string-list arr)
  54.     )
  55. )
  56. (setf *asc* (list
  57.     "NUL" "SOH"  "STX"  "ETX"  "EOT"
  58.     "ENQ" "ACK"  "BEL"  "BS"   "HT"
  59.     "LF"  "VT"   "FF"   "CR"   "SO"
  60.     "SI"  "DLE"  "DC1"  "DC2"  "DC3"
  61.     "DC4" "NAK"  "SYN"  "ETB"  "CAN"
  62.     "EM"  "SUB"  "ESC"  "FS"   "GS"
  63.     "RS"  "US"   "Spc"
  64.     ))
  65. (setf *control* (list
  66.     "NUL (null)"
  67.     "SOH (start of heading)"
  68.     "STX (start of text)"
  69.     "ETX (end of text)"
  70.     "EOT (end of transmission)"
  71.     "ENQ (enquiry)"
  72.     "ACK (acknowledge)"
  73.     "BEL (bell)"
  74.     "BS  (backspace)"
  75.     "TAB (horizontal tab)"
  76.     "LF  (line feed, NL new line)"
  77.     "VT  (vertical tab)"
  78.     "FF  (form feed, NP new page)"
  79.     "CR  (carriage return)"
  80.     "SO  (shift out)"
  81.     "SI  (shift in)"
  82.     "DLE (data link escape)"
  83.     "DC1 (device control 1)"
  84.     "DC2 (device control 2)"
  85.     "DC3 (device control 3)"
  86.     "DC4 (device control 4)"
  87.     "NAK (negative acknowledge)"
  88.     "SYN (synchronous idle)"
  89.     "ETB (end of trans. block)"
  90.     "CAN (cancel)"
  91.     "EM  (end of medium)"
  92.     "SUB (substitute, EOF end of file)"
  93.     "ESC (escape)"
  94.     "FS  (file separator)"
  95.     "GS  (group separator)"
  96.     "RS  (record separator)"
  97.     "US  (unit separator)"
  98.     ))
  99. (defun makeTable()
  100.     (let* ((sbuf "")
  101.            (abuf "")
  102.            (tbuf "")
  103.            (c #\Space))
  104.         (setf sbuf "    ")
  105.         (loop for i from 0 below 8 do
  106.             (setf sbuf (concatenate 'string sbuf "+----")))
  107.         (setf sbuf (concatenate 'string sbuf "+"))
  108.         (format t "~A~%" sbuf)
  109.         (setf sbuf "    ")
  110.         (setf sbuf (concatenate 'string sbuf "| 0- "))
  111.         (setf sbuf (concatenate 'string sbuf "| 1- "))
  112.         (setf sbuf (concatenate 'string sbuf "| 2- "))
  113.         (setf sbuf (concatenate 'string sbuf "| 3- "))
  114.         (setf sbuf (concatenate 'string sbuf "| 4- "))
  115.         (setf sbuf (concatenate 'string sbuf "| 5- "))
  116.         (setf sbuf (concatenate 'string sbuf "| 6- "))
  117.         (setf sbuf (concatenate 'string sbuf "| 7- "))
  118.         (setf sbuf (concatenate 'string sbuf "|"))
  119.         (format t "~A~%" sbuf)
  120.         (setf sbuf "+---")
  121.         (loop for i from 0 below 8 do
  122.             (setf sbuf (concatenate 'string sbuf "+----")))
  123.         (setf sbuf (concatenate 'string sbuf "+"))
  124.         (format t "~A~%" sbuf)
  125.         (loop for i from 0 below 16 do
  126.             (setf tbuf "")
  127.             (setf sbuf (convertItoA i 16))
  128.             (setf tbuf (concatenate 'string "| " sbuf " "))
  129.             (loop for j from 0 below 8 do
  130.                 (if (<= (+ (* j 16) i)  32)
  131.                     (setf abuf (format nil "| ~3A" (nth (+ (* j 16) i) *asc*)))
  132.                     (if (= (+ (* j 16) i)  127)
  133.                         (setf abuf (format nil "| ~3A" "DEL"))
  134.                         (progn
  135.                             (setf c (code-char (+ (* j 16) i)))
  136.                             (setf abuf (format nil "|  ~2A" c)) )))
  137.                 (setf tbuf (concatenate 'string tbuf abuf))
  138.             )
  139.             (setf tbuf (concatenate 'string tbuf "|"))
  140.             (format t "~A~%" tbuf)
  141.         )
  142.         (setf sbuf "+---")
  143.         (loop for i from 0 below 8 do
  144.             (setf sbuf (concatenate 'string sbuf "+----")))
  145.         (setf sbuf (concatenate 'string sbuf "+"))
  146.         (format t "~A~%" sbuf)
  147.         (format t "~%")
  148.         (loop for i from 0 below 16 do
  149.             (setf tbuf (format nil "~30A  ~34A" (nth i *control*) (nth (+ i 16) *control*)))
  150.             (format t "~A~%" tbuf)
  151.         )
  152.     ))
  153. (if (and (> (length ext:*args*) 0) (equal (nth 0 ext:*args*) "-h")) (progn
  154.     (printUsage)
  155.     (quit) ))
  156. (makeTable)




실행> clisp makeAsciiTable.lsp

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




 

Posted by Scripter
,

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

        (convertItoA number  radix)

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

(아래의 소스는 CLisp으로  실행된다.)


  1. ;;  Filename: makeRadixTable.lsp
  2. ;;            Show the radix table with 10-, 2-, 8-, 16-radices.
  3. ;;
  4. ;;  Execute: clisp makeRadixTable.lsp
  5. ;;
  6. ;;      Date:  2013. 9. 5.
  7. (setf *BASE36* "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")
  8. (defun println(s)
  9.     (if (equal s nil)
  10.         (format t "~%")
  11.         (format t "~A~%" s) ))
  12. (defun printUsage()
  13.     (println "Usage: clisp makeRadixTable.lsp")
  14.     (println "Show the radix table with 10-, 2-, 8-, 16-radices.") )
  15. (defun join-string-list (string-list)
  16.     ; (format nil "~{~A~^ ~}" string-list))
  17.     (format nil "~{~A~^~}" string-list))
  18. (defun to-right-align(s)
  19.     (let* ((n (length s))
  20.            (a (get-token s))
  21.            (k (length a)))
  22.          (if (= n 0) s)
  23.          (concatenate 'string (substring s k n) a) ))
  24. (defun get-token (s)
  25.   (let* ((i (if (find (elt s 0) "+-") 1 0))
  26.          (d (position-if 'nonwhite-char-p s :start i))
  27.          (f 0))
  28.     (if (equal d nil) s
  29.            (progn
  30.                (setf f (position-if 'white-char-p s :start (1+ d)))
  31.                (if (equal f nil) s
  32.                    (progn
  33.                         (substring s d f) )) )) ))
  34. (defun nonwhite-char-p (c)
  35.     (> (char-code c) (char-code #\Space)))
  36. (defun white-char-p (c)
  37.     (<= (char-code c) (char-code #\Space)))
  38. (defun convertItoA(num radix)
  39.     (let* ((isNegative nil)
  40.            (a 0)
  41.            (arr (list))
  42.            (q 0)
  43.            (r 0))
  44.         (if (equal radix nil) (setf radix 10))
  45.         (if (minusp num) (progn
  46.             (setf isNegative t)
  47.             (setf inum (- num)) ))
  48.         (setf q num)
  49.         (loop while (>= q radix) do
  50.             (setf r (mod q radix))
  51.             (setf q (floor (/ q radix)))
  52.             (setf arr (nconc arr (list (substring *BASE36* r (1+ r)))))
  53.         )
  54.        (setf arr (nconc arr (list (substring *BASE36* q (1+ q)))))
  55.        (if isNegative (nconc (ncons arr (list "-"))) )
  56.        ; (format t "~A~%" arr)
  57.        (setf arr (reverse arr))
  58.        (join-string-list arr)
  59.     )
  60. )
  61. (defun makeTable()
  62.     (let* ((sbuf "")
  63.            (abuf "")
  64.            (tbuf ""))
  65.         (loop for i from 0 below 4 do
  66.             (setf sbuf (concatenate 'string sbuf "+-------")) )
  67.         (setf sbuf (concatenate 'string sbuf "+"))
  68.         (format t "~A~%" sbuf)
  69.         (setf sbuf "|  Dec")
  70.         (setf sbuf (concatenate 'string sbuf (format nil "  |  Bin")))
  71.         (setf sbuf (concatenate 'string sbuf (format nil "  |  Oct")))
  72.         (setf sbuf (concatenate 'string sbuf (format nil "  |  Hex  |")))
  73.         (format t "~A~%" sbuf)
  74.         (setf sbuf "")
  75.         (loop for i from 0 below 4 do
  76.             (setf sbuf (concatenate 'string sbuf "+-------")) )
  77.         (setf sbuf (concatenate 'string sbuf "+"))
  78.         (format t "~A~%" sbuf)
  79.         (loop for i from 0 below 16 do
  80.             (setf sbuf (format nil "|   ~2D" i))
  81.             (setf abuf (convertItoA i 2))
  82.             (setf tbuf (format nil "  |  ~A" (to-right-align (format nil "~4A" abuf))))
  83.             (setf sbuf (concatenate 'string sbuf tbuf))
  84.             (setf abuf (convertItoA i 8))
  85.             (setf tbuf (format nil " |   ~A" (to-right-align (format nil "~2A" abuf))))
  86.             (setf sbuf (concatenate 'string sbuf tbuf))
  87.             (setf abuf (convertItoA i 16))
  88.             (setf tbuf (format nil "  |   ~A  |" (to-right-align (format nil "~2A" abuf))))
  89.             (setf sbuf (concatenate 'string sbuf tbuf))
  90.             (format t "~A~%" sbuf)
  91.         )
  92.         (setf sbuf "")
  93.         (loop for i from 0 below 4 do
  94.             (setf sbuf (concatenate 'string sbuf "+-------")) )
  95.         (setf sbuf (concatenate 'string sbuf "+"))
  96.         (format t "~A~%" sbuf)
  97. ))
  98. (if (and (> (length ext:*args*) 0) (equal (nth 0 ext:*args*) "-h")) (progn
  99.     (printUsage)
  100.     (quit) ))
  101. (makeTable)



실행> clisp makeRadixTable.lsp

+-------+-------+-------+-------+
|  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  |
+-------+-------+-------+-------+




 

Posted by Scripter
,

다음은  대화형 모드(interactive mode)에서 진법 변환(radix conversion)하는 Common Lisp 소스 코드이다.


메뉴는 주메뉴 Command: (S)et radix, (A)bout, (Q)uit or E(x)it
와 부메뉴 SubCommand: 'main()' to goto Main menu, 'exit()' or 'quit()' to exit
로 구성되어 있으며, 진법 변환의 핵심은 아래 소스의 52째 줄과 53째 줄에 있는

       (setf val (parse-integer s :radix srcRdx))
        (setf ret (write-to-string val :base destRdx))

이다. 지원되는 진법은 2진법에서 36진법까지이다.


  1. ;;  Filename: convertRadix.lsp
  2. ;;            Convert radix in a interactive mode.
  3. ;;
  4. ;;  Execute: clisp convertRadix.lsp
  5. ;;
  6. ;;      Date:  2013. 9. 5.
  7. (defun printUsage()
  8.     (format t "Usage: clisp convertRadix.lsp~%")
  9.     (format t "Convert radix in a interactive mode, where the maximum radix is 36.~%") )
  10. (defun printAbout()
  11.     (format t "    About: Convert radix in a interactive mode.~%") )
  12. (defun printMainMenu()
  13.     (format t "  Command: (S)et radix, (A)bout, (Q)uit or E(x)it~%") )
  14. (defun printMainPrompt()
  15.     (format t "  Prompt> ") )
  16. (defun printSubMenu(srcRadix destRadix)
  17.     (format t "    Convert Radix_~D to Radix_~D~%" srcRadix destRadix)
  18.     (format t "    SubCommand: 'main()' to goto Main menu, 'exit()' or 'quit()' to exit~%") )
  19. (defun printSubPrompt()
  20.     (format t "    Input Value>> ") )
  21. (setf *BASE36* "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")
  22. (defun join-string-list (string-list)
  23.     "Concatenates a list of strings and puts spaces between the elements."
  24.     (format nil "~{~A~^~}" string-list))
  25. (define-condition invalid-src-radix (error)
  26.   ((msg :reader msg :initarg :msg))
  27.   (:report (lambda (condition stream)
  28.              (format stream "Exception: ~A." (msg condition)))))
  29. (define-condition invalid-dest-radix (error)
  30.   ((msg :reader msg :initarg :msg))
  31.   (:report (lambda (condition stream)
  32.              (format stream "Exception: ~A." (msg condition)))))
  33. (defun convertRadix(s srcRdx destRdx)
  34.   (ignore-errors
  35.     (if (or (< srcRdx 2) (> srcRdx 36))
  36.         (error 'invalid-src-radix :msg (format nil "Invalid source radix: ~A" srcRdx)))
  37.     (if (or (< destRdx 2) (> destRdx 36))
  38.         (error 'invalid-dest-radix :msg (format nil "Invalid destination radix: ~A" destRdx)))
  39.     (let ((ret ""))
  40.         (setf val (parse-integer s :radix srcRdx))
  41.         (setf ret (write-to-string val :base destRdx))
  42.         (string-upcase ret)))
  43.   )
  44. (defun nonwhite-char-p (c)
  45.     (> (char-code c) (char-code #\Space)))
  46. (defun white-char-p (c)
  47.     (<= (char-code c) (char-code #\Space)))
  48. (defun safe-parse-integer (s)
  49.         (handler-case
  50.              (parse-integer s :radix 10)
  51.              (parse-error (c)
  52.                        (format t "예외상황 발생: ~A" c)
  53.                )
  54.         )
  55. )
  56. (defun get-token (s)
  57.   (let* ((i (if (find (elt s 0) "+-") 1 0))
  58.          (d (position-if 'nonwhite-char-p s :start i))
  59.          (f (position-if 'white-char-p s :start (1+ d))))
  60.     ; (format t "d = ~A~%" d)
  61.     ; (format t "f = ~A~%" f)
  62.     (substring s d f)))
  63. (defun get-two-tokens (s)
  64.   (let* ((i (if (find (elt s 0) "+-") 1 0))
  65.          (d (position-if 'nonwhite-char-p s :start i))
  66.          (f (position-if 'white-char-p s :start (1+ d)))
  67.          (d2 (position-if 'nonwhite-char-p s :start (1+ f)))
  68.          (f2 (position-if 'white-char-p s :start (1+ d2))))
  69.     (format t "d = ~A~%" d)
  70.     (format t "f = ~A~%" f)
  71.     (format t "d2 = ~A~%" d2)
  72.     (format t "f2 = ~A~%" f2)
  73.     (list (substring s d f) (substring s d2 f2)) ))
  74. (defun get-tokens (s)
  75.   (let ((arr (list))
  76.         (n (length s))
  77.         (x "")
  78.         (c #\Space))
  79.       (loop for i from 0 below n do
  80.           (setf c (aref s i))
  81.           (if (white-char-p c)
  82.               (if (> (length x) 0) (progn
  83.                    (push x arr)
  84.                    (setf x "") )))
  85.           (if (nonwhite-char-p c) (progn
  86.                    (setf x (concatenate 'string x (format nil "~A" c))) ))
  87.       )
  88.       (if (> (length x) 0)
  89.                    (push x arr))
  90.       (reverse arr) ))
  91. (defun doConvert(srcRadix destRadix)
  92.     (let ((line "")
  93.           (cmd "")
  94.           (innerLoop t)
  95.           (srcStr "")
  96.           (destStr ""))
  97.         (format t "~%")
  98.         (printSubMenu srcRadix destRadix)
  99.         (handler-case
  100.           (progn
  101.             (loop while innerLoop do
  102.                 (printSubPrompt)
  103.                 (setf cmd (read-line))
  104.                 (setf cmd (string-trim " " cmd))
  105.                 (if (equal (string-downcase cmd) "main()")
  106.                     (progn
  107.                         (setf innerLoop nil)
  108.                         (return nil) ))
  109.                 (if (or (equal (string-downcase cmd) "exit()") (equal (string-downcase cmd) "quit()"))
  110.                     (quit))
  111.                 (handler-case
  112.                   (progn
  113.                      (parse-integer cmd :radix srcRadix)
  114.                      (setf srcStr (string-upcase cmd))
  115.                      (setf destStr (convertRadix srcStr srcRadix destRadix))
                         (format t "        ( ~A )_~A   --->   ( ~A )_~A~%" srcStr srcRadix destStr destRadix)
  116.                      (format t "~%")
  117.                   )
  118.                  (parse-error (c)
  119.                        (format t "예외상황 발생: ~A" c)
  120.                        (format t "다시 입력하시오,~%~%") )
  121.                )
  122.             )
  123.         ))
  124.     t
  125.     ))
  126. (defun doStart()
  127.     (let ((line "")
  128.           (cmd "")
  129.           (outerLoop t)
  130.           (srcRadix 10)
  131.           (destRadix 10)
  132.           (srcStr "")
  133.           (destStr "")
  134.           (onlyOnce t))
  135.         (handler-case
  136.           (progn
  137.             (loop while outerLoop do
  138.                    (format t "~%")
  139.                    (if (equal onlyOnce t) (progn
  140.                         (format t "  The supported maximum radix is 36.~%")
  141.                         (setf onlyOnce nil)
  142.                         (printMainMenu)
  143.                         (printMainPrompt)
  144.                         (setf cmd (read-line))
  145.                         (setf cmd (string-trim " " cmd))
  146.                         (if (or (equal cmd "q") (equal cmd "Q") (equal cmd "x") (equal cmd "X")) (quit) )
  147.                         (if (or (equal cmd "a") (equal cmd "A")) (progn (printAbout) (setf onlyOnce t)) )
  148.                         (if (or (equal cmd "s") (equal cmd "S")) (progn
  149.                                (format t "  Input the source and target radices (say, 16 2): ")
  150.                                (setf line (read-line))
  151.                                (setf st (get-tokens line))
  152.                                (loop while (not (= (length st) 2)) do
  153.                                    (format t "  Input the source and target radices (say, 16 2): ")
  154.                                    (setf line (read-line))
  155.                                    (setf st (get-tokens line)) )
  156.                                ; (setf srcRadix (parse-integer (nth 0 st) :radix 10))
  157.                                ; (setf destRadix (parse-integer (nth 1 st) :radix 10))
  158.                                (setf srcRadix (safe-parse-integer (nth 0 st)))
  159.                                (setf destRadix (safe-parse-integer (nth 1 st)))
  160.                                (if (and (not (equal srcRadix nil)) (not (equal destRadix nil)))
  161.                                    (progn
  162.                                        (doConvert srcRadix destRadix)
  163.                                        (setf onlyOnce t)
  164.                                    )
  165.                                    (progn
  166.                                        (format t "두 수를 다시 입력하시오.~%")
  167.                                        (setf onlyOnce t)
  168.                                    )
  169.                                )
  170.                         ))
  171.             ))
  172.           )
  173.         ))
  174.     ))
  175. ;; Begin here
  176. (if (and (> (length ext:*args*) 0) (equal (nth 0 ext:*args*) "-h")) (progn
  177.     (printUsage)
  178.     (quit) ))
  179. (doStart)



실행> clisp convertRadix.lsp

  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




Posted by Scripter
,

다음은  이차방정식 x^2 - x - 1  = 0 의 양의 근 즉 황금비율(golden ratio)을 구하는 Common Lisp 애플리케이션 소스이다. 황금비율을 구하는 비례방정식은   1 : x = x : (x+1) 이며, 이를 이차방정식으로 표현한 것이 x^2 - x - 1  = 0 이다.

See:  http://en.wikipedia.org/wiki/Golden_ratio

아래의 소스는 CLisp 으로 테스트되었다.


 

  1. ;;  Filename: testGoldenRatio.lsp
  2. ;;    황금률(즉, 이차방정식 x^2 - x - 1  = 0 의 양의 근)을 계산한다.
  3. ;;
  4. ;;   Execute: clisp testGoldenRatio.lsp
  5. ;;
  6. ;;      Date:  2013. 9. 1.
  7. (defun printUsing()
  8.     (format t "Using: lisp testGoldenRatio.lsp [-h|-help]~%")
  9.     (format t "This calculates the value of the golden ratio.~%")
  10. )
  11. (defun handle-zero-error(msg)
  12.     (catch 'handle-zero-error
  13.       (foprmat t msg)
  14.       (quit)))
  15. ;; 이차방정식 a x^2 + b x + c  = 0 의 근을 구한다.
  16. (defun findQuadraticRoot(a b c)
  17.     (if (zerop a)
  18.         (throw 'fn-a 'done))
  19.     (if (< (- (* b b) (* 4 a c)) 0.0)
  20.         (throw 'fn-a 'done))
  21.     (setf x1 (/ (+ (- b) (sqrt (- (* b b) (* 4 a c)))) (* 2.0 a)))
  22.     (setf x2 (/ (- (- b) (sqrt (- (* b b) (* 4 a c)))) (* 2.0 a)))
  23.     (list x1 x2)
  24. )
  25. ;; 실행 시작 지점
  26. (if (and (> (length ext:*args*) 0) (or (equal (nth 0 ext:*args*) "-h") (equal (nth 0 ext:*args*) "-help"))) (progn
  27.     (printUsing)
  28.     (quit) ))
  29. (setf values (findQuadraticRoot 1.0 (- 1.0) (- 1.0)))
  30. (setf x1 (nth 0 values))
  31. (setf x2 (nth 1 values))
  32. (if (>= x1 x2) (progn
  33.     (format t "The bigger root is ~F, ~%" x1)
  34.     (format t "and the less root is ~F.~%" x2) )
  35.        (progn
  36.     (format t "The bigger root is ~F, ~%" x2)
  37.     (format t "and the less root is ~F.~%" x1) )
  38. )



실행> clisp testGoldenRatio.lsp
The bigger root is 1.618034,
and the less root is -0.618034.



Posted by Scripter
,