콘솔에 삼각형

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


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

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

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


삼각형 출력 예제 1
##  Filename: printTriangle1.jl
##            Print a triangle on console.
##
##  Execute: julia printTriangle1.jl
##
##      Date:  2013. 3. 5.
##    Author:  pkim __AT__ scripts ((DOT)) pe ((DOT)) kr

function printTriange()
    println("        *        ")
    println("       * *       ")
    println("      *   *      ")
    println("     *     *     ")
    println("    *       *    ")
    println("   *         *   ")
    println("  *           *  ")
    println(" *             * ")
    println("*****************")
end

printTriange()




위의 소스 코드는 아무 알고리즘도 없는 너무 단순한 코드이다. 이런 코드를 작성했다간 출력 모양이나 크기를 변경해야 하는 상황을 맞이하면 워드프로세서로 문서 만드는 것 이상으로 많은 수작업을 하거나 아니면 포기하는 지경에 이를 수도 있다. 그래서 다음 처럼 좀 더 나은 소스 코드를 작성하였다. Julia 언어의 출력 함수 print 와 prinln 을 적절히 섞어 구현하였다.


삼각형 출력 예제 2
##  Filename: printTriangle2.jl
##            Print a triangle on console.
##
##  Execute: julia printTriangle2.jl
##
##      Date:  2013. 3. 5.
##    Author:  pkim __AT__ scripts ((DOT)) pe ((DOT)) kr

function printTriange()
    for i = 0:7
        for k = 1:8-i
            print(" ")
        end
        for k = 1:2*i+2
            if k == 1 || k == 2*i+1
                print("*")
            else
                print(" ")
            end
        end
        for k = 1:8-i
            write(" ")
        end
        println("")
    end

    for i = 1:17
        print("*")
    end
    println("")
end

printTriange()



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

        whites = [" " for i =1:17]

이다. (이 구문은 Python 언어의 [" "]*17 에 해당한다.)



삼각형 출력 예제 3
##  Filename: printTriangle3.jl
##            Print a triangle on console.
##
##  Execute: julia printTriangle3.jl
##
##      Date:  2013. 3. 5.
##    Author:  pkim __AT__ scripts ((DOT)) pe ((DOT)) kr

function printTriange()
    line2 = [" " for i =1:17]
    for i = 0:7
        line2 = [" " for i =1:17]
        line2[8-i+1] =  "*"
        line2[8+i+1] =  "*"
        println(join(line2, ""))
    end

    line2 = ["*" for i =1:17]
    for i = 1:17
        line2[i] =  "*"
    end
    println(join(line2, ""))
end

printTriange()




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

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

은 지정된 개수(여기서는 17) 만큼 string을 중복 연결하는 구문이다.  (string^number 구문은 구문은 Groovy, Ruby, Python 언어의 string*number 에 해당한다.) 이들은 Julia 언어에서

        whites = repeat(" ", 17)
        stars = repeat("* ", 17)

로 작성해도 같은 의미이다.



삼각형 출력 예제 4
##  Filename: printTriangle4.jl
##            Print a triangle on console.
##
##  Execute: julia printTriangle4.jl
##
##      Date:  2013. 3. 5.
##    Author:  pkim __AT__ scripts ((DOT)) pe ((DOT)) kr

function printTriange()
    whites = " "^17
    stars  = "*"^17
    line2 = "$(whites[1:8])*$(whites[1:8])"
    println(line2)
    for i = 1:7
        line2 = "$(whites[1:8-i])*$(whites[8-i:7+i-1])*$(whites[7+i:])"
        println(line2)
    end
    println(stars)
end

printTriange()




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

    join(line2, "")

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



삼각형 출력 예제 5
##  Filename: printTriangle5.jl
##            Print a triangle on console.
##
##  Execute: julia printTriangle5.jl
##
##      Date:  2013. 3. 5.
##    Author:  pkim __AT__ scripts ((DOT)) pe ((DOT)) kr

function printTriange()
    whites = " "^17
    stars  = "*"^17
    start = 8
    line2 = [" " for i = 1:17]
    line2[start + 1] = "*"
    println(join(line2, ""))
    for i = 1:7
        line2 = [" " for i = 1:17]
        line2[start - i + 1] = stars[start - i + 1:start - i + 1]
        line2[start + i+ 1] = stars[start + i + 1:start + i + 1]
        println(join(line2, ""))
    end
    println(stars)
end

printTriange()




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



삼각형 출력 예제 6
##  Filename: printTriangle6.jl
##            Print a triangle on console.
##
##  Execute: julia printTriangle6.jl
##
##      Date:  2013. 3. 5.
##    Author:  pkim __AT__ scripts ((DOT)) pe ((DOT)) kr

function printTriange()
    whites = " "^8
    stars  = "*"^8
    start = 8
    line = whites * '*' * whites
    println(line)
    for i = 1:7
        n = length(whites)
        line = whites[1:n-i] * "*" * whites[n-i+1:n-1]
        println(line * " " * reverse(line))
    end
    line = stars * '*' * stars
    println(line)
end

printTriange()




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



삼각형 출력 예제 7
##  Filename: printTriangle7.jl
##            Print a triangle on console.
##
##  Execute: julia printTriangle7.jl
##
##      Date:  2013. 3. 5.
##    Author:  pkim __AT__ scripts ((DOT)) pe ((DOT)) kr

BASE36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

function itoa(num, radix)
   isNegative = false
   if num < 0
      isNegative = true
      num = -num
   end

   arr = ""
   q, r = num, 0
   while q >= radix
      # q, r = divmod(q, radix)
      r = mod(q, radix)
      q = div(q, radix)
      arr *= BASE36[r+1]
   end

   arr *= BASE36[q + 1]
   if isNegative
      arr *= "-"
   end

   return reverse(arr)
end


function printTriange()
    start = int(0x100) :: Int32
    total = 0
    val = start
    data = ""
    for k = 0:7
        val = (start << k) | (start >> k)
        data = itoa(val, 2)
        s = ""
        for i = 1:17 - length(data)
            s *= " "
        end
        for i = 1:length(data)
            if data[i] == '0'
                s *= " "
            else
                s *= "*"
            end
        end
        println(s)
        total += val
    end

    val = (start << 8) | (start >> 8)
    ## val = (1 << 16) | (start >> 8)
    total += val
    data = itoa(total, 2)
    s = ""
    for i = 1:length(data)
        if data[i] == '0'
            s *= " "
        else
            s *= "*"
        end
    end
    println(s)
end

printTriange()




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

            total |= val

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



삼각형 출력 예제 8
##  Filename: printTriangle8.jl
##            Print a triangle on console.
##
##  Execute: julia printTriangle8.jl
##
##      Date:  2013. 3. 5.
##    Author:  pkim __AT__ scripts ((DOT)) pe ((DOT)) kr

BASE36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

function itoa(num, radix)
   isNegative = false
   if num < 0
      isNegative = true
      num = -num
   end

   arr = ""
   q, r = num, 0
   while q >= radix
      # q, r = divmod(q, radix)
      r = mod(q, radix)
      q = div(q, radix)
      arr *= BASE36[r+1]
   end

   arr *= BASE36[q + 1]
   if isNegative
      arr *= "-"
   end

   return reverse(arr)
end


function printTriange()
    zeros  = "00000000"
    start = int(0x100) :: Int32
    total = 0
    val = start
    line = ""
    data = ""
    for k = 0:7
        val = (start << k) | (start >> k)
        data = itoa(val, 2)
        line = zeros[1:17-length(data)] * data
        line = replace(line, "0", " ")
        line = replace(line, "1", "*")
        println(line)
        total |= val
    end

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

printTriange()




소스 코드가 처음 것 보다 매우 복잡해졌지만, Julia 안어의 배열을 이용해서 구현해 보았다. 별(*) 문자만으로 구성된 마지막 줄 출력을 위해 배열 타입의 변수 last를 준비하였다. 또 배열에 속한 모든 item을 출력하는 Julia 코드

        printon(join(data, ""))

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



삼각형 출력 예제 9
##  Filename: printTriangle9.jl
##            Print a triangle on console.
##
##  Execute: julia printTriangle9.jl
##
##      Date:  2013. 3. 5.
##    Author:  pkim __AT__ scripts ((DOT)) pe ((DOT)) kr

function printTriange()
    start = 8
    data = [" " for i = 1:17]
    last = [" " for i = 1:17]

    data[start + 1] = "*"
    last[start + 1] = "*"
    println(join(data, ""))
    data[start + 1] = " "

    for k = 1:7
        data[start - k + 1] = "*"
        last[start - k + 1] = "*"
        data[start + k + 1] = "*"
        last[start + k + 1] = "*"
        println(join(data, ""))
        data[start - k + 1] = " "
        data[start + k + 1] = " "
    end

    last[start - 8 + 1] = "*"
    last[start + 8 + 1] = "*"
    println(join(last, ""))
end

printTriange()




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

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

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



삼각형 출력 예제 10
##  Filename: printTriangle10.jl
##            Print a triangle on console.
##
##  Execute: julia printTriangle10.jl
##
##      Date:  2013. 3. 5.
##    Author:  pkim __AT__ scripts ((DOT)) pe ((DOT)) kr

function printTriange()
    for y = 0:8
        for x = 0:16
            if (x + y - 8 == 0) || (y - x + 8 == 0) || (y - 8 == 0)
                a = "*"
            else
                a = " "
            end
            print(a)
        end
        println("")
    end
end

printTriange()




Posted by Scripter
,