SameasBefore
SameasBefore

Reputation: 299

php numbers script array loop

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.

Upvotes: 0

Views: 185

Answers (2)

nickb
nickb

Reputation: 59709

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);

Upvotes: 1

Puggan Se
Puggan Se

Reputation: 5846

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;
}

Upvotes: 0

Related Questions