Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 哈斯克尔Enigma编码机的时钟式计数器_Haskell_Character Encoding_Encryption_Modular Arithmetic - Fatal编程技术网

Haskell 哈斯克尔Enigma编码机的时钟式计数器

Haskell 哈斯克尔Enigma编码机的时钟式计数器,haskell,character-encoding,encryption,modular-arithmetic,Haskell,Character Encoding,Encryption,Modular Arithmetic,我正在试着给Enigma编码机编程。我已经设法使转子和反射器工作良好,但我正在努力解决转子的进展 对于任何不熟悉这一点的人。Enigma机器由3个替换密码转子和一个包含13对字符的反射器组成。要对字符进行编码,首先由第一个转子对其进行编码,然后将编码字符传递给第二个转子,然后依次通过一个或多个转子传递给反射器,反射器将此新字符与其配对的字符交换。然后,该成对字符通过转子以相反的方式反向编码,直到最终得到最终编码字符 在对单个字符进行编码之前,转子会移动。如果您有一条很长的消息,在编码任何东西之前

我正在试着给Enigma编码机编程。我已经设法使转子和反射器工作良好,但我正在努力解决转子的进展

对于任何不熟悉这一点的人。Enigma机器由3个替换密码转子和一个包含13对字符的反射器组成。要对字符进行编码,首先由第一个转子对其进行编码,然后将编码字符传递给第二个转子,然后依次通过一个或多个转子传递给反射器,反射器将此新字符与其配对的字符交换。然后,该成对字符通过转子以相反的方式反向编码,直到最终得到最终编码字符

在对单个字符进行编码之前,转子会移动。如果您有一条很长的消息,在编码任何东西之前,第一个转子会移动一个位置,然后这个字符会通过系统进行编码。然后,在第二个字符编码之前,第一个转子再次移位。转子不断移动,直到再次达到起动位置。第25个字符编码后,第一个转子到达其起始位置,但现在第二个转子移动一个位置。在第二个转子再次转动之前,第一个转子再转动26次。当第二个转子转动26次时,第三个转子转动一次。这种情况会一直发生,直到达到25,此时它们会重置回0,循环再次开始。这让我想起了一个分为小时、分钟和秒的时钟,其中秒在不断地转动,分钟变慢,小时变慢


我知道这可能可以用模运算编程,但我不知道怎么做?因此,任何帮助都将不胜感激。

您可以在命令式语言中使用Haskell的通用计数器

假设你有一些命令代码

def f(x) {
c = 0 ;

while ( c<k ) {
    x = g(x,c) ;
    c +=1; 

return z(x);
}
所以你可以把转子的位置作为一个内部参数

你也可以使用模式匹配

RotorState = (Int,Int,Int)
turnRotor :: RotorState ->RotorState
turnRotor (25, 25 , 25    )  = (0  , 0 ,  0)
turnRotor (_ , 25 , 25    )  = (_+1, 0 ,  0)
turnRotor (_ , __ , 25    )  = (_  , __+1,0)
turnRotor (_ , __  , ___  )  = (_  , __, ___+1)

玩得开心!我希望这是有帮助的

您可以在命令式语言中使用Haskell的通用计数器等价物

假设你有一些命令代码

def f(x) {
c = 0 ;

while ( c<k ) {
    x = g(x,c) ;
    c +=1; 

return z(x);
}
所以你可以把转子的位置作为一个内部参数

你也可以使用模式匹配

RotorState = (Int,Int,Int)
turnRotor :: RotorState ->RotorState
turnRotor (25, 25 , 25    )  = (0  , 0 ,  0)
turnRotor (_ , 25 , 25    )  = (_+1, 0 ,  0)
turnRotor (_ , __ , 25    )  = (_  , __+1,0)
turnRotor (_ , __  , ___  )  = (_  , __, ___+1)

玩得开心!我希望这是有帮助的

从机器的角度来看,转子是两件事:

  • 它是从一个符号到另一个符号的函数
  • 它可以成为另一个功能
我们可以为它编写一个类型,如下所示:

newtype Symbol = Symbol {representation :: Int}

data Rotor = Rotor {
    transformation :: Symbol -> Symbol,
    next :: Rotor
}
如果机器从反射中知道对称性,它可能是这样的

data Rotor = Rotor {
    forward :: Symbol -> Symbol,
    backward :: Symbol -> Symbol,
    next :: Rotor
}
(您也可以使用类似于
[(Symbol->Symbol,Symbol->Symbol)]

现在,我们如何构造一个
转子
?让我们来定义一个示例转子,IC

rotorICdefinition = map symbol $ "DMTWSILRUYQNKFEJCAZBPGXOHV"
现在,symbol需要有类型
Char->symbol
。像这样的事情应该可以

symbol :: Char -> Symbol
symbol x = Symbol $ ord x - ord 'A'
ord
中有一堆魔力。它已经知道字母表的顺序了。例如:

Prelude Data.Char> map ord "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
[65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90]
接下来,我们希望能够根据转子的定义来制作转子

rotorIC :: Rotor
rotorIC = makeRotor rotorICdefinition
因此,
makeRotor
应具有以下类型

makeRotor :: [Symbol] -> Rotor
我们可以把它定义为

makeRotor definition = makeRotor' 0
    where
        makeRotor' steps = Rotor {
            forward = forwardLookup steps,
            backward =  reverseLookup steps,
            next = makeRotor' ((steps+1) `mod` symbolModulus)
        }
        forwardLookupTable = array (minBound, maxBound) (zip symbols definition)
        reverseLookupTable = array (minBound, maxBound) (zip definition symbols)
        forwardLookup = lookup forwardLookupTable
        reverseLookup = lookup reverseLookupTable
        lookup lookupTable steps = (lookupTable !) . Symbol . (`mod` symbolModulus) . (+ steps) . representation 
这里发生了很多事情。我们制造了一个无限的转子流,每一个转子都比前一个旋转一步,从一个旋转了0步的转子开始<
makeRotor'
中的code>steps
正在跟踪其旋转了多少步。
转子
包括
向前
向后
变换,其中考虑了转子旋转的步数。下一个
转子是相同的,但又旋转了一步。为了避免最终溢出一个整数,我们取它的模
mod
存在的符号数,
symboldommodule
。(有更有效的方法可以做到这一点)。这两个查找基于一次构建的查找表,将范围
(minBound,maxBound)
中的每个符号映射到它根据
定义应该是什么。
lookup
本身就是获取输入,添加步骤数,获取符号数,然后返回查找表中该位置的内容

这要求我们定义新出现的
minBound
maxBound
symbols
symbolModules

instance Bounded (Symbol) where
    minBound = symbol 'A'
    maxBound = symbol 'Z' 

symbolModulus = (representation maxBound) - (representation minBound) + 1

-- This could have some other definition
symbols = map symbol $ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
我们将添加一个小UI,并将整个程序放在一起:

module Main (
    main
) where

import Data.Char
import Data.Array -- requires array package
import System.IO

main = go rotorIC
    where go rotor = do
            putStr "Input   : "
            hFlush stdout
            command <- getLine
            case command of
                "next" -> go (next rotor)
                [] -> return ()
                text -> case all (inRange (char minBound, char maxBound)) text of
                    True -> do
                        putStrLn . ("Forward : " ++) $ map (char . forward rotor . symbol) text
                        putStrLn . ("Backward: " ++)$ map (char . backward rotor . symbol) text
                        go rotor
                    _ -> do
                        putStrLn "Not all of the input was symbols"
                        go rotor 


newtype Symbol = Symbol {representation :: Int} deriving (Eq, Ord, Ix)

symbol :: Char -> Symbol
symbol x = Symbol $ ord x - ord 'A'

char :: Symbol -> Char
char x = chr $ representation x + ord 'A' 

instance Bounded (Symbol) where
    minBound = symbol 'A'
    maxBound = symbol 'Z' 

symbolModulus = (representation maxBound) - (representation minBound) + 1

-- This could have some other definition 
symbols = map symbol $ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

data Rotor = Rotor {
    forward :: Symbol -> Symbol,
    backward :: Symbol -> Symbol,
    next :: Rotor
}


rotorICdefinition = map symbol $ "DMTWSILRUYQNKFEJCAZBPGXOHV"

rotorIC :: Rotor
rotorIC = makeRotor rotorICdefinition

makeRotor :: [Symbol] -> Rotor

makeRotor definition = makeRotor' 0
    where
        makeRotor' steps = Rotor {
            forward = forwardLookup steps,
            backward =  reverseLookup steps,
            next = makeRotor' ((steps+1) `mod` symbolModulus)
        }
        forwardLookupTable = array (minBound, maxBound) (zip symbols definition)
        reverseLookupTable = array (minBound, maxBound) (zip definition symbols)
        forwardLookup = lookup forwardLookupTable
        reverseLookup = lookup reverseLookupTable
        lookup lookupTable steps = (lookupTable !) . Symbol . (`mod` symbolModulus) . (+ steps) . representation 
如果我们把
rotorICdefinition
放在开头,我们将返回字母表的前六个字母作为向后转换:

Input   : DMTWSIL
Forward : WKBXZUN
Backward: ABCDEFG
如果我们进入转子的下一步,我们会得到非常不同的结果:

Input   : next
Input   : ABCDEFG
Forward : MTWSILR
Backward: TQAONVY
但如果我们在“A”前面加上以1开头的字母,我们又会得到我们的定义:

Input   : ZABCDEF
Forward : DMTWSIL
Backward: RTQAONV
在转子上再进行25次下一步后,我们回到了开始的位置:

Input   : next
(25 times total)
Input   : next
Input   : ABCDEFG
Forward : DMTWSIL
Backward: RTQAONV

从机器的角度来看,转子是两件事:

  • 它是从一个符号到另一个符号的函数
  • 它可以成为另一个功能
我们可以为它编写一个类型,如下所示:

newtype Symbol = Symbol {representation :: Int}

data Rotor = Rotor {
    transformation :: Symbol -> Symbol,
    next :: Rotor
}
如果机器从反射中知道对称性,它可能是这样的

data Rotor = Rotor {
    forward :: Symbol -> Symbol,
    backward :: Symbol -> Symbol,
    next :: Rotor
}
(您也可以使用类似于
[(Symbol->Symbol,Symbol->Symbol)]

现在,我们如何构造一个
转子
?让我们来定义一个示例转子,IC

rotorICdefinition = map symbol $ "DMTWSILRUYQNKFEJCAZBPGXOHV"
现在,symbol需要有类型
Char->symbol
。像这样的事情应该可以

symbol :: Char -> Symbol
symbol x = Symbol $ ord x - ord 'A'
ord
中有一堆魔力。它已经知道字母表的顺序了。例如:

Prelude Data.Char> map ord "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
[65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90]
接下来,我们希望能够根据转子的定义来制作转子

rotorIC :: Rotor
rotorIC = makeRotor rotorICdefinition
因此,
makeRotor
应具有以下类型

makeRotor :: [Symbol] -> Rotor
我们可以