ちょっと前のネタになりますが、今年2021年5月に「ZONeエナジー プログラミングコンテスト “HELLO SPACE”」というのが実施されました。
内容はいわゆる競プロ、競技プログラミングなのですが、ストーリーが面白いですね。
宇宙人が襲来し、彼らが送ってきたメッセージを解読し、それからどうしよう、という内容です。
やってることは競プロですけど、バックストーリーがあったりするとやる気が出ます。
私は2nd ROUNDから参加し、3つの課題すべてをrustで書いてみました。
今回の記事では1つ目のお題、rot13暗号解読のrust版実装例を提示したいと思います。
お題1
宇宙人の謎のメッセージを解読する。メッセージはrot13という暗号化がなされている。
rot13は各文字のASCIIコードを13ずらすという暗号化。
(参考:https://ja.wikipedia.org/wiki/ROT13)
rot13解説
例えばhという文字をrot13で変換することを考えましょう。
hのASCIIコードは104、13を足すと117、ASCIIコードが117の文字はu、
ということでh→uと変換されます。この要領で行くと、例えば”hello”という文字列は
h→u
e→r
l→y
l→y
o→b(zを超えた場合はaから再度カウントする)
ということで、”uryyb”となります。
課題はこれを解読することなので、逆変換、つまり13引く処理になります。
実装例
question1.rs
use std::io; fn main() { let mut input = String::new(); let n_alpha = 'z' as u8 - 'a' as u8 + 1; while let Ok(n) = io::stdin().read_line(&mut input) { if n == 0 { break; } let s = input .trim() .bytes() .map(|c: u8| ((c - 'a' as u8 + 13) % n_alpha + 'a' as u8) as char) .collect::<String>(); println!("{}", s); input.clear(); } }
入力テキスト
question1.txt
puvxlhwva fubxha tbxvtralb jnerjnerun xvzvgnpuvgb lhxban xnaxrvjb xvmhxhgnzr xbabubfuvav lnggrxvgn fnffbxhqntn lhxbab fuvehfuvgbfvgr chermragbjb bartnvfuvgnv ranwvqbevaxh mbar jb whaovfuvgr ubfuvvabqn xbabartnvjb xnanrgrxhereron bgbanfuvxh xbabubfuvjb ngbavfhehgfhzbevqn jnerjnerun nenfbvtbgbjb abmbznanv znrzhxvan urawvjb xvgnvfuvgrveh
使用例
>question1.exe < question1.txt
出力結果
chikyujin shokun gokigenyo warewareha kimitachito yukona kankeiwo kizukutame konohoshini yattekita sassokudaga yukono shirushitosite purezentowo onegaishitai enajidorinku zone wo junbishite hoshiinoda kononegaiwo kanaetekurereba otonashiku konohoshiwo atonisurutsumorida warewareha arasoigotowo nozomanai maemukina henjiwo kitaishiteiru
ソースコードについて
まだそんなにRustに慣れているわけではないので、標準入力を読み取るのにも苦労しました。入力の書き方については例えば:
use std::io; use std::io::prelude::*; for line in io::stdin().lock().lines() { println!("{}", line.unwrap()); // ここに各行が読み込まれる }
のように書く方が関数型っぽくって格好いいんですが、処理が遅いらしいので question1.rs のようなコードにしました。なにやらlines()は行を読むたびにメモリアロケーションが起きるそうで、それよりはあらかじめ入力バッファ(question1.rsではString型変数inputがそれに対応)を用意するのがいいんだとか。
まとめ
rustはC~Java系統をやってきた私にとっては構文が独特ですが、C/C++相当のローレベル言語でありながら関数型的に流れるように書けるので慣れてくれば書きやすくも読みやすくもなると思いました。