Определить все слова строки длиной k в prolog

#string #recursion #prolog

#строка #рекурсия #prolog

Вопрос:

Слова — это любые символы, разделенные пробелами или начальной / конечной точками строки. Например. [w,o,r,d,1,' ',w,o,r,d,2]

Мне нужно найти все слова k-длины данной строки и добавить их в результирующую строку (разделенные пробелами). Это то, чего я ожидаю, например, в случае k = 5:

 ?- kthWords([w,o,r,d,1,'',w,r,d,'',w,o,r,d,2], 5, X).
X = [w,o,r,d,1,'',w,o,r,d,2].
  

Ответ №1:

Вы могли бы написать:

 final_kthWords(L,K,Outlist):-
         kthWords(L,K,L1),
         reverse(L1,[_|T]),
         reverse(T,Outlist).

kthWords([],_,[]):-!.
kthWords(L,K,L1):-
     find_word(L,Word,L2),
     length(Word,N),
     (N=:=K-> append(Word,[' '|T],L1),kthWords(L2,K,T);
     kthWords(L2,K,L1)).

find_word([],[],[]).
find_word([H|T],[H|T1],L):-dif(H,' '),find_word(T,T1,L).
find_word([H|T],[],T):- H = ' '.
  

kthWords/3 Вызывает find_word/2 Where, который находит слова и, наконец, kthWords возвращает выходной список, но в конце добавляет ' ' . Единственное, что final_kthWords(L,K,Outlist)/3 делается, это удаляет лишнее ' ' в конце списка и возвращает правильный список:

 ?- final_kthWords([w,o,r,d,1,' ',w,r,d,' ',w,o,r,d,2], 5, X).
X = [w, o, r, d, 1, ' ', w, o, r, d, 2] ;
false.
  

Ответ №2:

Надеюсь, что кто-то другой может предложить более простое решение… кажется, работает следующее

 kthWordsH([], 0, _, R0, R0).

kthWordsH([], N, _, _, []) :-
  N = 0.

kthWordsH([' ' | Tl], 0, Len, W, Revult) :-
  kthWordsH(Tl, Len, Len, [], Res0),
  append(Res0, [' ' | W], Revult).

kthWordsH([' ' | Tl], N, Len, _, Revult) :-
  N = 0,
  kthWordsH(Tl, Len, Len, [], Revult).

kthWordsH([H | Tl], 0, Len, _, Revult) :-
  H = ' ',
  kthWordsH(Tl, Len, Len, [], Revult).

kthWordsH([H | Tl], N, Len, Tw, Revult) :-
  H = ' ',
  N = 0,
  Nm1 is N-1,
  kthWordsH(Tl, Nm1, Len, [H | Tw], Revult).

kthWords(List, Len, Result) :-
  kthWordsH(List, Len, Len, [], Revult),
  reverse(Revult, Result).
  

Комментарии:

1. Что ж, интересное решение 🙂 1

Ответ №3:

Решение без обратного.

 % return a word of k length, or return [] otherwise
kword(K,L,W):- 
    length(L,K) -> append(L,[' '],W); W=[].

% if no more chars, then check final word in L and
% append to word list Ls to return Lw
kwords(K,[],L,Ls,Lw):- 
    kword(K,L,W),
    append(Ls,W,Lw).

% if char is space, then append to Ls if word of length K
% if not space, append char to "in progress" work list L
kwords(K,[C|Cs],L,Ls,Lw):- 
    (   C=' ' -> 
        (   kword(K,L,W),
            append(Ls,W,Ls0),
            L2 = []
        );
        (   append(L,[C],L2),
            Ls0 = Ls
        )
    ),
    kwords(K,Cs,L2,Ls0,Lw).

% intialise predicate call with empty word and empty result
kthWords(Cs,K,L):- kwords(K,Cs,[],[],L).