たいちょーの雑記

ぼくが3日に一度くらい雑記をかくところ

第55回シェル芸勉強会に参加しました

しました。

Q1

以下の図形を描く問題。ただし、forwhileは禁止とのこと。ナンテコッタ…

* * * * * * * *
* *         * *
*   *     *   *
*     * *     *
*     * *     *
*   *     *   *
* *         * *
* * * * * * * *
echo 11111111110000111010010110011001 | fold -w8 | sed 'y/10/* /' | pee 'cat' tac | sed 's/./& /g'

方針としては、上4行を取り出し、*10で表現、それをいい感じに置換・成形をします。上4行、つまり上半分だけとしたのは pee cat tac で鏡写しができるからですね。

PowerShellでの解答もやってみます

$lines=(@(1111, 1100, 1010, 1001) | %{ "$_"+[string]::Join("", "$_"[("$_".Length-1)..0]) });@($lines,$lines[($lines.Length-1)..0]) | %{ $_ -replace 1,'* ' -replace 0,'  ' }

方針はほぼ同じですが、01で表現するのは左上の4x4の範囲ですこれを左右反転、上下反転の順番で複製して置換、出力するというものです

Q2

以下のおしゃれなUNKOからASCIIなUNKOに戻す問題。おしゃれなUNKOってなんだろうね

echo 𝒰𝒩𝒦𝒪 
echo 𝒰𝒩𝒦𝒪 | uni i | awk '{print $12}' | tr -d '
' | awk 4

特殊文字を元に戻すとき、uninameなどを使うと楽です。自分はuniを使っています。好きなのを使えばよいです

github.com

PowerShell版もuniで情報を取り出して、切り出すだけなので省略します。

Q3

端末のフチに沿って@を出力する問題。

perl -e "print '@'x$(tput cols)"; yes | head -n"$(tput lines)"|sed "s/y/perl -e \"print '@'.' 'x($(tput cols)-2).'@'\"/e";perl -e "print '@'x$(tput cols)"

tput cols$COLUMNSなどで端末の幅が得られます。これを利用して文字を繰り返すべき回数を得ます。文字の繰り返しにはperlを使いましたがここはなんでも良いと思います

PowerShellでは$Host.UI.RawUIでアクセスできるInternalHostRawUserInterfaceオブジェクトから幅や高さといった情報が得られます。

$ $Host.UI.RawUI


ForegroundColor       : Gray
BackgroundColor       : Black
CursorPosition        : 0,30
WindowPosition        : 0,0
CursorSize            : 25
BufferSize            : 106,31
WindowSize            : 106,31
MaxWindowSize         : 106,31
MaxPhysicalWindowSize : 1904,62
KeyAvailable          : True
WindowTitle           : Windows PowerShell

この値を使って同様に描画していきます。PowerShellでも掛け算で文字の繰り返しを表現できるので以下のような感じで

"@"*$Host.UI.RawUI.WindowSize.Width; 0..($Host.UI.RawUI.WindowSize.Height-2) | %{ "@"+" "*($Host.UI.RawUI.WindowSize.Width-2)+"@" }; "@"*$Host.UI.RawUI.WindowSize.Width;
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@                                                                                                        @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Q4

端末上で💩を対消滅させ、そのエネルギーで🍣を生み出す問題。どういうことなの

(yes '@'{,,,,,,,,,,} | head -n11|awk '{$NR="💩";print}' | sed 'y/@ /__/' | awk '{print $1"  "$1}' | teip -f 2 rev; echo ______________________🍣______________________)|sed 'y/_/ /' | textimg -asl1

ちょっと端末上でというのが抜けていたのです…。方針としては1行ずつ左右から💩を近づけていくように出力し、最終行は🍣を挿入します

(yes '@'{,,,,,,,,,,} | head -n11|awk '{$NR="💩";print}' | sed 'y/@ /__/' | awk '{print $1"  "$1}' | teip -f 2 rev; echo ______________________🍣______________________)|sed 'y/_/ /'
💩                                          💩
  💩                                      💩
    💩                                  💩
      💩                              💩
        💩                          💩
          💩                      💩
            💩                  💩
              💩              💩
                💩          💩
                  💩      💩
                    💩  💩
                      🍣

これをtextimg-aでアニメーションにして画像を出力しています

Q5

wordsファイル内にある各単語について、同じ文字がちょうど3つ存在し、ほかに同じ文字がちょうど2つ存在するものを取り出す問題。前の問題との格差がすごい。

$ cat *55/words | sel 1 1 | teip -sf2 -- zsh -c "grep -o . | sort | uniq -c | sort -rn | tr -d '
'" | grep 3 | grep 2 | sel 1
multidimensional
sharecropper
antenna
constitutionals
Goolagong
nostalgically

selawk {print $HOGE}へのショートカットみたいなコマンドです。

github.com

ここでは awk '{print $1,$1}'の代わりに使っています。そしてteipで2カラム目に文字の集計を列挙します

$ cat *55/words | sel 1 1 | teip -sf2 -- zsh -c "grep -o . | sort | uniq -c | sort -rn | tr -d '
'" 
metabolizes       2 e      1 z      1 t      1 s      1 o      1 m      1 l      1 i      1 b      1 a
Manuela       2 a      1 u      1 n      1 l      1 e      1 M
Kroger       2 r      1 o      1 g      1 e      1 K
purchasable       2 a      1 u      1 s      1 r      1 p      1 l      1 h      1 e      1 c      1 b
luster       1 u      1 t      1 s      1 r      1 l      1 e
clattering       2 t      1 r      1 n      1 l      1 i      1 g      1 e      1 c      1 a
mesh       1 s      1 m      1 h      1 e
campus       1 u      1 s      1 p      1 m      1 c      1 a
seating       1 t      1 s      1 n      1 i      1 g      1 e      1 a
giblet       1 t      1 l      1 i      1 g      1 e      1 b
Tomas       1 s      1 o      1 m      1 a      1 T
hooch       2 o      2 h      1 c
Rivas       1 v      1 s      1 i      1 a      1 R
Django       1 o      1 n      1 j      1 g      1 a      1 D
Alger       1 r      1 l      1 g      1 e      1 A
multidimensional       3 i      2 n      2 m      2 l      1 u      1 t      1 s      1 o      1 e      1 d      1 a
Troilus       1 u      1 s      1 r      1 o      1 l      1 i      1 T
outtake       2 t      1 u      1 o      1 k      1 e      1 a
tries       1 t      1 s      1 r      1 i      1 e
Nobelist       1 t      1 s      1 o      1 l      1 i      1 e      1 b      1 N
...

これで一行に元の単語と単語を構成する文字種とその個数が列挙されます。ここから、3個と2個をgrepすればよいですね。

PowerShellでもやってみます

$ cat .\words |%{ @{t=$_; g=($_.ToCharArray()|group)} } |?{ [System.Linq.Enumerable]::Any($_.g, [System.Func[object,bool]] { param($x) $x.Count -eq 3 }) } |?{ [System.Linq.Enumerable]::Any($_.g, [System.Func[object,bool]]{param($x) $x.Count -eq 2})}|%{$_.t}

Where-ObjectGroup-Objectの組み合わせです。やっていることは先に説明したものと同じです。

Q6

格子状に💩を並べる問題。なんか錯視を起こしそう

yes "echo 1000 0101 0010 0101 1000 | fmt -1 | sed 'y/10/💩 /' | sed 's/.*/&&&&&&&&/' | sed -E 's/(.)(.*)/\1\2\1/'" | head -n8 | bash | uniq

Q1の方針と似ています。4x5を作ってから縦横へ展開します。

$ yes "echo 1000 0101 0010 0101 1000 | fmt -1 | sed 'y/10/💩 /' | sed 's/.*/&&&&&&&&/' | sed -E 's/(.)(.*)/\1\2\1/'" | head -n8
echo 1000 0101 0010 0101 1000 | fmt -1 | sed 'y/10/💩 /' | sed 's/.*/&&&&&&&&/' | sed -E 's/(.)(.*)/\1\2\1/'
echo 1000 0101 0010 0101 1000 | fmt -1 | sed 'y/10/💩 /' | sed 's/.*/&&&&&&&&/' | sed -E 's/(.)(.*)/\1\2\1/'
echo 1000 0101 0010 0101 1000 | fmt -1 | sed 'y/10/💩 /' | sed 's/.*/&&&&&&&&/' | sed -E 's/(.)(.*)/\1\2\1/'
echo 1000 0101 0010 0101 1000 | fmt -1 | sed 'y/10/💩 /' | sed 's/.*/&&&&&&&&/' | sed -E 's/(.)(.*)/\1\2\1/'
echo 1000 0101 0010 0101 1000 | fmt -1 | sed 'y/10/💩 /' | sed 's/.*/&&&&&&&&/' | sed -E 's/(.)(.*)/\1\2\1/'
echo 1000 0101 0010 0101 1000 | fmt -1 | sed 'y/10/💩 /' | sed 's/.*/&&&&&&&&/' | sed -E 's/(.)(.*)/\1\2\1/'
echo 1000 0101 0010 0101 1000 | fmt -1 | sed 'y/10/💩 /' | sed 's/.*/&&&&&&&&/' | sed -E 's/(.)(.*)/\1\2\1/'
echo 1000 0101 0010 0101 1000 | fmt -1 | sed 'y/10/💩 /' | sed 's/.*/&&&&&&&&/' | sed -E 's/(.)(.*)/\1\2\1/'

これをbashなどに渡すと

💩   💩   💩   💩   💩   💩   💩   💩   💩
 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 
  💩   💩   💩   💩   💩   💩   💩   💩  
 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 
💩   💩   💩   💩   💩   💩   💩   💩   💩
💩   💩   💩   💩   💩   💩   💩   💩   💩
 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 
  💩   💩   💩   💩   💩   💩   💩   💩  
 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 💩 
💩   💩   💩   💩   💩   💩   💩   💩   💩
...

という感じになります。よくみると縦方向に重複があるので、uniqで消します

PowerShellでもやってみます

1..8 |%{@("1000","0101","0010","0101","1000")|%{("$_"*8) -replace '^(.)(.*)','$1$2$1' }}|%{"$_" -replace 1,'??' -replace 0,' '} | Get-Unique

Q7

wordsの中からしりとりになっている行を取り出して、一行にする問題。

cat *55/words | sed -z 's/./\L&/g; s/
/ /g' | sed -r 's/(.) \1/\1@\1/g' | fmt -1 | grep @ | tr @ ' '
campus seating giblet tomas
lifeless secures
clews shove exhaust
orifice equivocal

sedを使って一行にしながら、すべてを小文字にします。そのあとスペースをはさんで同じ文字が続く場合に@を挿入します。それらの中から@を含む部分だけを取り出せば、しりとりになりますが…

ただし、もとのテキストはtomasTomasになっているので、この解答ではちょっと不十分ですね…。 Twitterでは以下のようなのを見かけて天才だなあと思いました。

sed -zr 's/(.)
(\1)/\1 \2/ig' *55/words | grep ' '

LT

今回はLTを行いました。owariコマンドをアップデートしましたよという感じの話です。

www.slideshare.net

聞いてくださった方ありがとうございました!

おわり

図形を書く問題は久しぶりな気がしました。やはりなかなか大変ですね…。まずは01で表現するみたいな方針が一致してくるのも面白いなーとおもいました。

今回も企画、開催ありがとうございました!

| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|
|        終        |
|    制作・著作    |
|   ̄ ̄ ̄ ̄ ̄ ̄ ̄  |
|    xztaityozx    |
|_________|
  ∧∧   ||         
  ( ゚д゚)||           
  /    づΦ