"METHINKS IT IS A WEASEL"をやってみる

30分プログラム、その589。エロと風俗情報満載 どう抜く?をやってみる。

ランダムな文字からMETHINKS IT IS A WEASELを作るプログラムを作れ。
簡単に流れを書いてみます。

  1. ランダムな20文字を持つ文字列をもった300個作ります。
  2. その文字列が"METHINKSITISAWEASEL"に近いものからソートします。
  3. それぞれの文字列のなか1文字を別の文字に変化させたものを3つ用意します。
  4. それを2:のソートをして上位300個残す。(900個あるうちで上位300個残すということです。)
  5. 以後3:と4:を繰り返す。

一応、できたはずだけれども、全然収束しない。ま、これでできたことにしておこう。

使い方

1> meth:main().
"IXLQONMCIVMVDISISGQ"
"AEMKIBPZIEFAXVVIGVA"
"MNEHNDXQWDTYAMMOQFE"
"AEMKINPYIEFAXVVIGVA"
"MEMKINPYIEFAXVVIGVA"
...
"METHINKOITJSAWEASEP"
"METCINKKGTISAWEASET"

ソースコード

-module(meth).
-compile([export_all]).

init() ->
    {A1,A2,A3} = now(),
    random:seed(A1,A2,A3).

make_list(F,N) ->
    [F() || _ <- lists:seq(1,N)].

%% random text
random_char() ->
    random:uniform($Z-$A+1) - 1 + $A.

random_string() ->
    make_list(fun random_char/0,19).

%% distance
%
% assumption: both arguments has same length
diff([],[]) ->
    0;
diff([X|XS],[X|YS]) ->
    diff(XS,YS);
diff([_|XS],[_|YS]) ->
    1 + diff(XS,YS).

answer() ->
    "METHINKSITISAWEASEL".

sort(Xs) ->
    lists:sort(fun(X,Y)->  diff(answer(),X) < diff(answer(),Y) end,Xs).

%%
update(_,_,[]) ->
    [];
update(0,X,[_|Ys]) ->
    [X | Ys];
update(N,X,[Y|Ys]) ->
    [Y | update(N-1,X,Ys)].
change(S)->
    update(random:uniform(length(S))-1,random_char(),S).

%%
loop(Xs) ->
    io:format("~p~n",[hd(Xs)]),
    Ys = lists:flatmap(fun(X)-> [change(X), change(X), change(X)]end, Xs),
    loop(lists:sublist(sort(Ys),300)).

main() ->
    loop(sort(make_list(fun random_string/0,300))).