Bashシェルで「1000 以下の回文素数で最大のものを示せ」を問いてみる

はじめに

前回のエントリ素数をワンライナーで求める というネタをやりました。

もともと、今日のエントリを解くための前置きだったのでした。 課題はこちらのサイトから拝借しました。

今日問いてみようと思っている内容は、タイトル通りなのですが、ちょっとわかりにくいので解説しておきます。

  • 回文数 : 逆さに読んでも内容が変わらない数。( 例 1、 11、 121 )
  • 回文素数 : 回文数であり、かつ素数。 ( 例 2、 11、 101 )

1000 以下回文 素数 で最大のものを求めてみたいと思います。

検証環境

1
2
3
4
5
$ uname -moi
x86_64 x86_64 GNU/Linux

$ bash -version | head -n 1
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)

前回のおさらい : 素数を求めるワンライナー

1 から 1000 までの素数をワンライナーで列挙してみます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ factor {1..1000} | awk 'NF==2 { print $2 }'
2
3
5
7
11
(省略)
971
977
983
991
997

解説は前回のエントリを参照ください。シェルなら簡単ですね。

素数の内、回文であるもののみを出力する

素数がわかったので、この内回文のみを抽出してみます。

ここからはいい方法が思い浮かばなかったので、地道にループ処理を記述してみます。

  1. while コマンドで読み込む
  2. REPLY という変数に格納されるため、読み込んだ文字列 $REPLY と 順序を rev でじっくり返した値を比較
  3. 等しかったら echo で出力する

実行結果は以下のとおりです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
$ factor {1..1000} | awk 'NF==2 { print $2 }' | while read -r; do [[ $REPLY == $(echo $REPLY | rev) ]] && echo $REPLY; done
2
3
5
7
11
101
131
151
181
191
313
353
373
383
727
757
787
797
919
929

最期の1行だけを出力

後は最期の1行だけが欲しいため、 tail -n 1 でフィルタします。

1
2
$ factor {1..1000} | awk 'NF==2 { print $2 }' | while read -r; do [[ $REPLY == $(echo $REPLY | rev) ]] && echo $REPLY; done | tail -n 1
929

ひとこと

昔はこれをGroovyという言語でときました。 いつの間にかシェルが指に馴染む人間になってしまった。