LoginSignup
7
1

More than 3 years have passed since last update.

マヤ文明の数字(マヤ数字)を生成する

Last updated at Posted at 2018-09-16

はじめに

今回はマヤ数字についてお話していきます。

マヤ数字とは

(マヤ文字って美しいですよね)
マヤ数字とはマヤ文明で使われていた数字です。

私たちが一般に使っているのは、
10個の記号を使って数字を表す"十進法"ですが
(10個の記号: 0123456789)

マヤ数字
20個の記号を使って数字を表す"二十進法"なんです!
(20個の記号: 𝋠𝋡𝋢𝋤𝋥𝋦𝋧𝋨𝋩𝋪𝋪𝋫𝋬𝋭𝋮𝋯𝋰𝋱𝋲𝋳)
※比較的最新の環境でないと上記のマヤ数字がみられません。

もっと詳細にいうと
"十進法"10 を底とし、底およびその冪を基準にして数を表す方法
"二十進法"20 を底とし、底およびその冪を基準にして数を表す方法
です。

マヤ数字のすごいところは"0"を表す記号があることですね。
古代から数字を発明し、暦の計算に使っていたマヤ人はすごいです。

マヤ数字の0

0

マヤ数字

MayaNumber

横棒は5ずつ増えます。

MayaNumber
MayaNumber

数値からマヤ数字へ変換

MayaGlyph.hpp
#pragma once
#include <iostream>
#include <vector>

namespace maya {

    //通常の数字をマヤ数字に変換する
    template <typename NormalNum, typename MayaNum>
    void mayaNumber(NormalNum num_, std::vector<MayaNum>& maya_num_) {
        //各位の上限値
        constexpr NormalNum num_20 = (NormalNum)20;
        constexpr NormalNum num_18 = (NormalNum)18;
        constexpr NormalNum num_0 = (NormalNum)0;
        //要素を消去
        maya_num_.clear();
        //元の数字が0以下の場合
        if (num_ <= num_0) {
            maya_num_.emplace_back((MayaNum)0);
            return;
        }
        //1桁目を選定 (0~19)
        maya_num_.emplace_back((MayaNum)(num_ % num_20));
        if ((num_ /= num_20) == 0) return;
        //2桁目を選定 (0~17)
        maya_num_.emplace_back((MayaNum)(num_ % num_18));
        if ((num_ /= num_18) == 0) return;
        //3桁目以降を選定 (0~19)
        while (true) {
            maya_num_.emplace_back((MayaNum)(num_ % num_20));
            if ((num_ /= num_20) == 0) return;
        }
    }
    template <typename MayaNum>
    void mayaNumber(const float num_, std::vector<MayaNum>& maya_num_) {
        mayaNumber((unsigned long long)num_, maya_num_);
    }
    template <typename MayaNum>
    void mayaNumber(const double num_, std::vector<MayaNum>& maya_num_) {
        mayaNumber((unsigned long long)num_, maya_num_);
    }
    template <typename MayaNum>
    void mayaNumber(const long double num_, std::vector<MayaNum>& maya_num_) {
        mayaNumber((unsigned long long)num_, maya_num_);
    }
    //マヤ数字を出力する
    template <typename MayaNum>
    void mayaNumberOutput(const std::vector<MayaNum>& maya_num_) {
        for (size_t i = 0; i < maya_num_.size(); ++i)
            std::cout << maya_num_[i] << ',';
    }
    template <>
    void mayaNumberOutput(const std::vector<unsigned char>& maya_num_) {
        for (size_t i = 0; i < maya_num_.size(); ++i)
            std::cout << (int)maya_num_[i] << ',';
    }
    template <>
    void mayaNumberOutput(const std::vector<signed char>& maya_num_) {
        for (size_t i = 0; i < maya_num_.size(); ++i)
            std::cout << (int)maya_num_[i] << ',';
    }
    //通常の数字をマヤ数字に変換して出力する
    template <typename NormalNum, typename MayaNum>
    void mayaNumberOutput(const NormalNum& num_, std::vector<MayaNum>& maya_num_) {
        mayaNumber(num_, maya_num_);
        mayaNumberOutput(maya_num_);
    }
    //通常の数字をマヤ数字に変換して出力する
    template <typename NormalNum>
    void mayaNumberOutput(const NormalNum& num_) {
        std::vector<unsigned char> maya_num_;
        mayaNumber(num_, maya_num_);
        mayaNumberOutput(maya_num_);
    }

}

まずは手始めにプログラミングしてみました。

原理

マヤ数字は20進法なので"mayaNumber()"で20進法へ変換します。
ただし、ここで注意点があります。

マヤ数字の下から2桁目は17までしかありません。
つまり下から2桁目が最上位になる正の数は20~359です。(20~399ではありません)
おそらくこの仕様は暦の計算がしやすくなるよう1年の長さ(365日)に近くなるように
考えられたからではないかと思います。

出力

Source.cpp
#include <MayaGlyph.hpp>

int main() {
    maya::mayaNumberOutput(100);
    return 0;
}
出力結果(元の数字が100の時)
0,5,
出力結果(元の数字が65536の時)
16,0,2,9,

これでデータ上ではマヤ数字の生成ができました!

マヤ数字を画像として出力する

楽に画像を出力するため、DxLibを使用してコードを書いていきます。

Source.cpp
#include <cstdint>
#include <string>
#include <MayaGlyph.hpp>
#include <DxLib.h>

int main()
{
    //マヤ数字を生成
    std::uint64_t num{};
    std::cin >> num;
    std::vector<size_t> maya_num;
    maya::mayaNumber(num, maya_num);
    if (maya_num.size() < 2) return 0;

    DxLib::SetOutApplicationLogValidFlag(0);
    DxLib::ChangeWindowMode(1);
    DxLib::SetGraphMode(1, 1, 32);
    if (DxLib::DxLib_Init() == -1) return -1;

    //数字の画像を読み込む
    constexpr size_t array_num = 20;
    int num_texture[array_num];
    for (size_t i = 0; i < array_num; ++i)
        num_texture[i] = DxLib::LoadGraph(std::string(std::to_string(i) + ".png").c_str(), 1);
    //画像サイズを元に作成する画像のサイズを決める
    int size_x, size_y;
    if (DxLib::GetGraphSize(num_texture[0], &size_x, &size_y) == -1) return -1;
    const int window_size_y = size_y * (int)maya_num.size();
    int screen = DxLib::MakeScreen(size_x, window_size_y, 1);

    DxLib::SetDrawScreen(screen);
    DxLib::ClearDrawScreen();
    for (size_t i = 0; i < maya_num.size(); ++i)
        DxLib::DrawExtendGraph(0, window_size_y - (size_y*(int)i + size_y), size_x, window_size_y - size_y * (int)i, num_texture[maya_num[i]], 1);
    //PNG形式で画像保存
    DxLib::SaveDrawScreenToPNG(0, 0, size_x, size_y*(int)maya_num.size(), std::string(std::to_string(num) + ".png").c_str(), 0);
    //終了処理
    DxLib::DxLib_End();
    return 0;
}

使用例

"100"のマヤ数字

100.png

"360"のマヤ数字

360.png

"65536"のマヤ数字

65536.png

"1000000000000"(1兆)のマヤ数字

1000000000000.png

"10000000000000000"(1京)のマヤ数字

手書きのマヤ数字を出力してみました。

10000000000000000.png

結論

マヤ数字っておもしろい!

ソースコードのライセンス

These codes are licensed under CC0.
CC0

7
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1