2015-06-30 2 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_/2 и binaryList/2 работы в обоих направлениях. Программа распадается из-за порядка создания экземпляра в оригинале binaryHex/2: binaryList/2 должен прибыть до binaryHex_/2, чтобы исходная задача бинарного шестнадцатеричного файла работала.

Я предполагаю, что эта проблема будет усугубляться, если я конвертирую шестнадцатеричный список в атом. Каковы некоторые стратегии, чтобы справиться с этой ситуацией, так что, продолжая программировать, я не сталкиваюсь с ошибками создания экземпляра? Любые комментарии/ответы о том, когда это невозможно, также поощряются.

+0

'' 11111111'' * атом *, а не * строка *. В Prolog строка * * (*, например, *, '" 11111111 "') представляет * список * * кодов символов *. – lurker

ответ

1

Я думаю, что то, о чем вы просите, не достижимо - вообще - в Прологе. Но так как я 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). Кроме того, более естественно использовать . Ah, а 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". 

Таким образом, вы получите "двунаправленность" просто с помощью списков. Короутинг здесь действительно переполнен. Хуже того, ваше исходное представление, используя атомы не могут справиться с ситуациями, как генерировать все bitstrings длины 8:

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

Доказывая, что нет bitstrings длины 7:

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

И доказывает, что bitstrings начиная с 10 не может соответствовать шестнадцатеричному номеру, начинающемуся с f.

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

Вы не можете сделать все это с атомами и when/2 деклараций.

Смежные вопросы