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

gist.github.com

回答

縛りは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つ一応用意しました。一つは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でできちゃいます