Imagine a necklace with lettered beads that can slide along the string. Here's an example of a necklace whose beads spell the word JESSICA.

necklace
Necklace with lettered beads that spell the name JESSICA.

In this example we could take the leftmost bead J of the necklace and slide it around to the other end to spell the word ESSICAJ. We could also take the two rightmost beads CA and slide them to the other end to spell the word CAJESSI.

Assignment

Define a class Necklace that can be used to represent necklaces. A string (str) with the letters on the beads must be passed when creating a necklace (Necklace).

If a necklace (Necklace) is passed to the built-in function str, a string (str) spelling the letters on its beads must be returned. If a necklace (Necklace) is passed to the built-in function repr, a string representation (str) must be returned that reads as a Python expression that creates a new necklace (Necklace) having the same letters on its beads as the necklace passed to the function repr. If a necklace (Necklace) is passed to the built-in function len, the number of beads (int) along its string must be returned.

We must be able to call at least the following methods on a necklace $$n$$ (Necklace):

Make sure the built-in operator == can be used to check if two necklaces $$n_1$$ and $$n_2$$ (Necklace) are the same. This is the case if necklace $$n_1$$ could be transformed into necklace $$n_2$$ by sliding some beads from one end to the other end of the necklace. However, when comparing the two necklaces, the order of the beads along the strings of $$n_1$$ and $$n_2$$ may not changed and no distinction must be made between uppercase and lowercase letters.

Make sure the built-in operator + can be used to add a necklace $$n$$ (Necklace) and an integer $$m \in \mathbb{Z}$$ (int): both $$n + m$$ and $$m + n$$. The result is a new necklace (Necklace) that is obtained by sliding a bead from one end to the other end of the necklace $$|m|$$ times, as with the method slide. However, when adding $$n$$ and $$m$$, the order of the beads along the string of $$n$$ may not change. If the built-in operator + is used to add a necklace $$n$$ (Necklace) and an object that is not an integer (int), an AssertionError must be raised with the message invalid operation.

Example

>>> necklace = Necklace('Jessica')
>>> necklace
Necklace('Jessica')
>>> print(necklace)
Jessica
>>> len(necklace)
7
>>> necklace.slide(1)
Necklace('essicaJ')
>>> necklace
Necklace('essicaJ')
>>> necklace.slide(-2)
Necklace('aJessic')
>>> necklace.slide(11)
Necklace('sicaJes')
>>> necklace.forms() # doctest: +SKIP
{'SICAJES', 'ESSICAJ', 'AJESSIC', 'JESSICA', 'CAJESSI', 'SSICAJE', 'ICAJESS'}
>>> necklace
Necklace('sicaJes')
>>> necklace.normal_form()
'AJESSIC'

>>> necklace == Necklace('Louise')
False
>>> Necklace('Louise') == Necklace('Elouis')
True

>>> necklace = Necklace('Emily')
>>> necklace
Necklace('Emily')
>>> necklace + 1
Necklace('milyE')
>>> necklace
Necklace('Emily')
>>> -2 + necklace
Necklace('lyEmi')
>>> necklace + 9
Necklace('yEmil')
>>> necklace + 'spam'
Traceback (most recent call last):
AssertionError: invalid operation

Epilogue

According to legend, when the pirate Olivier Levasseur1 was hanged in 1730, he flung a necklace into the crowd, crying,

Find my treasure, the one who may understand it!

The necklace (supposedly) contained this cryptogram, which people have been trying to decipher ever since. The will of fellow pirate Bernardin Nageon de L'Estang (allegedly) refers to

considerable treasure … buried on my dear île de France (now Mauritius)

and the puzzle may or may not be related to carvings found in the rocks at Bel Ombre2 beach in the Seychelles by L'Estang's descendant Rose Savy in 1923.

cryptogram
The Cryptogram of Olivier Levasseur.

Does any of this add up to anything? Who knows? Nick Pelling has a good skeptical discussion here3, including an interpretation of the cryptogram as a pigpen cipher4.