## (note (code cslai))

Notes on codes, projects and everything

# Learning a new language for more than 2 months (feat. Exercism)

## Luhn

Then there’s this checksum validator. Starting from the right, just double every digit in the odd index, minus 9 from it if it exceeds 9, then sum up the resulting digit, as well as the even-indexed digits. The result of the sum has to be 10-divisible.

```pub fn is_valid(code: &str) -> bool {
let _code = code.chars().filter(|x| !x.is_whitespace());

match _code.clone().count() {
_invalid if _invalid <= 1 => false,
_ => {
let result = _code
.map(|x| x.to_digit(10))
.rev()
.enumerate()
.map(|(idx, x)| match x {
Some(n) => Some(match (idx % 2 == 1, n * 2) {
(true, result) if result > 9 => result - 9,
(true, result) => result,
_ => n,
}),
None => None,
})
.fold(Some(0), |current, incoming| {
current.and_then(|x| match incoming {
Some(n) => Some(x + n),
None => None,
})
});

match result {
Some(n) if n % 10 == 0 => true,
_ => false,
}
}
}
}
```

This is one of the earlier submissions, and somehow I still struggle with ownership here. Then I started getting intrigue with the power of the Option enum. Then I had this

```pub fn is_valid(code: &str) -> bool {
let _code = code
.chars()
.filter(|x| !x.is_whitespace())
.collect::<Vec<char>>();

match _code.len() {
_invalid if _invalid <= 1 => false,
_ => _code
.iter()
.map(|x| x.to_digit(10))
.rev()
.enumerate()
.map(|(idx, x)| {
x.and_then(move |n| {
Some(match (idx % 2 == 1, n * 2) {
(true, result) if result > 9 => result - 9,
(true, result) => result,
_ => n,
})
})
}).fold(Some(0), |current, incoming| {
current.and_then(|x| match incoming {
Some(n) => Some(x + n),
None => None,
})
}).map_or(false, |n| n % 10 == 0),
}
}
```

## Atbash Cipher

I like breaking things, though I hate the frustration when things don’t work as expected. This time I am trying to send in a closure into a function as parameter. Of course this is not necessary the best solution but getting to this state took me quite some time due to the fight with the borrow checker.

```pub fn encode(plain: &str) -> String {
convert(
plain,
Some(&|idx, x| format!("{}{}", x, if (idx + 1) % 5 == 0 { " " } else { "" })),
)
}

/// "Decipher" with the Atbash cipher.
pub fn decode(cipher: &str) -> String {
convert(cipher, None::<&Fn(usize, char) -> String>)
}

fn transform(x: char) -> char {
match x {
x if x.is_alphabetic() => (219u8 - x as u8) as char,
x => x,
}
}

fn preprocess(text: &str) -> Vec<char> {
text.to_ascii_lowercase()
.chars()
.filter(|x| x.is_alphanumeric() && x.is_ascii())
.collect()
}

fn convert(text: &str, decorator: Option<&Fn(usize, char) -> String>) -> String {
(match decorator {
Some(_decorator) => preprocess(text)
.into_iter()
.enumerate()
.map(|(idx, x)| _decorator(idx, transform(x)))
.collect::<String>(),
None => preprocess(text)
.into_iter()
.map(|x| transform(x))
.collect::<String>(),
}).trim()
.to_string()
}```

Sometimes having someone experienced as a mentor is a good thing, he immediately pointed out some parts that can made the code simpler, yielding this

```/// "Encipher" with the Atbash cipher.
pub fn encode(plain: &str) -> String {
convert(
plain,
Some(&|idx, x| format!("{}{}", if idx != 0 && idx % 5 == 0 { " " } else { "" }, x)),
)
}

/// "Decipher" with the Atbash cipher.
pub fn decode(cipher: &str) -> String {
convert(cipher, None::<&Fn(usize, char) -> String>)
}

fn transform(x: char) -> char {
match x {
x if x.is_alphabetic() => (219u8 - x as u8) as char,
x => x,
}
}

fn convert(text: &str, decorator: Option<&Fn(usize, char) -> String>) -> String {
let preprocess = || {
text.chars()
.flat_map(char::to_lowercase)
.filter(|x| x.is_alphanumeric() && x.is_ascii())
};

(match decorator {
Some(_decorator) => preprocess()
.enumerate()
.map(|(idx, x)| _decorator(idx, transform(x)))
.collect::<String>(),
None => preprocess().map(|x| transform(x)).collect::<String>(),
})
}
```

The idea is more or less the same compared to the earlier iteration shown above, just slightly cleaner. 