0

I try to write a script and a problem. Can you let me know if you know how i can do this or ask someone if they know how can this be possibe.

  1. Max numbers which can be selected 1 to 20 numbers. it can loop and select any number between 1-20
  2. ignore these numbers e.g. 1,2,4,6,9,12 this will be array which can change.
  3. each array line can have upto 4 numbers
  4. Each array line needs to be unique 5.I need to have around 10 arrays unique
  5. Max 2 numbers can match previous numbers see below.

How can i go about doing this. Any help would be great.

e.g.


Array(
    [0] => Array
    (
        [0] => 3
        [1] => 16
        [2] => 22
        [3] => 24
    )
    [1] => Array
    (
        [0] => 3
        [1] => 16
        [2] => 7
        [3] => 13
    )
    [2] => Array
    (
        [0] => 20
        [1] => 17
        [2] => 10
        [3] => 18
    )
)


This not allow as some array match each other



Array(
    [0] => Array
    (
        [0] => 3
        [1] => 16
        [2] => 22
        [3] => 24
    )
    [1] => Array - cant have this as 3 of the numbers matchs the previous array.only two numbers can match.
    (
        [0] => 3
        [1] => 16
        [2] => 22
        [3] => 13
    )
    [2] => Array
    (
        [0] => 20
        [1] => 17
        [2] => 10
        [3] => 18
    )
)

Thank you.

4
  • I'm not understanding how it's possible to have a multi-dim array with 10 parent elements each housing up to 4 unique child elements when you only have 20 to choose from. To make this work you can only have a maximum of 2 child elements per parent element (20 total, 10 total array elements). Otherwise if you populate the first 5 parent elements with 4 child elements, you end up with 5 parent elements which are un-populated. Commented Nov 11, 2011 at 23:00
  • @Digital Precision this is completely possible, the current row only has to avoid matching more than 2 of the previous row, and by unique he just means two rows can use the same numbers as long as they are in a different order. Commented Nov 11, 2011 at 23:17
  • @dqhendricks: Interesting, I didn't get that from the OP. Commented Nov 12, 2011 at 0:28
  • Sorry i mean they need to be completely unique. any order of numbers. Commented Nov 12, 2011 at 18:24

2 Answers 2

1

This seems to satisfy your conditions: http://codepad.viper-7.com/WHkQeD

<?php
$num_arrays = 10; $num_elements = 4;
$min = 1; $max = 20;
$exclude_numbers = array( 1, 4, 6); // Add numbers here to exclude

$answer = array();
for( $i = 0; $i < $num_arrays; $i++)
{
    $answer[$i] = array();
    for( $j = 0; $j < $num_elements; $j++)
    {
        do
        {
            $current = rand( $min, $max);
            // If the previous array exists and there are more than two common elements when we add the $current element, continue
            if( isset( $answer[$i-1]) && count( array_intersect( $answer[$i-1], array_merge( $answer[$i], array( $current))) > 2)
            {
                continue;
            }
        } while( in_array( $current, $exclude_numbers) || in_array( $current, $answer[$i]));
        $answer[$i][$j] = $current;
    }
}

var_dump( $answer);

Edit: Here is a complete solution that satisfies all of your criteria.

Demo

<?php
$num_arrays = 10; $num_elements = 4;
$min = 1; $max = 20;
$exclude_numbers = array( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);

$answer = array();
for( $i = 0; $i < $num_arrays; $i++)
{
    $answer[$i] = array();
    for( $j = 0; $j < $num_elements; $j++)
    {
        do
        {
            // Get a random element
            $current = rand( $min, $max);
            $new_array = array_merge( $answer[$i], array( $current));

            // If the previous array has more than two common elements (because of the added $current), get a new $current
            if( isset( $answer[$i-1]) && count( array_intersect( $answer[$i-1], $new_array)) > 2)
            {
                $answer[$i] = array_diff( $new_array, $answer[$i-1]);
                $j = count( $answer[$i]) - 1;
                continue;
            }
        } while( in_array( $current, $exclude_numbers) || in_array( $current, $answer[$i]));

        $answer[$i][$j] = $current; 

        // If the array is complete, we need to check for unique arrays
        if( count( $answer[$i]) == $num_elements)
        {
            $k = $i - 1;
            while( $k >= 0)
            {
                if( count( array_diff( $answer[$k],  $answer[$i])) == 0)
                {
                    // This array is the same as a previous one, start over
                    $answer[$i] = array();
                    $j = -1;
                    break;
                }
                $k--;
            }
            // Optionally sort each array
            sort( $answer[$i]);
        }
    }
}

var_dump( $answer);
Sign up to request clarification or add additional context in comments.

4 Comments

The only thing it doesn't satisfy is ensuring that each array is unique (OP's #4), but can be added in the do() loop.
This is closest i have but still its not creating unique numbers of array and its not ignore the numbers i wont it to do.. i have set the value which then script repeated same numbers again and again. i try to see if i can chnage.
@SameasBefore - I've updated my answer with a solution that satisfies all of your criteria. Once you verify that it is working, please mark my answer as accepted. Thanks.
Some numbers are coming in as 2 per array rather then 4 if i bring it down and also if i say that only one number can macth previous array still i can see more then one..
0

somthing like:

function generate_list($max, $forbidden)
{
    $list = array();
    while(count($list) < 4)
    {
        $new = rand(1, $max);
        if(in_array($new, $forbidden))
        {
            continue;
        }

        $list[] = $new;
        $forbidden[] = $new;
    }

    return $list;
}

function count_max_same($new_list, $old_lists)
{
    $max_same = 0;
    foreach($old_lists as $current_list)
    {
        $max_same = max($max_same, count(array_intersect($new_list, $old_lists)));
    }
    return $max_same;
}

function generate_unique_lists($count_of_lists, $max, $forbidden, $max_same = 2, $max_tries = 1000)
{
    $lists = array();

    while($max_tries-- AND count($lists) < $count_of_lists)
    {
        $new_list = generate_list($max, $forbidden);
        if(count_max_same($new_list, $lists) <= $max_same)
        {
            $lists[] = $new_list;
        }
    }

    return $lists;
}

1 Comment

i was try to see what will be the result if i use the same script but they was no output in my browser.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.