2

我正在做一个小项目来精简序言。我现在要做的是,给定一个句子,返回一个单词列表。所以,我正在接受一个字符数组,例如“highs and lows”,并试图将它分成“highs”“和”“lows”。我正在使用字符数组,因为我想自己玩单词,而且我认为字符串不适用于此。

这是我的代码。

get_first_word([], _, []):-
  !.
get_first_word(X, Pivot, Input):-
  append(X, [Pivot|_], Input),
  !.

split_at([],_).
split_at(Input, Pivot):-
  get_first_word(X, Pivot, Input),
  writef(X),
  append(X, Y, Input),
  split_at(Y, Pivot).

我遇到的问题是这变成了一个无限循环。最终它会传递自己的空输入,而我的基本案例写得不够好,无法处理这个问题。我该如何解决?

4

3 回答 3

1

我认为这get_first_word遗漏了一个论点:它应该“返回”单词和其余部分,说明 Pivot 没有出现在输入中的可能性。

我还移动了参数以遵循传统的“开始时输入,结束时输出”。

get_first_word(Input, Pivot, Word, Rest):-
  append(Word, [Pivot|Rest], Input), !.
get_first_word(Input, _Pivot, Input, []).

split_at([], _).
split_at(Input, Pivot):-
  get_first_word(Input, Pivot, W, Rest),
  writef(W),nl,
  split_at(Rest, Pivot).

测试:

?- split_at("highs and lows", 0' ).
highs
and
lows
true .
于 2013-04-01T06:26:19.250 回答
1

如果使用 SWI-Prolog,值得考虑使用原子来表示句子、单词、单词的一部分等。正如你在这里看到的,你的问题变成了(如果你的句子是一个原子):

?- atomic_list_concat(Ws, ' ', 'highs and lows').
Ws = [highs, and, lows].

还有其他有用的谓词,例如atom_concat/3(我们可以说它是append/3用于原子的),或者sub_atom/5可以以多种方式使用。

作为旁注,SWI-Prolog 对原子的长度没有人为的限制,实际上建议使用原子而不是字符串或字符代码列表。

于 2013-04-01T13:30:59.927 回答
1

在描述列表时(在这种情况下:字符代码列表,这就是您的字符串),请始终考虑使用 DCG。例如:

string_pivot_tokens(Cs, P, Ts) :- phrase(tokens(Cs, P, []), Ts).

tokens([], _, Ts)     --> token(Ts).
tokens([C|Cs], P, Ts) -->
        (   { C == P } -> token(Ts), tokens(Cs, P, [])
        ;   tokens(Cs, P, [C|Ts])
        ).

token([])     --> [].
token([T|Ts]) --> { reverse([T|Ts], Token) }, [Token].

例子:

?- string_pivot_tokens("highs and lows", 0' , Ts), maplist(atom_codes, As, Ts).
Ts = [[104, 105, 103, 104, 115], [97, 110, 100], [108, 111, 119, 115]],
As = [highs, and, lows] ;
false.
于 2013-04-01T18:03:21.920 回答