I've been plugging away at the piglatin problem on Kattis, Pig Latin – Kattis, Kattis. Note their particular flavour of rules, so "y" counts as a vowel, for example. I'm pretty new to Rust, and I'm using Kattis to give me specific things to work on, and help improve. My approach so far is to write in Python (my usual language) to make sure I have the logic right, then attempt to produce something equivalent in rust. Sometimes that requires re-thinking the logic to suit the new language.
I got some working Rust code with relative ease for this one, but it was horribly slow. You know you're doing something wrong when Rust is taking longer than Python!
I've completely overhauled it and now have something that runs their test cases in 0.07s according to the kattis servers. What is baffling me, and now has me really curious is that there are some solutions on there that do it in 0.03s. Note that, as I understand it, on kattis you can't use external crates.
I can't see obvious ways to make this code faster, and I think I'm pretty happy with it, as is, but I'd love any feedback, and would be curious to see if there are ways this might be made faster?
use std::io::{self, BufRead};
fn is_vowel(letter: char) -> bool {
return letter == 'a' || letter == 'e' || letter == 'i' || letter == 'o' || letter =='u' || letter=='y'
}
fn pig_word(word: &str) -> String{
for (index, letter) in word.chars().enumerate() {
if is_vowel(letter){
if index == 0 {
return format!("{}{}", word, "yay");
} else {
let (tailit, headit) = word.split_at(index);
return format!("{}{}ay", headit, tailit);
}
}
}
return word.to_string();
}
fn folder(mut current: String, next: String) -> String {
if !current.is_empty() {
current.push(' ');
}
current.push_str(&next);
current
}
fn main() {
// set things up
let stdin = io::stdin();
for raw_line in stdin.lock().lines() {
let line = raw_line.unwrap();
println!("{}", line.split_whitespace().map(pig_word).fold(String::new(), folder));
}
}
p.s. a few things I was doing wrong originally:
- lots of casting between str, &str, char, String and vectors. I've no background with statically compiled languages, I knew lots of casting probably meant I was probably doing things wrong!
- Defined a static HashSet containing the vowels, because I used a set in python knowing it would be fast. Switching away from a hashset to that is_vowel function reduced runtime by about 20% or so. Haven't experimented with python to see if going away from set would speed things up there too.
- Didn't leverage map, stumbled across it after finding when I'd already got this whole thing written. beginner - Convert string to pig latin in Rust - Code Review Stack Exchange. Different logic there for piglatin makes most of that unusable, but I did do some experiments with bits of the code there, ultimately deciding not to use it. Runtime didn't change after I switched to map, but I wouldn't necessarily expect it to. Syntax is definitely cleaner.