python - 如何在 Prolog 中解决这个算术表达式难题?

标签 python prolog constraints

我有编程问题 ( https://blog.svpino.com/2015/05/08/solution-to-problem-5-and-some-other-thoughts-about-this-type-of-questions ):

Write a program that outputs all possibilities to put + or - or nothing between the numbers 1, 2, ..., 9 (in this order) such that the result is always 100. E.g.: 1 + 2 + 34 – 5 + 67 – 8 + 9 = 100.

我用 Python 解决了这个问题得到了 11 个答案:

import itertools   
for operator in [p for p in itertools.product(['+','-',''], repeat=8)]:
    values = zip([str(x) for x in range(1, length+1)], operator) + ['9']
    code = ''.join(itertools.chain(*values))
    if 100 == eval(code):
        print "%s = %d" % (code, eval(code))

这是我的第二个更长的 Python 代码 ( https://gist.github.com/prosseek/41201d6508f01cf1643e ):

[1, 2, 34, -5, 67, -8, 9]
[1, 23, -4, 56, 7, 8, 9]
[12, 3, -4, 5, 67, 8, 9]
[123, -4, -5, -6, -7, 8, -9]
[1, 23, -4, 5, 6, 78, -9]
[12, 3, 4, 5, -6, -7, 89]
[12, -3, -4, 5, -6, 7, 89]
[123, -45, -67, 89]
[123, 45, -67, 8, -9]
[1, 2, 3, -4, 5, 6, 78, 9]
[123, 4, -5, 67, -89]

我还在 Prolog 中找到了一个建议的解决方案 ( http://www.reddit.com/r/programming/comments/358tnp/five_programming_problems_every_software_engineer/cr2dvsz ):

sum([Head|Tail],Signs,Result) :-
   sum(Head,Tail,Signs,Result).
sum(X,[],[],X).

sum(First,[Second|Tail],['+'|Signs],Result) :-
   Head is First + Second,
   sum(Head,Tail,Signs,Result).
sum(First,[Second|Tail],['-'|Signs],Result) :-
   Head is First - Second,
   sum(Head,Tail,Signs,Result).
sum(First,[Second|[Third|Tail]],['+'|[''|Signs]],Result) :- 
   C    is Second*10+Third, 
   Head is First + C, 
   sum(Head,Tail,Signs,Result).
sum(First,[Second|[Third|Tail]],['-'|[''|Signs]],Result) :-
   C    is Second*10+Third,
   Head is First - C,
   sum(Head,Tail,Signs,Result).

但是,这给出了只有 4 个解决方案(不是预期的 11 个):

?- sum([1,2,3,4,5,6,7,8,9],X,100).
X = [+, +, -,+, +, +,'',+] ;
X = [+, +,'',-, + '', -,+] ;
X = [+,'', -,+, +, +,'',-] ;
X = [+,'', -,+ '', +, +,+] ;
false.

这是因为 '' 没有作为第一个列表项出现。所以解决方案 [12,...][123,...] 被跳过。

我尝试添加 sum(First,[Second|Tail],[''|Signs],Result) :- Head is First*10 + Second, sum(Head,Tail,Signs,Result)., 但这样做会返回 15 个解决方案,而不是 11 个。

解释说 1+23 错误解释为 ((1)+2)*10+3

?- sum([1,2,3], [+,''], Result). 
Result = 33.

那么,如何在Prolog中解决这个问题呢?如何教 Prolog 1 + 23 在这个例子中是 24

最佳答案

Python eval 的对应物可以用 read_term/3is/2 实现,或者

give_100(A) :-
    generate(1, S),
    atomic_list_concat(S, A),
    read_term_from_atom(A, T, []),
    T =:= 100.

generate(9, [9]).
generate(N, [N|Ns]) :-
    N < 9, sep(N, Ns).

sep(N, L) :-
    ( L = [+|Ns] ; L = [-|Ns] ; L = Ns ),
    M is N+1,
    generate(M, Ns).

示例查询:

?- give_100(X).
X = '1+2+3-4+5+6+78+9' ;
X = '1+2+34-5+67-8+9' ;
X = '1+23-4+5+6+78-9' ;
X = '1+23-4+56+7+8+9' ;
X = '12+3+4+5-6-7+89' ;
X = '12+3-4+5+67+8+9' ;
X = '12-3-4+5-6+7+89' ;
X = '123+4-5+67-89' ;
X = '123+45-67+8-9' ;
X = '123-4-5-6-7+8-9' ;
X = '123-45-67+89' ;
false.

关于python - 如何在 Prolog 中解决这个算术表达式难题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30134535/

相关文章:

list - 判断给定元素是否在 double 列表中

javascript - 在不使用 jquery 的情况下在 div/span 元素溢出上添加点/省略号

python - 如何在 python 中删除转义序列,如 '\xe2' 或 '\x0c'

python - Selenium 导致Windows错误

indexing - 为什么这个谓词留下一个选择点?

prolog - 序言中的递归引用

python - file.read()、file.readline() 和遍历文件对象的区别

python - 在要插入 mongodb 的字典列表中设置唯一字段

c# - MVC ActionLink 在添加约束后生成 NON-Restul URL

ios - 如何缩小 UILabel 行之间的间距而不剪切标签?