2017-12-09 3 views
2

私はPrologを初めて使い、1または-1の値を持つ一連のシンボルを持つ問題を解決しようとしました。私が必要とするのは、一度に1つの要素をすべて一緒に追加し、最初の合計がどのインデックスで0より下に下がるかを抽出することです。私は命令的な背景から来ているので、カウント変数とfor-loopであるが、明らかに私はPrologでそれを行うことはできない。私は本当にこれまで管理してきたProlog:一度にリストの1つの要素を合計する

value('(', 1). 
value(')', -1). 

main(R) :- readFile("input", R), ??? 

readFile(Path, R) :- 
    open(Path, read, File), 
    read_string(File, _, Str), 
    stringToCharList(Str, Xs), 
    maplist(value, Xs, R). 

stringToCharList(String, Characters) :- 
    name(String, Xs), 
    maplist(toChar, Xs, Characters). 

toChar(X, Y) :- name(Y, [X]). 

あなたが見ることができるように、すべてのシーケンスを含むファイルを読み込み、1と-1,2に変換することです。私はここからどこに行くのか分かりません。私はこの問題は3倍であると仮定します

  • 私はリストに
  • を、各要素を合計する必要がリスト
  • を反復処理する必要があり、私は特定のインデックスに

を返却する必要があります助言がありますか?私は何とか反復がゼロ以下の合計を落としたリストを切り捨てて、ちょうどその長さを返すことができますか?

+0

何あなたの入力ファイルが見えますか?それが有効なProlog用語または用語である場合、Prolog I/Oはそれらを読み取るだけで、解析する必要はありません。 – lurker

+0

ちょうど長い括弧の文字列。 – SindreKjr

+1

1と-1のリストがあるので、単純な再帰述語を実行してリストを歩き、0を押すまで合計を累積します。カウンタがインデックスになります。 'index_at_zero_sum(L、Index): - index_at_zero_sum(L、0、Index).'を開始します。 2番目の引数は当初の合計であり、もちろん '0'です。あなたの 'index_at_zero_sum/3'は再帰的になり、合計が0になったときに終了します。それ以外の場合はデフォルトで失敗します(ゼロの合計を達成しませんでした)。 – lurker

答えて

4

補助変数のPrologの原則を使用して、条件が必要なものに達するまでカウンタとして機能します。補助カウンタは、ベースケース内のその時点の変数で統一されます。

ここでは、盲目的に、あなたのコードが上記のように動作すると仮定しています。私はそれをテストしなかった(それはあなた次第です)。

main(IndexAtZeroSum) :- readFile("input", R), index_at_zero_sum(R, IndexAtZeroSum). 

readFile(Path, R) :- 
    open(Path, read, File), 
    read_string(File, _, Str), 
    stringToCharList(Str, Xs), 
    maplist(value, Xs, R). 

stringToCharList(String, Characters) :- 
    name(String, Xs), 
    maplist(toChar, Xs, Characters). 

toChar(X, Y) :- name(Y, [X]). 

% The following predicate assumes indexing starting at 0 
index_at_zero_sum([V|Vs], IndexAtZeroSum) :- 
    index_at_zero_sum(Vs, V, 0, IndexAtZeroSum). 

% When sum is zero, Index is what we want 
index_at_zero_sum(_, 0, Index, Index). 
index_at_zero_sum([V|Vs], Sum, CurIndex, Index) :- 
    S is Sum + V, 
    NextIndex is CurIndex + 1, 
    index_at_zero_sum(Vs, S, NextIndex, Index). 

index_at_zero_sum/2は、合計がゼロになる指定されたリストのインデックスを提供します。補助述語index_at_zero_sum/4を使用して、最初の値(合計は値そのもの)から始まり、現在のインデックスは0から始まります。したがって、2番目の引数はインデックス0の合計です。index_at_zero_sum/4へのその後の呼び出しインデックスをインクリメントし、合計が0になるまで合計を累積します。その時点で、ベースケースは成功し、4番目の引数を現在のインデックスと統合します。リストが空になる前に合計が0にならない場合、述部は失敗します。


また get_char/2を使用してファイル全体を読み取り、数値のリストを作成しないようにすることができます

index_at_zero_sum(Path, Index) :- 
    open(Path, read, File), 
    get_char(File, C), 
    value(C, V), 
    ( index_at_zero_sum(File, V, 0, Index) 
    -> close(File) 
    ; close(File), 
     fail 
    ). 

index_at_zero_sum(_, 0, Index, Index). 
index_at_zero_sum(File, Sum, CurIndex, Index) :- 
    get_char(File, C), 
    value(C, V), 
    S is Sum + V, 
    NewIndex is CurIndex + 1, 
    index_at_zero_sum(File, S, NewIndex, Index). 
+0

ありがとう!コメントのあなたのヒントは、私に正しい軌道に乗ったが、私は休憩をどのように処理する必要があるのか​​把握していない。とにかく、これはうまくいった。 :) – SindreKjr

関連する問題