如何根据另一个列表中另一个元素的索引从列表中写出元素?

时间:2019-03-29 10:49:42

标签: prolog

我是prolog的新手,我真的不知道该如何解决这个问题。我有一个包含7个数字的列表,我能够得到这些数字的最大值和最小值,但是之后我必须从另一个列表中写入一个与第一个列表的最小值和最大值相同的元素。

start :- writeln('Write in seven numbers then type end.'),
            fill(L),
            lght(L,Sm),
            write(Sm),
            writeln(L),
    avg(L,Arvg),
    writeln('Avg of list:'),
    write(Arvg),
            min(L,Min),write('a minimum:'),write(Min),
            max(L,Max),write('a maximum:'),write(Max)
            ffile(F).

min([F|T],Min):-min(T,Min,F).
min([F|T],Min,Act):- number(F),F < Act, Newact is F, min(T,Min,Newact).
min([_|T],Min,Act):- min(T,Min,Act).
min([],Min,Min).
max([F|T],Max):-max(T,Max,F).
max([F|T],Max,Act):- number(F),F > Act, Newact is F, max(T,Max,Newact).
max([_|T],Max,Act):- max(T,Max,Act).
max([],Max,Max).

例如,我真的不知道如何将最小值和最大值与一天匹配,例如来自另一个列表。 附言:我的代码可能包含非英语单词,因为我没有用全英语写出来。

3 个答案:

答案 0 :(得分:2)

回答问题的第一步是通过还返回索引来修改找到列表的最小值和最大值的谓词。例如,将代码修改为:

minimum([Head| Tail], Minimum, Index) :-
    minimum(Tail, Head, Minimum, 2, 1, Index).

minimum([], Minimum, Minimum, _, Index, Index).
minimum([Head| Tail], Minimum0, Minimum, Position, Index0, Index) :-
    NextPosition is Position + 1,
    (   Head @< Minimum0 ->
        minimum(Tail,     Head, Minimum, NextPosition, Position, Index)
    ;   minimum(Tail, Minimum0, Minimum, NextPosition,   Index0, Index)
    ).

我使用术语比较而不是算术比较来使谓词更笼统。通话示例:

| ?- minimum([7,3,4,5,1], M, I).
M = 1, I = 5
yes

| ?- minimum([7,3,1,4,5], M, I).
M = 1, I = 3
yes

| ?- minimum([1,7,3,4,5], M, I).
M = I, I = 1
yes

您能从这里继续并通过努力来更新答案吗?

答案 1 :(得分:1)

您可以采用以下方法:

  • 创建一个列表键-值对,其中原始值是键,索引是值;
  • 按键(原始值)排序;
  • 第一个和最后一个现在分别是最小值和最大值的索引;
  • 使用两个索引和nth1/3从另一个列表中获取所需的元素。

但是您真的需要索引吗?如果只是因为需要从其他列表中获取元素而认为自己需要它们,请考虑:

  • 列出一个键-值对列表,其中键是第一个列表中的元素,值是第二个列表中的对应元素;
  • 按键排序,获取第一个和最后一个值。

赞:

keys_vals_min_max(Keys, Values, Min, Max) :-
    pairs_keys_values(Pairs, Keys, Values),
    keysort(Pairs, [_-Min|Rest]),
    last(Rest, _-Max).

有了这个我得到:

?- keys_vals_min_max([2,7,1,3,5,4,6], [a,b,c,d,e,f,g], Min, Max).
Min = c,
Max = b.

容易,对吧?

(注意:keysort/2不会删除重复项,并且很稳定。)

请不要在您强迫用户一一输入数字的情况下执行此操作。这是荒唐的。如果您需要7个数字的列表,只需键入:[1,2,3,4,5,6,7]。如果您需要列表中数字的平均值,请定义一个名为list_average/2的谓词,并让用户像这样查询它:

?- list_average([1,2,3,4], Average).
Average = 2.5.

如果您认为自己需要状态,请不要担心太多。在顶层,您可以先写下您的输入内容,然后单击“向上”按钮以获取上一个查询,然后继续添加内容。例如:

?- L = [1,2,3].
L = [1, 2, 3].

?- L = [1,2,3], length(L, N).
L = [1, 2, 3],
N = 3.

?- L = [1,2,3], length(L, N), sumlist(L, Sum).
L = [1, 2, 3],
N = 3,
Sum = 6.

?- L = [1,2,3], length(L, N), sumlist(L, Sum), Average is Sum / N.
L = [1, 2, 3],
N = 3,
Sum = 6,
Average = 2.

如果您想要不同的输入怎么办?只需再次点击“向上”按钮,然后更改L

?- L = [1,42], length(L, N), sumlist(L, Sum), Average is Sum / N.
L = [1, 42],
N = 2,
Sum = 43,
Average = 21.5.

答案 2 :(得分:1)

谢谢您的回答!

我能够通过编写代码在第一个列表中搜索Min和Max的索引,然后将索引号与另一个列表进行匹配来完成任务。

index([Element|_], Element, 0).
index([_|Tail], Element, Index):-
   index(Tail, Element, Index1),
   Index is Index1+1.

我用这段代码搜索索引

match([Elem|_],Num,Num,Elem) :-
   !.
match([_|Tail],Num,Count,MatchedNumber) :-
   Count < Num,
   Count1 is Count+1,
   match(Tail,Num,Count1,MatchedNumber).

然后使用此代码将索引号与其他列表的

匹配