2015.08.29 jus共催勉強会資料
TRANSCRIPT
![Page 1: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/1.jpg)
JUS共催勉強会なぜシェルに仕事をさせてはいけないのか?USP友の会 会員 鳥海秀一
![Page 2: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/2.jpg)
自己紹介
名前:鳥海秀一職業:金融系のSE
ここ2年間、業務ではプログラムを組んでません
所属:USP友の会(2009年4月~)
日本UNIXユーザ会(2014年12月~)
![Page 3: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/3.jpg)
この勉強会のきっかけ
2014年12月13日~14日開催JUS シェルスクリプトワークショップ in 鳥取
![Page 4: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/4.jpg)
シェルスクリプトワーックショップ IN 鳥取
講師
今泉光之(USP友の会)
斉藤博文(日本GNU AWKユーザ会)
斎藤明紀(鳥取環境大学)
![Page 5: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/5.jpg)
詳しくはWEBで
https://www.usptomo.com/PAGE=20141231JUSWORKSHOP
![Page 6: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/6.jpg)
斎藤先生が示したパネル
シェルに仕事をさせてはいけない
シェルは glue language
他のコマンドに仕事をさせる
シェルは仕事手順の制御だけ
![Page 7: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/7.jpg)
なぜ、シェルに仕事をさせてはいけないのか?
![Page 8: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/8.jpg)
実際に、仕事をさせてみよう!
![Page 9: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/9.jpg)
仕事?
![Page 10: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/10.jpg)
仕事=重めの処理
![Page 11: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/11.jpg)
本日は、nクイーン問題を選択
![Page 12: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/12.jpg)
nクイーン問題とは
もともとは1848年に考案された、チェス盤(8×8マス)と8個のクイーン(飛車と角行を合わせた動きをする駒)を利用したパズル
どのクイーンもお互いのきき筋にいないようにする配置を求める
8クーイン問題をn×nのマスに応用したのがnクイーン問題
2クイーンと3クイーンには解がない
nが増えると計算量が爆発的に増える。解が判明しているのは26クイーン問題まで
![Page 13: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/13.jpg)
nクイーン問題の解の表現方法
(例)4クイーン
2 4 1 3↩️3 1 4 2↩️ と数の列で表現
![Page 14: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/14.jpg)
nクイーン問題の解法
nクイーン問題はバックトラック法で解く問題の代表例
解法はプログラムの入門書に必ずと言って良いほど登場
![Page 15: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/15.jpg)
バックトラック法の概説
0 1 2 3
1
2
3
4
再帰
ループ
メモ行上斜め下斜め
1
1
1
3
4
2
![Page 16: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/16.jpg)
プログラム例(JavaScript)
function nqueens(size) { var row=[], up=[], down=[], board=[]; (function queen(n) { if (n >= size) { console.log(board.join(' ‘));
} else { for (var i = 0; i < size; ++i) { if (!row[i] && !up[n+i] && !down[n-i+size-1]) { row[i]=up[n+i]=down[n-i+size-1]=1; board[n] = i+1; queen(n+1); row[i]=up[n+i]=down[n-i+size-1]=0;
} }
} }(0));
} nqueens(process.argv[2]);
![Page 17: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/17.jpg)
様々な言語のプログラム例
https://github.com/umidori/nqueens/tree/master/procedural
![Page 18: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/18.jpg)
例を参考にBashでnクイーン問題の解法プログラムを作成してください
![Page 19: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/19.jpg)
実演してみます
![Page 20: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/20.jpg)
プログラムの作成方針
1. 4クイーン問題を解くプログラムを作成
2. 4クイーン問題をnクイーン問題に拡張
全てのクイーンの組みを出力するプログラムを作成
同一行のクイーンを排除
斜め上のクイーンを排除
斜め下のクイーンを排除
![Page 21: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/21.jpg)
4クイーンの全ての組を出力board=() queen() { local i
if (($1 >= 4)); then echo ${board[@]} else for ((i = 1; i <= 4; ++i)); do board[$1]=$i queen $(($1 + 1)) done fi } queen 0
![Page 22: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/22.jpg)
同一行のクイーンを排除board=() row=() queen() { local i
if (($1 >= 4)); then echo ${board[@]} else for ((i = 1; i <= 4; ++i)); do if ((!row[i])); then row[$i]=1 board[$1]=$i queen $(($1 + 1)) row[$i]=0 fi done fi } queen 0
![Page 23: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/23.jpg)
斜めのクイーンを排除board=() row=() up=() down=() queen() { local i if (($1 >= 4)); then echo ${board[@]} else for ((i = 1; i <= 4; ++i)); do if ((!row[i]&&!up[$1+i]&&!down[$1-i+4])); then ((row[$i] = up[$1+i] = down[$1-i+4] = 1)) board[$1]=$i queen $(($1 + 1)) ((row[$i] = up[$1+i] = down[$1-i+4] = 0)) fi done fi } queen 0
![Page 24: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/24.jpg)
nクイーン問題に拡張n=$1 board=() row=() up=() down=() queen() { local i if (($1 >= n)); then echo ${board[@]} else for ((i = 1; i <= n; ++i)); do if ((!row[i]&&!up[$1+i]&&!down[$1-i+n])); then ((row[$i] = up[$1+i] = down[$1-i+n] = 1)) board[$1]=$i queen $(($1 + 1)) ((row[$i] = up[$1+i] = down[$1-i+n] = 0)) fi done fi } queen 0
![Page 25: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/25.jpg)
12クイーンを解いてみてください
![Page 26: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/26.jpg)
言語別12クイーン解答時間(参考値)(Mac Mini CPU:2.3GHz Core i7 メモリ:8GB)
言語 処理時間C言語 0.14秒Java8 1.12秒C# 0.55秒
Haskell 15.0秒Ocaml 0.14秒
Perl 2.59秒Python 2.48秒Ruby 1.94秒PHP 3.08秒
JavaScript 2.11秒Gauche 1.21秒
Bash 6分24秒
![Page 27: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/27.jpg)
なぜシェルに仕事をさせてはいけないのか?
1.処理速度が遅い
2.スクリプトが組みづらい(環境からの支援が乏しい)
![Page 28: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/28.jpg)
シェルが遅いのはなぜか
答え 変数のアクセス効率が良くないから
1. 変数は全て「変数名=値」という文字列
2. 配列は高速なランダムアクセスを実現しない
![Page 29: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/29.jpg)
では、どうするか?
![Page 30: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/30.jpg)
斎藤先生が示したパネル
シェルに仕事をさせてはいけない
シェルは glue language
他のコマンドに仕事をさせる
シェルは仕事手順の制御だけ
![Page 31: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/31.jpg)
シェルは glue language
シェルスクリプトでは、glue(のり)は主にパイプのこと
シェルスクリプトではパイプをうまく使うことが肝要
パイプをうまく使うには発想の転換が必要
例えば、nクイーン問題では後戻りしないバックトラック法という発想が必要になる
![Page 32: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/32.jpg)
後戻りしないバックトラック法の概説
1
2
3
4
計算の進行
![Page 33: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/33.jpg)
AWKとBashで作成してみます
![Page 34: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/34.jpg)
プログラムの作成方針
1. 4クイーン問題を解くプログラムを作成
2. 4クイーン問題をnクイーン問題に拡張
全てのクイーンの組みを出力するプログラムを作成
同一行のクイーンを排除
斜め上のクイーンを排除
斜め下のクイーンを排除
![Page 35: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/35.jpg)
4クイーンの全ての組を出力f() { awk '{for(i=1;i<=4;++i)print $0,i}'; }
echo | f | f | f | f
![Page 36: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/36.jpg)
同一行のクイーンを排除f() { awk '{for(i=1;i<=4;++i)print $0,i}'; } g() { awk '{for(i=1;i<NF;++i)if($i==$NF)next;print}'; }
echo | f | g | f | g | f | g | f | g
![Page 37: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/37.jpg)
斜めのクイーンを排除f() { awk '{for(i=1;i<=4;++i)print $0,i}'; } g() { awk '{for(i=1;i<NF;++i)if($i==$NF)next;print}'; } h() { awk '{for(i=1;i<NF;++i)if($i+i==$NF+NF)next;print}'; } i() { awk '{for(i=1;i<NF;++i)if($i-i==$NF-NF)next;print}'; }
echo | f | g | h | i | f | g | h | i | f | g | h | i | f | g | h | i
![Page 38: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/38.jpg)
関数をまとめるf() { awk '{for(i=1;i<=4;++i)print $0,i}' | awk '{for(i=1;i<NF;++i)if($i==$NF)next;print}' | awk '{for(i=1;i<NF;++i)if($i+i==$NF+NF)next;print}' | awk '{for(i=1;i<NF;++i)if($i-i==$NF-NF)next;print}' }
echo | f | f | f | f
![Page 39: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/39.jpg)
AWKプログラムをまとめる
f() { awk '{for(i=1;i<=4;++i)print $0,i}' | awk '{for(i=1;i<NF;++i)if($i==$NF||$i+i==$NF+NF||$i-i==$NF-NF)next;print}' }
echo | f | f | f | f
![Page 40: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/40.jpg)
さらにまとめるf() { awk '{for(i=1;i<=4;++i){for(j=1;j<=NF;++j)if($j==i||$j+j==i+NF+1||$j-j==i-NF-1)break;if(j>NF)print $0,i}}' }
echo | f | f | f | f
![Page 41: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/41.jpg)
nクイーンへの拡張法
1. ループ文を使用して、繰り返しを実現する
1. 変数に中間結果を格納する
2. ファイルに中間結果を格納する
2. 再帰を使用して、繰り返しを実現する
1. パイプに中間結果を通す
![Page 42: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/42.jpg)
変数に中間結果を格納する場合
n=$1
f() { … }
tmp="" for ((i=0;i<n;++i)); do tmp=$(echo "$tmp" | f) done echo "$tmp"
![Page 43: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/43.jpg)
ファイルに中間結果を格納する場合
n=$1
f() { … }
echo >tmp for ((i=0;i<n;++i)); do (rm tmp; f >tmp) <tmp done cat tmp rm tmp
![Page 44: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/44.jpg)
パイプに中間結果を通す場合
n=$1
f() { if (($1==0)); then echo else f $(($1-1)) | … fi }
f $1
![Page 45: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/45.jpg)
パイプを使ってnクイーンに拡張
n=$1 queen() { if (($1 == 0)); then echo else queen $(($1 - 1)) | awk '{for(i=1;i<='$n';++i){for(j=1;j<=NF;++j)if($j==i||$j+j==i+NF+1||$j-j==i-NF-1)break;if(j>NF)print $0,i}}' fi } queen $1
![Page 46: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/46.jpg)
12クイーンを解いてみてください
![Page 47: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/47.jpg)
パイプを使ったシェルスクリプトの特徴
1. 利点
1. 処理速度が速い
2. スクリプトが組みやすい
2. 欠点
1. プロセス数を意識する必要がある
2. 手続き的な発想とは異なる発想を必要とする
![Page 48: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/48.jpg)
パイプを使うスクリプトの発想
パイプを使うには手続き型プログラミングの発想ではなく関数型プログラミングの発想が必要となる
![Page 49: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/49.jpg)
SICPに載っているLISPによるnクイーンの解法
(define (queens board-size) (define (queen-cols k) (if (= k 0) (list empty-board) (filter↲ (lambda (positions) (safe? k positions)) (flatmap (lambda (rest-of-queens) (map (lambda (new-row) (adjoin-position new-row k rest-of-queens)) (enumerate-interval 1 board-size))) (queen-cols (- k 1)))))) (queen-cols board-size))
![Page 50: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/50.jpg)
関数が第一級オブジェクト参照透過性遅延評価カリー化並列化
関数型プログラム言語とパイプを使うシェルスクリプトとの共通点は?
閉包性の活用
![Page 51: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/51.jpg)
閉包性とは
抽象代数からきた言葉
集合の要素にある演算を作用させて得られた要素が、また集合の要素であるなら、要素の集合はその演算のもとで閉じているという
例えば、整数は加算、減算、乗算に対しては閉包性をもつ。整数に対するいずれの演算も、結果は整数になるため
![Page 52: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/52.jpg)
SICPでの閉包性の説明
困ったことに多くの普通のプログラム言語にあるデータ組合せ演算は閉包性を満足せず、閉包性を活用するのは煩わしい。(中略)対の使えるLispと違って、これらの言語には合成データを一様に操作するのが容易になる汎用の糊はない。
![Page 53: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/53.jpg)
閉包性を活用する言語の例
Lispリストに対するmap,filter,flattenなどの演算
SQLリレーションに対する8つのリレーショナル代数演算
シェルテキストに対するhead,tail,sortなどのコマンド
![Page 54: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/54.jpg)
関数型言語の発想に慣れるには
松
竹
梅手続き的プログラムを関数的プログラムに書き換えてみる
SICP(計算機プログラムの構造と解釈)を読む
シェル芸勉強会に参加する
![Page 55: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/55.jpg)
関数型言語としてのシェルの利点
開発環境開発環境はターミナル画面であるため超軽量
処理速度パイプを利用し、関数的に解いた方が速度的に有利
記述順と実行順の一致シェルスクリプトでは記述順と実行順が一致する
![Page 56: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/56.jpg)
言語別12クイーン解答時間(参考値)(Mac Mini CPU:2.3GHz Core i7 メモリ:8GB)
言語 手続き的プログラム 関数的プログラムC言語 0.14秒 ーJava8 1.12秒 2.78秒C# 0.55秒 2.17秒
Haskell 15.0秒 5.36秒Ocaml 0.14秒 3.53秒
Perl 2.59秒 34.4秒Python 2.48秒 11.9秒Ruby 1.94秒 17.0秒PHP 3.08秒 23分03秒
JavaScript 2.11秒 16分35秒Gauche 1.21秒 29.8秒
Bash 6分24秒 11.0秒
![Page 57: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/57.jpg)
シェルでは記述順と処理順が一致
普通、関数的なプログラムでは右から左に処理が進む
![Page 58: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/58.jpg)
Perlを使った4クイーンの解答例(右(この場合は下)から左(この場合は上)に処理が進行)
print map{join(" ",@$_)."\n"} map{$l=scalar(@x=@$_);map{[@x,$_]}grep{$y=$_;!grep{$y==$x[$_]||$l-$_==abs($y-$x[$_])}0..$l-1}1..4} map{$l=scalar(@x=@$_);map{[@x,$_]}grep{$y=$_;!grep{$y==$x[$_]||$l-$_==abs($y-$x[$_])}0..$l-1}1..4} map{$l=scalar(@x=@$_);map{[@x,$_]}grep{$y=$_;!grep{$y==$x[$_]||$l-$_==abs($y-$x[$_])}0..$l-1}1..4} map{$l=scalar(@x=@$_);map{[@x,$_]}grep{$y=$_;!grep{$y==$x[$_]||$l-$_==abs($y-$x[$_])}0..$l-1}1..4} []
![Page 59: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/59.jpg)
Bashを使った4クイーンの解答例(左(この場合は上)から右(この場合は下)に処理が進行)
echo | awk '{for(i=1;i<=4;++i){for(j=1;j<=NF;++j)if($j==i||$j+j==i+NF+1||$j-j==i-NF-1)break;if(j>NF)print $0,i}}' | awk '{for(i=1;i<=4;++i){for(j=1;j<=NF;++j)if($j==i||$j+j==i+NF+1||$j-j==i-NF-1)break;if(j>NF)print $0,i}}' | awk '{for(i=1;i<=4;++i){for(j=1;j<=NF;++j)if($j==i||$j+j==i+NF+1||$j-j==i-NF-1)break;if(j>NF)print $0,i}}' | awk '{for(i=1;i<=4;++i){for(j=1;j<=NF;++j)if($j==i||$j+j==i+NF+1||$j-j==i-NF-1)break;if(j>NF)print $0,i}}'
![Page 60: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/60.jpg)
まとめ
シェルに仕事をさせてはいけない
仕事をさせる場合はパイプを使う
パイプを使いこなすには発想の転換が必要
発想の転換にはシェル芸勉強会が最適
![Page 61: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/61.jpg)
ここで、シェル芸問題をひとつ
nクイーンの数列(例えば、2 4 1 3)を次のようなアスキーアートに変換してみましょう。+---+---+---+---+ | | | Q | | +---+---+---+---+ | Q | | | | +---+---+---+---+ | | | | Q | +---+---+---+---+ | | Q | | | +---+---+---+---+
![Page 62: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/62.jpg)
解答例1
awk '{ printf "+";for(i=1;i<=NF;++i)printf "---+";print ""; for(i=1;i<=NF;++i){printf "|";for(j=1;j<=NF;++j) if(i==$j) printf " Q |"; else printf " |";print ""; printf "+";for(j=1;j<=NF;++j)printf "---+";print ""}}'
![Page 63: 2015.08.29 JUS共催勉強会資料](https://reader031.vdocuments.net/reader031/viewer/2022020301/587d11141a28abae148b5b25/html5/thumbnails/63.jpg)
解答例2
while read i; do a=($i); printf $(printf "+%0${#a[@]}s\\\n%${#a[@]}s\n" | sed "s/ /|%${#a[@]}s\\\n+%0${#a[@]}s\\\n/g") | sed "s/0/---+/g;s/ / |/g" | eval sed "$(eval echo {1..${#a[@]}} | sed 's#[0-9][0-9]*# -e "$((${a[&-1]}*2))s/...|/ Q |/&"#g')"; done