[Python] Why does my Collapsing Matrix Cipher decryption produce wrong plaintext?

Discussão em 'Python' iniciado por Stack, Agosto 9, 2025.

  1. Stack

    Stack Membro Participativo

    I implemented the Collapsing Matrix Cipher decryption in Python.

    Cipher Specification

    Grid Initialization

    • Create a 5×5 grid.
    • Populate it with the unique letters of the keyword (ignore non-alphabetic characters), followed by the remaining letters of the alphabet in order.
    • Treat i and j as the same letter; skip j during grid creation. When decrypting, i and j are interchangeable.

    Character Decryption

    • For each ciphertext character C, find its position (row, col) in the current grid.
    • The original plaintext character P is at (row+1, col) (wrap around so row 4 becomes row 0).

    Collapse Step

    • After finding P, remove it from the grid.
    • Shift all characters after P in row-major order (left-to-right, top-to-bottom) forward by one to fill the gap.
    • Use the updated grid for the next character decryption.

    Here is the complete code I’m using:

    import sys

    def preprocess_keyword(keyword):
    seen = set()
    keyword = keyword.lower().replace('j', 'i')
    grid_letters = []

    for c in keyword:
    if c.isalpha() and c not in seen:
    seen.add(c)
    grid_letters.append(c)

    for char_code in range(ord('a'), ord('z') + 1):
    c = chr(char_code)
    if c == 'j':
    continue
    if c not in seen:
    seen.add(c)
    grid_letters.append(c)

    return [grid_letters[i*5:(i+1)*5] for i in range(5)]

    def decrypt_char(grid, cipher_char):
    cipher_char = 'i' if cipher_char == 'j' else cipher_char
    trow, tcol = -1, -1
    for r in range(5):
    try:
    c = grid[r].index(cipher_char)
    trow, tcol = r, c
    break
    except ValueError:
    continue
    if trow == -1:
    return None
    p_row = (trow + 1) % 5
    p_col = tcol
    return grid[p_row][p_col]

    def collapse_grid(grid, removed_char):
    flat = [char for row in grid for char in row]
    try:
    idx = flat.index(removed_char)
    except ValueError:
    return grid
    for i in range(idx, 24):
    flat = flat[i + 1]
    flat[24] = None
    return [flat[i*5:(i+1)*5] for i in range(5)]

    def process_test_case(keyword, ciphertext):
    grid = preprocess_keyword(keyword)
    plaintext = ''

    for c in ciphertext:
    p = decrypt_char(grid, c)
    if p is not None:
    plaintext += p
    grid = collapse_grid(grid, p)

    return plaintext

    def main():
    lines = sys.stdin.read().splitlines()
    line_idx = 0
    while line_idx < len(lines) and not lines[line_idx].strip():
    line_idx += 1
    if line_idx >= len(lines): return
    num_test_cases = int(lines[line_idx])
    line_idx += 1

    outputs = []
    for _ in range(num_test_cases):
    while line_idx < len(lines) and not lines[line_idx].strip():
    line_idx += 1
    if line_idx >= len(lines): break
    keyword = lines[line_idx]
    line_idx += 1
    if line_idx >= len(lines): break
    ciphertext = lines[line_idx]
    line_idx += 1
    outputs.append(process_test_case(keyword, ciphertext))

    print('\n\n'.join(outputs))

    if __name__ == "__main__":
    main()


    Test case:

    2

    crypto
    kcnarfm


    Expected output:

    hackathon


    Actual output:

    soxgbm


    I expected the decryption to match the example provided in the problem statement, but instead I’m getting incorrect plaintext. I’ve verified my grid initialization, so I suspect the issue is with my collapse_grid logic or the way I determine the plaintext character in decrypt_char.

    Continue reading...

Compartilhe esta Página