たくみん成長日記

開発とか趣味とかラブライブとかラブライブとかラブライブとか

悪魔の数字はごく普通の数字に潜んでるってこと

皆さんこんばんは。関タクミゼイアンです。

悪魔の数字は普通の数字に潜んでるんだよね。みんなはそれを理解しているのかって話。

僕はそれを確かめるためのツールを作っちゃったんだよね。
もうパンドラの箱は開いちゃってるんだよね。

ツールの概要

このツールは、数字を入力することで、その数字が悪魔の数字に変換できるかどうかをを知ることができるんだよね。 悪魔の数字に変換する処理は、以下の二つなんだよね。

  1. 1桁ずつ数値を分解し、すべて加算する。

  2. 1桁ずつ数値を分解し、すべて乗算する。

この2つの処理を繰り返して、悪魔の数字にするってこと。
図にすると、以下のような感じだよね。こんな感じで、悪魔の数字にできる処理を探索していくんだよね。

f:id:takuminv:20180919020158p:plain:w500

ツールの見た目

このツールは、ブラウザ上で動かすことができるんだよね。見た目は、以下の画像の通りなんだよね。 textboxに数字を入力し、変換ボタンを押すか、Enterキーを押すことで、変換が始まるんだよね。 f:id:takuminv:20180919003107p:plain:w500

試しに、123を入力してみるね。結果は、以下の画像の通りなんだよね。123というごく普通の数字も悪魔の数字の6になり得るってこと。

f:id:takuminv:20180919003700p:plain:w500

次は、12345676543を入力してみるね。こんな複雑な数字も悪魔の数字になり得るんだよね。

f:id:takuminv:20180919004125p:plain:w500

こんな感じで、このツールを使えばいつも使っている数字が悪魔の数字になり得るかどうかわかるってこと。

ソースコード

じゃあ次は、ソースコードを見ていくね。このツールは、JavaScriptで作ったんだよね。ライブラリとしてjQueryを使ったんだよね。 CSSはかけないから、Bootstrapを使ったんだよね。htmlは大したことないから、省略するね。

main的な

以下のコードは、main的なやつだよね。変換ボタンをクリックすることでクリックイベントが発火するんだよね。 textboxがフォーカスされているときに、Enterキーを押すことでも、イベントが発火するようにしているよ。

ボタンが押されると、まずは、textboxの値を取得して、数値かどうかを確認するんだよね。 数値じゃなければ、警告を表示するってこと。数値であれば、悪魔の数字への変換が始まるんだよね。

//====================================================================
// window.load
//====================================================================
$(function() {

    //----------------------------------------------------------------
    // textboxでEnterキーを押すことで、クリックイベント発火
    //----------------------------------------------------------------
    $('#number').on('keydown', function(e) {

        if (e.which == 13) {
        $('#button').trigger('click');
    }
    });

    //----------------------------------------------------------------
    // 変換ボタンを押すことで、悪魔の数字変換開始
    //----------------------------------------------------------------
    $("#button").click( function () {

        result_text = [];
        akuma_view_init();  // 結果表示要素を初期化
        number = $("#number").val(); // textboxの値を取得
        if(isNaN(number)){ // 値が数値がどうか
            not_number(); // 数値でないなら警告を表示
            return ;
        }
        if (number < 0) { // 数値が負数かどうか
            var chart_data = akuma_number_frequency(number*-1); // 0からnumberまでの悪魔の数字の頻度を求める
            chart_view(chart_data[0], chart_data[1], chart_data[2]); // 円グラフとして表示
        } else { 
            var viewcode = akuma_number(number, result_text); // 悪魔の数字に変換
            view_check_img(viewcode, result_text); // 結果を表示
        } 
    });
});

悪魔の数字に変換するakuma_number()

次は、悪魔の数字に変換するfunctionのakuma_numberを見ていくね。まず初めに、悪魔の数字かどうかチェックするんだよね。 これにより、入力された数値が悪魔の数字ならすぐに結果を表示できるってこと。 悪魔の数字じゃなければ、変換処理が始まるんだよね。 すべて加算する処理1を最初に行って、それでも変換できなければ処理2を行うってこと。

//--------------------------------------------------------------------
// 入力された数字をなんとか悪魔の数字にする
//--------------------------------------------------------------------
function akuma_number(number, result_text) {
    
    var check = check_akumanumber(number, result_text);  // 悪魔の数字かどうかチェック

    if ( check != 0 ) {return check;}
    var result = add_1(number, result_text,0);  // 処理1 すべて加算
    if ( result != 0 ) {return result;}  
    var result = mult_1(number, result_text,0); // 処理2 すべて乗算 
    if ( result != 0 ) {return result;} 
    return 0;
}

処理1のadd_1()と処理2のmult_1()

じゃあ、処理1のadd_1と処理2のmult_1を個別にみていくね。 このadd_1とmult_1は相互再帰を行ってるんだよね。 計算して、悪魔の数字なら終了、それ以外なら、再帰を使ってさらに探索するんだよね。 add_1とmult_1の違いは、計算が加算か、乗算かだけなんだよね。 すごい冗長のにおいがするけど気にしちゃだめなんだよね。

//--------------------------------------------------------------------
// 数字を1桁ずつ分解し、すべて足す (mult_1と相互再帰)
//--------------------------------------------------------------------
function add_1(number, result_text,c) {

    var num = [];
    if (parseInt(number/10) == 0 && (number != 6 || number != 9)) {return 0;} // 1桁になって悪魔の数字じゃなければ失敗

    num = numarray_split(number);  // 数値を1桁ずつ分解
    sum = num.reduce((s, n) => s + n, 0); // すべて加算
    result_text[c] = array_value_text(num, sum,"+"); // 計算過程の文字列を作成
    
    var check = check_akumanumber(sum, result_text);  // 悪魔の数字かどうかチェック
    if ( check != 0 ) {return check;}  // 悪魔の数字なら終了

    var result = add_1(sum, result_text,c+1);  // さらに、処理1を実行(再帰)
    if ( result != 0 ) {return result;} else {result_text.splice(c, 1);}
    
    var result = mult_1(sum, result_text,c+1); // 処理2を実行(相互再帰)
    if ( result != 0 ) {return result;} else {result_text.splice(c, 1);}

    return 0;
}
//--------------------------------------------------------------------
// 数字を1桁ずつ分解し、すべてかける (add_1と相互再帰)
//--------------------------------------------------------------------
function mult_1(number, result_text,c) {

    var num = [];
    if (parseInt(number/10) == 0 && (number != 6 || number != 9)) {return 0;}  // 1桁になって悪魔の数字じゃなければ失敗

    num = numarray_split(number); // 数値を1桁ずつ分解
    sum = num.reduce((s, n) => s * n, 1); // すべて乗算
    result_text[c] = array_value_text(num, sum,"×"); // 計算過程の文字列を作成
    
    var check = check_akumanumber(sum, result_text); // 悪魔の数字かどうかチェック
    if ( check != 0 ) {return check;} // 悪魔の数字なら終了
    
    var result = add_1(sum, result_text,c+1); // 処理1を実行(相互再帰)
    if ( result != 0 ) {return result;} else {result_text.splice(c, 1);}
    
    var result = mult_1(sum, result_text,c+1); // 処理2を実行(再帰)
    if ( result != 0 ) {return result;} else {result_text.splice(c, 1);}

    return 0;
}

悪魔の数字かどうかチェックするcheck_akumanumber()

最後に、悪魔の数字かどうかチェックするfunctionを見ていくね。 悪魔の数字かどうか判定する前に、18を666、27を999に変換、9を6、999を666に変換しているよ。 18は6+6+6、27は9+9+9だから悪魔の数字と同じ扱いなんだよね。9や999は反転させることで、6や666になるから、これも悪魔の数字になり得るってこと。 悪魔の数字6、666、それ以外の3パターンで、返却値を変えているんだよね。この返却値によってどの画像を表示するのか決定するってこと。

//--------------------------------------------------------------------
// 悪魔の数字になっているかチェック
//--------------------------------------------------------------------
function check_akumanumber(number, result_text) {

    number = check_extra_akumanumber(number, result_text);  // 18を666、27を999に変換
    number = check_reverse_akumanumber(number,result_text); // 9を6、999を666に変換

    if (number == 6) { // 悪魔の数字かどうか
        return 1;
    } else if (number == 666) {
        return 2;
    } else {
        return 0;
    }
}

それ以外のfunction

これ以外の、functionはほとんど結果を表示するためのものなんだよね。 htmlに要素を追加しているだけだから省略するってこと。

隠された機能

実は、このツールには隠された機能があるんだよね。 textboxに負数を入れることでその機能を使えるんだよね。 その機能とは、0から任意の数値(入力した負数の絶対値)の範囲でどれだけの数値が悪魔の数字になれるかを円グラフで表示する機能なんだよね。
試しに、-10000と入力してみるね。この場合だと、0から10000の範囲で、円グラフを表示するんだよね、小さいからちょっと見にくいけど、半分以上の数値が悪魔の数字になってるんだよね。 もうこれ完全に来ちゃってるよね。これはもうすごいことだよね。ヤバタクスゼイアンだよね。パンドラの箱は開いちゃったってこと。

f:id:takuminv:20180919013903p:plain:w500

おわりに

数字に隠された真実、私は点を置いただけ。それをつなげるのは皆さんですからね。信じるか信じないかはあなた次第です。