【問題と解答】jus共催 第46回人類はおそらくシェル芸に仕事を奪われるか奪われないかのどちらかであるシェル芸勉強会

Sat Feb 15 16:53:29 JST 2020 (modified: Sat Feb 15 16:53:29 JST 2020)
views: 990, keywords: プログラミング,勉強会,シェル芸,シェル芸勉強会

  このエントリーをはてなブックマークに追加 
  • 問題で使われているデータファイルはGitHubにあります。クローンは以下のようにお願いします。

Q1

 次のようなデータがあります。

$ cat data 
32 -12 42 -4 3 34 32 9 22 24 25 19 18 -14 -4

これを、次のように1列目に十の位、2列目に一の位の数を並べた表現(幹葉表示)に変換してください。

-0 44
 0 39
 4 2
-1 24
 3 224
 2 245
 1 89

解答例

$ cat data | tr ' ' \\n | sed 's/.$/ &/' | awk 'NF==1{print 0,$1}NF!=1' 
| sed 's/^- /-0 /' | sort -n 
| awk '{a[$1]=a[$1]$2}END{for(k in a)print k,a[k]}' | sed 's/^. / &/'
-0 44
 0 39
 4 2
-1 24
 3 224
 2 245
 1 89

Q2

 次のdata2は、1列目のデータに対して2列目にチェック用のビットを書き込んであるファイルです。 2列目の左右のビットがそれぞれ1列目の0と1の数の偶奇を表しており、 偶数なら0、奇数なら1になっています。1列目と2列目の整合性がとれていない行の番号を出力してください。

$ cat data2
0101010110101010101101010101101010101 10
0100000000010101010110101010101011101010 11
101011010101011010101010101010101010100101 00
010110101010111111111110101010101110 01
011010101010110101010101010101010 01

解答例

$ cat data2 | awk '{print gsub(/0/,"",$1)%2 gsub(/1/,"",$1)%2,$2}' | awk '$1!=$2{print NR}'
4

Q3

 次のファイルについて、1〜3列目の3行、4〜6列目の3行をそれぞれ3x3行列とみなして掛け算してください。

$ cat matrix
3 4 -2 1 -9 4
3 -1 2 3 -2 -8
2 5 6 0 2 -3

解答例

$ awk 'NR<4{for(i=1;i<=3;i++)a[NR][i]=$(i+3)}NR>=4{for(i=1;i<=3;i++)
{printf("%d ",$1*a[1][i] + $2*a[2][i] + $3*a[3][i])}print ""}' matrix matrix 
15 -39 -14 
0 -21 14 
17 -16 -50 

Q4

 A, B, C, Dの4種類の文字を2つにグループ分けするときの全通りのパターンを列挙してください。各グループかならず一つの文字が入っている(空集合を認めない)こととします。

解答例

$ echo {A..D}{A..D}{A..D}{A..D} | tr ' ' \\n | grep -Ev '(.).*\1' 
| awk '{for(i=1;i<4;i++){print substr($1,1,i), substr($1,i+1)}}' | tr ' ' \\n 
| awk 'BEGIN{a[1]="A";a[2]="B";a[3]="C";a[4]="D"}{for(i=1;i<=4;i++)if(index($1,a[i])){printf a[i]}print ""}' 
| xargs -n 2 | sort -u | awk '{print ($1~/A/) ? $1" "$2 : $2" "$1}' | sort -u
A BCD
AB CD
ABC D
ABD C
AC BD
ACD B
AD BC
$ echo {A..D}{A..D}{A..D}{A..D} | tr ' ' \\n | grep -Ev '(.).*\1' 
| awk '{for(i=1;i<4;i++){print substr($1,1,i), substr($1,i+1)}}' 
| opy '["".join(sorted(x)) for x in F[1:]]' | opy '[sorted(F[1:])]' | sort -u
['A', 'BCD']
['AB', 'CD']
['ABC', 'D']
['ABD', 'C']
['AC', 'BD']
['ACD', 'B']
['AD', 'BC']

Q5

 次のような出力(パスカルの三角形)を得てください。完全に左右対称である必要はありませんが、なるべく左右対称にしてください。

            1
           1 1
          1 2 1
         1 3 3 1
        1 4 6 4 1
      1 5 10 10 5 1
     1 6 15 20 15 6 1
   1 7 21 35 35 21 7 1
  1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1

解答例

$ n="0 1 0" ; for i in {1..10} ; do echo $n ;
n="0 "$(awk '{for(i=1;i<=NF-1;i++)printf $i+$(i+1)" "; print ""}' <<< $n)" 0 " ;
done | sed 's/^0 //;s/ 0$//' | tac 
| awk 'NR==1{a=length($0)}{d=(a-length($0))/2;for(i=1;i<d;i++)printf " ";print}' | tac
            1
           1 1
          1 2 1
         1 3 3 1
        1 4 6 4 1
      1 5 10 10 5 1
     1 6 15 20 15 6 1
   1 7 21 35 35 21 7 1
  1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1

Q6

 次のファイル内のそれぞれ数字について、上の桁の数からそれぞれ10, 9, 8, ..., 1をかけて総和を求めましょう。例えば4065170060なら、4*10 + 0*9 + 6*8 + ... + 0*1を計算してください。さらに、それぞれの行で求めた数について、最大公約数を求めてください。

$ cat isbn
4065170060
4774173444
4822239292
4048930699
4839952981
4839924015

解答例

### 総和 ###
$ cat isbn | rev | awk -F "" '{for(i=1;i<=NF;i++)a+=$i*i;print a;a=0}'
176
264
231
242
330
286
### 最大公約数 ###
$ cat isbn | rev | sed 's/./& /g' 
| awk '{for(i=1;i<=NF;i++)a+=$i*i;print a;a=0}' 
| python3 -c 'import sys;import numpy as np;a=[int(x) for x in sys.stdin];print(np.gcd.reduce(a))'
11

Q7

 41人を円形に並べ、1, 2, 3, 4, ..., 41番と番号をつけます。そして、生き残っている3人ごと(最初は3番, 6番, 9番, ...)の順に殺していきます。最後に残る二人は何番になるか、ワンライナーで答えてください。(ヨセフスの問題)

解答例

$ echo {1..41} | awk '{for(i=1;i<=3*39;i+=3){$(NF+1)=$i;$(NF+1)=$(i+1);print}}' | tail -n 1 | awk '{print $(NF-1),$NF}'
16 31

Q8

 SEND + MORE = MONEYの各アルファベットに0から9の数字1字を割り当てて足し算を完成させてください。異なるアルファベッドには異なる数字を割り当ててください。SMには0を割り当てないでください。答えが分かるものであれば出力はなんでも構いません。

解答例

$ seq -w 90123456 99999999 | grep '^....1' | grep -vE '(.).*\1' | awk -F "" '{print $1$2$3$4,$5$6$7$2,$5$6$3$2$8}' | awk '$1+$2==$3'
9567 1085 10652
### ベタにやった場合 ###
$ time seq -w 10234567 99999999 | grep -Ev '(.).*\1' | awk -F "" '{print $1$2$3$4,$5$6$7$2,$5$6$3$2$8}' | grep -v '^0' | grep -v ' 0' | awk '$1+$2==$3'
9567 1085 10652

real    3m27.610s
user    4m11.102s
sys 0m0.662s
### grepを分散させるとCPUが多い場合は速くなる ###
$ time seq -w 10234567 99999999 | grep -Ev '(.)\1' | grep -Ev '(.).\1' | grep -Ev '(.)..+\1' | awk -F "" '{print $1$2$3$4,$5$6$7$2,$5$6$3$2$8}' | grep -v '^0' | grep -v ' 0' | awk '$1+$2==$3'
9567 1085 10652

real    2m26.417s
user    6m13.170s
sys 0m2.952s


prev:【問題】jus共催 第46回人類はおそらくシェル芸に仕事を奪われるか奪われないかのどちらかであるシェル芸勉強会 next:jus共催 第46回シェル芸勉強会リンク集





このサイトではGoogle Analyticsやその他ソーシャルボタンのためにCookieを使用しています。もし同意いただけない場合はブラウザでクッキーを無効にして閲覧をお願いします。This site uses cookies for Google AdSense and some social buttons. If you cannot accept our use of cookies, please disable cookies on your browser.