スクリプト2(どこでもまとめ計算)
このページはマス旅の一部です。
PCがあればすぐできる「スクリプト」を使った数学を考えましょう。
今回は、PCで則プログラミングできる使い方をさぐる、「どこでもまとめ計算」。
1.どこでもまとめ計算
WindowsのコマンドプロンプトやLinuxのターミナルにも、プログラミング言語レベルの構文(繰り返し処理など)があることはあまり知られていません。
Chromebookでもメニューで選ぶだけでLinux環境が入ります。
Windows(PowerShell)を略して PS
Linux(LinuxのTerminalのbash)を略して BS とかきます。
プロンプトのあとに入力データを書いています。
出力は [OUT] からの行です。
// からはコメント行です。
変数を使って反復計算
メッセージなどがうっとうしかったら clear で画面をきれいにします。
<for文が使える>
//BS
for i in {1..5}; do echo "回数: $i" ; done
[OUT]
回数: 1
回数: 2
回数: 3
回数: 4
回数: 5
//「; do ... ; done」がブロックの区切り(他言語の { ... } の代わり)ですね。
//for item in items の構文が使えて、変数指定で出力できるので、簡単なプログラミングが組めそうです。
//PS
//PSは foreach を使い、変数名に $ をつけます。こちらは普通に中カッコ { } でブロック化できます。
foreach ($i in 1..5) { Write-Output "回数: $i" }
[OUT]
回数: 1
回数: 2
回数: 3
回数: 4
回数: 5
ただ連番を出力するだけでなく、計算処理を組み込めば大量の計算を一瞬でまとめて行えますね。ワクワクしてきます。
<Sum(総和)>
//BS
//sum=0 で初期化し、ループ内で sum+=i を実行します。
//途中は表示せず、最後に echo $sum で結果を出力します。
sum=0; for i in {1..10}; do ((sum+=i)); done; echo $sum
[OUT] 55
//PS
//変数には常に $ をつけます。最後に $sum とだけ書けば内容が表示されます。
$sum=0; foreach ($i in 1..10) {$sum += $i };$sum
[OUT] 55
※PSは記述ミスをしたときのエラー表示が真っ赤な文字で強烈です。タイピングには注意しましょう!
<Product(総乗・階乗)>
//product=1 で初期化し、加算を乗算(*=)に変更します。
//BS
product=1; for i in {1..10}; do ((product*=i)); done; echo $product
[OUT] 3628800
//PS
$product=1; foreach ($i in 1..10) {$product *= $i };$product
[OUT] 3628800
<九九の表(2重ループ)>
今度は for を入れ子にして、九九の表を出力してみましょう。
//BS
for i in {1..9}; do for j in {1..9}; do echo -n "$((i*j)) "; done; echo ""; done
[OUT]
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
//記号が増えてセミコロンだらけですね。
//「; do」がPythonの「:」や他言語の「{」にあたり、「; done」が「}」に相当します。
//echo -n は「改行なし出力」、最後の echo "" は「改行のみ」の処理です。
//PS
//PSでは文字出力に Write-Host を使い、改行なし指定は -NoNewline にします。
foreach ($i in 1..9) { foreach ($j in 1..9) { Write-Host "$($i * $j) " -NoNewline }; Write-Host "" }
[OUT]
(九九表が出力される)
<平方数の表>
九九表のアレンジで、$(10i + j)^2$ ($i$ は 1〜9、$j$ は 0〜9)の表を作ってみましょう。
//BS
for i in {1..9}; do for j in {0..9}; do echo -n "$(((10*i+j)**2)),"; done; echo ""; done
//PS
foreach ($i in 1..9) { foreach ($j in 0..9) { Write-Host "$([Math]::Pow(10*$i+$j,2))," -NoNewline }; Write-Host "" }
[OUT]
100,121,144,169,196,225,256,289,324,361,
400,441,484,529,576,625,676,729,784,841,
...
8100,8281,8464,8649,8836,9025,9216,9409,9604,9801,
<小数の平方数表>
さらにアレンジして、$\frac{(10i+j)^2}{100}$ を計算し、桁を揃えてきれいに出力してみます。
//BS
//桁揃えに printf を使用します。
for i in {1..9}; do for j in {0..9}; do num=$(echo "scale=2;((10*$i+$j)*(10*$i+$j))/100" \vert{} bc); printf "\%s\t" $num; done; echo ""; done
//PS
//"{0,7}" -f で7文字分・右揃えの書式を指定します。
foreach ($i in 1..9) { foreach ($j in 0..9) { $num = ((10*$i+$j)*(10*$i+$j))/100; Write-Host ("{0,7}" -f $num) -NoNewline }; Write-Host "" }
[OUT]
1.00 1.21 1.44 1.69 1.96 2.25 2.56 2.89 3.24 3.61
4.00 4.41 4.84 5.29 5.76 6.25 6.76 7.29 7.84 8.41
...
81.00 82.81 84.64 86.49 88.36 90.25 92.16 94.09 96.04 98.01
geogebraならfor文の入れ子をZipとSequenceで簡単に実現できる。
2.GeoGebraでのスマートなコード化
ターミナルでは手続き型(forループ)で泥臭く回した計算ですが、
われらがGeoGebraならどうでしょうか。
GeoGebraには `for` ループがありません。
その代わりに Sequence(数列) や Zip(リスト内包表記・写像)を使って、
エレガントに一括処理します。
# 計算部分
nums = Sequence(k, k, 1, 9)
numT = Join(nums, {10})
SUM = Sum(numT) // 1から10の和 (55)
PROD = Product(numT) // 1から10の積 (3628800)
numZ = Join({0}, nums)
kuku = Zip(Zip(i * j, i, nums), j, nums)
sqrs = Zip(Zip((10*i + j)^2, i, nums), j, numZ)
decisqrs = Zip(Zip(s / 100, s, row), row, sqrs)
# 表示部分
// FormulaText(decisqrs) を使うと、生成した2次元リストを一瞬で美しいLaTeX形式の行列・表として表示できます!
【GeoGebraならfor文の入れ子もZipとSequenceで鮮やかに解決!】
手続き型プログラミング(PSやBS)で書いた2重ループが、
GeoGebraでは数学的な「集合・リストの変換(内包表記)」として非常にすっきりと記述できます。
裏で動く複雑な処理を気にせず、
直感的に数学オブジェクトとして表を生成できるGeoGebraの強力さが際立ちますね。
しかし、
現代的なgeogebraには負けますが、
地味でも1行で2重ループが回せるスクリプトは何かのときに助かるでしょう。