Ad

Added a small benchmark, the output can be shown with "cargo test -- --nocapture" locally.

Code
Diff
  • pub fn sort_desc(mut n: u64) -> u64 {
        let mut digit_counts = [0; 10];
        while n > 0 {
            let digit = (n % 10) as usize;
            digit_counts[digit] += 1;
            n /= 10;
        }
        let mut result = 0;
        let mut fac = 1;
        for digit in 0..10 {
            for _ in 0..digit_counts[digit] {
                result += (digit as u64) * fac;
                fac *= 10;
            }
        }
        result
    }
    use std::iter::repeat;
    
    pub fn sort_desc_it(mut n: u64) -> u64 {
        let mut digit_counts = [0; 10];
        while n > 0 {
            digit_counts[n as usize % 10] += 1;
            n /= 10;
        }
        digit_counts
            .into_iter()
            .enumerate()
            .rev()
            .flat_map(|(digit, count)| repeat(digit as u64).take(count))
            .fold(0, |result, digit| result * 10 + digit)
    }
    use std::time::Instant;
    
    fn benchmark<F>(func: F, input: u64, iterations: u32) -> (u64, f64)
    where
        F: Fn(u64) -> u64,
    {
        let mut total_duration = 0.0;
        let mut result = 0;
        for _ in 0..iterations {
            let start = Instant::now();
            result = func(input);
            let duration = start.elapsed();
            total_duration += duration.as_secs_f64();
        }
        let avg_duration = total_duration / iterations as f64;
        (result, avg_duration)
    }
    
    • pub fn sort_desc(mut n: u64) -> u64 {
    • let mut digit_counts = [0; 10];
    • while n > 0 {
    • let digit = (n % 10) as usize;
    • digit_counts[digit] += 1;
    • n /= 10;
    • }
    • let mut result = 0;
    • let mut fac = 1;
    • for digit in 0..10 {
    • for _ in 0..digit_counts[digit] {
    • result += (digit as u64) * fac;
    • fac *= 10;
    • }
    • }
    • result
    • }
    • use std::iter::repeat;
    • pub fn sort_desc(mut n: u64) -> u64 {
    • pub fn sort_desc_it(mut n: u64) -> u64 {
    • let mut digit_counts = [0; 10];
    • while n > 0 {
    • digit_counts[n as usize % 10] += 1;
    • n /= 10;
    • }
    • digit_counts
    • .into_iter()
    • .enumerate()
    • .rev()
    • .flat_map(|(digit, count)| repeat(digit as u64).take(count))
    • .fold(0, |result, digit| result * 10 + digit)
    • }
    • }
    • use std::time::Instant;
    • fn benchmark<F>(func: F, input: u64, iterations: u32) -> (u64, f64)
    • where
    • F: Fn(u64) -> u64,
    • {
    • let mut total_duration = 0.0;
    • let mut result = 0;
    • for _ in 0..iterations {
    • let start = Instant::now();
    • result = func(input);
    • let duration = start.elapsed();
    • total_duration += duration.as_secs_f64();
    • }
    • let avg_duration = total_duration / iterations as f64;
    • (result, avg_duration)
    • }

This doesn't allocate and doesn't use crates, it works by counting digits using an array.
It's faster.

Code
Diff
  • pub fn sort_desc(mut n: u64) -> u64 {
        let mut digit_counts = [0; 10];
        while n > 0 {
            let digit = (n % 10) as usize;
            digit_counts[digit] += 1;
            n /= 10;
        }
        let mut result = 0;
        let mut fac = 1;
        for digit in 0..10 {
            for _ in 0..digit_counts[digit] {
                result += (digit as u64) * fac;
                fac *= 10;
            }
        }
        result
    }
    • use itertools::Itertools;
    • fn sort_desc(number: u64) -> u64 {
    • number.to_string().chars().sorted().rev().collect::<String>().parse().unwrap()
    • pub fn sort_desc(mut n: u64) -> u64 {
    • let mut digit_counts = [0; 10];
    • while n > 0 {
    • let digit = (n % 10) as usize;
    • digit_counts[digit] += 1;
    • n /= 10;
    • }
    • let mut result = 0;
    • let mut fac = 1;
    • for digit in 0..10 {
    • for _ in 0..digit_counts[digit] {
    • result += (digit as u64) * fac;
    • fac *= 10;
    • }
    • }
    • result
    • }