Task: Cistercian numerals


C++: #include <array>
#include <iostream>

template<typename T, size_t S>
using FixedSquareGrid = std::array<std::array<T, S>, S>;

struct Cistercian {
public:
    Cistercian() {
        initN();
    }

    Cistercian(int v) {
        initN();
        draw(v);
    }

    Cistercian &operator=(int v) {
        initN();
        draw(v);
    }

    friend std::ostream &operator<<(std::ostream &, const Cistercian &);

private:
    FixedSquareGrid<char, 15> canvas;

    void initN() {
        for (auto &row : canvas) {
            row.fill(' ');
            row[5] = 'x';
        }
    }

    void horizontal(size_t c1, size_t c2, size_t r) {
        for (size_t c = c1; c <= c2; c++) {
            canvas[r][c] = 'x';
        }
    }

    void vertical(size_t r1, size_t r2, size_t c) {
        for (size_t r = r1; r <= r2; r++) {
            canvas[r][c] = 'x';
        }
    }

    void diagd(size_t c1, size_t c2, size_t r) {
        for (size_t c = c1; c <= c2; c++) {
            canvas[r + c - c1][c] = 'x';
        }
    }

    void diagu(size_t c1, size_t c2, size_t r) {
        for (size_t c = c1; c <= c2; c++) {
            canvas[r - c + c1][c] = 'x';
        }
    }

    void drawOnes(int v) {
        switch (v) {
        case 1:
            horizontal(6, 10, 0);
            break;
        case 2:
            horizontal(6, 10, 4);
            break;
        case 3:
            diagd(6, 10, 0);
            break;
        case 4:
            diagu(6, 10, 4);
            break;
        case 5:
            drawOnes(1);
            drawOnes(4);
            break;
        case 6:
            vertical(0, 4, 10);
            break;
        case 7:
            drawOnes(1);
            drawOnes(6);
            break;
        case 8:
            drawOnes(2);
            drawOnes(6);
            break;
        case 9:
            drawOnes(1);
            drawOnes(8);
            break;
        default:
            break;
        }
    }

    void drawTens(int v) {
        switch (v) {
        case 1:
            horizontal(0, 4, 0);
            break;
        case 2:
            horizontal(0, 4, 4);
            break;
        case 3:
            diagu(0, 4, 4);
            break;
        case 4:
            diagd(0, 4, 0);
            break;
        case 5:
            drawTens(1);
            drawTens(4);
            break;
        case 6:
            vertical(0, 4, 0);
            break;
        case 7:
            drawTens(1);
            drawTens(6);
            break;
        case 8:
            drawTens(2);
            drawTens(6);
            break;
        case 9:
            drawTens(1);
            drawTens(8);
            break;
        default:
            break;
        }
    }

    void drawHundreds(int hundreds) {
        switch (hundreds) {
        case 1:
            horizontal(6, 10, 14);
            break;
        case 2:
            horizontal(6, 10, 10);
            break;
        case 3:
            diagu(6, 10, 14);
            break;
        case 4:
            diagd(6, 10, 10);
            break;
        case 5:
            drawHundreds(1);
            drawHundreds(4);
            break;
        case 6:
            vertical(10, 14, 10);
            break;
        case 7:
            drawHundreds(1);
            drawHundreds(6);
            break;
        case 8:
            drawHundreds(2);
            drawHundreds(6);
            break;
        case 9:
            drawHundreds(1);
            drawHundreds(8);
            break;
        default:
            break;
        }
    }

    void drawThousands(int thousands) {
        switch (thousands) {
        case 1:
            horizontal(0, 4, 14);
            break;
        case 2:
            horizontal(0, 4, 10);
            break;
        case 3:
            diagd(0, 4, 10);
            break;
        case 4:
            diagu(0, 4, 14);
            break;
        case 5:
            drawThousands(1);
            drawThousands(4);
            break;
        case 6:
            vertical(10, 14, 0);
            break;
        case 7:
            drawThousands(1);
            drawThousands(6);
            break;
        case 8:
            drawThousands(2);
            drawThousands(6);
            break;
        case 9:
            drawThousands(1);
            drawThousands(8);
            break;
        default:
            break;
        }
    }

    void draw(int v) {
        int thousands = v / 1000;
        v %= 1000;

        int hundreds = v / 100;
        v %= 100;

        int tens = v / 10;
        int ones = v % 10;

        if (thousands > 0) {
            drawThousands(thousands);
        }
        if (hundreds > 0) {
            drawHundreds(hundreds);
        }
        if (tens > 0) {
            drawTens(tens);
        }
        if (ones > 0) {
            drawOnes(ones);
        }
    }
};

std::ostream &operator<<(std::ostream &os, const Cistercian &c) {
    for (auto &row : c.canvas) {
        for (auto cell : row) {
            os << cell;
        }
        os << '\n';
    }
    return os;
}

int main() {
    for (auto number : { 0, 1, 20, 300, 4000, 5555, 6789, 9999 }) {
        std::cout << number << ":\n";

        Cistercian c(number);
        std::cout << c << '\n';
    }

    return 0;
}



Go: package main

import "fmt"

var n = make([][]string, 15)

func initN() {
    for i := 0; i < 15; i++ {
        n[i] = make([]string, 11)
        for j := 0; j < 11; j++ {
            n[i][j] = " "
        }
        n[i][5] = "x"
    }
}

func horiz(c1, c2, r int) {
    for c := c1; c <= c2; c++ {
        n[r][c] = "x"
    }
}

func verti(r1, r2, c int) {
    for r := r1; r <= r2; r++ {
        n[r][c] = "x"
    }
}

func diagd(c1, c2, r int) {
    for c := c1; c <= c2; c++ {
        n[r+c-c1][c] = "x"
    }
}

func diagu(c1, c2, r int) {
    for c := c1; c <= c2; c++ {
        n[r-c+c1][c] = "x"
    }
}

var draw map[int]func() 

func initDraw() {
    draw = map[int]func(){
        1: func() { horiz(6, 10, 0) },
        2: func() { horiz(6, 10, 4) },
        3: func() { diagd(6, 10, 0) },
        4: func() { diagu(6, 10, 4) },
        5: func() { draw[1](); draw[4]() },
        6: func() { verti(0, 4, 10) },
        7: func() { draw[1](); draw[6]() },
        8: func() { draw[2](); draw[6]() },
        9: func() { draw[1](); draw[8]() },

        10: func() { horiz(0, 4, 0) },
        20: func() { horiz(0, 4, 4) },
        30: func() { diagu(0, 4, 4) },
        40: func() { diagd(0, 4, 0) },
        50: func() { draw[10](); draw[40]() },
        60: func() { verti(0, 4, 0) },
        70: func() { draw[10](); draw[60]() },
        80: func() { draw[20](); draw[60]() },
        90: func() { draw[10](); draw[80]() },

        100: func() { horiz(6, 10, 14) },
        200: func() { horiz(6, 10, 10) },
        300: func() { diagu(6, 10, 14) },
        400: func() { diagd(6, 10, 10) },
        500: func() { draw[100](); draw[400]() },
        600: func() { verti(10, 14, 10) },
        700: func() { draw[100](); draw[600]() },
        800: func() { draw[200](); draw[600]() },
        900: func() { draw[100](); draw[800]() },

        1000: func() { horiz(0, 4, 14) },
        2000: func() { horiz(0, 4, 10) },
        3000: func() { diagd(0, 4, 10) },
        4000: func() { diagu(0, 4, 14) },
        5000: func() { draw[1000](); draw[4000]() },
        6000: func() { verti(10, 14, 0) },
        7000: func() { draw[1000](); draw[6000]() },
        8000: func() { draw[2000](); draw[6000]() },
        9000: func() { draw[1000](); draw[8000]() },
    }
}

func printNumeral() {
    for i := 0; i < 15; i++ {
        for j := 0; j < 11; j++ {
            fmt.Printf("%s ", n[i][j])
        }
        fmt.Println()
    }
    fmt.Println()
}

func main() {
    initDraw()
    numbers := []int{0, 1, 20, 300, 4000, 5555, 6789, 9999}
    for _, number := range numbers {
        initN()
        fmt.Printf("%d:\n", number)
        thousands := number / 1000
        number %= 1000
        hundreds := number / 100
        number %= 100
        tens := number / 10
        ones := number % 10
        if thousands > 0 {
            draw[thousands*1000]()
        }
        if hundreds > 0 {
            draw[hundreds*100]()
        }
        if tens > 0 {
            draw[tens*10]()
        }
        if ones > 0 {
            draw[ones]()
        }
        printNumeral()
    }
}