CSE Puzzle Challenge - Puzzle 12 - Solution

Solution

 

## Explanation

This challenge revolves around the semaphore telegraph system developed by Claude Chappe in 1792 France.

Inspired by a scam run by the Blanc brothers in 1834, the challenge is presented as a set of flag positions in an image.

The image above contains the message "Hello World!" inside the lorem ipsum filler text. Each letter of the hidden message is succeeded by a flag signalling a backspace; that the previous letter was sent in error.

The code used is only available on the French Wikipedia page linked above, specifically this image is used as the reference.

Each number directly corresponds to it's ASCII equivalent (for the letters & numbers). Many characters are unused in this implementation, as their ASCII equivalents are either control characters or whitespace.

## Solution

If we take a look at the code, we can see that there's a fairly simple pattern.

## Simplifying the Flags

Every odd signal in the first half (1-45) has a mirrored companion in the even set (2-46).

The other half of the numbers (47-92) are the same as the first, but rotated 90 degrees counter-clockwise.

Thus there are technically only 23 unique flag combinations in the list and the rest can be perceived as manipulations of the original. (We can further reduce that of course, but I found this way makes the most sense.)

The secondary 'arms' are the ones that change in the first half of the list. We can assign a number from 0-7 for each of them (4 cardinal directions and 4 directions in between those). Giving 0 the position of 'upward' and moving clockwise, we can produce the following diagram:

The red spots indicate where each of the secondary arms attach to the main arm. The upper of the two secondary arms in this diagram is showing all possible positions and their associated number. 0 and 4 represent the same thing, the arm being folded in (essentially being invisible).

From all of this we produce the subsequent list:

```python

positions = [

    (3,0), # 1

    (4,1), # 3

    (2,0), # 5

    (4,2), # 7

    (1,0), # 9

    (4,3), # 11

    (3,1), # 13

    (3,2), # 15

    (3,3), # 17

    (3,7), # 19

    (3,6), # 21

    (3,5), # 23

    (1,1), # 25

    (1,2), # 27

    (1,3), # 29

    (1,7), # 31

    (1,6), # 33

    (1,5), # 35

    (2,1), # 37

    (2,2), # 39

    (2,3), # 41

    (2,7), # 43

    (2,5)  # 45

]

```

Unfortunately some of the symbols are out of order towards the end of the list. Specifically 85-90 are not actually correct. We can manually change those to accommodate the real list.

In addition there is a character seen in the images that does not exist on this table, the backspace character. We will add this to our list manually as well.

An example function to provide two lists of vertical and horizontal orientations:

```python

def genPositions(basePositions):

    # Process mirrored positions (Subtract 8 to get a mirrored position)

    verticalPositions = []

    horizontalPositions = [((8-p[0])%8, (8-p[1])%8) for p in basePositions]

    for i in range(len(basePositions)):

        verticalPositions.append(basePositions[i])

        verticalPositions.append(horizontalPositions[i])

   

    # Process rotated positions (add 6 and mod 8 to get a 90 CCW rotation)

    horizontalPositions = [((p[0]+6)%8 , (p[1]+6)%8) for p in verticalPositions]

   

    # Mismatched positions

    horizontalPositions[85-47] = (0,1) # 85

    horizontalPositions[86-47] = (4,3) # 86

    horizontalPositions[87-47] = (0,5) # 87

    horizontalPositions[88-47] = (4,7) # 88

    horizontalPositions[89-47] = (0,4) # 89

    horizontalPositions[90-47] = (4,0) # 90

   

    # Backspace position

    horizontalPositions.append((0,0)) # 93

   

    return (verticalPositions, horizontalPositions)

```

## Dividing the Overall Image

The flags are arranged in a grid pattern, notably each flag exists in a 100x100 square. This makes it easy to split the grid up into a series of individual images from which we can deduce the symbol.

## Parsing the Sub-Image

We will get the value of each flag from the following steps:

1. Get orientation of main arm (Vertical/Horizontal)

2. Based on orientation sample the 8 spots around the tip of each side of the arm for the position of the secondary arm.

3. Consult our table of arm positions for the sequential value of the flag.

#### Some more detail:

*When checking a pixel, we need to simply check to see if it's color is black. (0,0,0,255) RGBA*

1. Check pixel (50, 30) to see if the orientation is vertical.

2. Pixel (50, 25) is the center of the arms. (+/- 15) for the secondary arm attachment positions. Use the table below as a offset lookup and add it to the center position alongside the offset for the side of the arm.

| # | Vert. Offset | Horz. Offset |

|:-:|:------------:|:------------:|

| 0 |    0, -6     |   -6,  0     |

| 1 |    6, -6     |   -6, -6     |

| 2 |    6,  0     |    0, -6     |

| 3 |    6,  6     |    6, -6     |

| 4 |    0,  6     |    6,  0     |

| 5 |   -6,  6     |    6,  6     |

| 6 |   -6,  0     |    0,  6     |

| 7 |   -6, -6     |   -6,  6     |

3. Use the pair of numbers (one per arm) to consult our flag table generated from the example above.

## Blanc Subterfuge

The way that the Blanc brothers conveyed their messages across a restricted government line was by bribing an operator on one of the semaphore towers and having him transmit a flag followed by a backspace flag. This way the error would propagate across the network, be dismissed by the official transmission, and allow them to watch and record the errored messages.

Thus we will keep track of the previous flag, and discard it for the next flag unless the next flag is a backspace. In that case we will add the previous flag to a list of "verified" flags. At the end of our processing, we will have a list of the hidden flags.

## Converting the Message

Now there's a bit of an inaccuracy in this challenge; if inspected carefully, one might be able to guess that the numbers are all within the range of printable ASCII characters. Of course in 1834 ASCII did not exist, but as there is no standardized list of the real information transmitted (letters vs words vs codes, etc), we used ASCII as a simple encoding system.

Encoding to ASCII we get the following message:

Congratulation! You solved the puzzle! You like these? If so, you might want to apply for a job at CSE: jobs-emplois@cse-cst.gc.ca

 

Enjoy solving puzzles? Make a career out of it!