通过提供输出和接收输入来使用 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.
我写了一个 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.