2021-01-25

Caesar Cipher

You are given string $S containing alphabets A..Z only and a number $N. Write a script to encrypt the given string $S using Caesar Cipher with left shift of size $N.

下面是 Caesar Cipher 的實作,使用 format 命令造出相對應的表格,並且使用 string toupper 轉換字串(用來確定輸入都是大寫字母), 再使用 string map 來產出需要的結果。事實上我在轉換表格同時處理了大寫和小寫,只是題目只要求大寫,以及處理 left shift 的要求。

#!/usr/bin/env tclsh
#
# You are given string $S containing alphabets A..Z only and a number $N.
# Write a script to encrypt the given string $S using Caesar Cipher with 
# left shift of size $N.
#
# Input: $S = "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG", $N = 3
# Output: "QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD"
#

set encryptMap {}
set decryptMap {}

proc createEncMap {shift} {
    set shift [expr 26 - $shift]
    for {set i 0} {$i < 26} {incr i} {
        append ::encryptMap [format "%c %c %c %c " \
            [expr {$i+65}] [expr {($i+$shift)%26+65}] \
            [expr {$i+97}] [expr {($i+$shift)%26+97}]]
    }
}

proc createDecMap {shift} {
    set shift [expr 26 - $shift]
    for {set i 0} {$i < 26} {incr i} {
        append ::decryptMap [format "%c %c %c %c " \
            [expr {$i+65}] [expr {($i-$shift)%26+65}] \
            [expr {$i+97}] [expr {($i-$shift)%26+97}]]
    }
}

if {$argc >= 2} {
    set orgstring [lindex $argv 0]
    set shift [lindex $argv 1]

    set orgstring [string toupper $orgstring]
    if {![string is integer $shift]} {
        puts "N should be a number."
        exit
    }
    set shift [expr abs($shift)%26]
} else {
    exit
}

createEncMap $shift
createDecMap $shift
set result [string map $encryptMap $orgstring]
puts "Plain: $orgstring"
puts "Output: $result"
puts "Check: [string map $decryptMap $result]"

沒有留言: