■ その後のProbrem35
100万以下の巡回素数の数を数えよ。
少ない桁だと答えがでるが、100万以上だと計算おわらず。
とりあえず差分リスト化し、高速化をねらう。
=>だめ。それでも計算おわらない。
「もうPrologでこの問題やるのが無理あるよなー」
「あ、そうだ。素数を先に求めておいて、Prologコード中に事実として埋めこんだらいいんじゃね?」と思い、rubyをつかってPrologコードを生成。100万以下の素数リストをあらかじめ埋め込んでおく。
=>だめ。どっちにしろ計算おわらない。
「もうrubyで最後まで解いたらよくね?」と思いrubyで最後まで書く。
この段階でようやく問題の解釈をまちがっていたことに気づく。
巡回素数ってすべての並びかえがぜんぶ素数であるような数のことじゃないのか。2桁以下だとどっちにしても答えが同じになるので気づかなかった。
しかしどっちみちPrologでは無理そうだ。あと試すとすれば並列計算が残っているが、この段階にくるまで結構苦労したのでもう嫌になってやめる。
rubyで最後まで書いて終了。
数値計算の遅いPrologではProject Eulerは解けない気がするぞ。
■ IT用語について
よくカタカナ語やアルファベット略字の多様が問題視されますが、わたしは、ITの人の日本語の動詞の使い方の方が独特だと思います。
「吐く」とか「叩く」とか。
「フィードを吐く」とか「SQLを叩く」とか「DNSをひく」とか。あれはかなり独特なオーラをはなつ言葉の使い方だと思う。
個人的には「名前空間を汚す」が好きだ。まず「名前空間」の時点でかなりギョッとする。「名称空間」とかじゃなくて「名前」というやわらかい言葉を選んでいるところがミソだと思う。名前と空間がくっついているところで、まずまったく意味がわからないのに、しかもそれを「汚す」ときた。これは恐い。「おまえの名前空間を汚してやる」って言われたら、それだけで泣いて謝って帰る気がする。
なんとなくそっち系の妄想みたいな語感がするのも素敵だ。
「名前解決」も結構好き。適当に2つの熟語を組み合わせたみたいな感がある。
■ Probrem 36
あんま覚えてない。PrologとちがってC++速いなあと思った記憶がある。
11個目をみつけるのがむずかしい。素朴に計算したら計算がおわらなかったので候補をしぼる方法を考えた。
■ 第五世代コンピュータ
Prologに触れていたせいで、第五世代コンピュータ計画が気になってきたので調べてみようと思う。
破産したプロジェクトというのは甘美なものである。
Prologマシンをつくって、いっぱいつないで並列計算させるとか、何に使うのか全然イメージわかないがすごいなあ。
「Logical Inference Per Second」っていうマシン評価の単位もおもしろいと思う。
■ Prolog
Brainfuckインタープリタを書いてみた。
遅い。メモリの表現がこれではダメなので、なんかもっと考えましょう。
#!/usr/bin/pl -q -t main -s
cmd(C,A) :-
C='>',!, A=incptr;
C='<',!, A=decptr;
C='+',!, A=inc;
C='-',!, A=dec;
C='.',!, A=putc;
C=',',!, A=getc;
C='[',!, A=ljmp;
C=']',!, A=rjmp.
bf_op(C) :-
member(C,[ '>','<','+','-','.',',','[',']' ]),!.
pointer(Prev,Next,Val,P) :- !,
P = pointer(Prev,Next,Val).
pointer(Prev,Next,Val,[Cmd|Arg],Res) :-
Cmd = next,!, Arg = [Self|_],
(
Next = [],!, Res = pointer(Self,[],0);
call(Next,[set_prev,Self,Next],Res)
);
Cmd = prev,!, Arg = [Self|_],
(
Prev = [],!, Res = pointer([],Self,0);
call(Prev,[set_next,Self,Prev],Res)
);
Cmd = inc,!, NewV is Val + 1,
Res = pointer(Prev,Next,NewV);
Cmd = dec,!, NewV is Val -1,
Res = pointer(Prev,Next,NewV);
Cmd = set_prev,!, Arg = [NewP,Self],
(
NewP = Prev,!, Res = Self;
% Next = [],!,
Res = pointer(NewP,Next,Val)
%;
% call(Next,[set_prev,Self,Next],NewN),
% Res = pointer(NewP,NewN,Val)
);
Cmd = set_next,!, Arg = [NewN,Self],
(
NewN = Next,!, Res = Self;
% Prev = [],!,
Res = pointer(Prev,NewN,Val)
%;
% call(Prev,[set_next,Self,Prev],NewP),
% Res = pointer(NewP,NewN,Val)
);
Cmd = set_val,!, Arg = [NewV],
Res = pointer(Prev,Next,NewV).
exec(incptr,P,Res) :- !,
call(P,[next,P],Res).
exec(decptr,P,Res) :- !,
call(P,[prev,P],Res).
exec(inc,P,Res) :- !,
call(P,[inc],Res).
exec(dec,P,Res) :- !,
call(P,[dec],Res).
exec(putc,P,Res) :- !,
arg(3,P,V), put(V), Res=P.
exec(getc,P,Res) :- !,
get_code(C),call(P,[set_val,C],Res).
exec(loop,P,Code,Res) :-
arg(3,P,V),
(
V=0,!,Res = P;
!,interpret(Code,P,Res2),
arg(3,Res2,V2),
(
V2=0,!, Res=Res2;
!,exec(loop,Res2,Code,Res)
)
).
interpret([IP|R],Pnt,Result) :-
atomic(IP),!,
cmd(IP,C), exec(C,Pnt,Res),
interpret(R,Res,Result);
is_list(IP),!,
exec(loop,Pnt,IP,Res),
interpret(R,Res,Result).
interpret([],Pnt,Pnt).
parse(IO,Cord) :- !,
parse(IO,[X,X],Cord).
parse(IO,[H,Tail],Cord) :-
get_char(IO,C),
C ¥= end_of_file,
(
C = '[',!,
parse(IO,[Tmpdl,Tmpdl],Inner),
Tail = [Inner|NewT],
parse(IO,[H,NewT],Cord);
C = ']',!,
Tail = [],
Cord = H;
bf_op(C),!,
Tail = [C|NewT],
parse(IO,[H,NewT],Cord)
).
parse(IO,[H,[]],H) :-
at_end_of_stream(IO),!.
parse(IO,M,C) :- !,
parse(IO,M,C).
script_arg(['--'|X],X) :- !.
script_arg([_|R],X) :- !,
script_arg(R,X).
load_arg(L) :-
current_prolog_flag(argv,A),
script_arg(A,L),
(
L=[],!,
writeln('usage: bfi.pl /path/to/code/');
true,!
).
main :-
load_arg([Fname|_]),
writeln('open:'), writeln(Fname),
open(Fname,read,IO),
parse(IO,Cord),
close(IO),
writeln('parse tree:'), writeln(Cord),
pointer([],[],0,P),
writeln('result:'),
interpret(Cord,P,_).
トラックバック(0)
このブログ記事を参照しているブログ一覧: 雑記2008年6月9日(月)
このブログ記事に対するトラックバックURL: http://www.at-akada.org/mt/mt-tb.cgi/928
コメントする