tech.guitarrapc.cóm

Technical updates

第24回◯◯o◯裏番組シェル芸勉強会 を PowerShell と C# でやってみる #シェル芸

久々のシェル芸です。

Bsh on Ubuntu on Windowsでやろうと思ったのですが、手元の環境が入らないのでそっとじ..。

今回は途中で飽きるまでということで、やってみました。

問題

安定の一撃サイトです。

https://blog.ueda.asia/?p=8639

コード全体

今回の回答です。BoUWかなぁと思いつつ、PowerShellがインストールできなかったのでやめました*1

6問まで回答しています。

言語 回答数 環境
C# 1,2,3 問 LinqPad
PowerShell 1,2,3,5,6 問 PowerShell.exe on Windows 10

https://gist.github.com/guitarrapc/1cec58eeb8af7bd3fa7b0116a363fbb8

回答

縛りは2つ、「ワンライナー」「ファイル読み込み」「複数行になっても問題ない」、です。

Q1. Q1ファイルについて、次のような出力を得てください。

Q1 ファイル

玉子 卵 玉子 玉子 玉子 玉子
玉子 玉子 卵 卵 卵 玉子
卵 玉子 卵 玉子 玉子 玉子
卵 玉子 卵 卵 卵 卵
玉子 卵 玉子

出力

玉子:5 卵:1
玉子:3 卵:3
玉子:4 卵:2
玉子:1 卵:5
玉子:2 卵:1

PowerShell / C# ともに行ごとに読み取ってほげもげでした。

C# だと、SelectしてGroupByして数をまとめて、OrderByして並びを整えて、Selectで成形した文字列出力です。

PowerShellも同様です。オペレータの挙動が微妙に違うのですが大枠同じです。

Q2. 次のようなテキストについて、繰り返し出てきた文字の2つ目以降を省いて出力してください。

例えばQ2のファイル

へのへのもへじ

の場合、「へのもじ」が正解の出力になります。

これは、C#では.Distinct()を使えば一瞬です。

PowerShellでも同様ですが、2つ一応用意しました。1つはHashtableのキーが重複不許可なことを利用しているのと、同様にDistinct()です。Hashsetでもなんでもいいと思いました。

ちなみにusing NameSpaceを使っていいなら、

using Namespace System.Linq;
cat .\Q2.txt -Encoding utf8 | %{[string]::new([Enumerable]::Distinct([char[]]$_))}

です。

Q3. 第一フィールドをキーにして%%でレコードを区切ってください。

金 日成
キム ワイプ
金 正日
キム タオル
金 正男

というデータを、

%%
キム タオル
キム ワイプ
%%
金 正男
金 正日
金 日成
%%

区切りをテキストで出す意味...は、おいておいてやります。

C# では、初期化変数を用意しちゃいました。なしで書くとどうなるか思いつかない当りできない子です。あと、ずるいと思いつつTuple使ってます。

PowerShellは、awkと同じ要領ですね。

Q4. Q4.xlsxのA1のセルには数字が書いてあります。その数字を出力してください。A4には文字列が書いてあるので余裕がある人はそれも特定してみましょう。

やりません*2

Q5. ファイルQ5について、xに好きな数を代入して各行の式を計算してください。

x + x^2
x + 1/x
x*x*x

余裕のある人は、例えばxに2を代入したければ、

$ echo 2 | ...

というようにecho <代入したい数>から始めてワンライナーで解いてみてください。

echoから初めてと言われた時点でC# はやめて、PowerShellのみで。また、2^2という構文がないため、Math.Pow(x,2) に書き換えています。

PowerShellの場合、ScriptBlockをInvokeという手とInvoke-Expressionを使うのが楽です。C# も似たようなものですね。

今回はInvoke-Expression (iex) を使っています。

Q6. 「玉子」と「卵」の数を数えて、数が少ない方を数が大きい方で置換してください。

卵卵玉子玉子玉子玉子玉子卵卵卵玉子玉子卵玉子玉子玉子玉子卵卵玉子卵玉子卵卵玉子卵玉子

ずるしちゃいました。汎用性がないのであまり好きじゃないのですが。

Q7. 飽きました

Q8. 飽きました

まとめ

C# というか、Linqできれいにつながると楽しいですね。PowerShellでつないでいくよりも可読性が圧倒的に高いのはいいなぁと。

ただ、コードは長くなりがちというのは仕方ないとはいえ感じました。

雑魚回答なので、もっと良い回答をぜひ。

*1:bashではやりません

*2:COM使ったら怒られそうだし。PowerShellはモジュール使っていいなら1 Cmdletでできちゃいます