世界のナベアツをプログラミングで グラフで可視化(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 実行例
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 実行例
なぜかラベルが出てこないです。。。
5.誤り
プログラミングで変数を大文字してはだめみたいです。(マクロ定数をはっきり判断できる)
つまり、Nを入力変数としてダメ。
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()