30歳過ぎてようやくプログラミング能力の必要性に気付いてスクリプティングを勉強中のTMutohです。
Infrastrucrure as Codeなんて言葉もあるくらいだしインフラ屋だからって全くできないのはマズいよね。
てことで、練習として大昔に流行ったアレをスクリプト化するってのをやってみました。
基本はFizzBuzzなので入門的なものとしてちょうどいいですね。
※ FizzBuzzってなに?って人はこちら
まず単一の数字に対しての処理を整理してみます。
入力
aという整数が与えられる。
処理
aが3の倍数かどうかを判定する。(四則演算・倍数判定)
aに"3"が含まれているかを判定する。(文字列の検索・繰り返し処理)
上記の何れかもしくは両方を満たす場合といずれも満たさない場合で出力を分岐。(論理和)
出力
ここでは下記の二種類しようと思います。
アホである場合:"(*゚σ▽゚)σ < (数字)!!"
アホではない場合:"(^o^) < (数字)!"
まずは1つ目の処理[aが3の倍数かどうかを判定する。]を書いてみます。
=====================
# 整数 a が3の倍数である場合フラグを立てる
if ($a % 3 -eq 0){
$aho = $True
}
=====================
※ %は割り算の余りを求める(剰余)式です。
ifステートメントを使わず[$a % 3 -eq 0]だけでもTrue/Falseが取れますが、後続処理の都合上変数$ahoにフラグを立てています。
2つ目の処理[aに3が含まれているかどうかを判定する。]を書いてみます。
=====================
# 整数 a に3が含まれる場合フラグを立てる
for ($i=0; $i -lt $a.ToString().Length; $i++){
if ($a.ToString()[$i] -eq "3"){
$aho = $True
}
}
=====================
forステートメントを用いて、aのi文字目($a[$i])を判定する処理を桁数分処理しています。
aを文字列型として読ませるためにToStringを用いています。
3つめの処理、「何れかもしくは両方を満たす場合といずれも満たさない場合でそれぞれに合わせた形式で出力」
=====================
# フラグチェック
if ($aho -eq $True){
# アホパターンの形式で出力
Write-Output ("(*゚σ▽゚)σ < " + $a + "!!")
}else{
# 通常パターンの形式で出力
Write-Output ("(^o^) < " + $a + "!")
}
=====================
以上の組み合わせで、[整数aが3の倍数であるか、3を含む数字である場合アホになる]が出来上がります。
ひとまとめにします。
=====================
# 整数 a が3の倍数である場合フラグを立てる
if ($a % 3 -eq 0) {
$aho = $True
}
# 整数 a に3が含まれる場合フラグを立てる
for ($i=0; $i -lt $a.ToString().Length; $i++){
if ($a.ToString()[$i] -eq "3"){
$aho = $True
}
}
# フラグチェック
if ($aho -eq $True){
# アホパターンの形式で出力
Write-Output ("(*゚σ▽゚)σ < " + $a + "!!")
}else{
# 通常パターンの形式で出力
Write-Output ("(^o^) < " + $a + "!")
}
=====================
単一の数字に対して処理するものが書けたので、あとはこれを指定した回数分処理するようにForEach-Objectで回します。
また、最終値をEndオプションとして指定出来るようにしておきます。
====<nabeatsu.ps1>====
param(
[int]$End
)
1..$End |ForEach-Object {
# フラグを初期化
$aho = $Null
# 3の倍数判定
if ($_ % 3 -eq 0) {
$aho = $True
}
# 3を含む判定
for ($i=0; $i -lt $_.ToString().Length; $i++){
if ($_.ToString()[$i] -eq "3"){
$aho = $True
}
}
# フラグチェック
if ($aho -eq $True){
# アホパターンの形式で出力
Write-Output ("(*゚σ▽゚)σ < " + $_ + "!!")
}else{
# 通常パターンの形式で出力
Write-Output ("(^o^) < " + $_ + "!")
}
}
====<nabeatsu.ps1>====
このスクリプトをオプション付きで実行することで、1から指定した値までの数字が3の倍数か3を含む数字ではアホになった状態で出力されます。
・補足
like演算子とor演算子を使うことでよりPowerShellっぽく簡潔になります。
====<nabeatsu2.ps1>====
param(
[int]$End
)
1..$End |ForEach-Object {
if (($_ % 3 -eq 0) -or ($_ -like "*3*")){
Write-Output ("(*゚σ▽゚)σ < " + $_ + "!!")
}else{
Write-Output ("(^o^) < " + $_ + "!")
}
}
====<nabeatsu2.ps1>====
int型かString型かを意識せずにまとめて処理できるあたりがそれっぽいですね。
・オマケ
並行して勉強中のPython3でも同じものを書いてみました。
====<nabeatsu.py>====
import sys
args = sys.argv
end = int(args[1])
for a in range(1, end+1):
aho = ''
if a % 3 == 0:
aho = True
for b in range(0, len(str(a))):
if str(a)[b] == "3":
aho = True
if aho == True:
print("(*゚σ▽゚)σ < {0}!!".format(a))
else:
print("(^o^) < {0}!".format(a))
====<nabeatsu.py>====
踊る阿呆に見る阿呆、同じ阿呆ならうんぬんかんぬん。
もっといいやり方があるとか、間違いなどあればどんどん指摘ください。
じゃあどれが正しいの?という点ですが、
画一的な正解はありません。
処理を実施する端末のスペックや整数aに入るであろう値(桁数など)によって
それぞれ処理速度も変わってきますし
運用の中でスクリプトのメンテナンスがちょいちょい入るのであれば
メンテナンスする人に分かりやすい処理内容の方がよい、などということもあります。
案件の中でスクリプトを作って納品する、という場合は
この辺りのお客様ヒヤリングや実際に動作させる環境での性能試験などを実施し、
最良のものを作っていく、ということが必要になります。
エンジニアの醍醐味ですね。