【问题标题】:PROLOG store nth element of list if string is found in list如果在列表中找到字符串,PROLOG 存储列表的第 n 个元素
【发布时间】:2018-04-14 10:58:27
【问题描述】:

我想做的是:

来自历史/2

来自历史(HL,FL)

如果列表包含单词“ate”,则FL是列表的第三个元素

如果列表包含所有单词 ["you","can","have"],则 FL 是列表的第 4 个元素

谓词应该在列表 HL 的列表上循环,如果其中一个列表包含上述单词,它应该根据找到的单词将第 3/4 个元素附加到 FL,否则它不应该得到任何东西.

?- fromHistory([[i,ate,x], [you,can,have,y]], FL).
FL = [x, y] ;
false.

?- fromHistory([[this,is,a,useless,input], [i,ate,x], [another,input],
                [another,useless,input], ["Ok"], [you,can,have,y]], FL).
FL = [x, y] ;
false.

x 和 y 并不总是在列表的末尾,而是在 ["ate"] 和 ["you","can","have"] 之后的字符串

我尝试使用here中的查找版本

find(X,Y,[X,Y|Tail]):-
   !.
find(X,Y,[_|Tail]):-
   find(X,Y,Tail).


foodFromHistory(HL1, FL):-
    flatten(HL1, HL),
    find(ate, FL1, HL),
    find([you, can, have], FL2, HL),
    FL = [FL1|FL2].

但是它不适用于 [you,can,have] 并返回 false,它也不适用于整个列表,而仅适用于第一次出现。

【问题讨论】:

  • 你的尝试在哪里?
  • 更新帖子...

标签: prolog


【解决方案1】:

根据经验,如果您需要逐个元素地处理一些事物的列表,首先要非常清楚地了解如何处理每个元素(在这种情况下,这些“元素”是输入短语)并实施和测试,而不用担心整个问题。所以:

如果列表包含单词“ate”,则FL是列表的第三个元素

如果列表包含所有单词 ["you","can","have"],则 FL 是列表的第 4 个元素

这不是一个很好的规范,但这里有一个实现,您可以在更大的问题之外进行测试和调整:

input_food([_Somebody, ate, Food], Food).
input_food(Input, Food) :-
    append(_Something, [you, can, have, Food | _Rest], Input).

就是这样!您有两个要求,每个要求都描述一个列表上的简单模式匹配。因此,Prolog 实现可以是两个子句,每个子句都在列表上实现一个简单的模式匹配。

让我们测试一下:

?- input_food([i, ate, x], Food).
Food = x ;
false.

?- input_food([you, ate, x], Food).
Food = x ;
false.

?- input_food([ok, you, can, have, strawberries], Food).
Food = strawberries ;
false.

?- input_food([this, sentence, no, food], Food).
false.

好的,我们现在需要做的就是遍历输入列表并收集input_food/2 为每个输入提供的食物(如果有)。这是标准:

inputs_foods([], []).
inputs_foods([I|Is], [Food|Fs]) :-
    input_food(I, Food),
    inputs_foods(Is, Fs).
inputs_foods([I|Is], Fs) :-
    \+ input_food(I, _Food),
    inputs_foods(Is, Fs).

而且它似乎主要做你想做的事:

?- inputs_foods([[this,is,a,useless,input], [i,ate,x], [another,input],
                [another,useless,input], ["Ok"], [you,can,have,y]], FL).
FL = [x, y] ;
false.

【讨论】:

    【解决方案2】:

    我不完全理解谓词应该如何工作,像[some,input,i,ate,x,some,other,input] 这样的数组呢,应该将 x 附加到列表中吗?

    您可以尝试制作自己的列表,例如 H1 = [i,ate,X|_],H2 = [you,can,have,Y|_],然后递归地遍历 HL 的成员并比较它们,并让您的解决方案将它们与 X 或 Y 统一起来。

    编辑:

    我为 [i,ate,x] 做了一些东西,现在你必须对 [you,can,have,y] 做出类似的方法。

    方法是检查列表[i,ate,X]是否是HL当前成员的子列表,如果是我们可以将X添加到我们的FL集合中。检查这是否是您所期望的:)

    fromHistory(HL,FL) :-
        findAnswers(HL,[],FL).
    
    findAnswers([],Answers,Answers).
    findAnswers([H|HL],FL,Answers) :-
           (isSublist([i,ate,X],H) -> append(FL,[X],FL2); FL2 = FL),
           findAnswers(HL,FL2,Answers).
    
    isSublist(SL, L) :-
        append([_,SL,_],L).
    

    【讨论】:

    • 我想在整个列表中找到“ate”之后的元素和[you,can,have]之后的元素。
    • 这给出了 FL = [ ]
    • 我的输出是这样的:?- fromHistory([[random],[k,i,ate,apple,mm],[i,ate,pear],[this,is,random]],X). X = [apple, pear].
    【解决方案3】:

    您的问题的解决方案可能是这样的:

    solve(L,FL,FLO):-
        member("ate",L),
        \+consequent(L),
        nth1(3,L,E),
        append(FL,[E],FLO).
    
    solve(L,FL,FLO):-
        \+member("ate",L),
        consequent(L),
        nth1(4,L,E),
        append(FL,[E],FLO).
    
    
    consequent(L):-
        nth1(P,L,"you"),
        P1 is P+1,
        nth1(P1,L,"can"),
        P2 is P+2,
        nth1(P2,L,"have").
    
    fromHistory([],L,L).
    fromHistory([H|T],L,FL):-
        solve(H,L,FLO),
        fromHistory(T,FLO,FL).
    

    所以首先检查ate 是否在列表中,you can have 是否不在列表中。然后您可以使用nth/3 找到您想要的元素,并使用append/3 将其附加到列表中。当您在列表中找到you can haveate 不在列表中时,类似的情况。当ateyou can have 都在列表中时,您必须决定要做什么。在此实现中,谓词失败。

    查询:

    ?- fromHistory([["you","can","have","hallo","at"],["ate","str1","str2"]],["test","aa"],L).
    L = ["test", "aa", "hallo", "str2"]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-18
      • 1970-01-01
      相关资源
      最近更新 更多