Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
First solution in Clear category for Rotating Grille Cipher by rybld2
from typing import List, Optional
def rot_90(m):
return [[m[i][j] for i in reversed(range(len(m)))] for j in range(len(m))]
def holes(m):
return [i for i, g in enumerate([c for h in m for c in h]) if g == 'X']
def motif(grille: List):
patt, nouv_grille = holes(grille), grille
for _ in range(3):
nouv_grille = rot_90(nouv_grille)
patt.extend(holes(nouv_grille))
return patt
def grille_correcte(grille: List, n):
grill = ''.join(grille)
return False if grill.count('X') != int(n ** .5) or len(grill) != n else len(set(motif(grille))) == n
def grille_encrypt(plaintext: str, grille: List[str], n=16) -> Optional[str]:
if not grille_correcte(grille, n): return None
patt, res = motif(grille), []
dico = {p: patt.index(p) for p in patt}
for k in range(len(plaintext) // n):
ss_res = ['?'] * n
for cl, v in dico.items(): ss_res[cl] = plaintext[v + k * n]
res.extend(ss_res)
return ''.join(res)
if __name__ == "__main__":
print("Example:")
print(grille_encrypt("cardangrilletest", [".X..", ".X..", "...X", "X..."]))
# These "asserts" are used for self-checking and not for an auto-testing
assert (
grille_encrypt("cardangrilletest", [".X..", ".X..", "...X", "X..."])
== "actilangeslrdret"
)
assert (
grille_encrypt(
"quickbrownfoxjumpsoverthelazydog", ["X...", "...X", "..X.", ".X.."]
)
== "qxwkbnjufriumcoopyeerldsatoogvhz"
)
assert (
grille_encrypt(
"quickbrownfoxjumpsoverthelazydog", [".XX.", ".XX.", "..X.", "X..."]
)
== None
)
assert grille_encrypt("cardangrilletest", ["...X", "....", "....", "...."]) == None
print("Coding complete? Click 'Check' to earn cool rewards!")
Nov. 10, 2022
Comments: