Prolog 算术拼图序言
我必须在列表中的数字之间加上+和-才能得到提供的数字。例如12-34=-22。我是这样做的:Prolog 算术拼图序言,prolog,Prolog,我必须在列表中的数字之间加上+和-才能得到提供的数字。例如12-34=-22。我是这样做的: arit(L, Ls, S) :- arit(L, Ls, S, 0). arit([], [], R, R). arit([E|L], Ls, R, S) :- S1 is S + E, Ls = [+|[E|Ns]], arit(L, Ns, R, S1). arit([E|L], Ls, R, S) :- S1 is S - E, Ls = [
arit(L, Ls, S) :- arit(L, Ls, S, 0).
arit([], [], R, R).
arit([E|L], Ls, R, S) :-
S1 is S + E,
Ls = [+|[E|Ns]],
arit(L, Ns, R, S1).
arit([E|L], Ls, R, S) :-
S1 is S - E,
Ls = [-|[E|Ns]],
arit(L, Ns, R, S1).
arit([E|L], Ls, R, S) :-
S1 is (S*10 + E),
Ls=[E|Ns],
arit(L, Ns, R, S1).
它是有效的,但有重复的答案(比如1+2+3和+1+2+3)。也许有人有一个建议如何优化它?编辑这段代码根本不起作用,请查看答案。事实上,您的代码没有正常工作。要确认此事实,请尝试以下查询:
?- put_arit2([1,2,3,4], L, 22).
false.
很容易检查,[-,1,2,+,3,4]
将是正确的答案
因此,我建议以下解决方案(在SWI Prolog中):
- 定义一个谓词,该谓词可以生成所有可能的列表(带有运算符)
- 将每个可能的列表转换为相应的算术表达式,并检查它是否具有所需的值
?- putop([1,2,3,4], L, 22).
L = [-, 1, 2, +, 3, 4] ;
false.
?- putop([1,2,3,4,5,6,7,8,9], L, 4).
L = [+, 1, +, 2, -, 3, 4, +, 5, +, 6, +, 7, +, 8, +, 9] ;
L = [+, 1, 2, +, 3, -, 4, +, 5, -, 6, -, 7, -, 8, +, 9] ;
L = [+, 1, 2, +, 3, -, 4, -, 5, +, 6, -, 7, +, 8, -, 9] ;
L = [+, 1, 2, -, 3, +, 4, +, 5, -, 6, -, 7, +, 8, -, 9] ;
L = [+, 1, 2, -, 3, +, 4, -, 5, +, 6, +, 7, -, 8, -, 9] ;
L = [+, 1, 2, -, 3, +, 4, 5, -, 6, 7, +, 8, +, 9] ;
L = [+, 1, 2, -, 3, -, 4, -, 5, -, 6, -, 7, +, 8, +, 9] ;
L = [+, 1, 2, -, 3, 4, -, 5, 6, -, 7, +, 8, 9] ;
L = [-, 1, +, 2, +, 3, 4, +, 5, 6, -, 7, 8, -, 9] ;
L = [-, 1, +, 2, 3, +, 4, 5, +, 6, -, 7, 8, +, 9] ;
L = [-, 1, -, 2, +, 3, 4, -, 5, +, 6, 7, -, 8, 9] ;
L = [-, 1, -, 2, 3, -, 4, +, 5, 6, -, 7, -, 8, -, 9] ;
L = [-, 1, 2, +, 3, +, 4, +, 5, -, 6, -, 7, +, 8, +, 9] ;
L = [-, 1, 2, +, 3, +, 4, -, 5, +, 6, +, 7, -, 8, +, 9] ;
L = [-, 1, 2, +, 3, -, 4, +, 5, +, 6, +, 7, +, 8, -, 9] ;
L = [-, 1, 2, +, 3, -, 4, -, 5, -, 6, 7, +, 8, 9] ;
L = [-, 1, 2, -, 3, -, 4, +, 5, -, 6, +, 7, +, 8, +, 9] ;
L = [-, 1, 2, -, 3, 4, +, 5, 6, -, 7, -, 8, +, 9] ;
false.
[编辑]如果您不想使用内置谓词原子列表\u concat/2
和从原子/3
读取\u term\u,那么您需要创建自己的谓词来计算数字和运算符列表
putop(L, E, V) :-
putop(L, E),
evaluate(E, V).
putop([], []).
putop(L, [O|D]) :-
member(O, [+,-]),
append([X|A], B, L),
append([X|A], C, D),
putop(B, C).
evaluate(List, Value) :-
evaluate(List, 0, Value).
evaluate([], Value, Value).
evaluate([Operator|List], Accumulator, Value) :-
operand(List, 0, Operand, Rest),
add(Operator, Accumulator, Operand, NewAccumulator),
evaluate(Rest, NewAccumulator, Value).
operand([], Accumulator, Accumulator, []).
operand([+|Rest], Accumulator, Accumulator, [+|Rest]).
operand([-|Rest], Accumulator, Accumulator, [-|Rest]).
operand([Digit|Rest], Accumulator, Value, List) :-
Digit \= +,
Digit \= -,
NewAccumulator is 10*Accumulator + Digit,
operand(Rest, NewAccumulator, Value, List).
add(+, Accumulator, Operand, NewAccumulator) :-
NewAccumulator is Accumulator + Operand.
add(-, Accumulator, Operand, NewAccumulator) :-
NewAccumulator is Accumulator - Operand.
看看这个问题:不是完全相同的问题,但是相同的想法哦,是的,我没有检查负数和两个数字。。是的,你的解决方案很好,但我尝试在没有任何prolog谓词的情况下(原子列表等)实现它。所以我认为这会减少解决方案,但对于初学者来说,如果我只能在列表的第一个数字后面,第一个元素后面放一个符号会怎么样?也许你知道我该怎么做?我对prolog很陌生,所以困在这些基本任务上很糟糕。现在我用晨视仪检查了它,哦,天哪,我的解决方案很快就不起作用了。@LorusIndicus在我的回答中看到了“编辑”。是的,我今天提出了类似的解决方案,非常感谢你的帮助。
putop(L, E, V) :-
putop(L, E),
evaluate(E, V).
putop([], []).
putop(L, [O|D]) :-
member(O, [+,-]),
append([X|A], B, L),
append([X|A], C, D),
putop(B, C).
evaluate(List, Value) :-
evaluate(List, 0, Value).
evaluate([], Value, Value).
evaluate([Operator|List], Accumulator, Value) :-
operand(List, 0, Operand, Rest),
add(Operator, Accumulator, Operand, NewAccumulator),
evaluate(Rest, NewAccumulator, Value).
operand([], Accumulator, Accumulator, []).
operand([+|Rest], Accumulator, Accumulator, [+|Rest]).
operand([-|Rest], Accumulator, Accumulator, [-|Rest]).
operand([Digit|Rest], Accumulator, Value, List) :-
Digit \= +,
Digit \= -,
NewAccumulator is 10*Accumulator + Digit,
operand(Rest, NewAccumulator, Value, List).
add(+, Accumulator, Operand, NewAccumulator) :-
NewAccumulator is Accumulator + Operand.
add(-, Accumulator, Operand, NewAccumulator) :-
NewAccumulator is Accumulator - Operand.