DEV Community

Discussion on: Challenge: find 'Kaprekar numbers'

Collapse
 
yondrin profile image
Alex Doroshenko

Seems I'm pretty late for this, but anyway, here's some Rust solution:

fn main() {
    (1usize..)
        .into_iter()
        .filter(is_kaprekar)
        .take(8)
        .for_each(|num| println!("{}", num));
}

fn is_kaprekar(n: &usize) -> bool {
    split_num(n * n).iter().sum::<usize>() == *n
}

fn split_num(num: usize) -> [usize; 2] {
    let num_str = num.to_string();
    let len = num_str.len();

    let (left, right) = num_str.split_at(len / 2);

    [as_usize(left), as_usize(right)]
}

fn as_usize(n: &str) -> usize {
    n.parse().unwrap_or(0)
}
Collapse
 
yondrin profile image
Alex Doroshenko • Edited

And if you consider that parts of a number should not necessarily be of equal size, the solution becomes a bit more wordy (suppose, a lot can be improved here):

fn main() {
    (1usize..)
        .into_iter()
        .filter(is_kaprekar)
        .take(8)
        .for_each(|num| println!("{}", num));
}

fn is_kaprekar(num: &usize) -> bool {
    NumberParts::of(num * num)
        .any(|(left, right)| {
            right > 0 && left + right == *num
        })
}

struct NumberParts {
    original_number: usize,
    split_position: usize,
}

impl NumberParts {
    fn of(original_number: usize) -> Self {
        NumberParts {
            original_number,
            split_position: 10usize.pow(
                (original_number as f64).log(10f64) as u32 + 1,
            ),
        }
    }
}

impl Iterator for NumberParts {
    type Item = (usize, usize);

    fn next(&mut self) -> Option<Self::Item> {
        let split = self.split_position;

        if split == 1 {
            None
        } else {
            self.split_position /= 10;
            Some((
                self.original_number / split,
                self.original_number % split,
            ))
        }
    }
}