Rust: codewars的Simple Substitution Cipher Helper算法题、N种不简单的解法集
来源:互联网 发布:指定dns解析域名 编辑:程序博客网 时间:2024/06/01 08:57
codewars是一个不错的刷题的网站,特别是对于rust爱好者而者,资源稀缺,是打发时光的利器。
今天不是专门安利codewars而来,主要是谈一道简单的加密和解密算法题。
说明:来源于codewars,Simple Substitution Cipher Helper。
一、要求如下:
其实就是26个字母,打乱后,但一一对应。要求对任一字符串,能进行加密和解密。
比如
let map1 = "abcdefghijklmnopqrstuvwxyz";let map2 = "etaoinshrdlucmfwypvbgkjqxz";let cipher = Cipher::new(map1, map2);cipher.encode("abc") // => "eta"cipher.encode("xyz") // => "qxz"cipher.encode("aeiou") // => "eirfg"cipher.decode("eta") // => "abc"cipher.decode("qxz") // => "xyz"cipher.decode("eirfg") // => "aeiou"
如果超出26个字母以外的字符,不加密。即”好”=》“好”
二、N种不同的算法,大开眼界
只能说,牛人太多,爽爽爽!这个是最好的教材。除本法提交的算法外,在此选集了近10种codewars中的精彩的解法,供平时学习。
1、个人提交的算法
use std::collections::HashMap;struct Cipher { encode: HashMap<String, String>, decode: HashMap<String, String>,}impl Cipher { fn new(map1: &str, map2: &str) -> Cipher { let _encode = map1.chars() .map(|x| x.to_string()) .zip(map2.chars().map(|y| y.to_string())) .collect::<HashMap<String, String>>(); let _decode = map2.chars() .map(|x| x.to_string()) .zip(map1.chars().map(|y| y.to_string())) .collect::<HashMap<String, String>>(); Cipher { encode: _encode, decode: _decode, } } fn encode(&self, string: &str) -> String { let mut _strs = String::from(""); let strs: Vec<_> = string.chars() .map(|x| match self.encode.get(&x.to_string()) { Some(s) => _strs.push_str(s), _ => _strs.push_str(&x.to_string()), }) .collect(); _strs } fn decode(&self, string: &str) -> String { let mut _strs = String::from(""); let strs: Vec<_> = string.chars() .map(|x| match self.decode.get(&x.to_string()) { Some(s) => _strs.push_str(s), _ => _strs.push_str(&x.to_string()), }) .collect(); _strs }}
2、codewars的最佳算法
struct Cipher { map: Vec<(char, char)>}impl Cipher { fn new(map1: &str, map2: &str) -> Cipher { Cipher { map: map1.chars().zip(map2.chars()).collect() } } fn encode(&self, string: &str) -> String { string.chars().map(|c| self.map.iter().find(|x| x.0 == c).map_or(c, |y| y.1)).collect() } fn decode(&self, string: &str) -> String { string.chars().map(|c| self.map.iter().find(|x| x.1 == c).map_or(c, |y| y.0)).collect() }}
3、其它算法
use std::collections::HashMap;struct Cipher { encode_map: HashMap<char, char>, decode_map: HashMap<char, char>,}impl Cipher { fn new(map1: &str, map2: &str) -> Cipher { let mut encode_map = HashMap::new(); encode_map.extend(map1.chars().zip(map2.chars())); let mut decode_map = HashMap::new(); decode_map.extend(map2.chars().zip(map1.chars())); Cipher { encode_map: encode_map, decode_map: decode_map } } fn encode(&self, string: &str) -> String { string.chars().map(|c| self.encode_map.get(&c).map_or(c, |v| *v)).collect() } fn decode(&self, string: &str) -> String { string.chars().map(|c| self.decode_map.get(&c).map_or(c, |v| *v)).collect() }}
4、BTreeMap
use std::collections::BTreeMap;struct Cipher { // We need a bidirectional cipher implementation, with dictionary per direction. // BTreeMap should likely work faster than HashMap with simplest hasher in our case. etree: BTreeMap<char, char>, dtree: BTreeMap<char, char>,}impl Cipher { fn new(map1: &str, map2: &str) -> Cipher { Cipher { // Hopefully BTreeMap is created balanced. etree: map1.chars().zip(map2.chars()).collect(), dtree: map2.chars().zip(map1.chars()).collect(), } } // Here be dragons, krakens, sandworms and impaired (de-)referencing conventions. fn encode(&self, string: &str) -> String { string.chars().map(|c| self.etree.get(&c).cloned().unwrap_or(c)).collect() } fn decode(&self, string: &str) -> String { string.chars().map(|c| self.dtree.get(&c).cloned().unwrap_or(c)).collect() }}
5、String
struct Cipher { map1: String, map2: String,}impl Cipher { fn new(map1: &str, map2: &str) -> Cipher { Cipher { map1: map1.into(), map2: map2.into()} } fn encode(&self, string: &str) -> String { string.chars().map( |c| { match self.map1.find(c) { Some(i) => self.map2.chars().nth(i).unwrap(), _ => c } } ).collect() } fn decode(&self, string: &str) -> String { string.chars().map( |c| { match self.map2.find(c) { Some(i) => self.map1.chars().nth(i).unwrap(), _ => c } } ).collect() }}
6、Vec
struct Cipher { from: Vec<u8>, to: Vec<u8>,}impl Cipher { fn new(map1: &str, map2: &str) -> Cipher { Cipher { from: map1.as_bytes().to_vec(), to: map2.as_bytes().to_vec(), } } fn encode(&self, string: &str) -> String { string.chars() .map(|c| self.from.iter().position(|&f| f == c as u8).map_or(c, |p| self.to[p] as char)) .collect() } fn decode(&self, string: &str) -> String { string.chars() .map(|c| self.to.iter().position(|&f| f == c as u8).map_or(c, |p| self.from[p] as char)) .collect() }}
7、
use std::collections::HashMap;fn get_default(m: &HashMap<char,char>,k: &char) -> char { match m.get(k) { Some(val) => *val, None => *k }}struct Cipher { encoding: HashMap<char,char>, decoding: HashMap<char,char>}impl Cipher { fn new(map1: &str, map2: &str) -> Cipher { let mut encoding = HashMap::new(); let mut decoding = HashMap::new(); for (x,y) in map1.chars().zip(map2.chars()) { encoding.insert(x,y); decoding.insert(y,x); } Cipher{encoding:encoding,decoding:decoding} } fn encode(&self, string: &str) -> String { string.chars().map(|c| get_default(&self.encoding,&c).to_string()) .collect::<Vec<String>>().join("") } fn decode(&self, string: &str) -> String { string.chars().map(|c| get_default(&self.decoding,&c).to_string()) .collect::<Vec<String>>().join("") }}
8、
use std::collections::HashMap;struct Cipher { encode: HashMap<char, char>, decode: HashMap<char, char>,}fn _code(map: &HashMap<char, char>, string: &str) -> String { string.chars() .map(|x| map.get(&x).unwrap_or(&x).clone()) .collect()}impl Cipher { fn new(map1: &str, map2: &str) -> Cipher { Cipher { encode: map1.chars() .zip(map2.chars()) .collect(), decode: map2.chars() .zip(map1.chars()) .collect(), } } fn encode(&self, string: &str) -> String { _code(&self.encode, string) } fn decode(&self, string: &str) -> String { _code(&self.decode, string) }}
9、
struct Cipher<'a> { map1:&'a [u8], map2:&'a [u8]}impl<'a> Cipher<'a> { fn new(map1: &'a str, map2: &'a str) -> Cipher<'a> { Cipher{map1:map1.as_bytes(), map2:map2.as_bytes()} } fn encode(&self, string: &str) -> String { string.bytes() .map(|b| self.map1 .iter() .position(|&m| b==m) .and_then(|i| self.map2.get(i)) .cloned() .unwrap_or(b) as char ) .collect() } fn decode(&self, string: &str) -> String { self.decoder().encode(string) } fn decoder(&self) -> Cipher{ Cipher{map1:self.map2, map2:self.map1} }}
10、
struct Cipher { table : std::collections::HashMap<char,char>}impl Cipher { fn new(map1: &str, map2: &str) -> Cipher { Cipher { table : map1.chars().zip(map2.chars()).collect() } } fn encode(&self, string: &str) -> String { string.chars().map(|x| self.table.get(&x).cloned().unwrap_or(x)).collect() } fn decode(&self, string: &str) -> String { string.chars().map(|x| self.decode_char(x)).collect() } fn decode_char(&self, c: char) -> char { self.table.iter().find(|kv| *kv.1 == c).map(|kv| *kv.0).unwrap_or(c) }}
11、个人认为的最佳解法
use std::collections::HashMap;struct Cipher { encode: HashMap<char, char>, decode: HashMap<char, char>}impl Cipher { fn new(map1: &str, map2: &str) -> Self { let encode = map1.chars().zip(map2.chars()).collect(); let decode = map2.chars().zip(map1.chars()).collect(); Cipher{encode: encode, decode: decode} } fn encode(&self, string: &str) -> String { string.chars().map(|ref c| *self.encode.get(c).unwrap_or(c)).collect() } fn decode(&self, string: &str) -> String { string.chars().map(|ref c| *self.decode.get(c).unwrap_or(c)).collect() }}
三、个别点评
看了其它人10种解法外,个人认为第11种解法最佳,思路清晰,代码简单,最为优雅,第10种也差不多,当然,各种优势。
我的解法的思路虽然相同,但用String并不是一个好的选择,过于笨重,增加了不少的代码量。
1、用char代替String
//在上面场景中,HashMap<char, char>较HashMap<String, String>结构更轻巧。fn new(map1: &str, map2: &str) { let _encode = map1.chars() .zip(map2.chars()) .collect::<HashMap<char, char>>();}//没有过多的转化
2、使用unwrap_or,可以省了一大段的代码:
string.chars().map(|ref c| *self.encode.get(c).unwrap_or(c)).collect()
阅读全文
0 0
- Rust: codewars的Simple Substitution Cipher Helper算法题、N种不简单的解法集
- Rust: codewars的prize draw算法
- Rust : codewars的up AND down 算法
- [Cryptography]Simple Substitution Cipher
- Rust: codewars 的Duplicate Encoder
- Rust: codewars的Bleatrix Trotter
- Rust: codewars的primes-in-numbers
- Rust : codewars的Sum of Pairs
- Rust: codewars的Roman Numerals Encoder
- Rust: codewars的Sum by Factors
- Rust: codewars的DNA to RNA Conversion
- Rust: codewars的Highest and Lowest
- Rust: codewars的Molecule to atoms
- Rust : codewars的Product of consecutive Fib numbers
- Rust: codewars 的Count of positives / sum of negatives
- 一道算法题的一种O(n)解法
- codewars-5kyu-Simple Pig Latin:正则表达式的使用
- 一道简单又不简单的算法笔试题
- 删除html
- HDU2295 Radar —— Dancing Links 可重复覆盖
- 概率论试卷题目
- C#---变量
- python执行报错:SyntaxError: Non-ASCII character '\xe8' in file .
- Rust: codewars的Simple Substitution Cipher Helper算法题、N种不简单的解法集
- java变量的作用域
- scp命令
- java并发编程学习8--同步器--信号量
- 杭电 6213 (map) 之 Chinese Zodiac
- 黑魔法~XOR linked list
- 理解Tomcat架构、启动流程及其性能优化
- JMX监控Zookeeper状态Java API
- 轮播图下方小圆点