2016-10-07 6 views
1

CharList (정수 목록)를 단어 목록으로 분할하는 다음 코드를 작성했습니다. 내가 추적을 실행하고 모든 작업을 수행하고 그것을 목록에 넣지 만 WordList 변수를 값에 바인딩하지 않습니다. Swipl를 사용프롤로그의 단어로 문자열 분할

splitintowords(CharList, WordList):- splitintowords_(CharList, [], [], WordList). 
splitintowords_([],[], Res, Res). 
splitintowords_([],Word, WordList,_):- 
    \+ Word = [], 
    append([Word], WordList, NWordList), 
    splitintowords_([],[], NWordList,_). 
splitintowords_([H|T],Word, WordList,_):- 
    alphabetic(H), 
    append([H], Word, NWord), 
    splitintowords_(T,NWord, WordList,_). 
splitintowords_([H|T],Word, WordList,_):- 
    \+ alphabetic(H), 
    append([Word], WordList, NWordList), 
    splitintowords_(T, [], NWordList,_). 

테스트 케이스 :

splitintowords(CharList, WordList):- 
    splitintowords_(CharList, [[]], WordList). 
splitintowords_([], WordList, WordList). 
splitintowords_([H|T], [Word|Words], _):- 
    alphabetic(H), 
    WordN = [H|Word], 
    splitintowords_(T, [WordN|Words], _). 
splitintowords_([H|T], Words):- 
    \+ alphabetic(H), 
    WordsN = [[]|Words], 
    splitintowords(T, WordsN). 

을이 하나가 간단하고 것 : 여기

string_codes('hello there, how are you?',T), splitintowords(T, W). 

는,이 중 하나가 작동하지 않습니다 내가 처음 쓴 대안 구현의 추적으로 동등한 일을하십시오.

+1

은 영문자/1을 사용하시기 바랍니다. – coder

+0

알파벳순 (N) : - char_type (N, alpha). – ejbs

+0

이 예제의 단어는 무엇입니까? '여보세요, 저기, 어떻게, 있니? ' –

답변

1

첫 번째 해결 방법은 올바른 목록을 작성하더라도 반환 할 목록 변수의 이름 대신 모든 항목과 통합되는 익명 변수 '_'을 전달하는 것입니다. 종료.

splitintowords(CharList, WordList):- splitintowords_(CharList, [], [], WordList). 

splitintowords_([],[], Res, Res). 
splitintowords_([],Word, WordList,L):- 
    \+ Word = [], 
    append([Word], WordList, NWordList), 
    splitintowords_([],[], NWordList,L). 
splitintowords_([H|T],Word, WordList,L):- 
    is_alpha(H), 
    append([H], Word, NWord), 
    splitintowords_(T,NWord, WordList,L). 
splitintowords_([H|T],Word, WordList,L):- 
    \+ is_alpha(H), 
    append([Word], WordList, NWordList), 
    splitintowords_(T, [], NWordList,L). 

: 코드를 부여 T,하지만 약간의 변화와 같은 .... 코드해야한다, 당신의 천국이 때문에

나는/1 대신 알파벳의 술어 is_alpha에서 빌드 솔루션을 시도 예 : 솔루션이 보여 매우 크기 때문에 ...., 당신이 w를 눌러 전체 솔루션을 볼 수

string_codes('hello there, how are you?',T), splitintowords(T, W). 
T = [104, 101, 108, 108, 111, 32, 116, 104, 101|...], 
W = [[117, 111, 121], [101, 114, 97], [119, 111, 104], [], [101, 114, 101, 104|...], [111, 108, 108|...]] ; 
false. 

참고 SWI - 프롤로그 :

?- string_codes('hello there, how are you?',T), splitintowords(T, W). 
T = [104, 101, 108, 108, 111, 32, 116, 104, 101|...], 
W = [[117, 111, 121], [101, 114, 97], [119, 111, 104], [], [101, 114, 101, 104|...], [111, 108, 108|...]] [write] 
T = [104, 101, 108, 108, 111, 32, 116, 104, 101, 114, 101, 44, 32, 104, 111, 119, 32, 97, 114, 101, 32, 121, 111, 117, 63], 
W = [[117, 111, 121], [101, 114, 97], [119, 111, 104], [], [101, 114, 101, 104, 116], [111, 108, 108, 101, 104]] ; 
false. 

(두 번째 T, W는 첫 번째 T, W의 전체 솔루션입니다.)

또한 두 번째 솔루션 이와 유사한 변화 :

splitintowords(CharList, WordList):- 
    splitintowords_(CharList, [[]], WordList). 

splitintowords_([], WordList, WordList). 

splitintowords_([H|T], [Word|Words], L):- 
    is_alpha(H), 
    WordN = [H|Word], 
    splitintowords_(T, [WordN|Words], L). 

splitintowords_([H|T], Words,L):- 
    \+ is_alpha(H), 
    WordsN = [[]|Words], 
    splitintowords_(T, WordsN,L). 

예 : 어딘가에 중간에 그것은 이전 솔루션에 비해 하나 개의 빈 목록이 더있다

?- string_codes('hello there, how are you?',T), splitintowords(T, W). 
T = [104, 101, 108, 108, 111, 32, 116, 104, 101, 114, 101, 44, 32, 104, 111, 119, 32, 97, 114, 101, 32, 121, 111, 117, 63], 
W = [[], [117, 111, 121], [101, 114, 97], [119, 111, 104], [], [101, 114, 101, 104, 116], [111, 108, 108, 101, 104]] ; 
false. 

참고. 당신은 빈 목록을 제거 할 경우 한 번 더 술어를 작성하여 매우 쉽게 될 것이다 :

delete([],[]). 
delete([H|T],[H|T1]):-dif(H,[]),delete(T,T1). 
delete([[]|T],T1):-delete(T,T1). 

예 :

?- delete([[], [117, 111, 121], [101, 114, 97], [119, 111, 104], [], [101, 114, 101, 104, 116], [111, 108, 108, 101, 104]],L). 
L = [[117, 111, 121], [101, 114, 97], [119, 111, 104], [101, 114, 101, 104, 116], [111, 108, 108, 101, 104]] ; 
false. 

은 (그것은 빈 목록을 제거).

편집

나는 또한 당신의 술어 alphabetic/1와 함께 테스트 is_alpha/1와 정확히 같은 출력을 생성합니다.

+0

물론 이죠! 나는 의미 론적 차이를 만들었다는 사실을 실제로 몰랐다. 나는 다른 어떤 것과 같은 이름 일 뿐이라고 생각했다. 또한 예, 나는 내 알고리즘으로 몇 가지 빈 목록을 얻을 것이라고 의심했다. :). – ejbs

+0

다행히 도와 줘서, '_'은 단지 익명 변수이고 익명으로하고 싶지는 않습니다. 재귀가없는 '-_'가없는 경우에는 일반적으로 술어가 리턴하는 매개 변수에 대해 신경 쓰지 않을 때 사용됩니다. – coder

1

더 나은 속도를 위해 차이 목록을 사용하여 구현했습니다. 그것은 꽤 stighforwardly 작동, 챠리스에서 머리를 가져, H는 어떤 분할 숯불과 통일 수 있다면, 그렇다면, 그것은 새로운 단어를 생성하고 Bcu에 추가, 아니, 그것은 Acu의 끝에 머리를 추가합니다.

%split_words(+Chars, +Splits, -Words). 
% it needs list of Chars, list of Split characters, and returns list of 
% words. 
split_words(Chars, Splits, Words) :- 
    split_words(Chars, Splits, X - X, Y - Y, Words). 
split_words([], _, [], Bcu, Words) :- listify(Bcu, Words). 
split_words([], _, Acu, Bcu, Words) :- 
    listify(Acu, W), add(Bcu, W, New), listify(New, Words). 
split_words([H|C], Splits, Acu, Bcu, Words) :- 
    member(H, Splits), !, listify(Acu, W), add(Bcu, W, New), 
    split_words(C, Splits, X - X, New, Words). 
split_words([H|C], Splits, Acu, Bcu, Words) :- 
add(Acu, H, New), split_words(C, Splits, New, Bcu, Words). 

add(X - [I|Y], I, X - Y). 

listify(X - [], X). 
1

나는 오해해야합니다. 나는 코드 대신 문자를 사용하여 어떤 일이 진행되고 있는지를 최상위 레벨에서 쉽게 볼 수 있습니다. 나는 표현과 프롤로그에서 코딩하려는 시도를 이해한다면, 당신은 일을하려고하고 있습니다 :

여기
?- string_chars("hello there, how are you?", Chars), 
    chars_words(Chars, Words). 
Chars = [h, e, l, l, o, ' ', t, h, e|...], 
Words = [[h, e, l, l, o], [t, h, e, r, e], [h, o, w], [a, r, e], [y, o, u]]. 

, 당신이 연속 alpha 문자를 모두 실행을 촬영 한 단어로 함께 다음 뒀다; 사이에 비 알파 문자를 모두 버렸습니다. 전면

  • 연속 알파 문자는
  • 버린 뒤 비 알파 문자 단어입니다

    1. 스트립 선도하는 비 알파 문자 :이 가정으로

      , 여기 당신이 그것을 접근 할 수있는 방법입니다 그리고 프롤로그에서 2

    로 이동 :

    chars_words([], []). 
    chars_words([C|Cs], Words) :- 
         strip_non_alpha([C|Cs], Rest), 
         chars_words_aux(Rest, Words). 
    
    chars_words_aux([], []). 
    chars_words_aux([C|Cs], [W|Ws]) :- 
         word_rest([C|Cs], W, Rest0), 
         strip_non_alpha(Rest0, Rest), 
         chars_words_aux(Rest, Ws). 
    

    언제든지 append/3을 사용할 필요가 없습니다. 원래 목록에서 단어 목록으로 문자 순서를 변경하지 않기 때문입니다.

    word_rest/3strip_non_alpha/2을 모두 정의하려면 partition_sorted/4이라는 술어를 사용했습니다. 리스트를 취하여 술어가 성공한 프론트와 나머지 (나머지의 첫 x 째 요소는 술어가 실패하는 원래리스트의 첫 x 째 요소입니다.)로 두 개를 분리합니다.

    strip_non_alpha(List, Rest) :- 
         partition_sorted(not_alpha, List, _, Rest). 
    
    word_rest(List, Word, Rest) :- 
         partition_sorted(alpha, List, Word, Rest). 
    
    not_alpha(X) :- \+ char_type(X, alpha). 
    alpha(X) :- char_type(X, alpha). 
    

    마지막으로, partition_sorted/4에 대한 순진 정의 : Goal이 성공하거나 선택 포인트 뒤에 떠나지 않고 한 번 실패하고 입력리스트가 바닥 인 경우에만 제대로 작동하기 때문에

    partition_sorted(Goal, List, True, False) :- 
         partition_sorted_aux(List, Goal, True, False). 
    
    partition_sorted_aux([], _, [], []). 
    partition_sorted_aux([X|Xs], Goal, True, False) :- 
         (  call(Goal, X) 
         ->  True = [X|True0], 
           partition_sorted_aux(Xs, Goal, True0, False) 
         ;  True = [], False = [X|Xs] 
         ). 
    

    이 정의는 순진하다.

  • +0

    안녕하세요! 질문에 답변 해 주셔서 감사합니다. 내 질문에 대한 귀하의 이해가 정확하고 구현이 훌륭합니다. 나는 내가 알고리즘 자체가 아니라 변수를 통합하는 과정에서 내가 잘못한 것을 이해하는 것에 주로 관심을 가졌기 때문에 받아들이지 않기로 동의했다 (그러나 'upvote'). – ejbs

    +0

    @ejbs 실제로 도움이되기를 바랍니다. 허용 된 대답과 대답은 동일한 입력에 대해 서로 다른 결과를 제공하지만 질문에 어떤 결과가 기대되는지는 아직 기록하지 않았습니다. –

    +0

    나는 그 사실을 깨닫지 못했습니다. 이것이 특정 경우에 발생합니까? 사실, 내가 "안녕하세요,", "많은", "많은 단어"라는 문자열을 "Hello", "This", "are", "Many", "words"라고 기대할 것입니다.나는 그것이 사용/수정되고있는 알고리즘이라면 결함이있는 출력 (관계없는 빈리스트를 돌려 줌)과 함께 문제가 없다. – ejbs