Rebol3 Code Examplex


Mayan numerals

Represent numbers using the Mayan numeral system.

Rebol [
    title: "Rosetta code: Mayan numerals"
    file:  %Mayan_numerals.r3
    url:   https://rosettacode.org/wiki/Mayan_numerals
]

to-mayan: function/with [
    "Converts a decimal integer to its Mayan numeral representation as a string."
    number [integer!]
][
    vigs: dec2vig number                 ;; break number into vigesimal (base-20) digits
    mayans: map-each v vigs [vig2quin v] ;; convert each digit to a 4-row glyph
    draw mayans                          ;; render glyphs into a bordered string
][
    ;; Dot patterns for values 0–4 (index 1–5); used as the "ones" row of a glyph
    mayan: [
        "    "
        " ∙  "
        " ∙∙ "
        "∙∙∙ "
        "∙∙∙∙"
    ]
    m0: " Θ  "                           ;; special glyph for zero
    m5: "────"                           ;; horizontal bar representing five

    ;; Decomposes n into a block of base-20 digits, most-significant first.
    dec2vig: function [n [integer!]] [
        digits: copy []
        if n = 0 [return [0]]            ;; zero is a single digit: 0
        while [n > 0] [
            insert digits (n // 20)      ;; prepend the least-significant digit
            n: to integer! (n / 20)      ;; shift right in base 20
        ]
        digits
    ]
    ; Converts a single vigesimal digit (0–19) into a 4-element block of strings.
    ; Each element is one row of the glyph, top to bottom.
    vig2quin: function [n [integer!]] [
        if n >= 20 [do make error! "Can't convert a number >= 20"]
        res: reduce [mayan/1 mayan/1 mayan/1 mayan/1] ;; start with four blank rows
        if n == 0 [res/4: m0  return res]             ;; zero gets the shell glyph
        fives: to integer! (n / 5)       ;; number of five-bars needed (0–3)
        rem: n // 5                      ;; remaining dots above the bars (0–4)
        res/(4 - fives): mayan/(rem + 1) ;; place dot row just above the bars
        repeat i fives [
            res/(4 - fives + i): m5      ;; fill lower rows with five-bars
        ]
        res
    ]
    ;; Renders a block of glyphs into a single box-drawn string.
    ;; Each glyph is a 4-element block of fixed-width strings (one row each).
    draw: function/with [mayans [block!]] [
        lm: length? mayans
        out: copy ""
        emit ul
        repeat i lm [
            repeat j 4 [emit hb]
            emit either i < lm [uc][ur]
        ]
        repeat i 4 [
            emit vb
            repeat j lm [
                emit mayans/:j/:i
                emit vb
            ]
            emit LF
        ]
        emit ll
        repeat i lm [
            repeat j 4 [emit hb]
            emit either i < lm [lc][lr]
        ]
    ][  ;; Box-drawing characters; corners/bars include newlines where needed.
        ul: "╔"  uc: "╦"  ur: "╗^/" hb: "═"
        ll: "╚"  lc: "╩"  lr: "╝^/" vb: "║"
        out: none
        emit: func[s][append out s]
    ]
]

numbers: [4005 8017 326205 886205 1081439556]

foreach n numbers [
    print rejoin ["Converting " n " to Mayan:"]
    print to-mayan n
]