2015-11-05 34 views
2

我需要創建一個謂詞,它接收一個數字列表並僅打印以7結尾的數字,並且其數字之和大於100PROLOG以7結尾且其數字之和的打印數字大於100

我所做的謂詞分開,但我需要幫助使兩個謂詞的工會,我的意思是,這兩個謂詞進入一個唯一的謂詞,這是我做的,到目前爲止:

%sum of digits greater than 100 
multi(X):- 
0 is X mod 100 
sum([],0). 
sum([P|Q],Z). 
multi(P), sum(Q,Z1), Z is P + Z1. 
sum([P|Q],Z). 
not multi(P), sum(Q,Z). 

%print the numbers that end in 7 
end(Y):- 
7 is Y mod 10. 
listend([],0). 
listend([P|Q]):- 
end(P),write(P), nl, listend(Q). 
listend([P|Q]):- 
not(end(P)), listend(Q). 
+0

程序文本中存在語法錯誤。 – repeat

回答

2

這適用於我:

?- filter([147, 24, 57, 17, 3667], X), write(X), nl, fail. 

sumdigits(0, 0). 
sumdigits(X, Z) :- 
    X > 0, 
    Z1 is X mod 10, 
    X2 is X // 10, 
    sumdigits(X2, Z2), 
    Z is Z1 + Z2. 

filter([], []). 
filter([H|X], [H|Y]) :- 
    sumdigits(H, D), 
    D > 10, 
    7 is H mod 10, !, 
    filter(X, Y). 
filter([_|X], Y) :- filter(X, Y). 

我得到:

[147, 57, 3667] 
No. 

我以爲你意味着的數字之和大於10,而不是100

+1

謝謝!但沒有數字的總和必須大於100 –

+0

@BrianDanielGarcía - 那麼你有一個問題。要得到一個數字總和大於'100'並以'7'結尾的數字,那麼最小的數字是'9 999 999 997',這不是一個有效的整數,所以代碼沒有返回結果。 – Enigmativity

+0

哦,我非常感謝你! –

4

使用

 
:- use_module (library(clpfd)). 

我們這樣做是這樣的:

n_base10(N, Ds) :- 
    n_base_digits(N, 10, Ds). 

n_base_digits(Expr, Base, Ds) :- 
    Base #> 1, 
    Ds = [_|_], 
    N #= Expr, 
    N #>= 0,         % N is non-negative 
    n_base_ref_acc_digits(N, Base, Ds, [], Ds). 

n_base_ref_acc_digits(N, Base, Ref, Ds0, Ds) :- 
    zcompare(Order, N, Base), 
    order_n_base_ref_acc_digits(Order, N, Base, Ref, Ds0, Ds). 

order_n_base_ref_acc_digits(<, N, _, [_] , Ds0, [N|Ds0]). 
order_n_base_ref_acc_digits(=, _, _, [_,_] , Ds0, [1,0|Ds0]). 
order_n_base_ref_acc_digits(>, N, Base, [_|Rs], Ds0, Ds) :- 
    N0 #= N // Base, 
    N1 #= N mod Base, 
    n_base_ref_acc_digits(N0, Base, Rs, [N1|Ds0], Ds). 

一些簡單的查詢:

?- n_base10(_, []). 
false. 

?- X #< 0, n_base10(X, Ds). 
false. 

?- n_base10(123, [1,2,3]). 
true.         

?- n_base10(123, Ds). 
Ds = [1,2,3]. 

?- n_base10(N, [1,7,9]). 
    N = 179 
; false. 

?- n_base10(459183754813957135135239458256, Ds). 
Ds = [4,5,9,1,8,3,7,5,4,8,1,3,9,5,7,1,3,5,1,3,5,2,3,9,4,5,8,2,5,6]. 

有關使用比其他10個基地如何?

 
?- member (Base,[2,8,10,16,36]), n_base_digits(N,Base,[1,2,3,4]). 
    Base = 8, N = 668 
; Base = 10, N = 1234 
; Base = 16, N = 4660 
; Base = 36, N = 49360 
; false. 

?- member(Base,[2,8,10,16,36]), n_base_digits(101,Base,Ds). 
    Base = 2, Ds = [1,1,0,0,1,0,1] 
; Base = 8, Ds =   [1,4,5] 
; Base = 10, Ds =   [1,0,1] 
; Base = 16, Ds =   [6,5] 
; Base = 36, Ds =   [2,29]. 

好的!按預期工作。

讓我們找到數字總和大於1007的整數作爲最不重要的十進制數字!

 
?- set_prolog_flag (toplevel_print_anon , false). 
true. 

?- _S #> 100, 
    n_base10(N, _Ds), 
    lists:last (_Ds, 7), 
    clpfd:sum (_Ds, #=, _S), 
    clpfd:labeling ([ff,min(N)], _Ds). 
    N = 499999999997 
; N = 589999999997 
; N = 598999999997 
... 

現在,你的問題的 「過濾」 的一部分......這是爲1,2,3一樣簡單。

首先,我們根據(@)/1定義(@)/2。它適合謂詞(#=)/2(#>)/2reification scheme(的if_/3(=)/3等),已經已經在很多logically-pure Prolog answers on StackOverflow.

@(G_0, T) :- @var(T), @G_0, T = true. 

二的被使用,我們定義具體化版本。

 
#=(X, Y, T) :- X #= Y #<==> B, bool01_t (B, T). 

#>(X, Y, T) :- X #> Y #<==> B, bool01_t(B, T). 

最後,使用Prolog lambdastfilter/3','/3,我們來電諮詢:

 
?- use_module(library(lambda)). 
true. 

?- Zs0 = [        /* Es: list of sample integers */ 
      499999999997,    /*  (digit sum = 101)  */ 
      9899999999970,    /*  (digit sum = 105)  */ 
      516666669999997,    /*  (digit sum = 103)  */ 
        5000007,    /*  (digit sum = 12)  */ 
      598999999997    /*  (digit sum = 101)  */ 
     ], 
    tfilter(\N^(      /* N: candidate integer  */ 
       @n_base10(N, Ds),  /* Ds: base-10 representation */ 
       @lists:last (Ds, D1),  /* D1: least significant digit */ 
       D1 #= 7,     /* D1:    equal to 7 */ 
       @clpfd:sum (Ds, #=, S), /* S: digit sum    */ 
       S #> 100     /* S:   greater than 100 */ 
      ), 
      Zs0, 
      Zs). 
Zs0 = [499999999997,9899999999970,516666669999997,5000007,598999999997], 
Zs = [499999999997,    516666669999997,  598999999997]. 

就像一個魅力!


注:1:使用SWI-Prolog的7.3版本。10(64位AMD64)

+0

'n_base_digits/3'看起來確實不錯,但它也可以擴展到負數嗎? – Fatalize

+0

@Fatalize。當然,它也可以用於這一點。提前處理標誌!這樣,您可以按原樣使用上述代碼。 – repeat