你如何找到列表中缺少的号码?

时间:2011-12-07 22:10:03

标签: prolog

假设我有一个List [1,2,4,5],我想有一个谓词,它返回3作为缺失的元素。您可以假设输入列表始终按顺序排序。

到目前为止我的解决方案:

% missing_number/2 (ListToBeChecked, ListToBeCompared, MissingNum)
missing_number([], [], []) :- !.
missing_number([Head | Tail], [Head | Rest], Number) :- 
    missing_number(Tail, Rest, Number).
missing_number(_, [X | _], [X | Node]) :- 
    missing_number(_, _, Number), !.

5 个答案:

答案 0 :(得分:4)

使用between/3生成从最小到最大的所有数字。使用memberchk/2(或member/2)查找遗失的内容。

L = [1,2,4,5],
L = [M|_],
last(L, N),
between(M, N, I),
\+ memberchk(I, L).

为读者练习:将其包含在谓词中。

编辑按照受欢迎的要求提供高效的解决方案:

missing([I,K|_], M) :-
    I1 is I+1,
    K1 is K-1,
    between(I1, K1, M).
missing([_|Ns], M) :-
    missing(Ns, M).

编辑2 :以上更优雅的版本,受@chac启发,不一定非常高效:

missing(L,M) :- append(_, [I,J|_], L), I1 is I+1, J1 is J-1, between(I1,J1,M).

答案 1 :(得分:3)

paradigmatic谓词附加/ 3多次可以帮助涉及列表的职责:这里足以检查不是后继的连续元素:

missing(L, M) :-
    append(_, [A,B|_], L),
    \+ succ(A, B), succ(A, M).

<强>已完成

能够实现长度的间隙&gt; 1,解决方案最终几乎与larsman one相同:

missing(L, M) :-
    append(_, [A,B|_], L),
    succ(A, S), succ(P, B), between(S, P, M).

succ / 2允许更具说明性的方法,但它明显慢于算术。

答案 2 :(得分:1)

它不适用于未排序的列表

missing([], []).
missing([H|T], R) :- missing([H|T], H, R).
missing([], _I, []).
missing([H|T], I, [I|R]) :-
    H =\= I,
    !,
    NextI is I + 1,
    missing([H|T], NextI, R).
missing([_|T], I, R) :-
    NextI is I + 1,
    missing(T, NextI, R).

答案 3 :(得分:0)

missing([], []).
missing([H|T], R) :- missing([H|T], H, R).
missing([], _I, []).
missing([H|T], I, [I|R]) :-
    H =\= I,
    !,
    NextI is I + 1,
    missing([H|T], NextI, R).
missing([_|T], I, R) :-
    NextI is I + 1,
    missing(T, NextI, R).

表示无助手谓词。

答案 4 :(得分:0)

请参阅以下内容: 实现是在JavaScript中。但算法可以转换。我希望这有帮助! 假设列表是升序的并且是一个算术系列 - n,n + 1,n + 2 ...此外,列表可以从任何地方开始,而不仅仅是0

    function getMissingNum() {
    var start = Math.floor(Math.random() * 150) / 1;
    var nElem = Math.floor(Math.random() * 20) / 1;
    var set = [];
    var rand = Math.floor(Math.random() * nElem) + start / 1;
    for (var i = start; i <= start + nElem; i++) {
        //skip one number randomly
        if (i == rand) continue;
        set.push(i);
    }

    var sum = 0;
    for (var i = 0; i < set.length; i++) {
        sum += set[i];
    }

    // SEE HERE: 
    // Total = N * (N + 1) / 2
    var max = set[set.length - 1];
    var min = set[0];// - 1;
    var actual = (((max * (max + 1)) / 2));
    var excluded = (((min * (min + 1)) / 2));
    var missing = actual - excluded - sum + start;
    if (min > start) {
        missing = missing + min;
    }
    return {
        missing: missing,
        min: min,
        max: max,
        actual: actual,
        excluded: excluded,
        rand: rand,
        start: start,
        nElem: nElem
    }
}

var results = [];
for (var i = 0; i < 100; i++) {
    var result = getMissingNum();
    if (result.rand != result.missing) {
        results.push(result);
    }
}