' ' Zig-zag Cipher ' Problem 2, AIC 2004 (Senior) ' Pascal Sample Solution ' ' ' This solution deciphers the message by: ' - first determining the length of the original message, textLength; ' - encrypting the integers 0 .. textLength-1 according to the scheme in the ' question. ' - reading the numbers left-to-right, top-to-bottom from the step above to ' generate a table that links index in the encrypted text to an index in ' the plain text. ' - use this table to decrypt the message. ' ' For example, to decrypt COPATGAHRRY in 3 rows, we consider the 12 integers ' 0, 1, 2, ... 11. Encrypting this into a 2-D array, dummyText, makes the ' array look like: ' ' 0 5 6 11 ' 1 4 7 10 ' 2 3 8 9 ' ' We can then generate a table, decryptMap, that matches the position in the ' encrypted text to their index in the original text: ' ' i 0 1 2 3 4 5 6 7 8 9 10 11 ' decryptMap[i] 0 5 6 11 1 4 7 10 2 3 8 9 ' ' We can then read the original message by printing out the characters in the ' order given by the table. ' ' const MAXMESSAGE = 10000 const MAXROWS = 100 ' decryptMap(i) = ciphertext index for plaintext(i). Dim decryptMap(MAXMESSAGE) As Long Dim dummyText(MAXROWS, MAXMESSAGE) As Long Dim rowLen(MAXROWS) As Long Dim rows As Long Dim ciphertext As String Dim textLength As Long ' currRow keeps track of the current row we are on (starting from 0) Dim currRow As Long ' currDir keeps track of the direction the text is currently heading ' (-1 for upwards, -1 for downwards). } Dim currDir As Long Dim i As Long Dim dummyIndex As Long Dim inputLine As String Sub Main() ' Open the I/O files. Open "zigin.txt" For Input As #1 Open "zigout.txt" For Output As #2 ' Read the number of rows the deciphered text will fill. Input #1, rows ' Start with an empty rowLen array - assume all rows are empty. For i = 1 To rows rowLen(i) = 0 Next i ' Read in the first line of text. Line Input #1, inputLine ciphertext = "" ' If the current line of text is a "#", then we have the entire input. While inputLine <> "#" ' We have a string which is not just a # ' Append it to the existing string. cipherText = cipherText & inputLine ' Read in the next line. Line Input #1, inputLine Wend Close #1 textLength = Len(ciphertext) ' We know the length of the encrypted text and the number of rows that it ' fills. ' Fill in the dummyText array with the encrypted version of the integers ' 0 .. textLength-1. ' Starting at row 0. currRow = 1 ' Heading down to begin with. currDir = 1 For i = 1 To textLength ' Mark this position in the dummy array. rowLen(currRow) = rowLen(currRow) + 1 dummyText(currRow, rowLen(currRow)) = i ' Move to the next row for the next character. currRow = currRow + currDir ' If we are at the top or the bottom, change direction. If currRow = rows then currDir = -1 ElseIf currRow = 1 then currDir = 1 End If Next i ' Construct the decryptMap array from the dummyText. dummyIndex = 1 For currRow = 1 To Rows For i = 1 to rowLen(currRow) decryptMap(dummyText(currRow, i)) = dummyIndex dummyIndex = dummyIndex + 1 Next i Next currRow ' We now know the order to print out the letters from the plain text. For dummyIndex = 1 to textLength Print #2, Mid$(ciphertext, decryptMap(dummyIndex), 1); Next dummyIndex Print #2, "" Close #2 End Sub