Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
numpy for easy rotations, itertools.compress and zip (length-check py3.10+) solution in 3rd party category for Rotating Grille Cipher by Phil15
from itertools import compress
from typing import List, Optional
import numpy as np # rotation, nice and easy
def grille_encrypt(plaintext: str, grille: List[str]) -> Optional[str]:
bool_grille = np.array([[ch == "X" for ch in row] for row in grille])
rots = [np.rot90(bool_grille, -k) for k in range(4)]
if (sum(rots) != 1).any():
return None # The key is defective.
permutation = [i for rot in rots for i in compress(range(16), rot.flat)]
return "".join(
s
# Get chunks of plaintext of length 16
for partial_text in zip(*[iter(plaintext)] * 16, strict=True)
# Apply the permutation on the partial text
for _, s in sorted(zip(permutation, partial_text, strict=True))
)
# Note that with python 3.10, "zip" accept a new keyword-only argument named "strict"
# which check if the iterables given in the arguments are of the small lengths.
# So here, it indirectly implies a check on the precondition "len(plaintext) % 16 == 0".
# And make sure that the permutation and partial texts are of same length 16.
Dec. 16, 2021
Comments: