Skip to content

Instantly share code, notes, and snippets.

@kotet
Created December 9, 2018 10:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kotet/20f8231a3dfa328cb81ccf491f502ac7 to your computer and use it in GitHub Desktop.
Save kotet/20f8231a3dfa328cb81ccf491f502ac7 to your computer and use it in GitHub Desktop.
シクシク素数列 Advent Calendar 2018
#!/usr/bin/rdmd
// 自然数を返す無限レンジ。
// map等の関数を使うためにはinputrangeである必要があり、
// inputrangeの条件を満たすためには
// front,popFront,emptyという3つの関数を実装する必要がある
struct NaturalNumber
{
long n = 1;
// 先頭の要素を返す
@property long front()
{
return n;
}
// 先頭の要素を取り除く
void popFront()
{
n++;
}
// 空であるか返す。無限レンジなので常にfalse
bool empty()
{
return false;
}
}
bool isPrime(long n)
{
// iには2からn-1までの整数が入る
foreach (i; 2 .. n)
{
if (n % i == 0)
{
return false;
}
}
return true;
}
bool is4949Prime(long n)
{
long tmp = n;
do
{
if (tmp % 10 == 4 || tmp % 10 == 9)
{
return isPrime(n);
}
tmp /= 10;
}
while (0 < tmp);
return false;
}
void main()
{
// 局所的 & 選択的インポート
import std.conv : to, text;
import std.array : join;
import std.range : take;
import std.stdio : readln, writeln;
import std.string : chomp;
import std.algorithm : filter, map;
long n = readln().chomp().to!long();
assert(1 <= n);
// 下のコードは
// writeln(join(map!(text)(take(filter!(is4949Prime)(NaturalNumber();), n)), ','));
// と等価。
NaturalNumber()
.filter!is4949Prime
.take(n)
.map!text
.join(',')
.writeln();
}
#!/usr/bin/rdmd
// 自然数を返す無限レンジ。
// map等の関数を使うためにはinputrangeである必要があり、inputrangeの条件を満たすためには
// front,popFront,emptyという3つの関数を実装する必要がある
struct NaturalNumber
{
long n = 1;
// 先頭の要素を返す
@property long front()
{
return n;
}
// 先頭の要素を取り除く
void popFront()
{
n++;
}
// 空であるか返す。無限レンジなので常にfalse
bool empty()
{
return false;
}
}
bool isPrime(long n)
{
foreach (i; 2 .. n)
{
if (n % i == 0)
{
return false;
}
}
return true;
}
bool is4949Prime(long n)
{
long tmp = n;
do
{
if (tmp % 10 == 4 || tmp % 10 == 9)
{
return isPrime(n);
}
tmp /= 10;
}
while (0 < tmp);
return false;
}
size_t[] createLookupTable(string str)
{
size_t[] result;
foreach (i, c; str)
{
if (c == ',')
{
// ~は配列に対する追加演算子。
// str[0..x]はstrの最初からx-1文字目までを表すので、
// コンマのインデックスを使うとそのコンマの手前までが表示できる
result ~= i;
}
}
// コンマは 100 - 1 == 99 個あるので、
// ここまででresultには N == 99 までの結果のインデックスが入っている。
// N == 100 の時は文字列全体を表示する
result ~= str.length;
return result;
}
void main()
{
import std.stdio : readln, writeln;
import std.string : chomp;
import std.conv : to, text;
import std.algorithm : filter, map;
import std.range : take, array;
import std.array : join;
long n = readln.chomp.to!long;
assert(1 <= n);
assert(n <= 100);
// enumはコンパイル時定数。数値リテラル100と同じような扱いを受ける
enum N = 100;
// この変数は値が実行ファイルに埋め込まれる。
// したがってその値の計算はコンパイル時に行われる
static immutable string str = NaturalNumber()
.filter!is4949Prime
.take(N)
.map!text
.join(',');
static immutable size_t[] lookuptable = createLookupTable(str);
// コンパイル時のassert
static assert(lookuptable.length == N);
// 実行時には配列を見るだけ
writeln(str[0 .. lookuptable[n - 1]]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment