第2回チキチキ!シェル芸人養成勉強会をPowerShellでやってみた Hbstudy#38シェルスクリプトでいろいろやってみよう!をPowerShellでやってみたたまたまUPS友の会様を覗いていたらあるじゃないですかー。 ということで、今回のお題はこれです。
シェルスクリプト大喜利 第八回 ~"for,while禁止"に喜びを感じる人の何と多い事か!曰くマゾな人が多い? ん~、forとかwhileは……なるべくなら避けてるので…
この投稿のサブタイトルにもありますように、"for,while禁止"という苦痛を伴うお題が今回あるんですが、ナゼかこれに対する投稿が殺到しとります。早速やってみました。 あと、繰り返しですが…一応。
※シェル環境前提なので、なるべくAliasを利用しているのはご了承ください。 ※私はAlias余り好きじゃない派です。 ※PowerShellとBashの大きな違いは | (パイプ)で渡されるのが文字列ではなくオブジェクトということを念頭に…
Get-Content #cat #gc Foreach-Object #% Sort-Object #sort
第1問 整数数列ネタ其の三「累乗数」
お題はこれです。1~n(nは引数で指定)の自然数の中の累乗数を全て求めるシェルスクリプトを書いてください。 累乗数とは何かと言うと、a = bc (a,b,cは全て自然数)と書き表せる数aのことです。加えてこの縛りです。
これまで寄せられている投稿を見ると、1を特別扱いしているものが多いのですね。もちろん特別扱いしようが答えをちゃんと出してくれさえすれば正解なのですよ。でもやっぱり1を特別扱いしないプログラムになっているとポイント高いですね。では、PowerShellで…nは引数で渡せってことなのでfunctionとも思いましたが一応ワンライナーで
begin{$n=10}process{1..$n | %{ $x=$_ ; 1..$n | % {"{0,-5}, {1}" -f "$x^$_",[System.Math]::Pow($x,$_)}}}結果表示です。
1^1 , 1 1^2 , 1 1^3 , 1 1^4 , 1 1^5 , 1 1^6 , 1 1^7 , 1 1^8 , 1 1^9 , 1 1^10 , 1 2^1 , 2 2^2 , 4 2^3 , 8 2^4 , 16 2^5 , 32 2^6 , 64 2^7 , 128 2^8 , 256 2^9 , 512 2^10 , 1024 3^1 , 3 3^2 , 9 3^3 , 27 3^4 , 81 3^5 , 243 3^6 , 729 3^7 , 2187 3^8 , 6561 3^9 , 19683 3^10 , 59049 4^1 , 4 4^2 , 16 4^3 , 64 4^4 , 256 4^5 , 1024 4^6 , 4096 4^7 , 16384 4^8 , 65536 4^9 , 262144 4^10 , 1048576 5^1 , 5 5^2 , 25 5^3 , 125 5^4 , 625 5^5 , 3125 5^6 , 15625 5^7 , 78125 5^8 , 390625 5^9 , 1953125 5^10 , 9765625 6^1 , 6 6^2 , 36 6^3 , 216 6^4 , 1296 6^5 , 7776 6^6 , 46656 6^7 , 279936 6^8 , 1679616 6^9 , 10077696 6^10 , 60466176 7^1 , 7 7^2 , 49 7^3 , 343 7^4 , 2401 7^5 , 16807 7^6 , 117649 7^7 , 823543 7^8 , 5764801 7^9 , 40353607 7^10 , 282475249 8^1 , 8 8^2 , 64 8^3 , 512 8^4 , 4096 8^5 , 32768 8^6 , 262144 8^7 , 2097152 8^8 , 16777216 8^9 , 134217728 8^10 , 1073741824 9^1 , 9 9^2 , 81 9^3 , 729 9^4 , 6561 9^5 , 59049 9^6 , 531441 9^7 , 4782969 9^8 , 43046721 9^9 , 387420489 9^10 , 3486784401 10^1 , 10 10^2 , 100 10^3 , 1000 10^4 , 10000 10^5 , 100000 10^6 , 1000000 10^7 , 10000000 10^8 , 100000000 10^9 , 1000000000 10^10, 10000000000結果だけ出力するならこれでも。
begin{$n=10}process{1..$n | %{ $x=$_ ; 1..$n | % {[System.Math]::Pow($x,$_)}}}[13/Feb/2013] 牟田口先生から、累乗数はそうじゃないと指摘をいただきました。
あれ、1~nの中の累乗数を求めるってそういう意味じゃないような気もする…たとえばn=10なら1,4,8,9を出力する必要があるんではなかろうか。
— 牟田口大介さん (@mutaguchi) 2013年2月13日
ご指摘を受けて、修正します。
単純に、小さい方から順に10個ならこうです。
1..10 | %{ $x=$_ ; 2..10 | % {[System.Math]::Pow($x,$_)}} | sort -Unique | select -First 10出力結果です。
1 4 8 9 16 25 27 32 36 49引数で渡せるようにします。 $scriptの小さい方から後ろに取得したい数を入れます。(一応最大数を大きくしてますが漏れがある場合は1..99と2..99を大きくすれば…!) 下のサンプルでは20個まで取得しています。
$script={param($n)1..99 | %{ $x=$_ ; 2..99 | % {[System.Math]::Pow($x,$_)}} | sort -Unique | select -First $n};& $script 20改行するとこうです。
$script={param($n)1..99 | %{ $x=$_ ; 2..99 | % {[System.Math]::Pow($x,$_)}} | sort -Unique | select -First $n} & $script 20出力結果です。
1 4 8 9 16 25 27 32 36 49 64 81 100 121 125 128 144 169 196 216
第2問 同一行内ソート
求める結果はこれだそうです。つまり英文字ソートをした結果文字列を、元の文字列の手前に挿入し、一行二単語にする。ただしデータは標準入力から受け取る、という動作です。これは、もう某星人に教わったLinqの御力の断片をお借りしてみたいわけで。(めそっどちぇーん とか 構文じゃなくてごめんさない)
PowerShellでStringをChar[]に変換するまずは、指定のファイルを作ります。
@("pans","pots","opt","snap","stop","tops") | Out-File -Encoding default -FilePath .\dic.txt読んでみましょう。
cat dic.txt出来てますね。
pans pots opt snap stop topsでは、お題をワンライナーでサクッと
cat dic.txt | %{"{0} $_" -f (("$(([system.Linq.Enumerable]::ToArray($_)) | sort )") -replace " ") }Linq!!Linq!!
anps pans opst pots opt opt anps snap opst stop opst tops
第3問 for,while文なしの九九
求める結果はこれだそうです。for文やwhile文を一切使わずに、九九の表を書いてください。 01*01=01 01*02=02 01*03=03 … 01*09=09 02*01=02 02*02=04 02*03=06 … 02*09=18 : : 09*01=09 09*02=18 09*03=27 … 09*09=81 といった感じです。ワンライナーでサクッと
1..9 | %{ "$($_ | %{ $x=$_; 1..9 | %{ "{0:00}*{1:00}={2:00}" -F $x, $_, $($_ * $x) }})"}結果です。
01*01=01 01*02=02 01*03=03 01*04=04 01*05=05 01*06=06 01*07=07 01*08=08 01*09=09 02*01=02 02*02=04 02*03=06 02*04=08 02*05=10 02*06=12 02*07=14 02*08=16 02*09=18 03*01=03 03*02=06 03*03=09 03*04=12 03*05=15 03*06=18 03*07=21 03*08=24 03*09=27 04*01=04 04*02=08 04*03=12 04*04=16 04*05=20 04*06=24 04*07=28 04*08=32 04*09=36 05*01=05 05*02=10 05*03=15 05*04=20 05*05=25 05*06=30 05*07=35 05*08=40 05*09=45 06*01=06 06*02=12 06*03=18 06*04=24 06*05=30 06*06=36 06*07=42 06*08=48 06*09=54 07*01=07 07*02=14 07*03=21 07*04=28 07*05=35 07*06=42 07*07=49 07*08=56 07*09=63 08*01=08 08*02=16 08*03=24 08*04=32 08*05=40 08*06=48 08*07=56 08*08=64 08*09=72 09*01=09 09*02=18 09*03=27 09*04=36 09*05=45 09*06=54 09*07=63 09*08=72 09*09=81[13/Feb/2013] 牟田口先生から、foreachもだめではと指摘があり……え…。
for,while縛りというならforeachもダメなんじゃね?
— 牟田口大介さん (@mutaguchi) 2013年2月13日
先生がここで再帰でとかれています。
再帰でがんばったけど… winscript.jp/powershell/fil… 微妙
— 牟田口大介さん (@mutaguchi) 2013年2月13日
やられてることは、foreachの内容を分解して$out変数にstring書き込み、これをforと同じ要領で引数で渡した$x,$yそれぞれを1..9まで順次実行ですね。
$out="" $s={ param($x,$y) $script:out+="0$x*0$y=$("{0:00}" -f ($x*$y))" if($y -lt 9) { $script:out+=" " $y++ &$s $x $y } elseif($x -lt 9) { $script:out+="`n" $x++ &$s $x 1 } } &$s 1 1 $out