diff --git a/solutions/c/rail-fence-cipher/1/rail_fence_cipher.c b/solutions/c/rail-fence-cipher/1/rail_fence_cipher.c new file mode 100644 index 0000000..59712bb --- /dev/null +++ b/solutions/c/rail-fence-cipher/1/rail_fence_cipher.c @@ -0,0 +1,108 @@ +#include "rail_fence_cipher.h" +#include +#include +#include +#include +#include + +enum direction { UPWARD, DOWNWARD}; +static inline size_t strcpy_without_spaces(char *dest, const char *src); + +char *encode(char *text, size_t rails) { + if (!text) return NULL; + size_t len = strlen(text); + + char *res = malloc(len + 1); + if (!res) return NULL; + + char *cleaned_text = malloc(len + 1); + if (!cleaned_text) {free(res); return NULL;} + + size_t count = strcpy_without_spaces(cleaned_text, text); + if (count < len) { + char *temp = realloc(cleaned_text, count + 1); + if (!temp){ + free(res); + free(cleaned_text); + return NULL; + } + cleaned_text = temp; + } + + len = count; + + if (len == 0 || rails <= 1) { + memcpy(res, cleaned_text, len + 1); + free(cleaned_text); + return res; + } + + count = 0; + for (size_t curr_row = 0; curr_row < rails; curr_row++) { + enum direction dir = DOWNWARD; + size_t row = 0; + for (size_t j = 0; j < len; j++) { + if (row == curr_row && count < len){ + res[count++] = cleaned_text[j]; + } + + if (dir == DOWNWARD) { + row++; + if (row == rails - 1) dir = UPWARD; + } else { + row--; + if (row == 0) dir = DOWNWARD; + } + } + } + + free(cleaned_text); + res[len] = '\0'; + return res; +} + +char *decode(char *ciphertext, size_t rails){ + if (!ciphertext) return NULL; + + size_t len = strlen(ciphertext); + + char *res = malloc(len + 1); + if (!res) return NULL; + + if (len <= 2 || rails <= 1){ + memcpy(res, ciphertext, len + 1); + return res; + } + + for (size_t cur_row = 0, j = 0; cur_row < rails; cur_row++) { + size_t row = 0; + enum direction dir = DOWNWARD; + for (size_t i = 0; i < len; i++) { + if (row == cur_row && j < len) { + res[i] = ciphertext[j++]; + } + + if (dir == DOWNWARD) { + row++; + if (row == rails - 1) dir = UPWARD; + } else { + row--; + if (row == 0) dir = DOWNWARD; + } + } + } + + res[len] = '\0'; + return res; +} + +static inline size_t strcpy_without_spaces(char *dest, const char *src){ + size_t count = 0; + for (size_t i = 0; src[i]; i++) { + if (!isspace(src[i])){ + dest[count++] = src[i]; + } + } + dest[count] = '\0'; + return count; +} diff --git a/solutions/c/rail-fence-cipher/1/rail_fence_cipher.h b/solutions/c/rail-fence-cipher/1/rail_fence_cipher.h new file mode 100644 index 0000000..f0185e2 --- /dev/null +++ b/solutions/c/rail-fence-cipher/1/rail_fence_cipher.h @@ -0,0 +1,10 @@ +#ifndef RAIL_FENCE_CIPHER_H +#define RAIL_FENCE_CIPHER_H + +#include + +char *encode(char *text, size_t rails); + +char *decode(char *ciphertext, size_t rails); + +#endif