通过提供输出和接收输入来使用 Prolog 谓词

Using a Prolog predicate by providing the output and receiving the input

我写了一个 Prolog 谓词,它转换数字中的数字列表。因此,例如,如果输入是列表 [1, 2, 3],则输出将是数字 123。这是我的代码:

convertListToNum([], Col, Col).

convertListToNum([H|T], Col, R):-
    Col2 is Col * 10 + H,
    convertListToNum(T, Col2, R).

convertListToNumMain(L, R):-
    convertListToNum(L, 0, R).

如您所见,谓词的参数是 L=input, R=output,因为我提供列表 L 作为 ConvertListToNumMain 的输入,我将得到 ConvertListToNumMain 中的数字作为输出=16=]。如果我尝试这个谓词,它会按预期工作:convertListToNumMain([1, 2, 3], R) 将作为输出 R=123.

现在我要做的是通过提供输出编号而不是输入列表来使用此功能。我将使用 L=output, R=input。所以我不会再提供列表 L,我会提供数字 R 并期望收到列表作为输出。所以我想要的是这样称呼:convertListToNumMain(L, 123) 并且我希望收到输出 L=[1, 2, 3]。但是,当我调用它时,出现错误 Arguments are not sufficiently instantiated。我认为这是因为在行 Col2 is Col * 10 + H 中我尝试使用列表的第一个元素,即使列表没有实例化,但我不确定。我该怎么做才能完成这项工作?

我想将数字列表转换为数字,然后将数字转换回数字列表,我认为我可以摆脱这个,但显然不是。另一种方法是创建另一个复杂且低效的谓词,它将在每个步骤中找到一个数字的最高有效数字,然后将其添加到列表中,找到没有最高有效数字的数字,然后进行下一次调用。或者至少那是我的想法。那是很多代码,而且(在我看来)效率更低。那么有什么方法可以通过提供输出来使用我已经拥有的东西吗?如果没有,是否有比我上面的想法更好的方法将数字转换为数字列表(当然是递归的,因为我使用的是 Prolog)?

没那么复杂。或者效率低下。

int_list( N , Ds ) :- nonvar(N), number_to_digits(N,Ds).
int_list( N , Ds ) :- nonvar(Ds), digits_to_number(Ds,0,N).

digits_to_number( [] , N , N ) .
digits_to_number( [D|Ds] , T , N ) :-
  T1 is 10 * T + D ,
  digits_to_number(Ds,T1,N).

number_to_digits( 0 , [0] ).
number_to_digits( N , Ds  ) :-
  N > 0,
  digits(N, [], Ds).

digits( N , T  , Ds ) :-
  N > 0,
  D  is N mod 10,
  N1 is N div 10,
  digits(N1,[D|T],Ds).
digits( 0 , Ds , Ds ) .

但使用内置谓词可能更容易 number_codes/2:

int_digits( N , Ds ) :- nonvar(Ds) , codes_digits(Cs,Ds) , number_codes(N,Cs)  .
int_digits( N , Ds ) :- nonvar(N)  , number_codes(N,Cs)  , codes_digits(Cs,Ds) .

codes_digits( []     , []     ) .
codes_digits( [C|Cs] , [D|Ds] ) :- code_digit(C,D), codes_digits(Cs,Ds).

code_digit(C,D) :- nonvar(C), D is C-48.
code_digit(C,D) :- nonvar(D), C is D+48.