Welcome to collectivesolver - Programming & Software Q&A with code examples. A website with trusted programming answers. All programs are tested and work.

Contact: aviboots(AT)netvision.net.il

Semrush - keyword research tool

Create your online store today with Shopify

Turn ChatGPT, Claude, Gemini, And CoPilot Into Your Personal Assistant, Business Coach, Content Creator, And More

AFFILIATE MARKETING Your all-in-one performance engine Manage affiliates, creators, and customer referrals in one unified platform—turning every partnership into measurable growth

Secure & Reliable Web Hosting, Free Domain, Free SSL, 1-Click WordPress Install, Expert 24/7 Support

Disclosure: My content contains affiliate links.

43,700 questions

57,014 answers

573 users

How to split a number N into M random positive parts whose sum is exactly N in Rust

1 Answer

0 votes
use std::collections::HashSet;

/*
    Split a number n into m random positive parts that sum to n.
*/

/*
    Split a number N into M random positive parts that sum to N.
 
    Algorithm (uniform integer composition):
    ----------------------------------------
    1. We want M positive integers p1, p2, ..., pM such that:
           p1 + p2 + ... + pM = N
 
    2. Generate (M - 1) random "cut points" in the range [1, N - 1].
       Example: N = 20, M = 4 → generate 3 cuts, e.g. {3, 11, 17}
       
    3. Sort the cut points.
 
    4. The parts are the differences between consecutive cuts:
         p1 = cut[0]
         p2 = cut[1] - cut[0]
         ...
         pM = N - cut[M-2]
 
    This produces a uniformly random composition of N into M parts.
*/

/*
    Important:
    -----------
    Random cut points must be UNIQUE.
    If two cut points are equal, their difference becomes 0,
    which produces an invalid part.
*/

// Generate m random positive parts summing to n
fn split_into_random_parts(n: i32, m: i32) -> Vec<i32> {
    if m <= 0 || n < m {
        panic!("Invalid n or m: require n >= m >= 1");
    }

    let mut cuts: Vec<i32> = Vec::with_capacity((m - 1) as usize);
    let mut used: HashSet<i32> = HashSet::new();   // ensures uniqueness

    // Generate UNIQUE cut points using the top-level function directly
    while cuts.len() < (m - 1) as usize {
        let c: i32 = rand::random_range(1..n); 
        if !used.contains(&c) {
            used.insert(c);
            cuts.push(c);
        }
    }

    // Sort the cut points
    cuts.sort();

    // Build the parts
    let mut parts: Vec<i32> = Vec::with_capacity(m as usize);
    let mut prev: i32 = 0;

    for c in cuts {
        parts.push(c - prev);   // guaranteed >= 1
        prev = c;
    }

    parts.push(n - prev);       // last part, also >= 1

    parts
}

fn main() {
    let n: i32 = 30;
    let m: i32 = 5;

    let parts: Vec<i32> = split_into_random_parts(n, m);

    println!("Splitting n = {} into m = {} random parts:", n, m);
    for p in parts {
        print!("{} ", p);
    }
    println!();
}



/*
run:

Splitting n = 30 into m = 5 random parts:
5 3 5 6 11

*/

 



answered Jul 19 by avibootz

Related questions

...