Generating random data is useful for everything from simulations and games to creating realistic test data for your applications.
This collection of 20 C# random data generation exercises covers the Random class in depth, generating random numbers within a range, random strings, shuffled collections, and weighted or seeded results for repeatable output.
Each exercise includes a Practice Problem, Purpose, Hint, and a full Solution with Explanation, so you understand how to generate randomness predictably and correctly.
Also, See: C# Exercises with 22 topic-wise sets and 620+ practice questions.
What You’ll Practice
- Fundamentals: The
Randomclass and generating numbers within a range. - Randomized Collections: Shuffling lists and picking random elements.
- Custom Generation: Random strings, passwords, and test data sets.
- Reproducibility: Using a seed for consistent, repeatable random results.
+ Table Of Contents (20 Exercises)
Table of contents
- Exercise 1: Random Ranges
- Exercise 2: Deterministic Randomness (Seeding)
- Exercise 3: Random Char Matrix
- Exercise 4: Weighted Coin Toss / True-False Bias
- Exercise 5: Random Fixed-Length Password
- Exercise 6: Cryptographically Secure Tokens
- Exercise 7: Random Pronounceable String
- Exercise 8: Random String from a Custom Alphabet
- Exercise 9: Random Date in Range
- Exercise 10: Random Coordinate Geo-Fencing
- Exercise 11: Random RGB Colors
- Exercise 12: Random TimeSpans
- Exercise 13: Synthetic User Objects
- Exercise 14: Random IP Addresses
- Exercise 15: Random Credit Card Generator
- Exercise 16: Array Shuffling (Fisher-Yates)
- Exercise 17: Random Selection with Replacement
- Exercise 18: Random Selection without Replacement
- Exercise 19: Weighted Random Selection
- Exercise 20: Weighted Random Selection
Exercise 1: Random Ranges
Practice Problem: Generate 5 random integers between 50 and 150 (inclusive) and 5 random double values between 10.0 and 50.0 using the System.Random class.
Purpose: This exercise helps you practice using Random.Next with an inclusive upper bound argument, and Random.NextDouble scaled into a custom range, since NextDouble alone only returns a value between 0.0 and 1.0.
Given Input: Integer range 50 to 150, double range 10.0 to 50.0, five values of each.
Expected Output (illustrative; the exact values will vary by run since no seed is used):
Random integers: 87 142 63 110 99 Random doubles: 24.61 41.08 15.92 38.47 29.03
▼ Hint
- Create a single instance of
Randomand reuse it for every call, rather than creating a new instance inside a loop. - Use
Next(minValue, maxValue + 1)to get an integer in an inclusive range, sinceNext‘s upper bound is exclusive by default. - Use
NextDouble()to get a fraction between 0.0 and 1.0, then scale and shift it into the desired range. - Loop five times for each type of value, printing each result as it’s generated.
▼ Solution & Explanation
Explanation:
new Random(): A single shared instance is created once and reused for every call, since creating a newRandominstance repeatedly in a tight loop can produce identical values on some systems due to the same seed being derived from the clock.random.Next(50, 151): Generates an integer from 50 up to, but not including, 151, effectively covering the inclusive range from 50 to 150.10.0 + random.NextDouble() * (50.0 - 10.0): Scales the 0.0-to-1.0 value fromNextDouble()into the desired 10.0-to-50.0 range, by multiplying by the range’s width and adding the minimum value as an offset.- Output varies by run: Since no fixed seed is provided, each execution of the program produces a different sequence of random values.
Exercise 2: Deterministic Randomness (Seeding)
Practice Problem: Initialize two instances of Random using the exact same integer seed. Generate a list of 10 numbers from both and verify that their outputs are perfectly identical.
Purpose: This exercise helps you practice using a fixed seed to make a Random instance’s output reproducible, which is useful for testing or replaying a specific sequence of “random” events.
Given Input: seed = 42
Expected Output: True
▼ Hint
- Create two separate
Randominstances, passing the exact same integer seed to each one’s constructor. - Generate a list of 10 numbers from each instance using a loop and the
Nextmethod. - Compare the two lists for equality using
SequenceEqual, since the default list equality check compares references rather than contents. - Confirm that both lists contain exactly the same numbers in exactly the same order.
▼ Solution & Explanation
Explanation:
new Random(seed): Passing the same seed value to both constructors ensures each instance starts from the exact same internal state, producing the same sequence of “random” numbers.- Two separate loops: Generate ten numbers from each instance independently, but since both started from the same seed, their sequences end up matching value for value.
listA.SequenceEqual(listB): Compares the two lists element by element, returning true only if every corresponding pair of values is equal and both lists are the same length.- Practical use: Seeding is useful for testing, since it lets a “random” scenario be reproduced exactly on demand rather than varying unpredictably between runs.
Exercise 3: Random Char Matrix
Practice Problem: Generate a random 5×5 grid (2D array) consisting entirely of uppercase characters from ‘A’ to ‘Z’.
Purpose: This exercise helps you practice combining a nested loop over a 2D array with a random character generator, converting a random integer into a letter using its position in the alphabet.
Given Input: A 5×5 grid to fill with random uppercase letters.
Expected Output (illustrative; letters will vary by run):
QJZTM XBLFK NRYCS HGVWD AEPOU
▼ Hint
- Declare a two-dimensional char array with 5 rows and 5 columns.
- Loop through both dimensions using nested
forloops, one for rows and one for columns. - Generate a random integer between 0 and 25 using
Next, then add it to the character'A'to get a random uppercase letter. - Print each row of the grid on its own line once the array has been fully populated.
▼ Solution & Explanation
Explanation:
char[5, 5] grid: Declares a two-dimensional array with 5 rows and 5 columns, capable of holding 25 individual characters.random.Next(0, 26): Generates an integer from 0 to 25, matching the 26 letters of the alphabet.(char)('A' + random.Next(0, 26)): Adds that random offset to the character'A', producing a random uppercase letter, since characters can be treated as numeric values in C#.- Nested loops for printing: The outer loop moves through each row, while the inner loop prints every character in that row before a newline is written.
Exercise 4: Weighted Coin Toss / True-False Bias
Practice Problem: Create a method GetBiasedBool(double trueProbability) that returns a bool. If the input is 0.75, it should return true roughly 75% of the time.
Purpose: This exercise helps you practice comparing a random fraction against a probability threshold to bias the outcome of a boolean result, rather than a plain 50/50 split.
Given Input: trueProbability = 0.75, called 10000 times.
Expected Output (illustrative; the exact count will vary slightly by run): approximately 7500 out of 10000 were true
▼ Hint
- Generate a random fraction between 0.0 and 1.0 using
NextDouble. - Return true if that fraction is less than the given
trueProbability, and false otherwise. - Test the method by calling it many times and counting how often it returns true.
- Compare the resulting count against the expected proportion to confirm the bias is roughly correct.
▼ Solution & Explanation
Explanation:
random.NextDouble() < trueProbability: Compares a random fraction between 0.0 and 1.0 against the given probability, so a highertrueProbabilitymakes the comparison succeed more often.- Proportional bias: Since
NextDouble()produces a roughly uniform spread of values across its range, a threshold of 0.75 causes the comparison to succeed for about 75% of all generated fractions. - Repeated testing: Calling
GetBiasedBoolmany times and counting the true results is the practical way to confirm a probability-based method behaves as expected, since any single call could go either way. - Static
Randomfield: Reusing one sharedRandominstance across all 10000 calls avoids the correlated-output problem that can occur from creating manyRandominstances in quick succession.
Exercise 5: Random Fixed-Length Password
Practice Problem: Generate a 12-character random password containing at least 2 uppercase letters, 2 lowercase letters, 2 digits, and 2 special characters.
Purpose: This exercise helps you practice guaranteeing a mix of required character categories by seeding specific characters from each category first, then filling the remainder randomly and shuffling the result.
Given Input: length = 12
Expected Output (illustrative; the exact password will vary by run, but always contains at least 2 of each required category): Xk9@fQ2!mZ7#
▼ Hint
- Define separate strings representing the uppercase, lowercase, digit, and special character sets.
- Pick exactly 2 characters from each of the four sets first, guaranteeing the minimum requirement for each category.
- Fill the remaining characters, up to the total length, by picking randomly from all four sets combined.
- Shuffle the resulting list of characters before converting it into a final string, so the guaranteed characters aren’t always in the same positions.
▼ Solution & Explanation
Explanation:
- Four separate character sets:
upper,lower,digits, andspecialeach represent one required category, kept apart so exactly 2 characters can be drawn from each. - Guaranteed minimums: The first loop adds 2 characters from every category before anything else, ensuring the final password can never fall short of the requirement no matter how the rest of the fill turns out.
while (passwordChars.Count < 12): Fills any remaining slots by drawing randomly from the combinedallstring, which includes every category.OrderBy(c => random.Next()): Shuffles the list of characters into a random order before joining them into the final string, so the guaranteed characters don’t always appear in the same fixed positions.
Exercise 6: Cryptographically Secure Tokens
Practice Problem: Use System.Security.Cryptography.RandomNumberGenerator to generate a secure, 32-byte hex string token suitable for password reset links.
Purpose: This exercise helps you practice using a cryptographically secure random number generator instead of System.Random, which matters whenever generated values need to be unpredictable for security purposes, such as a password reset link.
Given Input: Token length of 32 bytes.
Expected Output (illustrative; the exact token will vary by run): a 64-character hex string, e.g. 3f2a9b7c1e4d6f8a0b2c4d6e8f1a3b5c7d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a
▼ Hint
- Use
RandomNumberGenerator.Fillto populate a byte array with cryptographically secure random values. - Allocate a byte array of exactly 32 bytes before filling it.
- Convert the byte array into a readable string using
Convert.ToHexString. - Print the resulting string to see the final token.
▼ Solution & Explanation
Explanation:
new byte[32]: Allocates an empty array with room for exactly 32 random bytes, matching the requested token size.RandomNumberGenerator.Fill(tokenBytes): Populates the array with cryptographically secure random values, generated by the operating system’s secure random source rather than a predictable algorithm.Convert.ToHexString(tokenBytes): Converts the raw bytes into a readable hexadecimal string, doubling the character count since each byte becomes two hex characters.- Why not
System.Random:System.Randomis designed for speed and statistical distribution, not unpredictability against an attacker, so it isn’t suitable for anything security-sensitive like a password reset token.
Exercise 7: Random Pronounceable String
Practice Problem: Generate a random “pronounceable” 6-letter string by alternating between random vowels and random consonants.
Purpose: This exercise helps you practice building a string character by character using two separate random choices, alternating between two different character sets based on the current position.
Given Input: length = 6
Expected Output (illustrative; letters will vary by run): sokuve
▼ Hint
- Define two separate strings, one containing the vowels and one containing the consonants.
- Loop through each position of the desired length, checking whether the current index is even or odd.
- Pick a random character from the consonants string on one type of position and from the vowels string on the other.
- Build the final string by appending each randomly chosen character in sequence.
▼ Solution & Explanation
Explanation:
vowelsandconsonants: Two separate strings acting as the pools to randomly choose from, depending on which type of letter belongs at the current position.i % 2 == 0: Alternates between the two pools based on whether the current index is even or odd, starting with a consonant at position 0.consonants[random.Next(consonants.Length)]: Picks one random character from the consonants string, using a random index within its valid range.StringBuilder: Accumulates each chosen character efficiently before converting the whole sequence into a final string withToString().
Exercise 8: Random String from a Custom Alphabet
Practice Problem: Given a string mask like "ABC-###-XY", write a function to generate a random identifier where # is replaced by a random digit (0-9).
Purpose: This exercise helps you practice scanning a template character by character and substituting only the characters that match a specific placeholder, leaving every other character untouched.
Given Input: mask = "ABC-###-XY"
Expected Output (illustrative; digits will vary by run): ABC-482-XY
▼ Hint
- Loop through the mask string one character at a time.
- Check whether the current character is the placeholder symbol,
#. - If it is, append a randomly generated digit to the result instead of the placeholder itself.
- If it isn’t, append the original character unchanged, so the rest of the mask’s structure is preserved.
▼ Solution & Explanation
Explanation:
foreach (char c in mask): Walks through the mask one character at a time, examining each one individually.if (c == '#'): Checks whether the current character is the designated placeholder symbol.random.Next(0, 10): Generates a single random digit from 0 to 9 whenever a placeholder is encountered, appending it in place of the#.else { result.Append(c); }: Preserves every non-placeholder character exactly as it appears in the original mask, keeping the surrounding structure like “ABC-” and “-XY” intact.
Exercise 9: Random Date in Range
Practice Problem: Write a method that generates a random DateTime between January 1, 2020 and December 31, 2025. Ensure both the date and time parts are randomized.
Purpose: This exercise helps you practice converting a random fraction into a random position along a span of time, using the difference between two DateTime values measured in ticks.
Given Input: start = January 1, 2020, end = December 31, 2025
Expected Output (illustrative; the exact date and time will vary by run): 3/17/2023 8:42:19 AM
▼ Hint
- Calculate the total span between the start and end dates as a
TimeSpan. - Generate a random number of ticks somewhere within that span’s total tick count.
- Add that random number of ticks to the start date to land on a random point within the range.
- Print the resulting
DateTimeto see both its date and time portions.
▼ Solution & Explanation
Explanation:
TimeSpan span = end - start: Measures the total duration between the two boundary dates, expressed as aTimeSpanwith an underlying tick count.random.NextDouble() * span.Ticks: Scales a random fraction between 0.0 and 1.0 by the total number of ticks in the span, producing a random offset somewhere within that duration.start.AddTicks(randomTicks): Adds that random offset to the start date, landing on a random point that could fall on any day and at any time within the entire range.- Randomizing both date and time together: Since ticks represent the smallest unit of time in a
DateTime, this approach naturally randomizes the time of day along with the date, rather than only picking a random day and defaulting to midnight.
Exercise 10: Random Coordinate Geo-Fencing
Practice Problem: Given a central latitude and longitude, generate 10 random geographic coordinates that fall within a 5-kilometer radius.
Purpose: This exercise helps you practice converting a random angle and a random distance into an offset latitude and longitude, approximating a circular area around a central point.
Given Input: centerLatitude = 40.7128, centerLongitude = -74.0060, radiusKm = 5
Expected Output (illustrative; coordinates will vary by run): 10 lines of latitude/longitude pairs, each within roughly 5 kilometers of the center point, e.g. 40.7168, -74.0102
▼ Hint
- Generate a random angle between 0 and 2π (a full circle) using
NextDoublescaled by2 * Math.PI. - Generate a random distance between 0 and the maximum radius, using the square root of a random fraction to keep points evenly distributed across the circle’s area rather than clustered near the center.
- Convert the random distance and angle into a latitude offset and a longitude offset, using basic trigonometry and an approximate conversion factor for degrees per kilometer.
- Add each offset to the central latitude and longitude to produce one random coordinate, then repeat the process 10 times.
▼ Solution & Explanation
Explanation:
random.NextDouble() * 2 * Math.PI: Picks a random direction around the center point, covering the full 360 degrees of a circle expressed in radians.radiusKm * Math.Sqrt(random.NextDouble()): Picks a random distance from the center, using a square root so points are spread evenly across the circle’s entire area rather than bunching up near the middle.distance / 111.0: Converts a distance in kilometers into an approximate change in latitude degrees, since one degree of latitude is roughly 111 kilometers everywhere on Earth.- Longitude adjustment with
Math.Cos(centerLatitude * Math.PI / 180): Accounts for the fact that a degree of longitude covers less physical distance the farther a point is from the equator, since lines of longitude converge toward the poles.
Exercise 11: Random RGB Colors
Practice Problem: Generate a random (byte R, byte G, byte B) tuple representing an RGB color value, then format it into a valid hex color string (e.g., “#FF5733”).
Purpose: This exercise helps you practice generating three independent random byte values and combining them into a formatted string using a specific numeric format, in this case two-digit hexadecimal.
Given Input: None; three random byte values are generated for R, G, and B.
Expected Output (illustrative; values vary by run): #3FA9C2
▼ Hint
- Generate three separate random byte values, one each for R, G, and B, using
Nextwith a range of 0 to 255. - Store the three values together as a tuple, such as
(byte R, byte G, byte B). - Format each byte as a two-digit hexadecimal string using
ToString("X2"), which also pads a single hex digit with a leading zero. - Concatenate the three formatted values together with a leading
#to build the final hex color string.
▼ Solution & Explanation
Explanation:
random.Next(0, 256): Generates an integer from 0 to 255, matching the full valid range of a single byte.(byte)random.Next(0, 256): Casts that integer down to a byte, sinceNextitself returns an int rather than a byte directly.(byte R, byte G, byte B) color = (r, g, b): Packages the three separate byte values into a single named tuple, making them easy to pass around or return together.ToString("X2"): Formats each byte as exactly two uppercase hexadecimal digits, padding with a leading zero for values below 16 so every channel always contributes exactly two characters to the final string.
Exercise 12: Random TimeSpans
Practice Problem: Generate a random TimeSpan duration that is at least 30 minutes long but does not exceed 8 hours.
Purpose: This exercise helps you practice generating a random duration by picking a random number of minutes within a bounded range and converting that count into a TimeSpan.
Given Input: minMinutes = 30, maxMinutes = 480 (8 hours)
Expected Output (illustrative; duration varies by run): 03:47:00
▼ Hint
- Convert both boundary durations, 30 minutes and 8 hours, into a common unit such as total minutes.
- Generate a random integer number of minutes somewhere between those two boundary values, inclusive.
- Convert that random minute count into a
TimeSpanusingTimeSpan.FromMinutes. - Print the resulting
TimeSpanto see it displayed in a familiar hours-minutes-seconds format.
▼ Solution & Explanation
Explanation:
int maxMinutes = 8 * 60: Converts the 8-hour upper boundary into its equivalent number of minutes, so both boundaries are expressed in the same unit.random.Next(minMinutes, maxMinutes + 1): Generates a random integer between 30 and 480 minutes, inclusive, sinceNext‘s upper bound is normally exclusive.TimeSpan.FromMinutes(randomMinutes): Converts the random minute count into a properTimeSpanvalue, which automatically handles the conversion into hours, minutes, and seconds internally.Console.WriteLine(duration): Prints theTimeSpanusing its default format, displaying the duration as hours, minutes, and seconds.
Exercise 13: Synthetic User Objects
Practice Problem: Define a User class with Id (Guid), Username (string), Age (int), and IsActive (bool). Generate a list containing 100 entries filled with random but realistic dummy data.
Purpose: This exercise helps you practice combining several different random generation techniques, a GUID, a random name built from parts, a bounded random age, and a random boolean, into one cohesive object, then repeating that process to build a larger collection.
Given Input: count = 100
Expected Output (illustrative; values vary by run, showing the first entry only): Id: 3fa85f64-5717-4562-b3fc-2c963f66afa6, Username: user482, Age: 34, IsActive: True
▼ Hint
- Define the
Userclass with properties forId,Username,Age, andIsActivematching the required types. - Use
Guid.NewGuid()to generate a unique identifier for each user automatically. - Build a random username by combining a fixed prefix with a random number.
- Generate a random age within a reasonable adult range and a random boolean for
IsActive, then repeat the whole object-creation process in a loop to build the full list.
▼ Solution & Explanation
Explanation:
Guid.NewGuid(): Generates a statistically unique identifier for each user, without needing to track previously used values to avoid collisions."user" + random.Next(100, 1000): Builds a simple but varied username by appending a random three-digit number to a fixed prefix.random.Next(18, 66): Generates a random age within a realistic adult range, from 18 up to 65 inclusive.random.Next(0, 2) == 1: Generates a random boolean by picking either 0 or 1 and comparing it to 1, sinceRandomdoesn’t have a dedicated method for generating booleans directly.
Exercise 14: Random IP Addresses
Practice Problem: Generate a random, valid IPv4 string where each octet is randomly chosen between 0 and 255, while avoiding networking edge cases like 0.0.0.0.
Purpose: This exercise helps you practice generating four independent random octet values and joining them into a properly formatted address, while explicitly guarding against a reserved edge-case value.
Given Input: None; four random octets are generated.
Expected Output (illustrative; values vary by run): 192.168.47.203
▼ Hint
- Generate four separate random integers, each between 0 and 255, one for every octet of the address.
- Join the four octet values together into a single string, separated by literal periods.
- Check whether the very first octet came out to 0, since an address starting that way isn’t a valid usable address.
- If the first octet is 0, regenerate that value so the final result avoids the reserved case.
▼ Solution & Explanation
Explanation:
do { firstOctet = random.Next(0, 256); } while (firstOctet == 0);: Keeps regenerating the first octet specifically until it produces a value other than 0, avoiding the reserved0.0.0.0-style address.- The remaining three octets: Each generated independently using the full 0-to-255 range, since only the first octet needs the extra restriction in this exercise.
- String concatenation with periods: Joins the four octet values into the standard dotted format expected of an IPv4 address.
do-whileloop: Chosen over a plainifcheck because it guarantees the value is generated at least once and keeps retrying only when the excluded case actually occurs.
Exercise 15: Random Credit Card Generator
Practice Problem: Write a function to mock a random 16-digit credit card number string, implementing the Luhn algorithm so the generated number passes basic numerical validation checks.
Purpose: This exercise helps you practice generating a sequence of random digits and then calculating a check digit using the Luhn algorithm, so the resulting number passes the same validation formula real card numbers are checked against.
Given Input: None; 15 random digits are generated before the check digit is calculated.
Expected Output (illustrative; the digits before the final check digit vary by run, but the complete 16-digit number always passes Luhn validation): 4539148803436467
▼ Hint
- Generate the first 15 digits of the card number randomly, one digit at a time.
- Apply the Luhn algorithm to those 15 digits to calculate the correct final check digit.
- The Luhn algorithm doubles every second digit from the right, subtracting 9 from any result over 9, then sums all the digits together.
- Choose the check digit that makes the total sum a multiple of 10, and append it as the 16th and final digit.
▼ Solution & Explanation
Explanation:
for (int i = 0; i < 15; i++): Generates the first fifteen digits of the card number completely at random, one at a time.CalculateLuhnCheckDigit: Implements the Luhn algorithm, doubling every second digit counted from the right and subtracting 9 whenever that doubled value exceeds 9, then summing every digit together.10 - remainder: Determines the specific check digit needed to bring the total sum up to the next multiple of 10, which is the exact rule the Luhn algorithm’s validation check relies on.- Appending the check digit last: Completes the 16-digit number so that running the same Luhn calculation over the full number, including the new check digit, confirms it as valid.
Exercise 16: Array Shuffling (Fisher-Yates)
Practice Problem: Create a generic method void Shuffle<T>(List<T> list) that implements the Fisher-Yates algorithm to randomly reorder any collection in place.
Purpose: This exercise helps you practice implementing the Fisher-Yates algorithm, a proven method for shuffling a list in place with a genuinely uniform random distribution, unlike naive approaches that can introduce bias.
Given Input: numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Expected Output (illustrative; order varies by run): 7, 2, 9, 4, 1, 10, 3, 6, 8, 5
▼ Hint
- Write the method as generic using
<T>, so it can shuffle a list of any element type. - Loop backward through the list, starting at the last index and moving toward the first.
- At each step, pick a random index from 0 up to and including the current position.
- Swap the element at the current position with the element at that randomly chosen index.
▼ Solution & Explanation
Explanation:
static void Shuffle<T>(List<T> list): The<T>type parameter lets this single method shuffle a list of integers, strings, or any other type without rewriting it for each one.for (int i = list.Count - 1; i > 0; i--): Walks backward through the list, treating each position as the “current” slot to be finalized.random.Next(0, i + 1): Picks a random index from anywhere in the still-unshuffled portion of the list, including the current position itself.- Swapping
list[i]andlist[j]: Exchanges the two elements in place, which is what makes Fisher-Yates modify the original list directly rather than producing a new one.
Exercise 17: Random Selection with Replacement
Practice Problem: Write a program that picks 5 random elements from an array of strings (e.g., names of cities), allowing the same city to be picked multiple times.
Purpose: This exercise helps you practice selecting random elements from a collection independently, where each pick has no effect on future picks, allowing the same value to be chosen more than once.
Given Input: cities = ["Tokyo", "Paris", "Cairo", "Lima", "Oslo"]
Expected Output (illustrative; selections vary by run):
Paris Lima Paris Tokyo Oslo
▼ Hint
- Store the pool of possible values in an array.
- Loop for the number of picks you want, five in this case.
- Each time through the loop, generate a random index within the array’s valid range and select that element.
- Since each pick uses a fresh random index independent of previous picks, the same element can be selected more than once.
▼ Solution & Explanation
Explanation:
cities[random.Next(cities.Length)]: Picks one random element from the array using a freshly generated random index each time.- Independent picks: Since every loop iteration generates a brand new random index without excluding any previous selections, the same city can legitimately appear more than once in the results.
for (int i = 0; i < 5; i++): Controls the total number of picks, regardless of how many distinct values end up appearing.- No tracking needed: Unlike selection without replacement, this approach doesn’t need to remove or mark previously chosen elements, since repeats are allowed by design.
Exercise 18: Random Selection without Replacement
Practice Problem: Using LINQ, pick 3 unique, non-repeating elements from a list of 10 items.
Purpose: This exercise helps you practice selecting a random subset of distinct elements from a larger collection, ensuring no single element is picked more than once.
Given Input: A list of 10 items, "Item1" through "Item10".
Expected Output (illustrative; selections vary by run): Item7, Item2, Item9
▼ Hint
- Use
OrderBywith a random key to shuffle the entire list into a random order. - Take the first however-many elements you need from that shuffled sequence using
Take. - Since the shuffle rearranges every element without duplicating any of them, the elements taken from the front are guaranteed to be unique.
- Convert the result to a list to use it further.
▼ Solution & Explanation
Explanation:
items.OrderBy(x => random.Next()): Reorders the entire list into a random sequence by sorting according to a freshly generated random number for each element..Take(3): Grabs the first three elements from that shuffled sequence, effectively selecting three random items from the original list.- Guaranteed uniqueness: Since
OrderBysimply rearranges existing elements rather than duplicating them, no single item can appear twice in the shuffled sequence or in the final selection. .ToList(): Converts the resulting LINQ query into a concreteList<string>, so it can be printed, stored, or passed around like any other list.
Exercise 19: Weighted Random Selection
Practice Problem: Given an array of items and an array of their corresponding weights (e.g., ["Common Item", "Rare Item", "Epic Item"] with weights [80, 15, 5]), select one item at random according to those weights.
Purpose: This exercise helps you practice mapping a single random number onto a cumulative distribution of weights, so items with larger weights are proportionally more likely to be selected.
Given Input: items = ["Common Item", "Rare Item", "Epic Item"], weights = [80, 15, 5]
Expected Output (illustrative; the result varies by run, but “Common Item” should appear roughly 80% of the time across many calls): Common Item
▼ Hint
- Calculate the total sum of all the weights combined.
- Generate a single random number between 0 and that total sum.
- Loop through the items, subtracting each item’s weight from the random number until the number drops below the current item’s weight.
- Return the item at the point where the running subtraction causes the number to cross that threshold, since items with larger weights consume more of the random number’s range.
▼ Solution & Explanation
Explanation:
int totalWeight: Sums every weight in the array together, establishing the full range that the random number needs to cover.random.Next(0, totalWeight): Generates a single random number somewhere within that combined range, from 0 up to just under the total.if (randomValue < weights[i]): Checks whether the random number falls within the current item’s “slice” of the total range; if so, that item is the selected result.randomValue -= weights[i]: Shrinks the random number by the current item’s weight whenever it doesn’t fall within that item’s slice, moving on to check the next item’s slice using the same, now-reduced number.
Exercise 20: Weighted Random Selection
Practice Problem: Given an array of items and an array of their corresponding weights (e.g., ["Common Item", "Rare Item", "Epic Item"] with weights [80, 15, 5]), select one item at random according to those weights.
Purpose: This exercise helps you practice mapping a single random number onto a cumulative distribution of weights, so items with larger weights are proportionally more likely to be selected.
Given Input: items = ["Common Item", "Rare Item", "Epic Item"], weights = [80, 15, 5]
Expected Output (illustrative; the result varies by run, but “Common Item” should appear roughly 80% of the time across many calls): Common Item
▼ Hint
- Calculate the total sum of all the weights combined.
- Generate a single random number between 0 and that total sum.
- Loop through the items, subtracting each item’s weight from the random number until the number drops below the current item’s weight.
- Return the item at the point where the running subtraction causes the number to cross that threshold, since items with larger weights consume more of the random number’s range.
▼ Solution & Explanation
Explanation:
int totalWeight: Sums every weight in the array together, establishing the full range that the random number needs to cover.random.Next(0, totalWeight): Generates a single random number somewhere within that combined range, from 0 up to just under the total.if (randomValue < weights[i]): Checks whether the random number falls within the current item’s “slice” of the total range; if so, that item is the selected result.randomValue -= weights[i]: Shrinks the random number by the current item’s weight whenever it doesn’t fall within that item’s slice, moving on to check the next item’s slice using the same, now-reduced number.

Leave a Reply