2015-06-30 99 views
1

我有一個謂詞,它接收原子形式的二進制數,並返回一個十六進制代碼列表。Prolog如何獲取無意義的變量以產生輸出

?- binaryHex('11111111',X). 
X = [f, f]. 

當我嘗試從十六進制到二進制去,我得到這個錯誤:

?- binaryHex(X,[f,f]). 
ERROR: atom_codes/2: Arguments are not sufficiently instantiated 

我想這兩個變量產生正確的輸出。這是代碼。

hex('0000',0). hex('0001',1). hex('0010',2). hex('0011',3). 
hex('0100',4). hex('0101',5). hex('0110',6). hex('0111',7). 
hex('1000',8). hex('1001',9). hex('1010',a). hex('1011',b). 
hex('1100',c). hex('1101',d). hex('1110',e). hex('1111',f). 

binaryHex(X,Y) :- 
    atom_codes(X,A), 
    binaryList(A,B), 
    binaryHex_(B,Y). 

binaryList([],[]). 
binaryList([A,B,C,D|Ds],[Y|Ys]) :- 
    atom_codes(Y,[A,B,C,D]), 
    binaryList(Ds,Ys). 

binaryHex_([],[]). 
binaryHex_([B|Bs],[H|Hs]) :- 
    hex(B,H), 
    binaryHex_(Bs,Hs). 

在謂詞binaryHex_/2binaryList/2工作兩者兼得的變量。由於原始binaryHex/2binaryList/2中的實例化順序必須在binaryHex_/2之前,程序發生故障才能使二進制的原始任務以十六進制工作。

我想如果我將十六進制列表轉換爲原子,這個問題會複雜化。什麼是應對這種情況的一些策略,以便在繼續編程時我不會遇到實例化錯誤?對於何時無法實現的任何評論/回答也會受到鼓勵。

+0

''11111111''是* atom *,而不是*字符串*。在Prolog中,*字符*(*例如*,「」11111111「')代表*字符代碼*的*列表*。 – lurker

回答

1

我認爲你所要求的是不可實現的 - 一般來說 - 在Prolog中。但因爲我answered類似的問題,我會建議嘗試

binaryHex(X,Y) :- 
    when_2(atom_codes(X,A)), 
    when_2(binaryList(A,B)), 
    binaryHex_(B,Y). 

binaryList([],[]). 
binaryList([A,B,C,D|Ds],[Y|Ys]) :- 
    when_2(atom_codes(Y,[A,B,C,D])), 
    binaryList(Ds,Ys). 

:- meta_predicate when_2(0). 
when_2(P) :- 
    strip_module(P,_,Q), 
    Q =.. [_,A0,A1], 
    when((ground(A0);ground(A1)), P). 

當然,當/ 2必須由系統提供。

4

您的問題是您使用的是錯誤的表示形式。使用列表時,Prolog可以輕鬆處理您想要的內容,而無需額外的工作。即,字符列表(=長度爲1的原子)。此外,使用更自然。啊,而0就是一個整數,'0'就是對應的字符!


:- set_prolog_flag(double_quotes, chars). % More about double quotes 

hexdigit('0') --> "0000". 
hexdigit('1') --> "0001". 
hexdigit('2') --> "0010". 
hexdigit('3') --> "0011". 
hexdigit('4') --> "0100". 
hexdigit('5') --> "0101". 
hexdigit('6') --> "0110". 
hexdigit('7') --> "0111". 
hexdigit('8') --> "1000". 
hexdigit('9') --> "1001". 
hexdigit(a) --> "1010". 
hexdigit(b) --> "1011". 
hexdigit(c) --> "1100". 
hexdigit(d) --> "1101". 
hexdigit(e) --> "1110". 
hexdigit(f) --> "1111". 

hexnum([]) --> 
    []. 
hexnum([D|Ds]) --> 
    hexdigit(D), 
    hexnum(Ds). 

binaryHex(Bin, Hex) :- 
    phrase(hexnum(Hex), Bin). 

現在一些示例用法:


?- binaryHex("11111111",X). 
X = [f, f] ; 
false. 

?- binaryHex(H,"ff"). 
H = ['1', '1', '1', '1', '1', '1', '1', '1']. 

?- use_module(double_quotes). 
% double_quotes compiled into double_quotes 0.00 sec, 12 clauses 
true. 

?- binaryHex(H,"ff"). 
H = "11111111". 

所以,你只需使用列表獲得 「雙向性」。協調在這裏真的是過度。更糟的是,使用原子您的原始表示不能情況應付作爲產生長度爲8的所有位串:

?- length(L,8), binaryHex(L,Hex). 
L = "00000000", 
Hex = "00" ; 
L = "00000001", 
Hex = "01" ; 
L = "00000010", 
Hex = "02" ; 
L = "00000011", 
Hex = "03" ... 

證明不存在長度爲7的位串:

?- length(L,7), binaryHex(L,Hex). 
false. 

而且證明起始10位串不能對應於從f開始的十六進制數字。

?- binaryHex(['1','0'|L],[f|_]). 
false. 

你不能做所有這些與原子和when/2聲明。