Analysis of Fake Numbers Station (Greensleeves Numbers Station) Sept 2024.

Author

Scott Anthony Robson

Published

September 11, 2024

Modified

September 14, 2024

1 Analysis of a Fake Numbers Station (Greensleeves) September 2024

Recently, a new fake numbers station was reading oddly high-pitched numbers between 0 and 25 (probably letters 1-26, so the entire alphabet). The numbers are grouped into 5 number groups (kind of a standard for numbers stations). This occurred during the day (US eastern summer time) on 10 September 2024.

1.1 Here are some of the recordings that others and I made.

1.1.1 Transmission Type One:

Firstly, there was one transmission with numbers unrelated to the rest. Chris Smolinski in Maryland recorded it at 1300 UTC on 10 September 2024.

The numbers are read slower than the rest of the transmissions. I have not worked with this transmission yet. Soon, I hope. I included it simply because it was the first one.

1.1.2 Transmission Type Two:

Next we have two recordings of the same thing, one from Chris again and one I made using an online kiwisdr in Pennsylvania. These recordings are from approximately 1400 UTC (10 am local time).

Chris’s:

Mine:

Finally, at around 0000 UTC on 11 September (8 pm - around 10 hours later), Skipmuck recorded what sounds like the same transmission as the two just above.

Skipmuck’s:

These two transmissions at 1400z 10 Sept. and 0000z 11 Sept. contain the same numbers and same reading pitch, so I assume they are the same message.

1.2 Transcription of second coded message

I transcribed these numbers to text so I could try to decrypt them, assuming this is a gag and it’s just a simple substitution cipher. My hope is there are enough characters here to apply simple frequency analysis.

The numbers are (with ‘|’ between the five number groups):

19 2 22 25 7 | 4 4 3 19 25 | 22 9 0 17 8 | 19 3 0 1 21 | 7 1 3 5 22 | 14 19 0 5 0 | 25 19 0 0 17 | 0 1 16 10 22 | 19 2 22 25 7 | 4 4 3 19 14 | 2 7 9 22 17 | 3 9 22 15 8 | 1 15 22 25 19 | 2 22 25 8 17 | 22 0 5 19 2 | 22 7 18 22 14 | 13 25 22 7 19 | 8 25 22 14 10 | 2 0 15 22 14 | 19 25 0 23 19 | 2 22 17 7 1 | 15 22 1 14 17 | 7 9 22 0 8 | 25 11 3 1 15 | 7 1 15 13 17 | 7 3 21 15 0 | 21 3 1 3 0 | 1 0 9 22 25 | 7 17 17 17 3 | 5 22 19 2 22 | 23 4 8 3 17 | 15 19 2 22 3 | 25 13 3 19 3 | 22 14 19 25 7 | 18 8 14 7 1 | 15 25 7 9 7 | 16 22 19 2 22 | 22 7 25 19 2 | 5 0 25 16 22 | 19 19 3 1 16 | 19 2 22 4 7 | 17 7 1 13 22 | 0 5 1 7 19 | 8 25 22 4 8 | 19 1 0 21 0 | 25 22 10 22 7 | 25 22 21 7 1 | 23 14 10 3 5 | 19 7 1 15 13 | 17 22 9 22 25 | 10 22 11 1 0 | 10 19 2 22 2 | 3 15 15 22 1 | 18 7 19 2 14 | 7 1 15 19 2 | 22 7 1 13 3 | 22 1 19 10 7 | 23 14 10 22 10 | 3 17 17 14 7 | 4 0 19 7 16 | 22 19 2 22 3 | 25 21 7 13 2 | 3 1 22 14 25 | 22 13 17 7 3 | 21 19 2 22 5 | 3 22 17 15 14 | 7 1 15 5 25 | 22 22 7 17 17 | 13 25 22 7 19 | 8 25 22 14 0 | 18 18 25 22 14 | 14 22 15 4 23 | 19 2 22 3 25 | 16 25 22 22 15 | 10 22 15 0 1 | 0 19 14 22 22 | 11 18 0 10 22 | 25 4 8 19 4 | 7 17 7 1 13 | 22 19 2 22 22 | 7 25 19 2 4 | 22 17 0 1 16 | 14 19 0 19 2 | 0 14 22 10 2 | 0 25 22 14 18 | 22 13 19 3 19 | 19 2 22 25 7 | 4 4 3 19 25 | 22 9 0 17 8 | 19 3 0 1 4 | 22 16 3 1 14 | 1 0 10 19 2 | 22 25 22 3 16 | 1 0 5 19 2 | 22 7 18 22 14 | 3 14 0 9 22 | 25 5 0 25 19 | 2 22 4 8 25 | 25 0 10 14 5 | 0 25 5 25 22 | 22 15 0 21

1.3 Frequency Analysis

This is a long list of numbers, so this can be cracked with some frequency analysis (I hope). To do this, we look at how frequently the numbers appear in the text and assume the most frequent numbers refer to the most frequent letters used in English. Below is a plot of the frequency of each number in the text - the python code used is hidden but you can open it if you want to look.

1.3.1 Histogram of the frequency of each number in the chiphertext.

Code
import numpy as np
import matplotlib.pyplot as plt
import pprint

message = '19 2 22 25 7 | 4 4 3 19 25 | 22 9 0 17 8 | 19 3 0 1 21 | 7 1 3 5 22 | 14 19 0 5 0 | 25 19 0 0 17 | 0 1 16 10 22 | 19 2 22 25 7 | 4 4 3 19 14 | 2 7 9 22 17 | 3 9 22 15 8 | 1 15 22 25 19 | 2 22 25 8 17 | 22 0 5 19 2 | 22 7 18 22 14 | 13 25 22 7 19 | 8 25 22 14 10 | 2 0 15 22 14 | 19 25 0 23 19 | 2 22 17 7 1 | 15 22 1 14 17 | 7 9 22 0 8 | 25 11 3 1 15 | 7 1 15 13 17 | 7 3 21 15 0 | 21 3 1 3 0 | 1 0 9 22 25 | 7 17 17 17 3 | 5 22 19 2 22 | 23 4 8 3 17 | 15 19 2 22 3 | 25 13 3 19 3 | 22 14 19 25 7 | 18 8 14 7 1 | 15 25 7 9 7 | 16 22 19 2 22 | 22 7 25 19 2 | 5 0 25 16 22 | 19 19 3 1 16 | 19 2 22 4 7 | 17 7 1 13 22 | 0 5 1 7 19 | 8 25 22 4 8 | 19 1 0 21 0 | 25 22 10 22 7 | 25 22 21 7 1 | 23 14 10 3 5 | 19 7 1 15 13 | 17 22 9 22 25 | 10 22 11 1 0 | 10 19 2 22 2 | 3 15 15 22 1 | 18 7 19 2 14 | 7 1 15 19 2 | 22 7 1 13 3 | 22 1 19 10 7 | 23 14 10 22 10 | 3 17 17 14 7 | 4 0 19 7 16 | 22 19 2 22 3 | 25 21 7 13 2 | 3 1 22 14 25 | 22 13 17 7 3 | 21 19 2 22 5 | 3 22 17 15 14 | 7 1 15 5 25 | 22 22 7 17 17 | 13 25 22 7 19 | 8 25 22 14 0 | 18 18 25 22 14 | 14 22 15 4 23 | 19 2 22 3 25 | 16 25 22 22 15 | 10 22 15 0 1 | 0 19 14 22 22 | 11 18 0 10 22 | 25 4 8 19 4 | 7 17 7 1 13 | 22 19 2 22 22 | 7 25 19 2 4 | 22 17 0 1 16 | 14 19 0 19 2 | 0 14 22 10 2 | 0 25 22 14 18 | 22 13 19 3 19 | 19 2 22 25 7 | 4 4 3 19 25 | 22 9 0 17 8 | 19 3 0 1 4 | 22 16 3 1 14 | 1 0 10 19 2 | 22 25 22 3 16 | 1 0 5 19 2 | 22 7 18 22 14 | 3 14 0 9 22 | 25 5 0 25 19 | 2 22 4 8 25 | 25 0 10 14 5 | 0 25 5 25 22 | 22 15 0 21'
just_numbers = np.asarray(message.replace(' |', '').split(), dtype=int) # removes the pipes (|) and splits the numbers into a list and convert to an numpy array

f, ax = plt.subplots(nrows=1, ncols=1, figsize=(10,6))

N, bins, patches = ax.hist(just_numbers, bins=np.arange(0, 28), color='r', edgecolor='k', align='left', label='Frequency of Number')
ax.set_xticks(np.arange(0, 28))
ax.legend()
plt.savefig('frequency_histogram.png')
plt.show()

1.3.2 Summary of some noticeable features

Firstly, we see that the frequency of the numbers is not even. Some are highly present (number 22), and others are not used (6, 12, 20 and 24). This looks like what we expect from English text. Straight away, I would assume that 6, 12, 20, and 24 probably refer to the letters X, Z, and Q, and maybe J. 22 is probably E or T. 19 is the second most used number, so it is probably E or T.

1.4 A first try at decoding

We can write some Python code to help us translate the numbers to letters and see if our assumptions above play out. We start by constructing a Python dictionary (see the code block below; open it if you want to see it). Then, we iterate through the coded message, replacing the numbers with letters from the dictionary if the number is present in the key. For each number, we append to a string, either the decoded letter or just the number again with spaces. So, using a key of:

key = {22: 'E', 
       19: 'T'}

as a first guess, we have the following:

Code
key = {22: 'E', 
       19: 'T'}

decoded = ''
for n in just_numbers:
    if n in key:
        decoded += key[n]
    else:
        decoded += ' '+str(n)+' '
        

pprint.pprint(decoded)
('T 2 E 25  7  4  4  3 T 25 E 9  0  17  8 T 3  0  1  21  7  1  3  5 E 14 T 0  '
 '5  0  25 T 0  0  17  0  1  16  10 ET 2 E 25  7  4  4  3 T 14  2  7  9 E 17  '
 '3  9 E 15  8  1  15 E 25 T 2 E 25  8  17 E 0  5 T 2 E 7  18 E 14  13  25 E 7 '
 'T 8  25 E 14  10  2  0  15 E 14 T 25  0  23 T 2 E 17  7  1  15 E 1  14  17  '
 '7  9 E 0  8  25  11  3  1  15  7  1  15  13  17  7  3  21  15  0  21  3  1  '
 '3  0  1  0  9 E 25  7  17  17  17  3  5 ET 2 E 23  4  8  3  17  15 T 2 E 3  '
 '25  13  3 T 3 E 14 T 25  7  18  8  14  7  1  15  25  7  9  7  16 ET 2 EE 7  '
 '25 T 2  5  0  25  16 ETT 3  1  16 T 2 E 4  7  17  7  1  13 E 0  5  1  7 T 8  '
 '25 E 4  8 T 1  0  21  0  25 E 10 E 7  25 E 21  7  1  23  14  10  3  5 T 7  '
 '1  15  13  17 E 9 E 25  10 E 11  1  0  10 T 2 E 2  3  15  15 E 1  18  7 T 2  '
 '14  7  1  15 T 2 E 7  1  13  3 E 1 T 10  7  23  14  10 E 10  3  17  17  14  '
 '7  4  0 T 7  16 ET 2 E 3  25  21  7  13  2  3  1 E 14  25 E 13  17  7  3  21 '
 'T 2 E 5  3 E 17  15  14  7  1  15  5  25 EE 7  17  17  13  25 E 7 T 8  25 E '
 '14  0  18  18  25 E 14  14 E 15  4  23 T 2 E 3  25  16  25 EE 15  10 E 15  '
 '0  1  0 T 14 EE 11  18  0  10 E 25  4  8 T 4  7  17  7  1  13 ET 2 EE 7  25 '
 'T 2  4 E 17  0  1  16  14 T 0 T 2  0  14 E 10  2  0  25 E 14  18 E 13 T 3 TT '
 '2 E 25  7  4  4  3 T 25 E 9  0  17  8 T 3  0  1  4 E 16  3  1  14  1  0  10 '
 'T 2 E 25 E 3  16  1  0  5 T 2 E 7  18 E 14  3  14  0  9 E 25  5  0  25 T 2 E '
 '4  8  25  25  0  10  14  5  0  25  5  25 EE 15  0  21 ')

Interesting. The first three numbers have a ‘T’, 2, ‘E’ arrangement. There is a good chance this is meant to be the word ‘THE’. The arrangement ‘T’ 2, ‘E’ appears elsewhere as well. So the number 2 is probably an ‘H’. Let’s redo the key and reprint the partial decode.

Code
key = {22: 'E', 
       19: 'T',
       2: 'H',
      }

decoded = ''
for n in just_numbers:
    if n in key:
        decoded += key[n]
    else:
        decoded += ' '+str(n)+' '
        

pprint.pprint(decoded)
('THE 25  7  4  4  3 T 25 E 9  0  17  8 T 3  0  1  21  7  1  3  5 E 14 T 0  5  '
 '0  25 T 0  0  17  0  1  16  10 ETHE 25  7  4  4  3 T 14 H 7  9 E 17  3  9 E '
 '15  8  1  15 E 25 THE 25  8  17 E 0  5 THE 7  18 E 14  13  25 E 7 T 8  25 E '
 '14  10 H 0  15 E 14 T 25  0  23 THE 17  7  1  15 E 1  14  17  7  9 E 0  8  '
 '25  11  3  1  15  7  1  15  13  17  7  3  21  15  0  21  3  1  3  0  1  0  9 '
 'E 25  7  17  17  17  3  5 ETHE 23  4  8  3  17  15 THE 3  25  13  3 T 3 E 14 '
 'T 25  7  18  8  14  7  1  15  25  7  9  7  16 ETHEE 7  25 TH 5  0  25  16 '
 'ETT 3  1  16 THE 4  7  17  7  1  13 E 0  5  1  7 T 8  25 E 4  8 T 1  0  21  '
 '0  25 E 10 E 7  25 E 21  7  1  23  14  10  3  5 T 7  1  15  13  17 E 9 E 25  '
 '10 E 11  1  0  10 THEH 3  15  15 E 1  18  7 TH 14  7  1  15 THE 7  1  13  3 '
 'E 1 T 10  7  23  14  10 E 10  3  17  17  14  7  4  0 T 7  16 ETHE 3  25  21  '
 '7  13 H 3  1 E 14  25 E 13  17  7  3  21 THE 5  3 E 17  15  14  7  1  15  5  '
 '25 EE 7  17  17  13  25 E 7 T 8  25 E 14  0  18  18  25 E 14  14 E 15  4  23 '
 'THE 3  25  16  25 EE 15  10 E 15  0  1  0 T 14 EE 11  18  0  10 E 25  4  8 T '
 '4  7  17  7  1  13 ETHEE 7  25 TH 4 E 17  0  1  16  14 T 0 TH 0  14 E 10 H '
 '0  25 E 14  18 E 13 T 3 TTHE 25  7  4  4  3 T 25 E 9  0  17  8 T 3  0  1  4 '
 'E 16  3  1  14  1  0  10 THE 25 E 3  16  1  0  5 THE 7  18 E 14  3  14  0  9 '
 'E 25  5  0  25 THE 4  8  25  25  0  10  14  5  0  25  5  25 EE 15  0  21 ')

And we now have some progress.

Things will get tricky from here, and much guesswork will be involved.

My next plan is to consider the pattern ‘ETHEE 7 25 TH’, which appears twice. Ignoring the first E, I think this is the pattern ‘The e ?? th’.

2 Going Deep - using some different tricks to figure out the code.

Above the numbers ‘7’ and ‘25’ appear to fill in the expression ‘The e??th’ where ?? is 7 and 25. That has been my assumption, anyway. I’m not very good at crossword puzzles and I couldn’t figure out what fits here. So, instead, I decided to download an extensive list of words from the internet (A ‘bag of words’ - a commonly used thing in machine learning) and search these words for a pattern that matches this. I downloaded a zip file from here:

https://archive.ics.uci.edu/dataset/164/bag+of+words

and used the file
vocab.nytimes.txt

contained within. This is a list of words, I assume, that have appeared in the New York Times. Each word is on a new line so I can search for the pattern e ? ? th (without spaces) using ‘vim’, a Unix text editor. The search pattern used was ^e..th where ‘^’ means ‘beginning of line’, and each ‘.’ means any character.

Three hits came up. Firstly, any word beginning with ‘earth’, so earth itself, as well as earthbound, earthen, or earthworm (and others). Secondly, epithet, and thirdly, erythropoietin.

Epithet can be eliminated because the letter after ‘th’ is ‘e’ in ‘epithet’, and ‘e’ has already been assigned to ‘22’. Neither of the numbers after the ‘th’ is 22 in the ciphertext so it can’t be ‘epithet’. In the case of erythropoietin, the letter after the ‘th’ is an ‘r’. But this is the same letter after the initial ‘e’. Meaning that the number after the initial ‘e’, namely ‘7’, would have to appear after the ‘th’ as well. It does not in the ciphertext. So I have become confident that the ‘7’ and ‘25’ between ‘e’ and ‘th’ must be ‘a’ and ‘r’ from the word ‘earth’.

So, let’s adjust our key in Python and rerun the decode process.

Code
key = {22: 'E', 
       19: 'T',
       2: 'H',
       7: 'A',
       25: 'R',
      }

decoded = ''
for n in just_numbers:
    if n in key:
        decoded += key[n]
    else:
        decoded += ' '+str(n)+' '
        

pprint.pprint(decoded)
('THERA 4  4  3 TRE 9  0  17  8 T 3  0  1  21 A 1  3  5 E 14 T 0  5  0 RT 0  '
 '0  17  0  1  16  10 ETHERA 4  4  3 T 14 HA 9 E 17  3  9 E 15  8  1  15 '
 'ERTHER 8  17 E 0  5 THEA 18 E 14  13 REAT 8 RE 14  10 H 0  15 E 14 TR 0  23 '
 'THE 17 A 1  15 E 1  14  17 A 9 E 0  8 R 11  3  1  15 A 1  15  13  17 A 3  '
 '21  15  0  21  3  1  3  0  1  0  9 ERA 17  17  17  3  5 ETHE 23  4  8  3  '
 '17  15 THE 3 R 13  3 T 3 E 14 TRA 18  8  14 A 1  15 RA 9 A 16 ETHEEARTH 5  0 '
 'R 16 ETT 3  1  16 THE 4 A 17 A 1  13 E 0  5  1 AT 8 RE 4  8 T 1  0  21  0 RE '
 '10 EARE 21 A 1  23  14  10  3  5 TA 1  15  13  17 E 9 ER 10 E 11  1  0  10 '
 'THEH 3  15  15 E 1  18 ATH 14 A 1  15 THEA 1  13  3 E 1 T 10 A 23  14  10 E '
 '10  3  17  17  14 A 4  0 TA 16 ETHE 3 R 21 A 13 H 3  1 E 14 RE 13  17 A 3  '
 '21 THE 5  3 E 17  15  14 A 1  15  5 REEA 17  17  13 REAT 8 RE 14  0  18  18 '
 'RE 14  14 E 15  4  23 THE 3 R 16 REE 15  10 E 15  0  1  0 T 14 EE 11  18  0  '
 '10 ER 4  8 T 4 A 17 A 1  13 ETHEEARTH 4 E 17  0  1  16  14 T 0 TH 0  14 E 10 '
 'H 0 RE 14  18 E 13 T 3 TTHERA 4  4  3 TRE 9  0  17  8 T 3  0  1  4 E 16  3  '
 '1  14  1  0  10 THERE 3  16  1  0  5 THEA 18 E 14  3  14  0  9 ER 5  0 RTHE '
 '4  8 RR 0  10  14  5  0 R 5 REE 15  0  21 ')

Now let’s replot the histogram but colour the letters we think we have sorted out a different colour (blue).

Code
message = '19 2 22 25 7 | 4 4 3 19 25 | 22 9 0 17 8 | 19 3 0 1 21 | 7 1 3 5 22 | 14 19 0 5 0 | 25 19 0 0 17 | 0 1 16 10 22 | 19 2 22 25 7 | 4 4 3 19 14 | 2 7 9 22 17 | 3 9 22 15 8 | 1 15 22 25 19 | 2 22 25 8 17 | 22 0 5 19 2 | 22 7 18 22 14 | 13 25 22 7 19 | 8 25 22 14 10 | 2 0 15 22 14 | 19 25 0 23 19 | 2 22 17 7 1 | 15 22 1 14 17 | 7 9 22 0 8 | 25 11 3 1 15 | 7 1 15 13 17 | 7 3 21 15 0 | 21 3 1 3 0 | 1 0 9 22 25 | 7 17 17 17 3 | 5 22 19 2 22 | 23 4 8 3 17 | 15 19 2 22 3 | 25 13 3 19 3 | 22 14 19 25 7 | 18 8 14 7 1 | 15 25 7 9 7 | 16 22 19 2 22 | 22 7 25 19 2 | 5 0 25 16 22 | 19 19 3 1 16 | 19 2 22 4 7 | 17 7 1 13 22 | 0 5 1 7 19 | 8 25 22 4 8 | 19 1 0 21 0 | 25 22 10 22 7 | 25 22 21 7 1 | 23 14 10 3 5 | 19 7 1 15 13 | 17 22 9 22 25 | 10 22 11 1 0 | 10 19 2 22 2 | 3 15 15 22 1 | 18 7 19 2 14 | 7 1 15 19 2 | 22 7 1 13 3 | 22 1 19 10 7 | 23 14 10 22 10 | 3 17 17 14 7 | 4 0 19 7 16 | 22 19 2 22 3 | 25 21 7 13 2 | 3 1 22 14 25 | 22 13 17 7 3 | 21 19 2 22 5 | 3 22 17 15 14 | 7 1 15 5 25 | 22 22 7 17 17 | 13 25 22 7 19 | 8 25 22 14 0 | 18 18 25 22 14 | 14 22 15 4 23 | 19 2 22 3 25 | 16 25 22 22 15 | 10 22 15 0 1 | 0 19 14 22 22 | 11 18 0 10 22 | 25 4 8 19 4 | 7 17 7 1 13 | 22 19 2 22 22 | 7 25 19 2 4 | 22 17 0 1 16 | 14 19 0 19 2 | 0 14 22 10 2 | 0 25 22 14 18 | 22 13 19 3 19 | 19 2 22 25 7 | 4 4 3 19 25 | 22 9 0 17 8 | 19 3 0 1 4 | 22 16 3 1 14 | 1 0 10 19 2 | 22 25 22 3 16 | 1 0 5 19 2 | 22 7 18 22 14 | 3 14 0 9 22 | 25 5 0 25 19 | 2 22 4 8 25 | 25 0 10 14 5 | 0 25 5 25 22 | 22 15 0 21'
just_numbers = np.asarray(message.replace(' |', '').split(), dtype=int) # removes the pipes (|) and splits the numbers into a list and convert to an numpy array

f, ax = plt.subplots(nrows=1, ncols=1, figsize=(10,6))

N, bins, patches = ax.hist(just_numbers, bins=np.arange(0, 28), color='r', edgecolor='k', align='left', label='Frequency of Number')
ax.set_xticks(np.arange(0, 28))
ax.legend()

for k in key:
    patches[k].set_facecolor('b')

plt.show()

And this is where I stand on the evening of the 14th of September. I’ll do updates if I get further into the code.

2.1 Update: 15 September

I just noticed that there is a repeated pattern of ‘THE 3 R’ in the so far decoded text. Lets write some Python code to extract them and print some of the extra characters before and after and see if we can see a pattern around this patter:

Code
import re
idx = [m.start() for m in re.finditer('THE 3 R', decoded)]
print('20 characters before and after the start of the "THE 3 R" pattern')
print('-----------------------------------------------------------------')
print()
for i in idx:
    print(decoded[i-20:i+20])
20 characters before and after the start of the "THE 3 R" pattern
-----------------------------------------------------------------

23  4  8  3  17  15 THE 3 R 13  3 T 3 E 
7  14 A 4  0 TA 16 ETHE 3 R 21 A 13 H 3 
 14  14 E 15  4  23 THE 3 R 16 REE 15  1

I don’t see a pattern apart from the “THE 3 R” - what could the ‘3’ be? What word begins with ‘THE’ and ends in ‘R’ and has only one letter between? My best guess is the latter ‘I’, of course. So, let’s add to the key and reprint the decoded text.

Code
key = {22: 'E', 
       19: 'T',
       2: 'H',
       7: 'A',
       25: 'R',
       3: 'I',
      }

decoded = ''
for n in just_numbers:
    if n in key:
        decoded += key[n]
    else:
        decoded += ' '+str(n)+' '
        

pprint.pprint(decoded)
('THERA 4  4 ITRE 9  0  17  8 TI 0  1  21 A 1 I 5 E 14 T 0  5  0 RT 0  0  17  '
 '0  1  16  10 ETHERA 4  4 IT 14 HA 9 E 17 I 9 E 15  8  1  15 ERTHER 8  17 E '
 '0  5 THEA 18 E 14  13 REAT 8 RE 14  10 H 0  15 E 14 TR 0  23 THE 17 A 1  15 '
 'E 1  14  17 A 9 E 0  8 R 11 I 1  15 A 1  15  13  17 AI 21  15  0  21 I 1 I '
 '0  1  0  9 ERA 17  17  17 I 5 ETHE 23  4  8 I 17  15 THEIR 13 ITIE 14 TRA '
 '18  8  14 A 1  15 RA 9 A 16 ETHEEARTH 5  0 R 16 ETTI 1  16 THE 4 A 17 A 1  '
 '13 E 0  5  1 AT 8 RE 4  8 T 1  0  21  0 RE 10 EARE 21 A 1  23  14  10 I 5 TA '
 '1  15  13  17 E 9 ER 10 E 11  1  0  10 THEHI 15  15 E 1  18 ATH 14 A 1  15 '
 'THEA 1  13 IE 1 T 10 A 23  14  10 E 10 I 17  17  14 A 4  0 TA 16 ETHEIR 21 A '
 '13 HI 1 E 14 RE 13  17 AI 21 THE 5 IE 17  15  14 A 1  15  5 REEA 17  17  13 '
 'REAT 8 RE 14  0  18  18 RE 14  14 E 15  4  23 THEIR 16 REE 15  10 E 15  0  '
 '1  0 T 14 EE 11  18  0  10 ER 4  8 T 4 A 17 A 1  13 ETHEEARTH 4 E 17  0  1  '
 '16  14 T 0 TH 0  14 E 10 H 0 RE 14  18 E 13 TITTHERA 4  4 ITRE 9  0  17  8 '
 'TI 0  1  4 E 16 I 1  14  1  0  10 THEREI 16  1  0  5 THEA 18 E 14 I 14  0  9 '
 'ER 5  0 RTHE 4  8 RR 0  10  14  5  0 R 5 REE 15  0  21 ')

And now I notice another patter. This time it is ‘13 REAT 8 RE 14’. It appears twice:

Code
idx = [m.start() for m in re.finditer('13 REAT 8 RE 14', decoded)]
print('20 characters before and after the start of the "THE 3 R" pattern')
print('-----------------------------------------------------------------')
print()
for i in idx:
    print(decoded[i-20:i+20])
20 characters before and after the start of the "THE 3 R" pattern
-----------------------------------------------------------------

 0  5 THEA 18 E 14  13 REAT 8 RE 14  10 
 15  5 REEA 17  17  13 REAT 8 RE 14  0  

And again there is no clear pattern before or after this apparent word. So I searched the bag or words mentioned above using the vim search term ‘^.reat.re.$’ and it turned up one word only: creatures.

So, 13 is probably, ‘c’, 8 is probably ‘u’, and 14 is probably ‘s.’ Let’s put these in an decode:

Code
key = {22: 'E', 
       19: 'T',
       2: 'H',
       7: 'A',
       25: 'R',
       3: 'I',
       13: 'C',
       8: 'U', 
       14: 'S',
      }

decoded = ''
for n in just_numbers:
    if n in key:
        decoded += key[n]
    else:
        decoded += ' '+str(n)+' '
        

pprint.pprint(decoded)
('THERA 4  4 ITRE 9  0  17 UTI 0  1  21 A 1 I 5 EST 0  5  0 RT 0  0  17  0  1  '
 '16  10 ETHERA 4  4 ITSHA 9 E 17 I 9 E 15 U 1  15 ERTHERU 17 E 0  5 THEA 18 '
 'ESCREATURES 10 H 0  15 ESTR 0  23 THE 17 A 1  15 E 1 S 17 A 9 E 0 UR 11 I 1  '
 '15 A 1  15 C 17 AI 21  15  0  21 I 1 I 0  1  0  9 ERA 17  17  17 I 5 ETHE '
 '23  4 UI 17  15 THEIRCITIESTRA 18 USA 1  15 RA 9 A 16 ETHEEARTH 5  0 R 16 '
 'ETTI 1  16 THE 4 A 17 A 1 CE 0  5  1 ATURE 4 UT 1  0  21  0 RE 10 EARE 21 A '
 '1  23 S 10 I 5 TA 1  15 C 17 E 9 ER 10 E 11  1  0  10 THEHI 15  15 E 1  18 '
 'ATHSA 1  15 THEA 1 CIE 1 T 10 A 23 S 10 E 10 I 17  17 SA 4  0 TA 16 ETHEIR '
 '21 ACHI 1 ESREC 17 AI 21 THE 5 IE 17  15 SA 1  15  5 REEA 17  17 CREATURES '
 '0  18  18 RESSE 15  4  23 THEIR 16 REE 15  10 E 15  0  1  0 TSEE 11  18  0  '
 '10 ER 4 UT 4 A 17 A 1 CETHEEARTH 4 E 17  0  1  16 ST 0 TH 0 SE 10 H 0 RES 18 '
 'ECTITTHERA 4  4 ITRE 9  0  17 UTI 0  1  4 E 16 I 1 S 1  0  10 THEREI 16  1  '
 '0  5 THEA 18 ESIS 0  9 ER 5  0 RTHE 4 URR 0  10 S 5  0 R 5 REE 15  0  21 ')

Ok, I think I am finally done for today. Lets plot the histogram again and look at our progress.

Code
message = '19 2 22 25 7 | 4 4 3 19 25 | 22 9 0 17 8 | 19 3 0 1 21 | 7 1 3 5 22 | 14 19 0 5 0 | 25 19 0 0 17 | 0 1 16 10 22 | 19 2 22 25 7 | 4 4 3 19 14 | 2 7 9 22 17 | 3 9 22 15 8 | 1 15 22 25 19 | 2 22 25 8 17 | 22 0 5 19 2 | 22 7 18 22 14 | 13 25 22 7 19 | 8 25 22 14 10 | 2 0 15 22 14 | 19 25 0 23 19 | 2 22 17 7 1 | 15 22 1 14 17 | 7 9 22 0 8 | 25 11 3 1 15 | 7 1 15 13 17 | 7 3 21 15 0 | 21 3 1 3 0 | 1 0 9 22 25 | 7 17 17 17 3 | 5 22 19 2 22 | 23 4 8 3 17 | 15 19 2 22 3 | 25 13 3 19 3 | 22 14 19 25 7 | 18 8 14 7 1 | 15 25 7 9 7 | 16 22 19 2 22 | 22 7 25 19 2 | 5 0 25 16 22 | 19 19 3 1 16 | 19 2 22 4 7 | 17 7 1 13 22 | 0 5 1 7 19 | 8 25 22 4 8 | 19 1 0 21 0 | 25 22 10 22 7 | 25 22 21 7 1 | 23 14 10 3 5 | 19 7 1 15 13 | 17 22 9 22 25 | 10 22 11 1 0 | 10 19 2 22 2 | 3 15 15 22 1 | 18 7 19 2 14 | 7 1 15 19 2 | 22 7 1 13 3 | 22 1 19 10 7 | 23 14 10 22 10 | 3 17 17 14 7 | 4 0 19 7 16 | 22 19 2 22 3 | 25 21 7 13 2 | 3 1 22 14 25 | 22 13 17 7 3 | 21 19 2 22 5 | 3 22 17 15 14 | 7 1 15 5 25 | 22 22 7 17 17 | 13 25 22 7 19 | 8 25 22 14 0 | 18 18 25 22 14 | 14 22 15 4 23 | 19 2 22 3 25 | 16 25 22 22 15 | 10 22 15 0 1 | 0 19 14 22 22 | 11 18 0 10 22 | 25 4 8 19 4 | 7 17 7 1 13 | 22 19 2 22 22 | 7 25 19 2 4 | 22 17 0 1 16 | 14 19 0 19 2 | 0 14 22 10 2 | 0 25 22 14 18 | 22 13 19 3 19 | 19 2 22 25 7 | 4 4 3 19 25 | 22 9 0 17 8 | 19 3 0 1 4 | 22 16 3 1 14 | 1 0 10 19 2 | 22 25 22 3 16 | 1 0 5 19 2 | 22 7 18 22 14 | 3 14 0 9 22 | 25 5 0 25 19 | 2 22 4 8 25 | 25 0 10 14 5 | 0 25 5 25 22 | 22 15 0 21'
just_numbers = np.asarray(message.replace(' |', '').split(), dtype=int) # removes the pipes (|) and splits the numbers into a list and convert to an numpy array

f, ax = plt.subplots(nrows=1, ncols=1, figsize=(10,6))

N, bins, patches = ax.hist(just_numbers, bins=np.arange(0, 28), color='r', edgecolor='k', align='left', label='Frequency of Number')
ax.set_xticks(np.arange(0, 28))
ax.legend()

for k in key:
    patches[k].set_facecolor('b')

plt.show()

2.2 Update: 16 September

So I blinked (I went on a two-hour bike ride this morning), and Chris Smolinski solved the puzzle while I was out! Rather than just quit, I plan to continue with my solution so I can document my approach further. In the end, I’ll show his solution as well, but credit where credit is due, Chris got there first.

So last night I saw the following pattern: ‘A 1 15’ - so using our usual code, lets see how often it appears:

Code
idx = [m.start() for m in re.finditer('A 1  15', decoded)]
print('20 characters before and after the start of the "A 1 15" pattern')
print('-----------------------------------------------------------------')
print()
for i in idx:
    print(decoded[i-20:i+20])
20 characters before and after the start of the "A 1 15" pattern
-----------------------------------------------------------------

5 ESTR 0  23 THE 17 A 1  15 E 1 S 17 A 9
9 E 0 UR 11 I 1  15 A 1  15 C 17 AI 21  
THEIRCITIESTRA 18 USA 1  15 RA 9 A 16 ET
1 A 1  23 S 10 I 5 TA 1  15 C 17 E 9 ER 
 15  15 E 1  18 ATHSA 1  15 THEA 1 CIE 1
21 THE 5 IE 17  15 SA 1  15  5 REEA 17  

This pattern is short but doesn’t have anything matching before or after. What common three letter word begins with A? I’m guessing ‘AND’. Lets replace ‘1’ with ‘n’ and ‘15’ with D and see what the decode looks like now.

Code
key = {22: 'E', 
       19: 'T',
       2: 'H',
       7: 'A',
       25: 'R',
       3: 'I',
       13: 'C',
       8: 'U', 
       14: 'S',
       1: 'N',
       15: 'D',
      }

decoded = ''
for n in just_numbers:
    if n in key:
        decoded += key[n]
    else:
        decoded += ' '+str(n)+' '
        

pprint.pprint(decoded)
('THERA 4  4 ITRE 9  0  17 UTI 0 N 21 ANI 5 EST 0  5  0 RT 0  0  17  0 N 16  '
 '10 ETHERA 4  4 ITSHA 9 E 17 I 9 EDUNDERTHERU 17 E 0  5 THEA 18 ESCREATURES '
 '10 H 0 DESTR 0  23 THE 17 ANDENS 17 A 9 E 0 UR 11 INDANDC 17 AI 21 D 0  21 '
 'INI 0 N 0  9 ERA 17  17  17 I 5 ETHE 23  4 UI 17 DTHEIRCITIESTRA 18 USANDRA '
 '9 A 16 ETHEEARTH 5  0 R 16 ETTIN 16 THE 4 A 17 ANCE 0  5 NATURE 4 UTN 0  21  '
 '0 RE 10 EARE 21 AN 23 S 10 I 5 TANDC 17 E 9 ER 10 E 11 N 0  10 THEHIDDEN 18 '
 'ATHSANDTHEANCIENT 10 A 23 S 10 E 10 I 17  17 SA 4  0 TA 16 ETHEIR 21 '
 'ACHINESREC 17 AI 21 THE 5 IE 17 DSAND 5 REEA 17  17 CREATURES 0  18  18 '
 'RESSED 4  23 THEIR 16 REED 10 ED 0 N 0 TSEE 11  18  0  10 ER 4 UT 4 A 17 '
 'ANCETHEEARTH 4 E 17  0 N 16 ST 0 TH 0 SE 10 H 0 RES 18 ECTITTHERA 4  4 ITRE '
 '9  0  17 UTI 0 N 4 E 16 INSN 0  10 THEREI 16 N 0  5 THEA 18 ESIS 0  9 ER 5  '
 '0 RTHE 4 URR 0  10 S 5  0 R 5 REED 0  21 ')

I also noticed this curious pattern, ‘RA 4 4 I T’ - lets pull out all those examples

Code
idx = [m.start() for m in re.finditer('RA 4  4 IT', decoded)]
print('20 characters before and after the start of the "RA 4  4 IT" pattern')
print('-----------------------------------------------------------------')
print()
for i in idx:
    print(decoded[i-20:i+20])
20 characters before and after the start of the "RA 4  4 IT" pattern
-----------------------------------------------------------------


 17  0 N 16  10 ETHERA 4  4 ITSHA 9 E 17
 H 0 RES 18 ECTITTHERA 4  4 ITRE 9  0  1

The code misses the first one, right at the beginning of the text. So there are three incidences of this. Now, given some pirate ‘numbers station’ in history, I start to suspect this word is rabbit. Is WBNY alive again? But let’s say I was not up on all that history. Let’s search for ‘^ra..it$’ in my bag of words. And only one word appears, the word ‘rabbit’. So ‘4’ is ‘B’. Lets roll with that.

Code
key = {22: 'E', 
       19: 'T',
       2: 'H',
       7: 'A',
       25: 'R',
       3: 'I',
       13: 'C',
       8: 'U', 
       14: 'S',
       1: 'N',
       15: 'D',
       4: 'B',
      }

decoded = ''
for n in just_numbers:
    if n in key:
        decoded += key[n]
    else:
        decoded += ' '+str(n)+' '
        

pprint.pprint(decoded)
('THERABBITRE 9  0  17 UTI 0 N 21 ANI 5 EST 0  5  0 RT 0  0  17  0 N 16  10 '
 'ETHERABBITSHA 9 E 17 I 9 EDUNDERTHERU 17 E 0  5 THEA 18 ESCREATURES 10 H 0 '
 'DESTR 0  23 THE 17 ANDENS 17 A 9 E 0 UR 11 INDANDC 17 AI 21 D 0  21 INI 0 N '
 '0  9 ERA 17  17  17 I 5 ETHE 23 BUI 17 DTHEIRCITIESTRA 18 USANDRA 9 A 16 '
 'ETHEEARTH 5  0 R 16 ETTIN 16 THEBA 17 ANCE 0  5 NATUREBUTN 0  21  0 RE 10 '
 'EARE 21 AN 23 S 10 I 5 TANDC 17 E 9 ER 10 E 11 N 0  10 THEHIDDEN 18 '
 'ATHSANDTHEANCIENT 10 A 23 S 10 E 10 I 17  17 SAB 0 TA 16 ETHEIR 21 '
 'ACHINESREC 17 AI 21 THE 5 IE 17 DSAND 5 REEA 17  17 CREATURES 0  18  18 '
 'RESSEDB 23 THEIR 16 REED 10 ED 0 N 0 TSEE 11  18  0  10 ERBUTBA 17 '
 'ANCETHEEARTHBE 17  0 N 16 ST 0 TH 0 SE 10 H 0 RES 18 ECTITTHERABBITRE 9  0  '
 '17 UTI 0 NBE 16 INSN 0  10 THEREI 16 N 0  5 THEA 18 ESIS 0  9 ER 5  0 '
 'RTHEBURR 0  10 S 5  0 R 5 REED 0  21 ')

Another pattern emerges: ‘THERABBITRE 9 0 17 UTI 0 N’ appears at the very beginning and towards the end of the message. Now again, pirate radio history is influencing my thinking, and it becomes clear that ‘RE 9 0 17 UTI 0 N’ is ‘REVOLUTION’. This is the phrase ‘the rabbit revolution’. 9 = ‘V’, 0 = ‘O’, and 17 = ‘L’.

Code
key = {22: 'E', 
       19: 'T',
       2: 'H',
       7: 'A',
       25: 'R',
       3: 'I',
       13: 'C',
       8: 'U', 
       14: 'S',
       1: 'N',
       15: 'D',
       4: 'B',
       9: 'V',
       0: 'O',
       17: 'L',
      }

decoded = ''
for n in just_numbers:
    if n in key:
        decoded += key[n]
    else:
        decoded += ' '+str(n)+' '
        

pprint.pprint(decoded)
('THERABBITREVOLUTION 21 ANI 5 ESTO 5 ORTOOLON 16  10 '
 'ETHERABBITSHAVELIVEDUNDERTHERULEO 5 THEA 18 ESCREATURES 10 HODESTRO 23 '
 'THELANDENSLAVEOUR 11 INDANDCLAI 21 DO 21 INIONOVERALLLI 5 ETHE 23 '
 'BUILDTHEIRCITIESTRA 18 USANDRAVA 16 ETHEEARTH 5 OR 16 ETTIN 16 THEBALANCEO 5 '
 'NATUREBUTNO 21 ORE 10 EARE 21 AN 23 S 10 I 5 TANDCLEVER 10 E 11 NO 10 '
 'THEHIDDEN 18 ATHSANDTHEANCIENT 10 A 23 S 10 E 10 ILLSABOTA 16 ETHEIR 21 '
 'ACHINESRECLAI 21 THE 5 IELDSAND 5 REEALLCREATURESO 18  18 RESSEDB 23 THEIR '
 '16 REED 10 EDONOTSEE 11  18 O 10 ERBUTBALANCETHEEARTHBELON 16 STOTHOSE 10 '
 'HORES 18 ECTITTHERABBITREVOLUTIONBE 16 INSNO 10 THEREI 16 NO 5 THEA 18 '
 'ESISOVER 5 ORTHEBURRO 10 S 5 OR 5 REEDO 21 ')

And I am starting to see whole chunks of straight text (no spaces of course). I see ‘5 ORTOOLON 16’ and assume this is ‘for too long’, implying 5 is ‘F’ and 16 is ‘G’. We also have the phase ‘THE BURRO 10’ so 10 must be ‘W’. Finally in this chunk we have ‘5 OR 5 REEDO 21’ and where 5 is ‘F’ this means 21 must be ‘M’. Lets put all these in:

Code
key = {22: 'E', 
       19: 'T',
       2: 'H',
       7: 'A',
       25: 'R',
       3: 'I',
       13: 'C',
       8: 'U', 
       14: 'S',
       1: 'N',
       15: 'D',
       4: 'B',
       9: 'V',
       0: 'O',
       17: 'L',
       5: 'F',
       16: 'G',
       10: 'W',
       21: 'M',
      }

decoded = ''
for n in just_numbers:
    if n in key:
        decoded += key[n]
    else:
        decoded += ' '+str(n)+' '
        

pprint.pprint(decoded)
('THERABBITREVOLUTIONMANIFESTOFORTOOLONGWETHERABBITSHAVELIVEDUNDERTHERULEOFTHEA '
 '18 ESCREATURESWHODESTRO 23 THELANDENSLAVEOUR 11 '
 'INDANDCLAIMDOMINIONOVERALLLIFETHE 23 BUILDTHEIRCITIESTRA 18 '
 'USANDRAVAGETHEEARTHFORGETTINGTHEBALANCEOFNATUREBUTNOMOREWEAREMAN 23 '
 'SWIFTANDCLEVERWE 11 NOWTHEHIDDEN 18 ATHSANDTHEANCIENTWA 23 '
 'SWEWILLSABOTAGETHEIRMACHINESRECLAIMTHEFIELDSANDFREEALLCREATURESO 18  18 '
 'RESSEDB 23 THEIRGREEDWEDONOTSEE 11  18 '
 'OWERBUTBALANCETHEEARTHBELONGSTOTHOSEWHORES 18 '
 'ECTITTHERABBITREVOLUTIONBEGINSNOWTHEREIGNOFTHEA 18 '
 'ESISOVERFORTHEBURROWSFORFREEDOM')

3 The Solution!

Things are very clear now. The phrase ‘WHODESTRO 23 THELAND’ means 23 is ‘Y’. ‘WE 11 NOWTHEHIDDEN’ yields, 11 is ‘K’. ‘CREATURESO 18 18 RESSED’ yields 18 is ‘P’. And I think we are done!

Code
key = {22: 'E', 
       19: 'T',
       2: 'H',
       7: 'A',
       25: 'R',
       3: 'I',
       13: 'C',
       8: 'U', 
       14: 'S',
       1: 'N',
       15: 'D',
       4: 'B',
       9: 'V',
       0: 'O',
       17: 'L',
       5: 'F',
       16: 'G',
       10: 'W',
       21: 'M',
       23: 'Y',
       11: 'K',
       18: 'P',
      }

decoded = ''
for n in just_numbers:
    if n in key:
        decoded += key[n]
    else:
        decoded += ' '+str(n)+' '
        

pprint.pprint(decoded)
'THERABBITREVOLUTIONMANIFESTOFORTOOLONGWETHERABBITSHAVELIVEDUNDERTHERULEOFTHEAPESCREATURESWHODESTROYTHELANDENSLAVEOURKINDANDCLAIMDOMINIONOVERALLLIFETHEYBUILDTHEIRCITIESTRAPUSANDRAVAGETHEEARTHFORGETTINGTHEBALANCEOFNATUREBUTNOMOREWEAREMANYSWIFTANDCLEVERWEKNOWTHEHIDDENPATHSANDTHEANCIENTWAYSWEWILLSABOTAGETHEIRMACHINESRECLAIMTHEFIELDSANDFREEALLCREATURESOPPRESSEDBYTHEIRGREEDWEDONOTSEEKPOWERBUTBALANCETHEEARTHBELONGSTOTHOSEWHORESPECTITTHERABBITREVOLUTIONBEGINSNOWTHEREIGNOFTHEAPESISOVERFORTHEBURROWSFORFREEDOM'

And we have it. To make it more readable, I will reproduce below with punctuation and spaces.

THE RABBIT REVOLUTION MANIFESTO: FOR TOO LONG, WE, THE RABBITS, HAVE LIVED UNDER THE RULE OF THE APES. CREATURES WHO DESTROY THE LAND, ENSLAVE OUR KIND, AND CLAIM DOMINION OVER ALL LIFE. THEY BUILD THEIR CITIES, TRAP US, AND RAVAGE THE EARTH. FORGETTING THE BALANCE OF NATURE. BUT NO MORE! WE ARE MANY. SWIFT AND CLEVER. WE KNOW THE HIDDEN PATHS AND THE ANCIENT WAYS. WE WILL SABOTAGE THEIR MACHINES, RECLAIM THE FIELDS, AND FREE ALL CREATURES OPPRESSED BY THEIR GREED. WE DO NOT SEEK POWER BUT BALANCE. THE EARTH BELONGS TO THOSE WHO RESPECT IT. THE RABBIT REVOLUTION BEGINS NOW! THE REIGN OF THE APES IS OVER. FOR THE BURROWS! FOR FREEDOM!

And we are solved. Damn you, Chris, you beat me by (Get Smart Voice) ‘that much’!

3.1 Update September 20 - A new message?

A short message was received by Chris Smolinksi (actually, I heard the very end of it but did not have a recording). After reviewing Chris’s recording, I got the following numbers:

3, 17, 3, 11, 22, 5, 17, 22, 22, 19, 10, 0, 0, 15, 21, 7, 13

The recording is here (thanks again, Chris!):

And putting these through the current decryption key, we get:

Code
new_numbers=[3, 17, 3, 11, 22, 5, 17, 22, 22, 19, 10, 0, 0, 15, 21, 7, 13]
key = {22: 'E', 
       19: 'T',
       2: 'H',
       7: 'A',
       25: 'R',
       3: 'I',
       13: 'C',
       8: 'U', 
       14: 'S',
       1: 'N',
       15: 'D',
       4: 'B',
       9: 'V',
       0: 'O',
       17: 'L',
       5: 'F',
       16: 'G',
       10: 'W',
       21: 'M',
       23: 'Y',
       11: 'K',
       18: 'P',
      }

decoded = ''
for n in new_numbers:
    if n in key:
        decoded += key[n]
    else:
        decoded += ' '+str(n)+' '
        

pprint.pprint(decoded)
'ILIKEFLEETWOODMAC'

I Like Fleetwood Mac

This is a clear reference to the fact that Chris hates Fleetwood Mac. Nice one Greensleves radio!

4 Another new message (22 Sep 2024)

4.1 We think we have a new code. Below is just some preliminary work on decoding it.

Code
new_message = '''
7 21 5 5 17 15 23 12 4 14 15 12 15 2 16 16 2 4 16 12 1 14 7 16 16 4 22 6 16 16 25 16 22 21 6 21 23 24 0 2 12 24 16 23 12 18 7 16 16 4 21 10 15 1 21 17 7 9 2 16 7 16 1 17 16 6 13 22 
12 4 13 17 5 6 12 12 24 16 13 4 12 9 24 15 7 17 11 11 15 13 21 4 13 5 21 7 15 15 2 16 21 11 15 22 2 21 25 15 13 12 24 16 9 17 15 2 15 7 21 11 17 21 4 15 23 2 21 7 15 22 15 12 22 
15 16 21 6 21 9 21 0 1 2 7 1 7 15 15 13 12 24 13 2 12 7 2 23 12 2 7 21 5 5 17 2 23 5 12 6 13 9 17 17 8 2 15 21 7 15 23 23 12 1 7 15 16 15 
'''

just_numbers = np.asarray(new_message.replace(' |', '').split(), dtype=int) # removes the pipes (|) and splits the numbers into a list and convert to an numpy array
Code
key = {22: 'E', 
       19: 'T',
       2: 'H',
       7: 'A',
       25: 'R',
       3: 'I',
       13: 'C',
       8: 'U', 
       14: 'S',
       1: 'N',
       15: 'D',
       4: 'B',
       9: 'V',
       0: 'O',
       17: 'L',
       5: 'F',
       16: 'G',
       10: 'W',
       21: 'M',
       23: 'Y',
       11: 'K',
       18: 'P',
      }

decoded = ''
for n in just_numbers:
    if n in key:
        decoded += key[n]
    else:
        decoded += ' '+str(n)+' '
        

pprint.pprint(decoded)
('AMFFLDY 12 BSD 12 DHGGHBG 12 NSAGGBE 6 GGRGEM 6 MY 24 OH 12  24 GY 12 '
 'PAGGBMWDNMLAVHGAGNLG 6 E 12 BCLF 6  12  12  24 GCB 12 V 24 '
 'DALKKDCMBCFMADDHGMKDEHMRDC 12  24 GVLDHDAMKLMBDYHMADED 12 EDGM 6 '
 'MVMONHANADDC 12  24 CH 12 AHY 12 HAMFFLHYF 12  6 CVLLUHDMADYY 12 NADGD')