加速计数器游戏

时间:2016-08-03 03:49:10

标签: performance rust

我正在尝试解决关于hackerrank的Rust算法问题。我的回答超过了一些较大的测试用例。大约有5个人完成了它,所以我相信这是可能的,我认为他们在发布模式下编译。我缺少什么加速?

游戏的主旨是一个反击(主要是inp)有条件地减少,并且根据谁不能再减少它,选择胜利者。

use std::io;

fn main() {
    let n: usize = read_one_line().
        trim().parse().unwrap();
    for _i in 0..n{
        let inp: u64 = read_one_line().
            trim().parse().unwrap();
        println!("{:?}", find_winner(inp)); 
    }
    return;
}

fn find_winner(mut n: u64) -> String{
    let mut win = 0;
    while n>1{
        if n.is_power_of_two(){
            n /= 2;
        }
        else{
            n -= n.next_power_of_two()/2;
        }
        win += 1;
    }
    let winner = 
        if win % 2 == 0{
            String::from("Richard")
        } else{
            String::from("Louise")
        };
    winner
}

fn read_one_line() -> String{
    let mut input = String::new();
    io::stdin().read_line(&mut input).expect("Failed to read");
    input
}

2 个答案:

答案 0 :(得分:2)

您的内循环可以由内置函数组合替换:

let win = if n > 0 {
    n.count_ones() + n.trailing_zeros() - 1
} else {
    0
};

此外,不是每次调用find_winner时都分配字符串, 可以返回一个字符串切片:

fn find_winner(n: u64) -> &'static str {
    let win = if n > 0 {
        n.count_ones() + n.trailing_zeros() - 1
    } else {
        0
    };

    if win % 2 == 0 {
        "Richard"
    } else{
        "Louise"
    }
}

答案 1 :(得分:2)

避免内存分配有助于加速应用程序。

目前,read_one_line函数正在为每次调用执行一次内存分配,如果您将String作为&mut参数提供,则可以避免这种情况:

fn read_one_line(input: &mut String) -> &str {
    io::stdin().read_line(input).expect("Failed to read");
    input 
}

请注意我如何更改返回类型以返回切片(借用input):此处进一步使用不需要修改原始字符串。

另一项改进是I / O. Rust完全是关于显式性的,这意味着io::stdin()是原始I / O:每次调用read_line都会触发与内核的交互。

您可以(而且应该)使用std::io::BufReader缓冲I / O.构建一次,然后将其作为参数传递:

fn read_one_line<'a, R>(reader: &mut R, input: &'a mut String) -> &'a str
    where R: io::BufRead
{
    reader.read_line(input).expect("Failed to read");
    input
}

注意:

  • 使其更通用(R)比指定BufReader的确切类型更容易:)
  • 注释生命周期是强制性的,因为返回类型可以借用参数

完全放弃:

fn read_one_line<'a, R>(reader: &mut R, input: &'a mut String) -> &'a str
    where R: io::BufRead
{
    reader.read_line(input).expect("Failed to read");
    input
}

fn main() {
    let mut reader = io::BufReader::new(io::stdin());
    let mut input = String::new();

    let n: usize = read_one_line(&mut reader, &mut input).
        trim().parse().unwrap();

    for _i in 0..n{
        let inp: u64 = read_one_line(&mut reader, &mut input).
            trim().parse().unwrap();
        println!("{:?}", find_winner(inp)); 
    }
    return;
}

更大的胜利可能是I / O(甚至可能就足够了)。

不要忘记同时申请@ John的建议,这样你就可以在主循环中免费分配了!