問題はこちら->http://nabetani.sakura.ne.jp/hena/orde30sumt/
無限に長い領域ということで、最初は遅延評価を使った無限リスト問題かと思いましたが、
1から順に計算すると時間がかかりそうですし、最下部によって範囲が限定されていますので、
普通の解き方で挑戦しました。
まず下の列から順に、リストに入れるセルの範囲を決めます。
問題の規則をうまくあてはめられるよう(右端は無視)、作成する上の列のリストの範囲は、
可能なら下位、上位とも下の列と重複している範囲より1セルづつ増やします。
「面白くないセル」の数字を0にして、加えても影響がないようにして保存します(fun/2)。
take/3で上のセルとの関係を計算し、必要な部分を取り出してcalc/5で1セルずつ計算しています。
下位のリスト内のセルの開始位置が上のセルの幅より短いときは、上のリストをすべて使います。
それ以外のときは、最初のセルを除外して使います。
下の列のセルの下端と上端に当たる上の列のリスト内の位置を求め、その間の数字を合計します。
上のセルの下端は最初は1、その後は1つ前の下のセルの上端又は上端+1に当たる位置を、
上下のリスト内のセルの開始位置の差と両方のセルの幅から計算しています。
これを下のセルすべてに対し行います。
変数はその列以下の列とそれより上の列の2つを持たなければならないので多くなっています。
基本はこれだけですが、takeの部分をできるだけ計算せずにリスト操作だけで書こうとして、
だいぶ時間を無駄にしました。
また1000の剰余をとる部分もうっかりして、とんでもない数字が出るのに困惑したりしました。
%swi-Prolog version 7.4.2
%start.
%:-initialization(start). % ideone
fun([H|T],R):-fun([H|T],[],[H],L),reverse(L,R). %suuji no henkan
fun([_,X],_,R,[X|R]).
fun([X,Y],[],_,[X,Y]).
fun([X,Y,Z|T],L,R,FR):-(not((X=:=Y,Y=:=Z))->R1=[Y|R];R1=[0|R]),fun([Y,Z|T],[X|L],R1,FR).
range(N,L,R):-
reverse(L,[H|T]),MAX is N*H,MIN is MAX-H,range1(N,T,[[1,H,MIN,MAX]],R).
range1(_,[],R,R).
range1(N,[H|T],R1,R):-
R1=[[_,_,MIN1,MAX1]|_],MA is MAX1-1,D1 is MIN1 div H,D2 is MA div H,
X is max(D1-1,0),MIN is X*H, MAX is (D2+2)*H,RE is D2+2-X, %RE repeat
R2=[RE,H,MIN,MAX],range1(N,T,[R2|R1],R).
calc(F,TO,_,N,N):-F>TO.
calc(F,TO,L,N,R):-nth1(F,L,V),N1 is V+N,F1 is F+1,calc(F1,TO,L,N1,R).
take([_],L,L).
take([H,K|T],L,R):-
fun(L,[H1|T1]),H=[_,W,MIN,_],K=[RE,W1,MIN1,_],
(MIN1<W->(DIF is MIN1-MIN,L1=[H1|T1]);(DIF is MIN1-MIN-W,L1=T1)),
take1(DIF,RE,W1,W,1,L1,[],L2),take([K|T],L2,R).
take1(_,0,_,_,_,_,L,R):-reverse(L,R).
take1(DIF,RE,W1,W,F,L,R,FR):-
P is DIF+W1,divmod(P,W,X,Y),(Y=:=0->TO is X;TO is X+1),
calc(F,TO,L,0,N),N1 is N mod 1000,R1=[N1|R],
RE1 is RE-1,(Y=:=0->F1 is TO+1;F1=TO),take1(P,RE1,W1,W,F1,L,R1,FR).
solve(N,L,R):-
range(N,L,[H|T]),H=[_,W,MIN,MAX],FR is MIN div W+1 ,TO is MAX div W,
numlist(FR,TO,L1),take([H|T],L1,R),!.
start:-str(S),
split_string(S,"\n","",L),pre(L).
pre([]):-!.
pre([S|T]):-
split_string(S,"\s","\s",[_,B,C]),split_string(B,"/","",[X,Y]),
atomics_to_string(L,",",X),maplist(atom_number,L,L1),atom_number(Y,Y1),
solve(Y1,L1,R),disp(R,C),pre(T).
disp([R],C):-number_string(R,S),(S==C->write("pass ");write(" fail ")),writeln(S),!.
str("0 4,6,1,5/3 14
1 1/1 1
2 6/1 1
3 4,6/3 9
4 68/68 68
5 360/10 10
6 2,7,8/8 256
7 37,88/71 504
8 5,4,1,4/6 10
9 123/4567 4567
10 473,601/397 9
11 47,89,82/38 402
12 4,8,1,2,10/10 98
13 5,6,7,9,5,2/5 48
14 538,846,73/778 213
15 80,48,65,83/100 830
16 1,4,6,10,5,7,5/5 904
17 10,4,1,6,1,2,3,5/3 9
18 3,1,4,1,5,9,2/14 385
19 33,32,75,24,36/76 491
20 43,59,32,2,66,42/58 849
21 985,178,756,798/660 675
22 3,4,3,4,5,2,3,10,2/5 334
23 9,3,4,3,1,9,4,9,3,9/5 516
24 883,184,29,803,129/129 154
25 4,77,53,79,16,21,100/59 690
26 49,94,4,99,43,78,22,74/1 282
27 292,871,120,780,431,83/92 396
28 4,2,9,1,5,10,7,6,8,9,10/3 234
29 9,5,7,6,9,3,4,10,8,6,4,5/6 990
30 11,87,44,12,3,52,81,33,55/1 384
31 9,2,6,9,5,1,3,6,1,9,2,1,4/9 498
32 68,62,15,97,5,68,12,87,78,76/57 751
33 792,720,910,374,854,561,306/582 731
34 5,10,1,7,5,3,5,7,4,8,9,6,1,9,6/5 768
35 7,2,7,8,3,4,2,10,6,10,3,1,10,2/10 120
36 4,2,10,7,8,9,8,1,9,7,9,10,9,4,7,2/8 40
37 41,55,80,12,39,94,2,96,45,89,25/68 152
38 907,371,556,955,384,24,700,131/378 600
39 30,68,36,40,10,74,42,24,4,47,91,51/4 180
40 807,276,175,555,372,185,445,489,590/287 80
41 92,41,37,49,26,68,36,31,30,34,19,18,94/85 626
42 529,153,926,150,111,26,465,957,890,887/118 114
43 59,1,87,64,17,37,95,25,64,68,52,9,57,92/94 998
44 979,772,235,717,999,292,727,702,710,728,556/33 912
45 40,93,46,27,75,53,50,92,52,100,19,35,52,31,54/59 512
46 800,778,395,540,430,200,424,62,342,866,45,803/931 260
47 85,90,67,61,17,57,24,25,5,50,88,31,55,26,21,98/58 884
48 510,515,70,358,909,557,886,766,323,624,92,342,424/552 238
49 892,751,88,161,148,585,456,88,14,315,594,121,885,952/833 700
50 940,824,509,787,942,856,450,327,491,54,817,95,60,337,667/637 206
51 408,412,30,930,372,822,632,948,855,503,8,618,138,695,897,852/377 212").
上の解答で問題ないのですが、例えば、「最下部の列の数字がxを超えるときの値y」などが、
問われた場合のため遅延評価ではありませんが上限を限定しないで解いてみました。
rangeでは下限のみ求めています。
セルの下端上端と数字のセットは一つずつ下の列に送り、
funはデータを最大3個に制限することで簡潔になっています。
calcではsumの初期値は0。上のセルの上端が下のセルの下端の位置より小さいときは無視。
上のセルの上端が下のセルの下端以上の位置にあるときは、そのセルの数字を加えます。
上のセルの上端が下のセルの上端以上になったら、検索は中止し、上位のセルの位置を保存し、
sumとセルの下端上端のセットを下の列の該当のリストに加えて、下の列の処理に移ります。
最下位まで行ったら最上位に戻ります。
より複雑な、calcで複数のセルを求めて下位に送る方法よりやや時間がかかりますが許容範囲内です。
range(N,L,R):-
reverse(L,[H|T]),MIN is (N-1)*H+1,range1(T,[[H,MIN]],R).
range1([],R,R).
range1([H|T],R1,R):-
R1=[[_,MIN1]|_],D1 is (MIN1-1) div H,
X is max(D1-1,0),MIN is X*H+1, %RE repeat
R2=[H,MIN],range1(T,[R2|R1],R).
%suuji no henkan
fun([X],[X]).
fun([_,_],[]).
fun([_:X:_,F:Y:T,_:Z:_],R):-not((X=:=Y,Y=:=Z))->R=[F:Y:T];R=[F:0:T].
calc([],H2,TH,_,R):-R=[H2,TH,[]].
calc([_:_:MINA|T],[W2,MIN2],TH,SUM,R):-
MINA<MIN2,!,calc(T,[W2,MIN2],TH,SUM,R).
calc([MINB:X:MINA|T],[W2,MIN2],_,SUM,R):-
MID2 is MIN2+W2-1,MID2=<MINA,!,SUM1 is (SUM+X) mod 1000,
MID3 is MID2+1,H21=[W2,MID3],
(MINA=:=MID2->TH1=T;TH1=[MINB:X:MINA|T]),R=[H21,TH1,[MIN2:SUM1:MID2]].
calc([MINB:X:MINA|T],H2,TH,SUM,R):-
append(TH,[MINB:X:MINA],TH1),SUM1 is SUM+X,calc(T,H2,TH1,SUM1,R).
take([],R0,_,TL,P,P1,_,F0,R):-
append(P1,P,P2),R=[R0,TL,P2,F0],!.
take([H2|T1],R0,[TH|TT],TO,[P1,P2|T],P0,[FH|FT],F0,R):-
length(P1,N),(FH<N->((N>3->P1=[_|P11];P11=P1),fun(P11,CH),append(TH,CH,TH2));
(P11=P1,TH2=TH)),calc(TH2,H2,[],0,[H21,TH3,P21]),length(P11,N1),
append(P2,P21,P3),append(R0,[H21],R01),append(TO,[TH3],TO1),append(P0,[P11],P01),
append(F0,[N1],F01),take(T1,R01,TT,TO1,[P3|T],P01,FT,F01,R).
%p2 ue no retu p3 sita no retu
solve(_,_,_,L,_,R):- % zentai no kurikaesi
last(L,[_:R:_]),!.
solve(FR,[H|T],TL,[H1|T1],FL,R):-
H=[W,MIN],MAX is MIN+W-1,append(H1,[MIN:FR:MAX],H11),
take(T,[],TL,[],[H11|T1],[],FL,[],[R1,TL1,PL,FL1]), %[H|T]->rule [H11|T1]->cell no list
FR1 is FR+1,MIN1 is MIN+W,H2=[W,MIN1],solve(FR1,[H2|R1],TL1,PL,FL1,R).
solve(N,L,R):-
range(N,L,[H|T]),H=[W,MIN],FR is (MIN-1) div W+1,length(L,M),length(RL,M),length(FL,M),
maplist(=([]),RL),maplist(=(0),FL),copy_term(RL,TL),solve(FR,[H|T],TL,RL,FL,R),!.
start:-str(S),
split_string(S,"\n","",L),pre(L).
pre([]):-!.
pre([S|T]):-
split_string(S,"\s","\s",[_,B,C]),split_string(B,"/","",[X,Y]),
atomics_to_string(L,",",X),maplist(atom_number,L,L1),atom_number(Y,Y1),
solve(Y1,L1,R),disp(R,C),pre(T).
disp(R,C):-number_string(R,S),(S==C->write("pass ");write(" fail ")),writeln(S),!.
上の解を書いているとき、感覚的に上位から一方的に流れてくるのが気になり、
イテレータではどうなるのか試してみました。
Nimのイテレータが使いやすそうでしたので、@cielavenirさんの
https://qiita.com/cielavenir/items/5728944867e609fd52a7#_reference-c0d5be4ce507e7695841
等を参考にNimで書いてみました。
takeは二つくらいの関数に分けるところでしょうがさぼっています。
セルの情報が数値と上下端の位置でなく、下端の位置と幅と数値です。
他はやっていることはすぐ上のプログラムとほぼ同じですが、
calcでは完成したセルを順次下位に送りながら、最後まで検索しています。
(上のと同じにしたら時間がかかりすぎました)
これでもfun等が複雑にならないのはいいところです。
しかし同じような方法ではPrologのほうが早いということは、イテレータの仕組みは、
結構負荷のかかる仕組みなのでしょうか。
NimはAtom editer上で扱えば、パズルを解く程度ならインタプリタ感覚で使えるし、
速くてよいのですが、今回は型の部分や読み込みの部分で結構苦労しました。
#atom editer,ideone
import os,strutils,sequtils,times
#import math #これがないと累乗が使えない
import algorithm,nre
#import sets,lists,critbits,queues,intsets,options,tables,hashes
const str="""0 4,6,1,5/3 14
1 1/1 1
2 6/1 1
3 4,6/3 9
4 68/68 68
5 360/10 10
6 2,7,8/8 256
7 37,88/71 504
8 5,4,1,4/6 10
9 123/4567 4567
10 473,601/397 9
11 47,89,82/38 402
12 4,8,1,2,10/10 98
13 5,6,7,9,5,2/5 48
14 538,846,73/778 213
15 80,48,65,83/100 830
16 1,4,6,10,5,7,5/5 904
17 10,4,1,6,1,2,3,5/3 9
18 3,1,4,1,5,9,2/14 385
19 33,32,75,24,36/76 491
20 43,59,32,2,66,42/58 849
21 985,178,756,798/660 675
22 3,4,3,4,5,2,3,10,2/5 334
23 9,3,4,3,1,9,4,9,3,9/5 516
24 883,184,29,803,129/129 154
25 4,77,53,79,16,21,100/59 690
26 49,94,4,99,43,78,22,74/1 282
27 292,871,120,780,431,83/92 396
28 4,2,9,1,5,10,7,6,8,9,10/3 234
29 9,5,7,6,9,3,4,10,8,6,4,5/6 990
30 11,87,44,12,3,52,81,33,55/1 384
31 9,2,6,9,5,1,3,6,1,9,2,1,4/9 498
32 68,62,15,97,5,68,12,87,78,76/57 751
33 792,720,910,374,854,561,306/582 731
34 5,10,1,7,5,3,5,7,4,8,9,6,1,9,6/5 768
35 7,2,7,8,3,4,2,10,6,10,3,1,10,2/10 120
36 4,2,10,7,8,9,8,1,9,7,9,10,9,4,7,2/8 40
37 41,55,80,12,39,94,2,96,45,89,25/68 152
38 907,371,556,955,384,24,700,131/378 600
39 30,68,36,40,10,74,42,24,4,47,91,51/4 180
40 807,276,175,555,372,185,445,489,590/287 80
41 92,41,37,49,26,68,36,31,30,34,19,18,94/85 626
42 529,153,926,150,111,26,465,957,890,887/118 114
43 59,1,87,64,17,37,95,25,64,68,52,9,57,92/94 998
44 979,772,235,717,999,292,727,702,710,728,556/33 912
45 40,93,46,27,75,53,50,92,52,100,19,35,52,31,54/59 512
46 800,778,395,540,430,200,424,62,342,866,45,803/931 260
47 85,90,67,61,17,57,24,25,5,50,88,31,55,26,21,98/58 884
48 510,515,70,358,909,557,886,766,323,624,92,342,424/552 238
49 892,751,88,161,148,585,456,88,14,315,594,121,885,952/833 700
50 940,824,509,787,942,856,450,327,491,54,817,95,60,337,667/637 206
51 408,412,30,930,372,822,632,948,855,503,8,618,138,695,897,852/377 212"""
proc generate(min,w:int):iterator:(int,int,int) =
return iterator:(int,int,int) =
var min=min
var x=((min-1) div w)+1
while true:
yield (min,w,x)
x+=1
min=min+w
proc take(min2,w2:int,prev:iterator:(int,int,int)):iterator:(int,int,int) =
return iterator:(int,int,int) =
var
bef,aft:seq[(int,int,int)]
ln,min,w,y,min1,w1,x,sum,tp:int
min2=min2
(min1,w1,x)=prev()
bef= @[]
aft= @[]
while true:
#規則に則って数字を選ぶ代わりにいらない数字も0にして保存する
#セルの開始位置と幅の情報をつける
add(bef,(min1,w1,x))
ln=bef.len
if ln==1:
add(aft,(min1,w1,x))
elif ln>=3:
if ln>3:
bef.delete(0)
if bef[0][2]==bef[1][2] and bef[1][2]==bef[2][2]:
add(aft,(bef[1][0],bef[1][1],0))
else:
add(aft,(bef[1][0],bef[1][1],bef[1][2]))
#下位のセルと重複した上位のセルの数を合計し下位のセルに送る
ln=aft.len
if not(aft== @[]):
sum=0
tp=0
while tp<ln :
min=aft[tp][0]
w=aft[tp][1]
y=aft[tp][2]
if min+w-1<min2:
aft.delete(0)
ln-=1
elif min+w>=min2+w2:
sum=(sum+y) mod 1000
yield (min2,w2,sum)
min2=min2+w2
if min+w==min2:
sum=0
tp+=1
else:
sum=0
else:
sum=sum+y
tp+=1
(min1,w1,x)=prev()
proc limit(n:int,list:seq[int]):seq[array[0..1,int]]=
var dat:seq[array[0..1,int]]
dat= @[]
var li=list
var min=(n-1)*li[0]+1
dat.add([min,li[0]])
li.delete(0)
for w in li:
min=max(((min-1) div w)-1,0)*w+1
dat.add([min,w])
return dat
proc solve(n:int,list:seq[int]):int=
var nl=limit(n,list)
nl.reverse
var z=generate(nl[0][0],nl[0][1])
nl.delete(0)
for i in nl:
z=take(i[0],i[1],z)
var res=z()
return res[2]
proc main()=
var sel:string
for s in str.splitLines :
var s1=s.replace(re"(\s+)"," ").split(" ")
var s2=s1[1].split("/")
var s3=s2[0].split(",")
s3.reverse
var s4=map(s3,proc(x:string):int=x.parseint)
var ans=solve(s2[1].parseint,s4)
if ans==s1[2].strip.parseInt:
sel="pass"
else:
sel="fail"
echo(sel," ",ans)
main()
イテレーターを使ったプログラムを書いているうちに、erlangでメッセージ交換をしながら、
データを渡す方法を試してみたくなりました。(速さが心配ですが)
しかししばらくerlangで書いていなかったため、文法をほとんど忘れてしまい、
プロセスの生死も想定通りにいかずに行き詰まっています。
投稿の旬も過ぎそうですので、とりあえず今までに完成したものを投稿します。
2月17日追加。
プロセスの問題ではなかったようで、答えが出るようになったら、
プロセスがどうなっているかわかりませんが、フリーズしなくなりました。
solve/3から各段のセルの開始位置と幅の情報を持たせてプロセスtake/2を作ると、
takeが逐次的に下の段の情報を持った子のプロセス(take)を作ります。
最後に情報を持たないプロセスができたら、
数字を求めるメッセージ(req)を親のプロセスに送ります。
親のプロセスは、reqが来たらデータリスト(DL)に要素があればれば、子のプロセスにすべて送り、
無ければさらに親のプロセスにreqを送り変数Reqをtrueにします。
親から{data,{Min1,W1,X}}が送られてきたら、calc/7で新しい数字を作り、
作れればDlに追加し、Reqがtrueなら子に送り、Reqをfalseにします。
作れなければ親にreqを送ります。
これを繰り返します。
{ans,Num}メッセージが来たら、親に同じメッセージを送り停止します。
solveのループではreqが来たら当たらしい数字を送り、
{ans,Num}が来たら、Numを戻り値とします。
その数値をsolve内で答え合わせして終わりです。
どういうわけかfunがエラーになりますのでchaにしています。
%Erlang/OTP 21,Eshell V10.1
% erl -> c(e30). ->e30:start().
-module(e30).
-export([take/2,cha/1,calc/7,loop2/8,solve/3,start/0]).
take([],Up)->
Up! req,
receive
{data,{_,_,X}}->
Up! {ans,X}
end;
take([{Min2,W2}|T],Up)->
Self=self(),
Pid=spawn(e30,take,[T,Self]), % Pid iranai?
loop2([],[],Min2,W2,Pid,Up,[],false).
cha([X])->[X];
cha([_,_])->[];
cha([{_,_,X},{F,W,X},{_,_,X}])->[{F,W,0}];
cha([_,{F,W,X},_])->[{F,W,X}].
calc([],Nl,Min2,_,_,_,Dl)->{Min2,Nl,Dl};
calc([{Min,W,_}|T],_,Min2,W2,Pid,Sum,Dl) when Min+W-1<Min2->
calc(T,T,Min2,W2,Pid,Sum,Dl);
calc([{Min,W,Y}|T],Nl,Min2,W2,Pid,Sum,Dl) when Min+W>=Min2+W2->
Sum1=(Sum+Y) rem 1000,
Dl1=lists:append(Dl,[{Min2,W2,Sum1}]),
Min21=Min2+W2,
if
Min+W==Min21->calc(T,T,Min21,W2,Pid,0,Dl1);
true->calc([{Min,W,Y}|T],Nl,Min21,W2,Pid,0,Dl1)
end;
calc([{_,_,Y}|T],Nl,Min2,W2,Pid,Sum,Dl)->
Sum1=Sum+Y,
calc(T,Nl,Min2,W2,Pid,Sum1,Dl).
loop2(Data,Nl,Min2,W2,Pid,Up,Dl,Req)->
receive
{ans,Num}->
Up! {ans,Num};
{data,{Min1,W1,X}}->
Data1=lists:append(Data,[{Min1,W1,X}]),
if
erlang:length(Data1)>3->[_|Data2]=Data1;
true->Data2=Data1
end,
Nl1=lists:append(Nl,cha(Data2)),
{Min21,Nl2,Dl1}=calc(Nl1,Nl1,Min2,W2,Pid,0,Dl),
if
Dl1=:=[]->Up! req,loop2(Data2,Nl2,Min21,W2,Pid,Up,[],Req);
true->
if Req==true->send(Pid,Dl1),Req1=false,Dl2=[];
true->Req1=Req,Dl2=Dl1
end,
loop2(Data2,Nl2,Min21,W2,Pid,Up,Dl2,Req1)
end;
req->
if
Dl=:=[]->Up! req,Req1=true;
true->send(Pid,Dl),Req1=false
end,
loop2(Data,Nl,Min2,W2,Pid,Up,[],Req1)
end.
send(_,[])->[];
send(Pid,[H|T])->
Pid! {data,H},
send(Pid,T).
range([],R)->R;
range([H|T],R1)->
[{Min1,_}|_]=R1,
D1 = (Min1-1) div H,
X = max(D1-1,0),Min = X*H+1, %RE repeat
R2={Min,H},range(T,[R2|R1]).
loop1(Fr,Min,W,Pid)->
receive
req->
Pid! {data,{Min,W,Fr}},
Fr1 = Fr+1,Min1 = Min+W,
loop1(Fr1,Min1,W,Pid);
{ans,Num}->
Num
end.
solve(N,L,A)->
[H0|T0]=lists:reverse(L),Min=(N-1)*H0+1,[H|T]=range(T0,[{Min,H0}]),
{Min1,W1}=H,Fr = ((Min1-1) div W1)+1, Self = self(),
Pid=spawn(e30,take,[T,Self]),
Num=loop1(Fr,Min1,W1,Pid),
if
Num==A->Str="pass ";
true->Str="fail "
end,
io:format("~p~p~n",[Str,Num]).
start()->
S=str(),
Str=string:tokens(S,"\n"),
pre(Str).
pre([])-> ok;
pre([H|T])->
[_,LS,NS,AS]=string:tokens(H," /"),
NL=string:tokens(LS,","),
L=lists:map(fun(X)->string:to_integer(X) end,NL),
L1=lists:map((fun(X)->{Y,_}=X,Y end),L),
{N,_}=string:to_integer(NS),
{A,_}=string:to_integer(AS),
solve(N,L1,A),
pre(T).
str()->
"0 4,6,1,5/3 14
1 1/1 1
2 6/1 1
3 4,6/3 9
4 68/68 68
5 360/10 10
6 2,7,8/8 256
7 37,88/71 504
8 5,4,1,4/6 10
9 123/4567 4567
10 473,601/397 9
11 47,89,82/38 402
12 4,8,1,2,10/10 98
13 5,6,7,9,5,2/5 48
14 538,846,73/778 213
15 80,48,65,83/100 830
16 1,4,6,10,5,7,5/5 904
17 10,4,1,6,1,2,3,5/3 9
18 3,1,4,1,5,9,2/14 385
19 33,32,75,24,36/76 491
20 43,59,32,2,66,42/58 849
21 985,178,756,798/660 675
22 3,4,3,4,5,2,3,10,2/5 334
23 9,3,4,3,1,9,4,9,3,9/5 516
24 883,184,29,803,129/129 154
25 4,77,53,79,16,21,100/59 690
26 49,94,4,99,43,78,22,74/1 282
27 292,871,120,780,431,83/92 396
28 4,2,9,1,5,10,7,6,8,9,10/3 234
29 9,5,7,6,9,3,4,10,8,6,4,5/6 990
30 11,87,44,12,3,52,81,33,55/1 384
31 9,2,6,9,5,1,3,6,1,9,2,1,4/9 498
32 68,62,15,97,5,68,12,87,78,76/57 751
33 792,720,910,374,854,561,306/582 731
34 5,10,1,7,5,3,5,7,4,8,9,6,1,9,6/5 768
35 7,2,7,8,3,4,2,10,6,10,3,1,10,2/10 120
36 4,2,10,7,8,9,8,1,9,7,9,10,9,4,7,2/8 40
37 41,55,80,12,39,94,2,96,45,89,25/68 152
38 907,371,556,955,384,24,700,131/378 600
39 30,68,36,40,10,74,42,24,4,47,91,51/4 180
40 807,276,175,555,372,185,445,489,590/287 80
41 92,41,37,49,26,68,36,31,30,34,19,18,94/85 626
42 529,153,926,150,111,26,465,957,890,887/118 114
43 59,1,87,64,17,37,95,25,64,68,52,9,57,92/94 998
44 979,772,235,717,999,292,727,702,710,728,556/33 912
45 40,93,46,27,75,53,50,92,52,100,19,35,52,31,54/59 512
46 800,778,395,540,430,200,424,62,342,866,45,803/931 260
47 85,90,67,61,17,57,24,25,5,50,88,31,55,26,21,98/58 884
48 510,515,70,358,909,557,886,766,323,624,92,342,424/552 238
49 892,751,88,161,148,585,456,88,14,315,594,121,885,952/833 700
50 940,824,509,787,942,856,450,327,491,54,817,95,60,337,667/637 206
51 408,412,30,930,372,822,632,948,855,503,8,618,138,695,897,852/377 212".
ところで前の解答を投稿後「どう書く」の皆さんの解答を拝見しました。
angel-p57 さんの
https://github.com/angel-p57/yhpg/blob/master/e30/solve.rb
が、よくわからないながらも何となく私の最初の解答に似ているような気がするのですが、
いずれにせよ一時間でしかもこんなに簡潔に書いてしまうなんて驚きです。
2019.2.24追加
前のプログラムのloop2/8ではsend/2を使わない方が論理的にすっきりします。
遅いと勘違いしていました。
loop2(Data,Nl,Min2,W2,Pid,Up,Dl,Req)->
receive
{ans,Num}->
Up! {ans,Num};
{data,{Min1,W1,X}}->
Data1=lists:append(Data,[{Min1,W1,X}]),
if
erlang:length(Data1)>3->[_|Data2]=Data1;
true->Data2=Data1
end,
Nl1=lists:append(Nl,cha(Data2)),
{Min21,Nl2,Dl1}=calc(Nl1,Nl1,Min2,W2,Pid,0,Dl),
if
Dl1=:=[]->Up! req,loop2(Data2,Nl2,Min21,W2,Pid,Up,[],Req);
true->
if Req==true->[H|Dl2]=Dl1,Pid! {data,H},Req1=false;
true->Req1=Req,Dl2=Dl1
end,
loop2(Data2,Nl2,Min21,W2,Pid,Up,Dl2,Req1)
end;
req->
if
Dl=:=[]->Up! req,Req1=true,T=[];
true->[H|T]=Dl,Pid! {data,H},Req1=false
end,
loop2(Data,Nl,Min2,W2,Pid,Up,T,Req1)
end.
また、どう書く第24回の問題とCodeIqの「撤去作業の果てに現れる数列」も
Erlangで書き直してみました。
https://qiita.com/smallbigcats/items/defcdf5eb1e6bc7f92f5