假设我有一个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), !.
答案 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);
}
}