Skip to content

Commit 7b2306d

Browse files
committed
feat(codewars): solution for 3kyu task
1 parent 94c8ea2 commit 7b2306d

File tree

4 files changed

+132
-0
lines changed

4 files changed

+132
-0
lines changed

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codewars/rail_fence_cypher/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "rail_fence_cypher"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]

codewars/rail_fence_cypher/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Rail Fence Cipher: Encoding and Decoding
2+
3+
[codewars](https://www.codewars.com/kata/58c5577d61aefcf3ff000081/train/rust)
4+
5+
Create two functions to encode and then decode a string using the Rail Fence Cipher. This cipher is used to encode a string by placing each character successively in a diagonal along a set of "rails". First start off moving diagonally and down. When you reach the bottom, reverse direction and move diagonally and up until you reach the top rail. Continue until you reach the end of the string. Each "rail" is then read left to right to derive the encoded string.
6+
7+
For example, the string "WEAREDISCOVEREDFLEEATONCE" could be represented in a three rail system as follows:
8+
9+
W E C R L T E
10+
E R D S O E E F E A O C
11+
A I V D E N
12+
The encoded string would be:
13+
14+
WECRLTEERDSOEEFEAOCAIVDEN
15+
Write a function/method that takes 2 arguments, a string and the number of rails, and returns the ENCODED string.
16+
17+
Write a second function/method that takes 2 arguments, an encoded string and the number of rails, and returns the DECODED string.
18+
19+
For both encoding and decoding, assume number of rails >= 2 and that passing an empty string will return an empty string.
20+
21+
Note that the example above excludes the punctuation and spaces just for simplicity. There are, however, tests that include punctuation. Don't filter out punctuation as they are a part of the string.
22+
23+
## Examples
24+
25+
assert_eq!(encode_rail_fence_cipher("WEAREDISCOVEREDFLEEATONCE", 3), "WECRLTEERDSOEEFEAOCAIVDEN");
26+
assert_eq!(decode_rail_fence_cipher("WECRLTEERDSOEEFEAOCAIVDEN", 3), "WEAREDISCOVEREDFLEEATONCE");
27+
assert_eq!(encode_rail_fence_cipher("Hello, World!", 3), "Hoo!el,Wrdl l");
28+
assert_eq!(decode_rail_fence_cipher("Hoo!el,Wrdl l", 3), "Hello, World!");

codewars/rail_fence_cypher/src/lib.rs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
fn single_rail<Handler>(size: usize, num_rails: usize, rail_num: usize, mut handler: Handler)
2+
where
3+
Handler: FnMut(usize),
4+
{
5+
let mut n = rail_num;
6+
let mut down_line = true;
7+
let mut from_down_to_up_modifier = 2 * (num_rails - rail_num - 1);
8+
let mut from_up_to_down_modifier = 2 * rail_num;
9+
10+
if from_down_to_up_modifier == 0 {
11+
from_down_to_up_modifier = from_up_to_down_modifier;
12+
}
13+
14+
if from_up_to_down_modifier == 0 {
15+
from_up_to_down_modifier = from_down_to_up_modifier;
16+
}
17+
18+
while n < size {
19+
handler(n);
20+
21+
n += if down_line {
22+
from_down_to_up_modifier
23+
} else {
24+
from_up_to_down_modifier
25+
};
26+
27+
down_line = !down_line;
28+
}
29+
}
30+
31+
pub fn encode_rail_fence_cipher(text: &str, num_rails: usize) -> String {
32+
let chars: Vec<_> = text.chars().collect();
33+
let size = chars.len();
34+
let mut result = "".to_owned();
35+
36+
for rail_num in 0..num_rails {
37+
single_rail(size, num_rails, rail_num, |n| {
38+
result.push(chars[n]);
39+
});
40+
}
41+
42+
result
43+
}
44+
45+
pub fn decode_rail_fence_cipher(text: &str, num_rails: usize) -> String {
46+
let size = text.chars().count();
47+
let mut chars = text.chars();
48+
let mut result: Vec<char> = vec![' '; size];
49+
50+
for rail_num in 0..num_rails {
51+
single_rail(size, num_rails, rail_num, |n| {
52+
result[n] = chars.next().unwrap();
53+
});
54+
}
55+
56+
result.iter().collect()
57+
}
58+
59+
#[cfg(test)]
60+
mod tests {
61+
use super::*;
62+
63+
#[test]
64+
fn basic_tests() {
65+
assert_eq!(encode_rail_fence_cipher("abcdefghi", 2), "acegibdfh");
66+
assert_eq!(encode_rail_fence_cipher("abcdefghi", 3), "aeibdfhcg");
67+
assert_eq!(encode_rail_fence_cipher("abcdefghi", 4), "agbfhceid");
68+
assert_eq!(encode_rail_fence_cipher("abcdefghi", 5), "aibhcgdfe");
69+
70+
assert_eq!(decode_rail_fence_cipher("acegibdfh", 2), "abcdefghi");
71+
assert_eq!(decode_rail_fence_cipher("aeibdfhcg", 3), "abcdefghi");
72+
assert_eq!(decode_rail_fence_cipher("agbfhceid", 4), "abcdefghi");
73+
assert_eq!(decode_rail_fence_cipher("aibhcgdfe", 5), "abcdefghi");
74+
75+
assert_eq!(
76+
encode_rail_fence_cipher("WEAREDISCOVEREDFLEEATONCE", 3),
77+
"WECRLTEERDSOEEFEAOCAIVDEN"
78+
);
79+
assert_eq!(
80+
decode_rail_fence_cipher("WECRLTEERDSOEEFEAOCAIVDEN", 3),
81+
"WEAREDISCOVEREDFLEEATONCE"
82+
);
83+
assert_eq!(
84+
encode_rail_fence_cipher("Hello, World!", 3),
85+
"Hoo!el,Wrdl l"
86+
);
87+
assert_eq!(
88+
decode_rail_fence_cipher("Hoo!el,Wrdl l", 3),
89+
"Hello, World!"
90+
);
91+
}
92+
}

0 commit comments

Comments
 (0)