"Mathematical puzzles that train the program brain more" _pp.018-020 (code: Ruby)-> Rust

I thought that rewriting "Mathematical puzzles to train the programmer's brain" with Rust might be just right for preventing blurring.

Example 2 Combination with permutation (pp.018-020)

Ruby

I feel that pre2_1.rb in the book p.018 does not give the correct answer. By definition, permutation code is

r.upto(n) do |i|

It's not ... So, the code that gives the correct answer.

ex2.rb


require "test/unit"

def nPr(n, r)
    result = 1
    (n-r+1).upto(n) do |i|
        result *= i
    end
    result
end

def nCr(n,r)
    result = 1
    1.upto(r) do |i|
        result = result * (n - i + 1) / i
    end
    result
end

class NPrTest < Test::Unit::TestCase
    def test_nPr
        assert_equal 1, nPr(1,1), "1P1 should return 1."
        assert_equal 720, nPr(6,6), "6P6 should return 720."
        assert_equal 20, nPr(5,2), "5P2 should return 20."
    end

    def test_nCr
        assert_equal 1, nCr(1,1), "1C1 should return 1."
        assert_equal 1, nCr(6,6), "6C6 should return 1."
        assert_equal 10, nCr(5,2), "5C2 should return 10."
    end
end

Rust

main.rs


fn main() {
    println!("{n}P{r} = {x}", n = 5, r = 2, x = permutation(5, 2));
    println!("{n}C{r} = {x}", n = 5, r = 2, x = combination(5, 2));
}

pub fn permutation(n: i64, r: i64) -> i64 {
    let mut result = 1;
    for i in (n - r + 1)..=n {
        result *= i;
    }
    return result;
}

pub fn combination(n: i64, r: i64) -> i64 {
    let mut result = 1;
    for i in 1..=r {
        result = result * (n - i + 1) / i;
    }
    return result;
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_permutation() {
        assert_eq!(permutation(1, 1), 1);
        assert_eq!(permutation(6, 6), 720);
        assert_eq!(permutation(5, 2), 20);
    }

    #[test]
    fn test_combination() {
        assert_eq!(combination(1, 1), 1);
        assert_eq!(combination(6, 6), 1);
        assert_eq!(combination(5, 2), 10);
    }
}

Solid transplant. by the way,

result = result * (n - i + 1) / i;

And write

result *= (n - i + 1) / i;

Is it different to write? I'm glad I proceeded while writing the test.

I'm wondering, "How about using mut all the time? ", But as long as it's closed in one function, I don't think it's too much noise.

2020/09/29 postscript

I got a concise code example. Experimented as permutation2 () and combination2 ().

main.rs


fn main() {
    println!("{n}P{r} = {x}", n = 5, r = 2, x = permutation(5, 2));
    println!("{n}C{r} = {x}", n = 5, r = 2, x = combination(5, 2));
}

pub fn permutation(n: i64, r: i64) -> i64 {
    let mut result = 1;
    for i in (n - r + 1)..=n {
        result *= i;
    }
    return result;
}

pub fn combination(n: i64, r: i64) -> i64 {
    let mut result = 1;
    for i in 1..=r {
        result = result * (n - i + 1) / i;
    }
    return result;
}

pub fn permutation2(n: i64, r: i64) -> i64 {
    (n - r + 1..=n).product()
}

pub fn combination2(n: i64, r: i64) -> i64 {
    (1..=r).fold(1, |p, i| p * (n - i + 1) / i)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_permutation() {
        assert_eq!(permutation(1, 1), 1);
        assert_eq!(permutation(6, 6), 720);
        assert_eq!(permutation(5, 2), 20);
        assert_eq!(permutation(1,1), permutation2(1,1));
        assert_eq!(permutation(6,6), permutation2(6,6));
        assert_eq!(permutation(5,2), permutation2(5,2));
    }

    #[test]
    fn test_combination() {
        assert_eq!(combination(1, 1), 1);
        assert_eq!(combination(6, 6), 1);
        assert_eq!(combination(5, 2), 10);
        assert_eq!(combination(1, 1), combination2(1,1));
        assert_eq!(combination(6, 6), combination2(6,6));
        assert_eq!(combination(5, 2), combination2(5,2));
    }
}

Certainly the same result. The code is also easy to understand.

Recommended Posts

"Mathematical puzzles that train the program brain more" _pp.018-020 (code: Ruby)-> Rust
"Mathematical puzzles that train the program brain more" _Q39 (code: Ruby)-> Rust
"Mathematical puzzles that train the program brain more" _Q02 (code: Ruby)-> Rust
"Mathematical puzzles that train the program brain more" _Q17 (code: Ruby)-> Rust
"Mathematical puzzles that train the program brain more" _Q01 (code: Ruby)-> Rust
"Mathematical puzzles that train your program brain more" _Q61 (code: Ruby)-> Rust (& SQL)
"Math puzzles that train your program brain more" _Q41 (code: Ruby)-> Rust
"Math puzzles that train your program brain more" _Q18 (code: Ruby)-> Rust
"Mathematical puzzle to train the program brain more" _Q40 (code: Ruby)-> Rust unfinished
An attempt at "a math puzzle that trains the Rust brain more".
The languages that influenced Rust