リアルタイムどう書く過去問(第20回)


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

論理問題を探していて見つけました、
問題を見たとき、1分ごとに続けて60分条件をクリアすれば成功という方法を思いつき、
どのくらい時間がかかるのか気になりコードを書いてみました。
この方法でも瞬時に解けましたが、問題10をパスしないことがわかり、
オーソドックスに?開始時間と終了時間で検証することにしました。
会議開始の時間は1分ごとに検証しています。
fil/3で各自の条件を取り出しています。
IさんとJさんはどちらかがいればよいのでorでつなぎ、
Zさんはtest/3をand(すべての条件をクリアすれば成功)で統一するためnotを使っていますので、
(TB<=N)->(TB>N)、(N+60<=TE)->(N+60>TE)、or-> andとなっています。
問題に数字、アルファベット、ハイフンが混在していて、入出力に苦労しました。

fil(_,[],[]).
fil(X:_,[H|T],L):-fil(X:_,T,L1),(H=X:_->L=[H|L1];L=L1).

test(_,_,[]):-!.
test(P,N,[P:TB-TE|T]):-P\=z,!,(TB>=N+60;N>=TE),test(P,N,T).
test(P,N,[P:TB-TE|T]):-(TB>N;N+60>TE),test(P,N,T).

se(P,N,L):-
     fil(P:_,L,L1),!,(L1==[]->(P==z->false;true);test(P,N,L1)).

solve(L,N):-
     between(600,1020,N),se(a,N,L),se(b,N,L),(se(i,N,L);se(j,N,L)),not(se(z,N,L)),!.
solve(_,0).

start:-str(S),split_string(S,"\n","",L),maplist(split,L,L1),pre(L1).

split(S,L):-split_string(S,"\s","\s",L).

pre([]).
pre([[_,B,Q]|T]):-concat_atom(B1,",",B),maplist(sp,B1,L),solve(L,R),disp(R,Q),pre(T).

disp(0,A):-
     !,S="-",disp1(S,A).
disp(R,A):-
     D is R div 60,M is R mod 60,N1 is D*100+M,N2 is N1+100,
     concat_atom([N1,N2],"-",S),atom_chars(X,A),disp1(X,S).

disp1(S,A):-(A==S->Str=" pass ";Str=" fail "),write(Str),writeln(S).

htom(N,R):-N1 is N div 100,N2 is N mod 100,R is N1*60+N2.

sp(B,R):-
     concat_atom([X,Y],'-',B),atom_codes(X,[H|T]),atom_codes(X1,T),
     atom_number(X1,N1),atom_number(Y,N2),htom(N1,NF),htom(N2,NT),
     atom_chars(H1,[H]),downcase_atom(H1,H2),R=H2:NF-NT.

%start.

str("0    A1050-1130,B1400-1415,I1000-1400,I1600-1800,J1100-1745,Z1400-1421,Z1425-1800    1425-1525
1       A1000-1200,B1300-1800,Z1000-1215,Z1230-1800     -
2       Z0800-2200      1000-1100
3       A1000-1700,Z0800-2200   1700-1800
4       A1000-1701,Z0800-2200   -
5       A1000-1130,B1230-1800,Z0800-2200        1130-1230
6       A1000-1129,B1230-1800,Z0800-2200        1129-1229
7       A1000-1131,B1230-1800,Z0800-2200        -
8       A1000-1130,B1229-1800,Z0800-2200        -
9       A1000-1130,B1231-1800,Z0800-2200        1130-1230
10      A1000-1130,B1230-1800,Z0800-1130,Z1131-2200     -
11      A1000-1130,B1231-1800,Z0800-1130,Z1131-2200     1131-1231
12      Z0800-0801      -
13      Z0800-1031,Z1129-1220,Z1315-1400,Z1459-1600     1459-1559
14      Z0800-2200,I1000-1600,J1030-1730        1600-1700
15      Z0800-2200,I1000-1600,J1130-1730        1000-1100
16      Z0800-2200,I1000-1600,J1130-1730,A0800-1025     1025-1125
17      Z0800-2200,I1000-1600,J1130-1730,A0800-1645     1645-1745
18      Z0800-2200,I1000-1600,J1130-1730,A0800-1645,I1735-2200  -
19      Z0800-2200,I1000-1600,J1130-1730,A0800-1645,J1735-2200  1645-1745
20      Z1030-2200,I1000-1600,J1130-1730        1030-1130
21      Z1035-1500,I1000-1600,J1130-1730,Z1644-2200     1644-1744
22      I2344-2350,A2016-2253,Z1246-1952        1246-1346
23      Z2155-2157,B1822-2032,Z1404-2000,Z2042-2147,Z2149-2154  1404-1504
24      Z2231-2250,Z2128-2219,B2219-2227,B2229-2230,Z0713-2121,A0825-1035,B1834-2001    1035-1135
25      J0807-1247,I0911-1414,B1004-1553,Z0626-1732,Z1830-1905,A1946-1954,A0623-1921    -
26      J1539-1733,J0633-1514,Z1831-1939,J1956-1959,I0817-1007,I1052-1524,Z1235-1756,Z0656-1144         1524-1624
27      Z2319-2350,B0833-2028,I2044-2222,A1410-2201,Z2044-2228,Z0830-2023,Z2242-2306,I2355-2359         -
28      B2001-2118,Z0712-1634,I1941-2102,B1436-1917     1000-1100
29      A0755-1417,B2303-2335,Z0854-2150,Z2348-2356,Z2156-2340,I1024-1307,Z2357-2359    1417-1517
30      A1958-1959,B0822-1155,I1518-1622,Z1406-1947,A1800-1822,A0904-1422,J1730-1924,Z1954-1958,A1946-1956      1422-1522
31      B1610-1910,I2121-2139,A0619-1412,I2147-2153,Z0602-2111,I0841-2031,A1657-1905,A1956-2047,J0959-1032,Z2131-2147   1412-1512
32      Z0623-1900,A0703-1129,I1815-1910,J1956-1957,I0844-1518,Z1902-1935,B1312-1342,J1817-1955         1129-1229
33      J1246-1328,B1323-1449,I1039-1746,Z1218-2111     1449-1549
34      A1958-1959,I1943-1944,I0731-1722,Z0845-1846,J1044-1513,Z1910-1923,B1216-1249    1513-1613
35      A1855-2047,Z0946-1849,Z2056-2059,I1855-1910,B1946-2058,I1956-2025,Z1905-2054,J0644-1800,I0720-1618      1618-1718
36      J1525-1950,Z0905-1933,A1648-1716,I2051-2054,I2015-2044,I0804-1958,B0934-1100,Z1953-2037         1100-1200
37      Z1914-1956,J0823-1610,Z0641-1841,J1800-1835,A0831-1346,I1926-1941,I1030-1558,I1738-1803         1558-1658
38      Z0625-1758,J1033-1351,B1816-2236,I0838-1615,J2247-2255  1351-1451
39      J0603-1233,A1059-1213,I1326-2103,Z0710-1459     1213-1313
40      B1302-1351,J1410-2038,A0755-1342,J0637-0658,Z2148-2159,Z1050-2131,A1543-1844,I1615-1810         1351-1451
41      Z0746-2100,A2122-2156,I1022-1144,J0947-1441,A1333-1949  1144-1244
42      J0718-1243,Z1443-1818,B2055-2057,A0714-1238,Z1045-1344,A1643-1717,B1832-2039,J1623-1931         1238-1338
43      Z1921-1933,A1208-1418,I0827-1940,Z0757-1917,J0653-1554,B1859-1909       1554-1654").

2018.7.17追加
Juliaに移してみました。
今までPrologでは問題のデータ数が不定のときの入力に苦労したのですが、Juliaのほうが楽です。
本体に関しては、引数の扱いに関して忘れていたことがあって引っ掛かりましたが、
そのほかは思ったより楽にできました。

str="10     A1000-1130,B1230-1800,Z0800-1130,Z1131-2200     -
11  A1000-1130,B1231-1800,Z0800-1130,Z1131-2200     1131-1231
12  Z0800-0801  -
13  Z0800-1031,Z1129-1220,Z1315-1400,Z1459-1600     1459-1559
14  Z0800-2200,I1000-1600,J1030-1730    1600-1700"

function solve(s2)
    function se(p,n)  #s2を引数にして関数を外に出しても s2 が変わる
        s=deepcopy(s2)
       if p=='Z'
           res=false
       else
          res=true
       end
       while s!=[]
          cond=pop!(s)
          if cond[1]==p
              from=parse(cond[2:5])
              to=parse(cond[7:10])
              tb=div(from,100)*60+mod(from,100)
              te=div(to,100)*60+mod(to,100)
              if p=='Z'
                 if tb<=n && n+60<=te
                    res=true
                    break
                 end
              else
                 if tb<n+60 && n<te
                    res=false
                    break
                 end
             end
         end
       end
       return res
    end

  ans="-"
  for i in 600:1020
      if se('A',i) && se('B',i) && se('Z',i) && (se('I',i) || se('J',i))
          i1=div(i,60)
          i2=mod(i,60)
          ans=string(i1*100+i2)*"-"*string((i1+1)*100+i2)
          break
      end
  end
  return ans
end

function main()
str0=split(str,"\n")
for s0 in str0
  s1=split(s0,"\t")
  s2=split(s1[2],",")
  ans=solve(s2)
  if s1[3]==ans
   print("ok ")
  else
   print("no" )
   end
   println(ans)
end
end

main()

2018.7.22追加。
すみません。prologのdisp/2の最後disp1(X,S)が間違っていました。
disp1(S,X)が正しいです。

disp(0,A):-
     !,S="-",disp1(S,A).
disp(R,A):-
     D is R div 60,M is R mod 60,N1 is D*100+M,N2 is N1+100,
     concat_atom([N1,N2],"-",S),atom_chars(X,A),disp1(S,X).

2018.7.24追加
すみません、もう少しましなコードにならないか考えていましたら、
またまたPrologのほうに間違いが見つかってしまいました。
Zさんの条件にnotを使っていますので、一日中暇なときfalse->trueになるのでした。
そのような条件のテストケースがありませんでしたので、パスしてしまいました。
テストケースの例と正しいse/3は次のようになります。

se(P,N,L):-fil(P:_,L,L1),test(P,N,L1).

%"44      A1208-1418,I0827-1940,J0653-1554,B1859-1909       -"

なお1分ごとに続けて60分条件をクリアすれば成功という方法も、少しの修正でOKでした。
「どう書く」の皆さんはこちらの方法で解かれた方が多いようです