Railfence

// railfence.go
// description: Rail Fence Cipher
// details: The rail fence cipher is a an encryption algorithm that uses a rail fence pattern to encode a message. it is a type of transposition cipher that rearranges the characters of the plaintext to form the ciphertext.
// time complexity: O(n)
// space complexity: O(n)
// ref: https://en.wikipedia.org/wiki/Rail_fence_cipher
package railfence

import (
	"strings"
)

func Encrypt(text string, rails int) string {
	if rails == 1 {
		return text
	}

	// Create a matrix for the rail fence pattern
	matrix := make([][]rune, rails)
	for i := range matrix {
		matrix[i] = make([]rune, len(text))
	}

	// Fill the matrix
	dirDown := false
	row, col := 0, 0
	for _, char := range text {
		if row == 0 || row == rails-1 {
			dirDown = !dirDown
		}
		matrix[row][col] = char
		col++
		if dirDown {
			row++
		} else {
			row--
		}
	}
	var result strings.Builder
	for _, line := range matrix {
		for _, char := range line {
			if char != 0 {
				result.WriteRune(char)
			}
		}
	}

	return result.String()
}
func Decrypt(cipherText string, rails int) string {
	if rails == 1 || rails >= len(cipherText) {
		return cipherText
	}

	// Placeholder for the decrypted message
	decrypted := make([]rune, len(cipherText))

	// Calculate the zigzag pattern and place characters accordingly
	index := 0
	for rail := 0; rail < rails; rail++ {
		position := rail
		down := true // Direction flag
		for position < len(cipherText) {
			decrypted[position] = rune(cipherText[index])
			index++

			// Determine the next position based on the current rail and direction
			if rail == 0 || rail == rails-1 {
				position += 2 * (rails - 1)
			} else if down {
				position += 2 * (rails - 1 - rail)
				down = false
			} else {
				position += 2 * rail
				down = true
			}
		}
	}

	return string(decrypted)
}