行のシャッフル

行のシャッフル - みずぴー日記にインスパイヤされているわけですが、ほぼ同時に同じようなネタを考えていました。 それは、あまり料理のレパートリーのない人がうまくごまかすために自分の作れる料理をシャッフルすることで偏ることなく料理を作れるのではないかということを考えていました。

さて、とりあえずシャッフルを行う関数ですが、今までに何度も出てきていますので、スクリプト自体は見慣れたものになっています。

#! /usr/local/bin/nawk -f
# shuffle_lines.awk
# 行をシャッフルする
# usage: nawk -f shuffle_lines.awk file[s]

{
    line[NR] = $0;
}

END {
    shuffle_array(line);

    for (i = 1; i <= NR; i++) {
        print line[i];
    }
}

# 配列をシャッフルする
#   in:     配列
#   out:    元々の配列をシャフルされた配列に置換する
function shuffle_array(arr,    num_arr, tmp, a, i, j) {
    srand();

    for (a in arr) {
        num_arr++;
    }

    for (i = num_arr; i >= 1; i--) {
        j = int((i + 1) * rand());

        if (j == 0) {
            j = 1;
        }

        tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}

seq コマンドで試してみましょう。

$ seq 10 | nawk -f shuffle_lines.awk
8
4
1
3
2
7
9
5
6
10

ここで以下のようなファイルを用意して、シャッフルをすると飽きのこない献立ができあがります。

$ cat dishes.txt
カレーライス
ハヤシライス
パスタ
生姜焼き
ラーメン
おでん
すき焼き
焼肉
麻婆豆腐
青椒肉糸
回鍋肉
肉野菜炒め
焼き魚
お刺身

$ nawk -f shuffle_lines.awk dishes.txt
ハヤシライス
パスタ
回鍋肉
肉野菜炒め
すき焼き
お刺身
おでん
カレーライス
青椒肉糸
焼肉
ラーメン
焼き魚
生姜焼き
麻婆豆腐

そういえば、インスパイヤ元が一行野郎で書かれているので、awk でも一行野郎でシャッフルしてみます。

$ nawk '{a[NR]=$0}END{for(i in a)print a[i]}' dishes.txt
ハヤシライス
パスタ
生姜焼き
ラーメン
おでん
すき焼き
焼肉
麻婆豆腐
青椒肉糸
回鍋肉
肉野菜炒め
焼き魚
お刺身
カレーライス

awk の配列は連想配列で、呼び出す際にはインデックス順にならないため、それなりにシャッフルされるはずなのですが、あまりシャッフルされていませんでした。 残念。

tag_nawk.pngtag_nawk.pngtag_nawk.pngtag_nawk.png