我在Prolog中写了一个密码,但我不确定如何传递参数,所以我可以加密和解密输入。
caesar(L1,L2,L3) :-
maplist(cipher, L1, PC), string_to_list(L2,PC),
maplist(decipher,L2,PC), string_to_list(L3,PC).
cipher(A,B) :-
B is A+1.
decipher(A,B) :-
B is A-1.
答案 0 :(得分:2)
我认为您的代码存在一些问题。
你的描述说, ...所以我可以加密和解密输入。这意味着L3
应该是L1
的解密。您的代码会解密L2
(这是加密L1
的输出)。
第二个问题是您重用PC
变量。一旦变量在一个谓词子句中在Prolog中实例化,就无法在没有回溯的情况下重新实例化。所以你需要一个新的变量,或者你的子句中的第二行会失败。
如果您只是处理列表,那么更正后的版本可能会是这样的:
caesar(L1, L2, L3) :-
maplist(cipher, L1, Encode), string_to_list(L2, Encode),
maplist(decipher, L1, Decode), string_to_list(L3, Decode).
如果您确实打算L3
解密L1
被加密的结果,请在最后一行中将L1
替换为L2
。此外,正如@false说明的那样,SWI Prolog中不推荐使用string_to_list/2
,而是string_codes/2
。
请注意,在Prolog中,表达式"abc"
和[97, 98, 99]
表示相同的内容。 Prolog将它们视为等效物,您实际上可以互换使用。如果你想使用原子(单引号),那么你可以使用atom_codes/2
:
caesar2(L1, L2, L3) :-
atom_codes(L1, List1),
maplist(cipher, List1, Encoded), atom_codes(L2, Encoded),
maplist(decipher, List1, Decoded), atom_codes(L3, Decoded).
哪个会产生相同的结果,但你会使用单引号作为原子。
答案 1 :(得分:1)
您提供可以通过多种方式处理的测试用例?- caesar("hello",L2).
。
由于SWI 7默认为字符串。但这不是常见的编码。对于其他编码
see this
最直接和最传统的方法是。
:- set_prolog_flag(double_quotes,codes).
将此指令放入您的文件后,或在顶层发出:
?- set_prolog_flag(double_quotes,codes).
true.
?- L = "hello".
L = [104, 101, 108, 108, 111].
现在,可以直接应用编码方法。 Julius Caesar使用的方法与您指出的方法略有不同。特别是他使用模数,有时是不同的偏移量。此外,他不知道ASCII,只有大写字母,没有数字(只有像XVII)。允许我包括新的字母G(C与马尾),J(我与马尾),U(花式V),W(花式VV)。否则我们需要一个明确的表。
以下是使用library(clpfd)
的一般密码关系。 0'A
是A的字符代码,0'Z
是Z的字符代码。
:- use_module(library(clpfd)).
cypher(Code, A,B) :-
[A,B] ins 0'A..0'Z, % only letters!
B #= 0'A+((A-0'A)+Code)mod 26.
请注意,这是一种关系;它可以用来编码:
?- cypher(1, 0'A, Y).
Y = 0'B.
...还要解码:
?- cypher(1, X, 0'B).
X = 0'A.
所以最后我们可以将这种关系应用于代码列表:
?- maplist(cypher(1),"ABC",L), atom_codes(A, L).
L = [66, 67, 68],
A = 'BCD'.
?- maplist(cypher(1),"ABC","BCD").
true.
?- maplist(cypher(1),X,"BCD"), atom_codes(A, X).
X = [65, 66, 67],
A = 'ABC'.
总是被迫将整数转换回可读的东西,这很烦人。不是吗?嗯,有一个更好的方法:
:- set_prolog_flag(double_quotes, chars).
另一种方法是使用字符,它们具有很大的优势,即答案现在更具可读性,但使用library(double_quotes)
它们是完全可读的。简单下载吧。
?- set_prolog_flag(double_quotes, chars).
true.
?- L = "ABC".
L = ['A', 'B', 'C'].
?- use_module(double_quotes).
true.
?- L = "ABC", L = [C|Cs].
L = "ABC",
C = 'A',
Cs = "BC".
然而,我们的密码关系现在变得更加复杂,因为我们必须将字符转换为代码:
xcypher(Code, ACh, BCh) :-
( nonvar(ACh) -> char_code(ACh, A) ; char_code(BCh, B) ),
cypher(Code, A, B),
char_code(ACh, A),
char_code(BCh, B).
这就是凯撒阅读的内容(proof):
?- maplist(xcypher(1),Xs, "SPNBOFTFWOUEPNWT").
Xs = "ROMANESEVNTDOMVS".