オフラインリアルタイムどう書く(E30)

問題はこちら->http://nabetani.sakura.ne.jp/hena/orde30sumt/

無限に長い領域ということで、最初は遅延評価を使った無限リスト問題かと思いましたが、
1から順に計算すると時間がかかりそうですし、最下部によって範囲が限定されていますので、
普通の解き方で挑戦しました。
まず下の列から順に、リストに入れるセルの範囲を決めます。
問題の規則をうまくあてはめられるよう(右端は無視)、作成する上の列のリストの範囲は、
可能なら下位、上位とも下の列と重複している範囲より1セルづつ増やします。
「面白くないセル」の数字を0にして、加えても影響がないようにして保存します(fun/2)。
take/3で上のセルとの関係を計算し、必要な部分を取り出してcalc/5で1セルずつ計算しています。
下位のリスト内のセルの開始位置が上のセルの幅より短いときは、上のリストをすべて使います。
それ以外のときは、最初のセルを除外して使います。
下の列のセルの下端と上端に当たる上の列のリスト内の位置を求め、その間の数字を合計します。
上のセルの下端は最初は１、その後は1つ前の下のセルの上端又は上端+1に当たる位置を、
上下のリスト内のセルの開始位置の差と両方のセルの幅から計算しています。
これを下のセルすべてに対し行います。
変数はその列以下の列とそれより上の列の2つを持たなければならないので多くなっています。
基本はこれだけですが、takeの部分をできるだけ計算せずにリスト操作だけで書こうとして、
だいぶ時間を無駄にしました。
また1000の剰余をとる部分もうっかりして、とんでもない数字が出るのに困惑したりしました。

```Prolog
%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で複数のセルを求めて下位に送る方法よりやや時間がかかりますが許容範囲内です。

```Prolog
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上で扱えば、パズルを解く程度ならインタプリタ感覚で使えるし、
速くてよいのですが、今回は型の部分や読み込みの部分で結構苦労しました。

```Nim
#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
%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を使わない方が論理的にすっきりします。
遅いと勘違いしていました。

```Erlang
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