はじめに
この記事はシクシク素数列 Advent Calendar 2018の10日目の記事です。同時に合成数列の和アドベントカレンダーの番外編記事を投稿していますのでこちらもご覧ください。
解答
少し長めです。空白区切りのリストをカンマ区切りにする方法に苦しんで長くなってしまいました。
#!/usr/bin/jconsole.sh echo ([`(','&[)@.(=&' '))"0@(".^:_1)@(p:@I.@(1&=)@}.@(([,((}.@((<.@(%&10)@{.,+./@(4&=,9&=)@(10&|)@{.)^:(*./@(0&~:@{.,1&~:@}.))^:_)@p:)@#@}.))^:({.~:(+/@}.))^:_)) ".@>(2}ARGV) exit ''
実行例
$ ./script.ijs 2 19,29 $ ./script.ijs 4 19,29,41,43 $ ./script.ijs 100 19,29,41,43,47,59,79,89,97,109,139,149,179,191,193,197,199,229,239,241,269,293,347,349,359,379,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,509,541,547,569,593,599,619,641,643,647,659,691,709,719,739,743,769,797,809,829,839,8...
出力が長いと途切れてしまうんですが、これの解決方法がわかりません……
解説
数字中に4, 9 が含まれるかを判定する
}.@((<.@(%&10)@{.,+./@(4&= , 9&=)@(10&|)@{.)^:(*./@(0&~:@{.,1&~:@}.))^:_)
(proc)^:(cond)^:_
というのが不定回ループするためのidiomで、再帰は関数単位でしか使えないのに比べて柔軟性があります。10で割っていきながら余りを見て、各桁で4か9が含まれたら1、そうでなければ0を返しています。リストを使った高度なループパターンを構築したと思ったんですが詳細を忘れました。
4949素数列を生成する
p:@I.@(1&=)@}.@(([,(}.@((<.@(%&10)@{.,+./@(4&= , 9&=)@(10&|)@{.)^:(*./@(0&~:@{.,1&~:@}.))^:_)@#@}.))^:({.~:(+/@}.))^:_)
ちょっと読めないですね……。
空白区切りをカンマ区切りに変換する
([`(','&[)@.(=&' '))"0@(".^:_1)
".^:_1
がtoStringにあたる秀逸なコードで、".
が eval相当、^:_1
は逆関数にあたります。これどうやって実現しているんでしょう。
おわりに
スクリプト書いたの昔過ぎて何をしているのか忘れてしまいました。よくこんなの書いたと思います。