Happy Number

  • Given an integer determine if it is a happy number
    • happy : when repeatedly summing the squares of its digits and summing eventually lead to 1
    • unhappy : never reach 1 (the process gets stuck in a loop)
  • Examples: 23 is happy, 116 is unhappy

The point:

  • Similar to detecting a loop BUT we don’t have the linked list (see 04_fast_slow_pointers\73_linked_list_loop.ipynb)
  • Use 2 ptrs : One fast and one slow
  • Fast move 2 numbers at a time while slow move one number at a time *fast = get_next(get_next(fast)) *slow = get_next(slow)
  • If they meet => cycle = unhappy
  • If we reach 1 => happy

Complexity :

Time Space
O(n) O(1)
  • O(n) because we traverse the list
  • O(1) in space because no growing datastructure are created

About Rust :

  • See black_box in the for loop
  • Yes I know, I should use some sort of cache in the for loop but I just wanted to make a quick test
  • YES : tested on the Rust Playground
use std::time::Instant;
use std::hint::black_box;

fn get_next_number(mut x:u32)->u32{
    let mut next_num : u32 = 0;
    while x > 0{
        let digit = x % 10;
        x /= 10;
        next_num += digit.pow(2); // add the square of the digit to the next number
    }
    next_num
}

fn happy_number(n:u32)->bool{
    let mut slow = n;
    let mut fast = n;
    loop {
        slow = get_next_number(slow);
        fast = get_next_number(get_next_number(fast));

        if fast == 1 {
            return true;
        }

        if slow == fast {
            return false;
        }
    }
}

// fn main(){     // no main() if this code runs in a Jupyter cell 
    
    println!("{}", happy_number(116)); // false
    println!("{}", happy_number(23));  // true
    
    const K_MAX: u32 = 1_000_000;
    let start = Instant::now();
    for i in 1..K_MAX+1{ // from 1 to k_Max included. Avoid 0
        // happy_number(i);
        black_box(happy_number(i)); // Prevents the optimized compiler from simply not calling the function if its result is not used
    }
    let duration = start.elapsed();
    println!("Execution time: {} ms", duration.as_millis());
    
// } // end of local scope OR end of main()       

false
true
Execution time: 79 ms

Back to top

Published on: Jun 22 2025 at 09:00 AM | Last updated: Jun 22 2025 at 09:00 AM

Copyright © 1964-2025 - 40tude