Polybius Square

After a recent question about cryptography, I got playing with an ancient Greek method of encoding called a Polybus Square with the ultimate intention of making it the core of an encryption scheme.

The script below explains how it works. My problem is that I have incorrectly derived the last two statements in my script which find the row and column for the entry and find myself stabbing in the dark for the mistakes. Try “A” for example, or “J”.

(* POLIBUS SQUARE
		1	 	2	 	3	 	4	 	5
1	 	A	 	B	 	C	 	D	 	E
2	 	F	 	G	 	H	 	I/J	 	K
3	 	L	 	M	 	N	 	O	 	P
4	 	Q	 	R	 	S	 	T	 	U
5	 	V	 	W	 	X	 	Y	 	Z
*)

set tText to "Polybius square, also known as the Polybius , 
checkerboard invented by the Ancient Greek historian 
and scholar Polybius, is a scheme for making the alphabet
representable as pairs of numbers which code the
row and column of the letter in the square. Since 26 
letters don't fall into place in a 5 x 5 diagram, I and J
are lumped together. The numbers can be added by
using a 6 x 6 if I/J are still lumped together."

--tLetters to {"A", "B", "C", "D", "E", "F", "G", "H", "I/J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}

set Punc to {13, 32, 44, 46} -- return, space, comma, period
set sq to 5

set tChoice to text returned of (display dialog "Enter the Letter" default answer "")

set Ltr to id of tChoice

if Ltr is in Punc then
	set LID to Ltr
else
	if Ltr > 96 and Ltr < 123 then set Ltr to Ltr - 32
	if Ltr = 75 then set Ltr to 74
	set LID to Ltr - 65
end if

set tCol to (LID - 1) mod sq + 1
set tRow to (LID + sq - 1) div sq

So, the Matrix got you Adam? :slight_smile:

I have had a look into your code, (but not nearly as thorough as I should, first of all: I don’t understand why you consider punctuation, since you don’t deal with punctuation in your code.

And it seems to me that you subtract one too many from the character when you map it down to 1 … 25. I also find it troublesome that characters deviates in value with regards to they are over or below “I”.

Using your formulaes:
When you feed them and ‘A’ will be 65, LId will be 65 − 65 == 0;when 0 is set into the first formula, then you will end up with position zero, ( I take you look at the first col as col number 1.

When you insert a LID of 0 into your second formula, then you get ( (0 + 5) −1 ) / 5 = 0.

Solution to this particular problem:
Now, if you add 1 to both of those results it may look nice. That is, when LID=0, then you could set a LID factor to 1, 0 otherwise, and add them to your row and column calculations.

It is not solved for B however. I think the best solution is to add 1 to the formula, so that Lid = CharValue +1 − 65 as long as the letter is not greater than “I”

trying for O:

id of O - 65 = 14: ( 14 − 1 ) mod 5 + 1 = 4 ( column)

( 14 + 5 −1 ) div 5 = 3 => Your formulaes holds for “O”

trying for “Z” :

id of Z - 65 = 25: ( 25 −1 ) mod 5 + 1 = 5 ( column)

25 +5 −1 div 5 = 5 = Your formulaes holds for “Z”

Conclusion: you lack an "edge case for when “A” is the character, like you would have coded, one way or another in different schemes, like this:
You still have the trouble of adjusting the numbers starting with “J”, I am quite unsure how you have thought you’d implement this.

Well, if I were to code it, I’d first of all map all the characters to a number. then I’d look up the position in a list with binarySearch! :slight_smile: then I’d fetch the corresponding number in the other table. Not so fancy, but your scheme for keeping 26 characters in a 5X5 table justifies it for me. It is of course both a slower and duller approach, and not feeding the intellect, but it should be easier to make to work.


to rowAndCol for anIndicie
	-- 25 becomes ( 5, 5 )
	-- 14 becomes ( 3, 4 )
	--  1 becomes ( 1, 1 )
	local rows, cols
	if (nr mod 5 = 0) then ” edge case
		set rows to anIndicie div 5
		set cols to 5
	else
		set rows to (anIndicie / 5) + 1
		set cols to (anIndicie mod 5)
	end if
	return {row, col}
end rowAndCol

to anIndice for aRow by aCol
	-- ( 1, 1 ) becomes 1 
	-- ( 3, 4 ) becoms 14
	-- ( 5, 5 ) becomes 25
	local theIndicie
	set theIndice to (aRow - 1) * 5
	set theIndice to theIndicie + aCol
	return theIndicie
end anIndice

Hi Adam,

assuming the matrix indexes are 1 based, this should do it


property sq : 5

set tChoice to text returned of (display dialog "Enter the Letter" default answer "")
set Ltr to id of tChoice

if Ltr > 96 and Ltr < 123 then set Ltr to Ltr - 32
if Ltr > 73 then set Ltr to Ltr - 1
set LID to Ltr - 64

if LID < 1 or LID > 25 then display dialog "Letters only" buttons {"Cancel"} default button "Cancel"
set tCol to (LID - 1) mod sq + 1
set tRow to (LID + sq - 1) div sq


Hi Adam.

According to Wikipedia, that should be “Polybius Square”. :slight_smile:

I see Stefan’s posted a solution similar to mine while I was working on it. A key point is that every ID above I’s has to be adjusted.

If you stick to your original idea of setting LID to Ltr - 65, the last two lines become:

set tCol to LID mod sq + 1
set tRow to LID div sq + 1

Thank you Nigel and Stefan. I thought I had tried that unsuccessfully. Senior brain rot. I corrected the originator’s name in the subject heading – I had it right in the script itself.

I have since discovered that the fix doesn’t work for “Z”, (ID = 25) returning 1, 6 instead of 5, 5 so a test for 25 is required.

Hello. I used the code below and it works for me.

It is StefanK’s solution.


(* POLIBUS SQUARE
       1        2        3        4        5
1        A        B        C        D        E
2        F        G        H        I/J        K
3        L        M        N        O        P
4        Q        R        S        T        U
5        V        W        X        Y        Z
*)

set tText to "Polybius square, also known as the Polybius , 
checkerboard invented by the Ancient Greek historian 
and scholar Polybius, is a scheme for making the alphabet
representable as pairs of numbers which code the
row and column of the letter in the square. Since 26 
letters don't fall into place in a 5 x 5 diagram, I and J
are lumped together. The numbers can be added by
using a 6 x 6 if I/J are still lumped together."


set tChoice to "j" 
set Ltr to id of tChoice

if Ltr > 96 and Ltr < 123 then set Ltr to Ltr - 32
if Ltr > 73 then set Ltr to Ltr - 1
set LID to Ltr - 64

set tCol to (LID - 1) mod sq + 1
set tRow to (LID + sq - 1) div sq

Stefan’s script and the variation I described both return 5, 5.

Ah. I see what you’ve probably done. You get 1 and 6 if you use my last two lines without changing Stefan’s ‘Ltr - 64’ to ‘Ltr - 65’.