如何在Prolog中实现密码算法?

如何在Prolog中实现密码算法?,prolog,cryptarithmetic-puzzle,clpfd,Prolog,Cryptarithmetic Puzzle,Clpfd,7个不同的字母中的每一个代表不同的数字。其目的是找到字母的数字替换,从而得到算术正确的和。然后,解决方案应产生满足上述加法问题的所有数字组合。输入诸如crypto(P,I,N,G,O,F,U)之类的查询应该会返回您的解决方案 密码算术难题是这样的: P I N G P O N G + F U N --------- I G N I P substitution_cipher( ping + pong + fun , ignip , Expr , Sum , Key ) . 假设这

7个不同的字母中的每一个代表不同的数字。其目的是找到字母的数字替换,从而得到算术正确的和。然后,解决方案应产生满足上述加法问题的所有数字组合。输入诸如
crypto(P,I,N,G,O,F,U)
之类的查询应该会返回您的解决方案

密码算术难题是这样的:

  P I N G
  P O N G
+   F U N
---------
I G N I P
substitution_cipher( ping + pong + fun , ignip , Expr , Sum , Key ) .

假设这是我们正在讨论的一个简单的替换密码(只是为了好玩),我将尝试一下。应该注意的是,这完全没有经过测试

我将以一种通用的方式来设置它,因此您可以说:

substitution_cipher( CipherExpr , CipherResult , Expr , Result , Key ).
我们将制定一个规则,加密的东西由原子表示,所以你可以这样说:

  P I N G
  P O N G
+   F U N
---------
I G N I P
substitution_cipher( ping + pong + fun , ignip , Expr , Sum , Key ) .
并得到你期望的结果

所以

首先,您需要密码文本中的字符集(离散、唯一):

character_set( Expr , Charset ) :-
  setof( C , A^Cs^( atoms_in_expression( Expr , A ) , atom_chars(A,Cs) , member(C,Cs) ) , Charset ) .

atom_in_expression( Expr , Value ) :- atom(Expr) .
atom_in_expression( Expr , Value ) :-
  Expr =.. [ _ , Left , Right ] ,
  (
    values( Left  , Value )
  ;
    values( Right, Value
  ) .
上面的代码遍历表达式的解析树,如
a*b+c*d
,找到每个叶节点(原子),将它们分解为组成它们的字符
setof/3
确保生成的列表已排序且唯一

一旦你有了它,你需要一种生成所有可能键的方法(key==字符和数字之间的映射)。我们希望能够说一些类似的话

generate_key( [a,b,c] , Key )
回来

Key = [a:1,b:2,c:3]
等等

因此:

然后你需要一种解码密码表达式的方法,比如

ping + pong + fun
并[尝试]将其转换回正确的数字。这与遍历解析树并枚举叶节点原子没有多大区别,但这里我们需要将它们恢复为数字形式

如果表达式是一个原子,我们

  • 将其分解为其组成特征
  • 使用我们的键,将每个字符映射到对应的数字
  • 然后我们把数字列表变回一个数字

    解码(密钥、密码、明文):- 原子(密码表达式), 原子字符(密码表达式,Cs), findall(D,(成员(C,Cs),成员(C:D,Key)->true;D=C),Ds), 数字字符(明文、Ds)

一般情况很简单。像
ping+pong
这样的中缀表达式实际上是prolog术语
+(ping,pong)
。我们:

  • 将中缀术语(如
    ping+pong
    )分解为运算符(
    +
    )及其左右子表达式
  • 然后我们递归地解码左、右子表达式
  • 最后,我们重新组合[解码]表达式

    解码(密钥、密码、明文):- CipherExpr=。。[Op,L,R], 解码(L,L1), 解码(R,R1), PlainExpr=。。[Op,L1,R1]

然后,您可以将其全部放在一起:

substitition_cipher( CipherExpr , CipherResult , PlainExpr , PlainResult , Key ) :-
  character_set( CipherExpr = CipherResult , Charset ) ,
  generate_key( Charset, Key ) ,
  decode( Key , CipherExpr   , PlainExpr   ) ,
  decode( Key , CipherResult , PlainResult ) ,
  PlainResult =:= PlainExpr
  .
使用基于到的,我们运行以下查询:

?- Eq = ([P,I,N,G] + [P,O,N,G] + [F,U,N] #= [I,G,N,I,P]),
   crypt_arith_(Eq,Zs),
   labeling([],Zs).
  Eq = ([7,1,9,4] + [7,0,9,4] + [6,2,9] #= [1,4,9,1,7]), Zs = [7,1,9,4,0,6,2]
; Eq = ([8,1,4,7] + [8,3,4,7] + [9,2,4] #= [1,7,4,1,8]), Zs = [8,1,4,7,3,9,2]
; Eq = ([8,1,4,7] + [8,9,4,7] + [3,2,4] #= [1,7,4,1,8]), Zs = [8,1,4,7,9,3,2]
; false.

隐马尔可夫模型。。。。你有没有试着在谷歌上搜索“Prolog发送更多的钱”?根据stackoverflow的指导方针,你的问题不符合真正的问题,我看不出有问题。陈述的结尾有一个问号,它构成了主题,但它不构成问题。您尝试了什么,您在解决问题的过程中遇到了什么阻碍?请参阅。@false:显然,只有当有人登录时,链接才能正确解决!