🐌

席替えをするシェルスクリプト

2021/10/10に公開

自社で席替えをする時にシェルスクリプトを書くことがことがある。 shufnl でさくっと書けるのでメモをしておく。

今回は例として8名の座席をランダムに振り分けるスクリプトを書く。
macOS の場合は gnuutils が必要。

手順1: 座席番号を決める

座席ごとに番号をつける。

1 2
3 4
(通路)
5 6
7 8

手順2: 名前が書かれたファイルを用意する

ファイルにせず echocat で済ますこともある。
今回は日本の名字人口トップ8に集結していただいた。

佐藤
鈴木
高橋
田中
伊藤
渡辺
山本
中村

手順3: shufnl でランダムに席を決める

$ cat names.txt | shuf | nl
     1  高橋
     2  鈴木
     3  中村
     4  佐藤
     5  山本
     6  渡辺
     7  伊藤
     8  田中

手順4: 座席番号と置換して座席表っぽくする

sed は GNU sed を使う。
s/\b1\b/渡辺/; といった sed のコマンドを生成している。

$ cat names.txt | shuf | nl | awk '{print "s/\\b"$1"\\b/"$2"/;"}' | sed -f - seats
渡辺 山本
佐藤 中村
(通路)
鈴木 高橋
伊藤 田中

番外編1: 特定の人たちは近くにしたい

諸事情により特定のペアは離れてほしくないこともある。
今回は例として、佐藤と鈴木を近い席にさせる。

手順1: ペアを1行にする

佐藤と鈴木は同じ行に空白区切りで書く。

佐藤 鈴木
高橋
田中
伊藤
渡辺
山本
中村

手順2: shufxargs -n1nl でランダムに席を決める

必ず佐藤の次が鈴木になるので二人は近い座席になる。

$ cat names.txt | shuf | xargs -n1 | nl
     1  渡辺
     2  田中
     3  中村
     4  佐藤
     5  鈴木
     6  山本
     7  高橋
     8  伊藤

しかし、二人の座席は斜めだったり通路を挟んだりする場合がある。
また、 2 と 4 とか 5 と 7 といったパターンが生まれない。

番外編2: 特定の人たちは隣接させたい

佐藤と鈴木には横に並んでもらう。
面倒なのでランダムに配置したあとに近くの席の人と相談して交換してもらうことにしよう。

手順1: 佐藤と鈴木以外も2組のペアを作る

佐藤と鈴木以外のペアがランダムに組まれるようにする。

$ cat <(cat names.txt | grep ' ') <(cat names.txt | grep -v ' ' | shuf | paste - - )
佐藤 鈴木
伊藤    山本
中村    高橋
田中    渡辺

手順2: shuf して xargs -n1 して nl する

佐藤は必ず奇数になる。
座席表上、佐藤が奇数でその次の数字が鈴木ならば、斜めになることも通路を挟むこともない。

$ cat <(cat names.txt | grep ' ') <(cat names.txt | grep -v ' ' | shuf | paste - - ) | shuf | xargs -n1 | nl
     1  伊藤
     2  高橋
     3  田中
     4  渡辺
     5  山本
     6  中村
     7  佐藤
     8  鈴木

ただし佐藤と鈴木の並び方は常に左右になる。上下の隣接にはならない。
もし上下の隣接が良いなら座席番号の配置を変えれば良い。

ちなみに

実際の席替えは、ランダムだと困る特定の人は先に座席を固定しておいて、残りの座席をスクリプトでランダムに決めることもある。
その時の状況によって制約が変わるので、書いたシェルスクリプトはその都度書き捨てている。

Discussion