世界のナベアツをプログラミングで       グラフで可視化(python)

(個人用)


1.世界ナベアツとは

3の倍数および3がつく数でアホになるという。
始めてこういうネタ知りました。(なぜこんなものがあるんだ)

2.目的

2-1   入門

3の倍数および3がつく数でアホになる「世界のナベアツ」をシミュレートするプログラムを書きます。

入力された整数Nに対し、1~Nまでカウントアップしながら「アホになる数」で「アホ」と表示させます。

例:
1
2
3 アホ
4
5
6 アホ
7
(略)
12 アホ
13 アホ
14
15 アホ

2-2   応用

 入力された整数Nに対し、1~Nまでのうち「アホになる数」の割合を算出する(可能ならグラフに描くなど可視化する)

3.アルゴリズム

まずは考えなきゃいけないのは、どのように実現したいかを以下で考えています。

問題を部分に分けて考えたい。

3-1  3の倍数と一の位の数は3の場合
3-2  残りの位の数は3の場合(3の倍数を除く)

3-1 3の倍数と一の位の数は3の場合

これは簡単だ

つまり、N(入力値)に対して、割り算したら、余りが0     と 余りは3

N/3 = 商 ・・・0   (商は不明)
N/10 = 商 ・・・3   (商は不明)

C言語:

if(N%3==0  ||  number%10){

   printf("aho\n");

}

python:

if number % 3 == 0 or number % 10 == 3:   
   
   print(" アホ")

できた。


補足:なぜ一の位の数は3の場合を含めているかという指摘がありました。

回答:

入力値が大きい場合、一の位の数は3を判断できれば、計算を楽にできます。(例えば、33333,34333)

3-2: 残りの位の数は3の場合(3の倍数を除く)

2の位の数~Nの位の数を調べる必要があります。(3かどうか)

まず桁数を調べます。
なぜかというと、

3-1で、N/10 = 商 ・・・3   (商は不明)
つまり、N/10をN-1回で調べられますためだ。

ループ使えば、調べられます。(ここでは、関数の形で)

C言語:

int numbers(int N)
{
    while (N != 0)
    {
        N /= 10;
        ++digit;
    }
}

python:

def numbers(N):
    global digit
    while N != 0:
        N //= 10
        digit += 1


digitはグローバル変数であり、桁数を表しています。


3-3 注意してほしい

3-1と3-2の場合では、重複する場合があります。つまり、3の倍数を除なければならなりません。

3-4    解決策

どうやって解決するかというと、3-1で、もしすでに、ahoになったら、3-2の実行を止める仕組みになればよいです。
(ヒント:break/continue)

3-5    実行例

図1,実行例

4.応用

可視化、つまり、グラフで表示させたい。
ここでは、二つの線グラフを表示させたい。
(グラフの表示では、別のアプリが必要みたいで、c言語を省略する。)

4-1   Nの変化より、アホの数
4-2   N変化により、アホの割合

4-1   アホの数

数を計算するために、1-Nの間に、一つずつ当たりのアホの数を記憶すればよいです。

3-1,3-2では、すでに、1-Nの間、アホを表示させるため、if文の中のprintで表示しているため、その下に、ある変数(plus)を一個ずつ足し算しすると、最後の結果はN個当たりのアホの数を占めます。

例えば、

numbers(N)=14, numbers(aho)=5

この5は最後の結果であり、何回も足しています。

つまり、途中で、一回止めて、メモすると、一個一個の値

(numbers(N),numbers(aho))が与えられています。

一個一個メモすればよいです。

このデータを保存するために、配列(aho_list)を利用します。

以下はコードとなります。

aho_list = []   #定義なし
#...中略

#3-1の場合

    if number % 3 == 0 or number % 10 == 3:
      print(" アホ")
      plus += 1       #ahoの数をメモしていく
      aho_list.append(plus)    #配列に保存
      continue


4-2  アホの割合


4-1でメモした値を1~Nで割り算して、一個一個のデータになります。

割合=アホの数/入力値
(height1は二つ目のグラフの縦軸である)

height1 = [value / i for i, value in enumerate(aho_list, start=1)]

4-3   グラフ表示

グラフ表示のために、ax.plot,plt.plotでできます。

#こっちはplt.plot使うと、なぜか表示できませんので、
以下はコードです。

#横軸のラベルを入力値(なぜかplt.xlabel,ylabelはだめ || 漢字入力はだめかも)
ax.set_xlabel('Input number')
#縦軸のラベルをアホの数
ax.set_ylabel('aho number')
plt.show()

height1 = [value / i for i, value in enumerate(aho_list, start=1)]
#アホの割合を縦軸、1~Nまでを横軸
plt.plot(left,height1,color='c')
#横軸のラベルを入力値(なぜか表示されてない)
ax.set_xlabel('Input number')
#縦軸のラベルをアホの割合
ax.set_ylabel('aho ratio')
plt.show()

ああ、最後にplt.show入力しないと、変な英語がいっぱい出てます。

4-4  実行例


図2,横軸は入力値、縦軸はahoの数


図3,横軸は入力値,縦軸はahoの割合

なぜかラベルが出てこないです。。。

5.誤り

プログラミングで変数を大文字してはだめみたいです。(マクロ定数をはっきり判断できる)

つまり、Nを入力変数としてダメ。

図4,「プログラミングを上達するために」
(https://www.cc.kyoto-su.ac.jp/~yamada/ap/advance.html)

6.コード

import numpy as np
import matplotlib.pyplot as plt


aho_list = []
def numbers(N):
    global digit
    while N != 0:
        N //= 10
        digit += 1

digit = 0
plus = 0
fig, ax = plt.subplots()
N = int(input("どこまでの数を表示したいですか:"))
numbers(N)

for number in range(1, N +1):
    print(number, end='')
    if number % 3 == 0 or number % 10 == 3:
      print(" アホ")
      plus += 1
      aho_list.append(plus)
      continue


    else:
      x = number // 10
      for _ in range(digit):
          d = x % 10
          if d == 3:
            print(" アホ", end='')
            plus += 1
            break
          x //= 10
      aho_list.append(plus)
    print()

print("アホになる割合は{:.2f}%です。".format(plus * 100 / N))
left = list(range(1, N + 1))
height = aho_list
#アホの数を縦軸、1~Nを横軸
ax.plot(left,height,color='r')

#横軸のラベルを入力値(なぜかplt.xlabel,ylabelはだめ || 漢字入力はだめかも)
ax.set_xlabel('Input number')
#縦軸のラベルをアホの数
ax.set_ylabel('aho number')
plt.show()

height1 = [value / i for i, value in enumerate(aho_list, start=1)]
#アホの割合を縦軸、1~Nまでを横軸
plt.plot(left,height1,color='c')
#横軸のラベルを入力値(なぜか表示されてない)
ax.set_xlabel('Input number')
#縦軸のラベルをアホの割合
ax.set_ylabel('aho ratio')
plt.show()

この記事が気に入ったらサポートをしてみませんか?