https en wikipedia orgwikirailfencecipher def encryptinputstring str key int str tempgrid listliststr for in rangekey lowest key 1 if key 0 raise valueerrorheight of grid can t be 0 or negative if key 1 or leninputstring key return inputstring for position character in enumerateinputstring num position lowest 2 puts it in bounds num minnum lowest 2 num creates zigzag pattern tempgridnum appendcharacter grid joinrow for row in tempgrid outputstring joingrid return outputstring def decryptinputstring str key int str grid lowest key 1 if key 0 raise valueerrorheight of grid can t be 0 or negative if key 1 return inputstring tempgrid listliststr for in rangekey generates template for position in rangeleninputstring num position lowest 2 puts it in bounds num minnum lowest 2 num creates zigzag pattern tempgridnum append counter 0 for row in tempgrid fills in the characters splice inputstringcounter counter lenrow grid appendlistsplice counter lenrow outputstring reads as zigzag for position in rangeleninputstring num position lowest 2 puts it in bounds num minnum lowest 2 num creates zigzag pattern outputstring gridnum0 gridnum pop0 return outputstring def bruteforceinputstring str dictint str results for keyguess in range1 leninputstring tries every key resultskeyguess decryptinputstring keyguess return results if name main import doctest doctest testmod shuffles the character of a string by placing each of them in a grid the height is dependent on the key in a zigzag formation and reading it left to right encrypt hello world 4 hwe olordll encrypt this is a message 0 traceback most recent call last valueerror height of grid can t be 0 or negative encrypt b this is a byte string 5 traceback most recent call last typeerror sequence item 0 expected str instance int found puts it in bounds creates zigzag pattern generates a template based on the key and fills it in with the characters of the input string and then reading it in a zigzag formation decrypt hwe olordll 4 hello world decrypt this is a message 10 traceback most recent call last valueerror height of grid can t be 0 or negative decrypt my key is very big 100 my key is very big generates template puts it in bounds creates zigzag pattern fills in the characters reads as zigzag puts it in bounds creates zigzag pattern uses decrypt function by guessing every key bruteforce hwe olordll 4 hello world tries every key
def encrypt(input_string: str, key: int) -> str:
    
    temp_grid: list[list[str]] = [[] for _ in range(key)]
    lowest = key - 1

    if key <= 0:
        raise ValueError("Height of grid can't be 0 or negative")
    if key == 1 or len(input_string) <= key:
        return input_string

    for position, character in enumerate(input_string):
        num = position % (lowest * 2)  
        num = min(num, lowest * 2 - num)  
        temp_grid[num].append(character)
    grid = ["".join(row) for row in temp_grid]
    output_string = "".join(grid)

    return output_string


def decrypt(input_string: str, key: int) -> str:
    
    grid = []
    lowest = key - 1

    if key <= 0:
        raise ValueError("Height of grid can't be 0 or negative")
    if key == 1:
        return input_string

    temp_grid: list[list[str]] = [[] for _ in range(key)]  
    for position in range(len(input_string)):
        num = position % (lowest * 2)  
        num = min(num, lowest * 2 - num)  
        temp_grid[num].append("*")

    counter = 0
    for row in temp_grid:  
        splice = input_string[counter : counter + len(row)]
        grid.append(list(splice))
        counter += len(row)

    output_string = ""  
    for position in range(len(input_string)):
        num = position % (lowest * 2)  
        num = min(num, lowest * 2 - num)  
        output_string += grid[num][0]
        grid[num].pop(0)
    return output_string


def bruteforce(input_string: str) -> dict[int, str]:
    
    results = {}
    for key_guess in range(1, len(input_string)):  
        results[key_guess] = decrypt(input_string, key_guess)
    return results


if __name__ == "__main__":
    import doctest

    doctest.testmod()