Generate a 9 digit number with no more than 3 duplicate numbers

514 Views Asked by At

I'm trying to create a scratch card like system in php that displays a winner or loser based on random generate numbers.

I know i can create a random number using mt_rand or rand ranging from 0-9 but the issue i have is making sure there is no more than one duplicate of 3

9 digit number is out put with 100% no matching digits or a 9 digit number with one number appearing a maximum of 3 times like so 2948410427

the reason i am doing it this way is i have a lot of themed cards each theme has 10 small icons these icons are numbered 0-9 web the user opens my application it will randomly select a theme and then send a request to my server with this theme

the server will then generate the numbers and then these numbers will be output in json like so

{
    "Theme": "Space",
    "one": 3,
    "two": 6,
    "three": 0,
    "four": 7,
    "five": 1,
    "six": 3,
    "seven": 2,
    "eight": 9,
    "nine": 3,
    "winner": true
}

my application will then use these numbers to link to the images

1.png
2.png
3.png

and so on filling up the scratched grid.

this is the best way i can think todo it wile also allowing for random theme selection and random winners.

if anyone else can think of a better way i would be happy to hear it.

3

There are 3 best solutions below

6
On BEST ANSWER

If you shuffle and slice 3 times, slicing 3 values then you will get 9 values and only ever have at most 3 of any value:

$array = range(1, 9);
$keys  = array('one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');

shuffle($array);
$result = array_slice($array, 0, 3);
shuffle($array);
$result = array_merge($result, array_slice($array, 0, 3));
shuffle($array);
$result = array_merge($result, array_slice($array, 0, 3));

$result = array_combine($keys, $result);

I like Severin Pappadeux's answer, with the following changes:

$array = array_merge($r = range(1, 9), $r, $r);
$keys  = array('one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');
shuffle($array);
$result = array_combine($keys, array_slice($array, 0, 9));

To check for 3 of the same value, count the values and search for 3:

if($v = array_search(3, array_count_values($result))) {
    echo "You won with $v"; // :-)
} else {
    echo "Loser";           // :-(
}
2
On

Create a base with 2 x [0-9] range.
Add one random number then shuffle them all.

Slice out the first nine digits from the array and join them to create the scratch card.

This means it's random if the scratch card is a winning card and it's random what number is three of.

$base = array_merge(range(0,9), range(0,9));
$winning_number = [mt_rand(0,9)];

$all_numbers = array_merge($base, $winning_number);
shuffle($all_numbers);

$scratch_card = array_slice($all_numbers, 0,9);

echo join($scratch_card);

https://3v4l.org/NjItR

5
On

Following answer of @AbraCadaver, how about (sorry, my PHP is very rusty)

$src  = array_merge($r=range(1, 9), $r, $r); /* 123456789123456789123456789 */
$keys = array('one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');

shuffle($src);
$result = array_slice($src, 0, 9);

$result = array_combine($keys, $result);

all combinations would be allowed and equally distributed with max 3 of repeating numbers

UPDATE

Just tried on http://phptester.net version where initial array is a bit different, and outcome (after pressing test button for 50 or so times) is visible a bit different. Curios if quality of shuffle() implementation is any good...

$src = array_merge(range(1, 9), range(9, 1, -1), range(1, 9)); /* 123456789987654321123456789 */
print_r($src);
shuffle($src);
$result = array_slice($src, 0, 9);
print_r($result);