Как найти последовательность чисел php

(PHP 4, PHP 5, PHP 7, PHP 8)

rangeCreate an array containing a range of elements

Description

range(string|int|float $start, string|int|float $end, int|float $step = 1): array

Parameters

start

First value of the sequence.

end

The sequence is ended upon reaching the
end value.

step

If a step value is given, it will be used as the
increment (or decrement) between elements in the sequence. step
must not equal 0 and must not exceed the specified range. If not specified,
step will default to 1.

Return Values

Returns an array of elements from start to
end, inclusive.

Examples

Example #1 range() examples


<?php
// array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
foreach (range(0, 12) as $number) {
echo
$number;
}

echo

"n";// The step parameter
// array(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
foreach (range(0, 100, 10) as $number) {
echo
$number;
}

echo

"n";// Usage of character sequences
// array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i');
foreach (range('a', 'i') as $letter) {
echo
$letter;
}

echo

"n";// array('c', 'b', 'a');
foreach (range('c', 'a') as $letter) {
echo
$letter;
}
?>

Notes

Note:

Character sequence values are limited to a length of one. If a length greater
than one is entered, only the first character is used.

Palz

10 years ago


To create a range array like

Array
(
    [11] => 1
    [12] => 2
    [13] => 3
    [14] => 4
)

combine two range arrays using array_combine:

array_combine(range(11,14),range(1,4))


php at keith tyler dot com

9 years ago


So with the introduction of single-character ranges to the range() function, the internal function tries to be "smart", and (I am inferring from behavior here) apparently checks the type of the incoming values. If one is numeric, including numeric string, then the other is treated as numeric; if it is a non-numeric string, it is treated as zero.

But.

If you pass in a numeric string in such a way that is is forced to be recognized as type string and not type numeric, range() will function quite differently.

Compare:

<?php
echo implode("",range(9,"Q"));
// prints 9876543210echo implode("",range("9 ","Q"));  //space after the 9
// prints 9:;<=>?@ABCDEFGHIJKLMNOPQ
echo implode("",range("q","9 "));
// prints qponmlkjihgfedcba`_^][ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:987654
?>

I wouldn't call this a bug, because IMO it is even more useful than the stock usage of the function.


luca.favorido ATgmailDOT com

6 years ago


The function "range" is very useful to get an array of characters as range('C','R') does.

At work, I had to extend the function range($a,$b) to work in this special case: with two uppercase strings $a and $b, it should return all the possible strings between $a and $b.
This could be used for example to get the excel column indexes.
e.g. <?php range('A','AD') ==> array('A','B','C',...,'Z','AA','AB','AC','AD') ?>

So I wrote the function getrange($min,$max) that exactly does this.

<?phpfunction getcolumnrange($min,$max){
     
$pointer=strtoupper($min);
     
$output=array();
      while(
positionalcomparison($pointer,strtoupper($max))<=0){
        
array_push($output,$pointer);
        
$pointer++;
      }
      return
$output;
}

function

positionalcomparison($a,$b){
  
$a1=stringtointvalue($a); $b1=stringtointvalue($b);
   if(
$a1>$b1)return 1;
   else if(
$a1<$b1)return -1;
   else return
0;
}
/*
* e.g. A=1 - B=2 - Z=26 - AA=27 - CZ=104 - DA=105 - ZZ=702 - AAA=703
*/
function stringtointvalue($str){
  
$amount=0;
  
$strarra=array_reverse(str_split($str));

   for(

$i=0;$i<strlen($str);$i++){
     
$amount+=(ord($strarra[$i])-64)*pow(26,$i);
   }
   return
$amount;
}
?>


Alien426

7 years ago


The function will generate an array of integers even if your numerical parameters are enclosed in quotes.
<?php
var_dump
( range('1', '2') ); // outputs  array(2) { [0]=> int(1) [1]=> int(2) }
?>

An easy way to get an array of strings is to map strval() to the range:
<?php
var_dump
( array_map('strval', range('1', '2')) ); // outputs  array(2) { [0]=> string(1) "1" [1]=> string(1) "2" }
?>

gtisza at gmail dot com

10 years ago


You might expect range($n, $n-1) to be an empty array (as in e.g. Python) but actually PHP will assume a step of -1 if start is larger than end.

ccb_bc at hotmail dot com

3 years ago


<?php
   
function natural_prime_numbers(array $range, bool $print_info = false) : array {
       
$start_time = time();
       
$primes_numbers = array();
       
$print = '';
       
$count_range  = count($range);
        foreach(
$range as $number){
           
$values_division_number = array();
            if(
$number === 0 || $number === 1 || !is_int($number)){ // eliminate 0, 1 and other no integer
               
continue;
            }
            if(
$number != 2 && $number%2 === 0){ // eliminate 2 and pairs numbers
               
continue;
            }
            for(
$i = 1; $i <= $number; $i++){
               
$resultado_divisao = $number / $i;
               
$values_division_number[$i] = $resultado_divisao;

                if(

$count_range <= 20){ // $count_range <= 20 (+ performance)
                   
$print .= PHP_EOL;
                   
$info = 'The number '.$number.' divided by the number '.$i.' is equal to: '.($number / $i);
                   
$print .= $info;
                    if(
$i === $number){
                       
$print .= PHP_EOL;
                    }
                }                   
array_walk($values_division_number, function($value, $index) use (&$values_division_number, &$number){ // reference change values
                    // eliminate floats and others numbers not are equal 1 and own number
                   
if(is_float($value) && $value != $number && $value > 1){
                        unset(
$values_division_number[$index]);
                    }
                });
$values_division_number = array_values($values_division_number); // reindex array

                // here we want only array with 2 indexes with the values 1 and own number (rule to a natural prime number)

if(count($values_division_number) === 2 && $values_division_number[0] === $number && $values_division_number[1] === 1){
                   
$primes_numbers[$number] = $number;
                }

            }
        }
        return array(

'length_prime_numbers' => count($primes_numbers),
           
'prime_numbers' => array_values($primes_numbers),
           
'print' => $print,
           
'total_time_processing' => (time() - $start_time).' seconds.',
        );
    }
   
var_dump(natural_prime_numbers(range(0, 11))); // here the range() function ;-)

    // Result:
    // array (size=3)
    //   'length_prime_numbers' => int 5
    //   'prime_numbers' =>
    //     array (size=5)
    //       0 => int 2
    //       1 => int 3
    //       2 => int 5
    //       3 => int 7
    //       4 => int 11
    //   'print' => string '
    // O número 2 dividido pelo número 1 é igual a: 2
    // O número 2 dividido pelo número 2 é igual a: 1

    // O número 3 dividido pelo número 1 é igual a: 3
    // O número 3 dividido pelo número 2 é igual a: 1.5
    // O número 3 dividido pelo número 3 é igual a: 1

    // O número 5 dividido pelo número 1 é igual a: 5
    // O número 5 dividido pelo número 2 é igual a: 2.5
    // O número 5 dividido pelo número 3 é igual a: 1.6666666666667
    // O número 5 dividido pelo número 4 é igual a: 1.25
    // O número 5 dividido pelo '...

    // **************************** //
    //
    // * Remember that the function is recursive, that is: a range of 5000 takes more than 1 minute on a processor Intel® Core™ i5-8250U (3.40 GHz).
    //
    // **************************** //

?>

chris at laflash dot org

16 years ago


Quick HTML menus with minimum and maximum sets of years:

<?php
   
/*
    ** Quick HTML menus with minimum and maximum sets of years.
    ** @author Chris Charlton <chris@laflash.org>
    ** @license FREE!
    */

    // Years range setup

$year_built_min = 1900;
   
$year_built_max = date("Y");
?>
<select id="yearBuiltMin" size="1">
    <?php // Generate minimum years foreach (range($year_built_min, $year_built_max) as $year) { ?>
        <option value="<?php echo($year); ?>"><?php echo($year); ?></option>
        <?php } ?>
</select>

<select id="yearBuiltMax" size="1">
      <?php // Generate max years foreach (range($year_built_max, $year_built_min) as $year) { ?>
        <option value="<?php echo($year); ?>"><?php echo($year); ?></option>
        <?php } ?>
</select>


ThinkMedical at Gmail dot com

14 years ago


foreach(range()) whilst efficiant in other languages, such as python, it is not (compared to a for) in php*.

php is a C-inspired language and thus for is entirely in-keeping with the lanuage aethetic to use it

<?php
//efficiant
for($i = $start; $i < $end; $i+=$step)
{
       
//do something with array
}//inefficiant
foreach(range($start, $end, $step) as $i)
{
       
//do something with array
}
?>

That the officiant documentation doesnt mention the for loop is strange.

Note however, that in PHP5 foreach is faster than for when iterating without incrementing a variable.

* My tests using microtime and 100 000 iterations consistently (~10 times) show that for is 4x faster than foreach(range()).


moficer at host dot sk

7 years ago


php 5.6.16

<?php
var_export
(range('Z', 'a'));/*
array (
  0 => 'Z',
  1 => '[',
  2 => '\',
  3 => ']',
  4 => '^',
  5 => '_',
  6 => '`',
  7 => 'a',
)
*/


ktamas77 at gmail dot com

10 years ago


if you need zero padding, string prefixes or any other masks, then a simple combination of array_map, inline functions and sprintf is your friend.

<?php

$a

= array_map(function($n) { return sprintf('sample_%03d', $n); }, range(50, 59) );print_r($a);?>

Will result:

Array
(
    [0] => sample_050
    [1] => sample_051
    [2] => sample_052
    [3] => sample_053
    [4] => sample_054
    [5] => sample_055
    [6] => sample_056
    [7] => sample_057
    [8] => sample_058
    [9] => sample_059
)


jazzduck AT gmail DOT com

9 years ago


Despite the line above that says that the $step value should be "given as a positive number," the range() function will in fact correctly handle reversed (decrementing) ranges. For example:

<?php print_r( range( 24, 20 ) ); ?>
Array
(
    [0] => 24
    [1] => 23
    [2] => 22
    [3] => 21
    [4] => 20
)

<?php print_r( range( 20, 11, -3 ) ); ?>
Array
(
    [0] => 20
    [1] => 17
    [2] => 14
    [3] => 11
)

It will actually ignore the sign of the $step argument, and determine whether to increment or decrement based purely on whether $start > $end or $end > $start. For example:

<?php print_r( range( 20, 11, 3 ) ); ?>
Array
(
    [0] => 20
    [1] => 17
    [2] => 14
    [3] => 11
)

<?php print_r( range( 11, 20, -3 ) ); ?>
Array
(
    [0] => 11
    [1] => 14
    [2] => 17
    [3] => 20
)


m0sh3 at hotmail dot com

16 years ago


Here's how i use it to check if array is associative or not:

<?phpif (array_keys($arr)===range(0, sizeof($arr)-1)) {
// not associative array} else {
// associative array }?>


Ray.Paseur often uses Gmail

9 years ago


Interestingly, these two statements produce identical 26-character alphabet arrays.

<?php
$arr
= range('A''Z');
$arr = range('AA', 'ZZ');


dries at volta dot be

11 years ago


Ever wanted to generate an array with a range of column names for use in Excel file related parsing?
I've wrote a function that starts at the A column and adds column names up until the column you specified.

<?php/**
* This function creates an array with column names up until the column
* you specified.
*/
function createColumnsArray($end_column, $first_letters = '')
{
 
$columns = array();
 
$length = strlen($end_column);
 
$letters = range('A', 'Z');// Iterate over 26 letters.
 
foreach ($letters as $letter) {
     
// Paste the $first_letters before the next.
     
$column = $first_letters . $letter;// Add the column to the final array.
     
$columns[] = $column;// If it was the end column that was added, return the columns.
     
if ($column == $end_column)
          return
$columns;
  }
// Add the column children.
 
foreach ($columns as $column) {
     
// Don't itterate if the $end_column was already set in a previous itteration.
      // Stop iterating if you've reached the maximum character length.
     
if (!in_array($end_column, $columns) && strlen($column) < $length) {
         
$new_columns = createColumnsArray($end_column, $column);
         
// Merge the new columns which were created with the final columns array.
         
$columns = array_merge($columns, $new_columns);
      }
  }

  return

$columns;
}
?>

Usage:

<?php// Return an array with all column names from A until and with BI.
createColumnsArray('BI');?>


me at phpscott dot com

11 years ago


So, I needed a quick and dirty way to create a dropdown select for hours, minutes and seconds using 2 digit formatting, and to create those arrays of data, I combined range with array merge..

<?php

$prepend
= array('00','01','02','03','04','05','06','07','08','09');

$hours     = array_merge($prepend,range(10, 23));

$minutes     = array_merge($prepend,range(10, 59));

$seconds     = $minutes;

?>



Super simple.


captvanhalen at gmail dot com

15 years ago


Here is a home rolled range() function that uses the step feature for those unfortunate souls who cannot use PHP5:

<?php
function my_range( $start, $end, $step = 1) {$range = array();

    foreach (

range( $start, $end ) as $index) {

        if (! ((

$index - $start) % $step) ) {
           
$range[] = $index;
        }
    }

    return

$range;
}
?>


jay at NOspam dot myd3 dot com

14 years ago


This is a modified version of thomas' range_string() function. It's simpler, cleaner, and more robust, but it lacks the advanced features his function had, hopefully it will be of assitance to someone.

Examples:

    input: "1, 2, 3, 4, 5, 6" --> output: 1, 2, 3, 4, 5, 6
    input: "1-6" --> output: 1, 2, 3, 4, 5, 6
    input: "1-6" --> output: 1, 2, 3, 4, 5, 6
    input: "1 - -6" --> output: 1, 2, 3, 4, 5, 6
    input: "0 - 0" --> output: 0
    input: "1, 4-6, 2" --> output: 1, 2, 4, 5, 6
    input: "6,3-1" --> output: 1, 2, 3, 6

<?php

define

('RANGE_ARRAY_SORT', 1);
define('RANGE_ARRAY', 2);
define('RANGE_STRING_SORT', 3);
define('RANGE_STRING', 4);

function

range_string($range_str, $output_type = RANGE_ARRAY_SORT)
{
   
// Remove spaces and nother non-essential characters
   
$find[]    = "/[^d,-]/";
   
$replace[] = "";// Remove duplicate hyphens
   
$find[]    = "/-+/";
   
$replace[] = "-";// Remove duplicate commas
   
$find[]    = "/,+/";
   
$replace[] = ",";$range_str = preg_replace($find, $replace, $range_str);// Remove any commas or hypens from the end of the string
   
$range_str = trim($range_str,",-");$range_out = array();
   
$ranges    = explode(",", $range_str);

        foreach(

$ranges as $range)
    {

                if(

is_numeric($range) || strlen($range) == 1)
        {
           
// Just a number; add it to the list.
           
$range_out[] = (int) $range;
        }
        else if(
is_string($range))
        {
// Is probably a range of values.
          
$range_exp = preg_split("/(D)/",$range,-1,PREG_SPLIT_DELIM_CAPTURE);$start = $range_exp[0];
           
$end   = $range_exp[2];

                    if(

$start > $end)
            {
                for(
$i = $start; $i >= $end; $i -= 1)
                {
                   
$range_out[] = (int) $i;
                }
            }
            else
            {
                for(
$i = $start; $i <= $end; $i += 1)
                {
                   
$range_out[] = (int) $i;
                }
            }

                    }
    }

        switch (

$output_type) {
        case
RANGE_ARRAY_SORT:
           
$range_out = array_unique($range_out);
           
sort($range_out);

                    case

RANGE_ARRAY:
            return
$range_out;
            break;

                    case

RANGE_STRING_SORT:
           
$range_out = array_unique($range_out);
           
sort($range_out);

                    case

RANGE_STRING:

                default:
            return

implode(", ", $range_out);
            break;
    }
}
// Sample Usage:
$range = range_string("6, 3-1");?>


qz

7 years ago


If you're looking to fill an array to get a hash with 0-9 numerical values, using
range(0,9);
is a faster solution compared to
array_fill(0, 10, '');

krdr dot mft at gmail dot com

9 years ago


I've been introduced with range() function not so long ago, and I found that examples about it is somewhat wrong, even inefficient:

<?php
$o
= "";
$time_start = microtime(true);
foreach(
range(1, 10000) as $val) {
   
$o .= $val;
}
$time_end = microtime(true);
$time = $time_end - $time_start;
echo
'rangein: '.$time.'<br />'; $o = "";
$time_start = microtime(true);
$a = range(1, 10000);
foreach(
$a as $val) {
   
$o .= $val
}
$time_end = microtime(true);
$time = $time_end - $time_start;
echo
'rangeout: '.$time.'<br />'; ?>

Which gives results:

rangein: 0.0025348663330078
rangeout: 0.0019199848175049

In some cases difference is even bigger and proportional to the range generated. I suppose that results of range() are cached/hashed.

Note: execution order does affects execution times, but difference still exists


manuel at levante dot de

16 years ago


<?php
function srange ($s) {
 
preg_match_all("/([0-9]{1,2})-?([0-9]{0,2}) ?,?;?/", $s, $a);
 
$n = array ();
  foreach (
$a[1] as $k => $v) {
   
$n  = array_merge ($n, range ($v, (empty($a[2][$k])?$v:$a[2][$k])));
  }
  return (
$n);
}
$s = '1-4 6-7 9-10';
print_r(srange($s));
?>

Return:
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    [4] => 6
    [5] => 7
    [6] => 9
    [7] => 10
)

mohammed dot hussein dot mahmoud at gmail dot com

1 year ago


You could use negative numbers in place of the `step` parameter. You need to make sure that the `start` is bigger than `end`. Note that range() function in php generates the range inclusive, i.e. it also includes the `end` parameter and not just up to it but not including it like most other languages.
The following snippet of code should explain what I mean about negative steps:

<?php// 100, 90, 80, 70, 60, 50, 40, 30, 20, 10, 0
print_r(range(100, 0, -10));?>

What happens basically is that the range function does not really care about what is bigger or smaller, it just adds the step to the start and appends that to the a temp result variable as long as it did not reach the end param value. In this case, adding negative numbers is like minus (computers do that for 2's complement under the hood.) This will cause the number to go from 100 to 90 and then the function will check if 90 reached 0 yet. Since it wouldn't have done that, it will keep adding -step (-10 in that case) to the latest result (i.e. 90) and so on and so forth.

Since range() is said to be better and faster than array_fill() I believe it was important for me to try it out and actually post this note on the official documentation just to make sure people can use this.


lsblsb at gmx dot de

9 years ago


I needed a function, that creates a letter range with arbitrary length.
You specify via the $length parameter, how many entries you need.
Logic is analog to the logic of the column-titles in a calc-sheet.

<?php/**
  * create a letter range with arbitrary length
  * @param int $length
  * @return array
  */
function createLetterRange($length)
{
   
$range = array();
   
$letters = range('A', 'Z');
    for(
$i=0; $i<$length; $i++)
    {
       
$position = $i*26;
        foreach(
$letters as $ii => $letter)
        {
           
$position++;
            if(
$position <= $length)
               
$range[] = ($position > 26 ? $range[$i-1] : '').$letter;
        }
    }
    return
$range;
}
?>


pyetrosafe at gmail dot com

9 years ago


To create a simple array or a multidimensional array with defined size and null values​​, use this expression:

<?php

$SimpleArray

= array_map(function($n) { return null; }, range(1, 3) );
$MultiArray = array_map(function($n) { return array_map(function($n) { return null; }, range(1, 2) ); }, range(1, 3) );var_dump($SimpleArray);
var_dump($MultiArray);// And will print:
?>
>>$SimpleArray
array(3) {
  [0]=>  NULL
  [1]=>  NULL
  [2]=>  NULL
}

>>$MultiArray
array(3) {
  [0]=>  array(2) {
    [0]=>    NULL
    [1]=>    NULL
  }
  [1]=>  array(2) {
    [0]=>    NULL
    [1]=>    NULL
  }
  [2]=>  array(2) {
    [0]=>    NULL
    [1]=>    NULL
  }
}

?>


derek at php dot net

18 years ago


This should emulate range() a little better.

<?php

function range_wroar($low, $high, $step = 1) {

   
$arr = array();

   
$step = (abs($step)>0)?abs($step):1;

   
$sign = ($low<=$high)?1:-1;

    if(
is_numeric($low) && is_numeric($high)) {

       
//numeric sequence

       
for ($i = (float)$low; $i*$sign <= $high*$sign; $i += $step*$sign)

           
$arr[] = $i;

    }    else    {

       
//character sequence

       
if (is_numeric($low))

            return
$this->range($low, 0, $step);

        if (
is_numeric($high))

            return
$this->range(0, $high, $step);

       
$low = ord($low);

       
$high = ord($high);

        for (
$i = $low; $i*$sign <= $high*$sign; $i += $step*$sign) {
$arr[] = chr($i);

        }

    }

    return
$arr;

}

?>

subscription101 at hotmail dot com

17 years ago


A much simpler way of creating a range of even numbers is by starting with an even number:

<?php

    range

(2, 10, 2);?>


j dot gizmo at aon dot at

18 years ago


i figured i'd add some more functionality to the myRange() functions below.
now you can, besides giving a $step parameter,
1. count backwards
2. count with letters
3. give whatever parameter you want, there's nothing (i know of) that will cause an endless loop (try a negative $step for the previous function....)

<?php
function myRange($num1, $num2, $step=1)
{
    if (
is_numeric($num1) && is_numeric($num2))
    {
       
//we have a numeric range
       
$step = ( abs($step)>0 ? abs($step) : 1 ); //make $step positive
       
$dir = ($num1<=$num2 ? 1 : -1); //get the direction
       
for($i = (float)$num1; $i*$dir <= $num2*$dir; $i += $step*$dir)
        {
           
$temp[] = $i;
        }
    }
    else
    {
       
//we have a character range
       
$num1=ord((string)$num1); //convert to ascii value
       
$num2=ord((string)$num2);
       
$step = ( abs($step)>0 ? abs($step) : 1 ); //make $step positive
       
$dir = ($num1<=$num2 ? 1 : -1); //get direction
       
for($i = $num1; $i*$dir <= $num2*$dir; $i += $step*$dir)
        {
           
$temp[] = chr($i);
        }
    }
    return
$temp;
}
print_r(myRange( 1, 3, 0.5 )); //you can use fractional steps
print_r(myRange( "a", "k", 3 )); //or count letters
print_r(myRange( "5", "9" )); //numbers are detected even if hidden in strtings
print_r(myRange( "!", "%", 1/pi() )); //or mess around with senseless parameters?>


emory underscore smith at hotmail

17 years ago


since its not stated explicitly above, thought id point out that you arent limited to using integers.

however, be careful when doing so, as you might not get the range you expect!

to illustrate:

<?php
$am
= range(500,1600,10);
$fm = range(88.1,107.9,.2);
print_r($am);
print_r($fm);
?>

print_r($am) yields the expected result:

             Array
(
    [0] => 500
    [1] => 510
    [2] => 520
    ...
    [109] => 1590
    [110] => 1600
)

print_r($fm), however, falls a bit (1%) short:

Array
(
    [0] => 88.1
    [1] => 88.3
    [2] => 88.5
    ...
    [97] => 107.5
    [98] => 107.7
)

    so, if you want to use a non-integral step size params for numeric ranges, be sure to account for fp representation accuracy and error accumulation; a step size of something like pi or 1/10 could spell disaster for a large range. if in doubt, use integral steps and divide ... something like <?php range(88.1,108,.2) ?> might work to recover 107.9, but would not be scalable like, say <?php array_map(create_function('$x','return $x/10;'),range(881,1079,2)) ?>.

-emory


unicod3 at hotmail dot com

8 years ago


a function to get column index by letter 

function getColumnNumber($char){
    $alphabet = range('a','z');
    $alphabet2 = range('a','z');
    $newAlphabet = $alphabet;
    foreach($alphabet as $k => $r)
    {
        foreach($alphabet2 as $row){
            $newAlphabet[] = $r.$row;
        }
    }
    $key = array_search($char, $newAlphabet);
    return ($key !== false) ? $key : null;
}


Aram Kocharyan

12 years ago


Here's a function to generate ranges from strings:

<?php/*  Creates an array of integers based on a given range string of format "int - int"
    Eg. range_str('2 - 5'); */
function range_str($str) {
   
preg_match('#(\d+)\s*-\s*(\d+)#', $str, $matches);
    if (
count($matches) == 3 ) {
        return
range($matches[1], $matches[2]);
    }
    return
FALSE;
}
// Test
$array = range_str(' 2 - 4 ');
print_r($array);?>

This outputs:

Array
(
    [0] => 2
    [1] => 3
    [2] => 4
)


I’m making a Yahtzee game and I need a way to calculate a small straight (a sequence of 4 numbers in order). So valid ones would be: 1,2,3,4 | 2,3,4,5 | 3,4,5,6.

I have an array of 5 numbers and I need to figure out if one of those 3 combinations is in that array.

For those not familiar with Yahtzee, there are 5 dice (the five numbers in the array) that can be from 1-6.

asked May 12, 2009 at 2:13

roflwaffle's user avatar

roflwaffleroflwaffle

29.3k21 gold badges71 silver badges94 bronze badges

2

function isStraight($hand) {
    $straights = array(range(1, 4), range(2, 5), range(3, 6));
    foreach($straights as $solution) {
        if(array_intersect($solution, $hand) == $solution) {
            return $solution;
        }
    }
    return false;
}

$hand = array(1,5,2,4,3);

var_dump(isStraight($hand));

Not sure about the rules of the game, but that should do it.

The function is going to return the first solution it finds — in this case [1,2,3,4]. It is going to return the boolean false if it doesn’t find any straights in the hand. Hope this helps.

answered May 12, 2009 at 2:19

Paolo Bergantino's user avatar

Paolo BergantinoPaolo Bergantino

479k81 gold badges516 silver badges436 bronze badges

1

Perhaps something like this: — warning — air coding

function findSequenceLength(array $array)
{
  // Filter duplicates out - and sort the array.
  $sorted = array_unique($array, SORT_NUMERIC);

  $lastValue = null;
  $thisSeq = 0;
  $longestSeq = 0;
  foreach ($sorted as $value)
  {
    if ( ( $lastValue !== null ) && $value == $lastValue + 1)
    {
      // our value is exactly one above the last entry
      // increase the counter
      $thisSeq++;
    } else {
      // sequence ended - save the value
      $longestSeq = max($longestSeq, $thisSeq);
      $thisSeq = 1;
    }
    $lastValue = $value;
  }
  return max($longestSeq, $thisSeq);
}

$sequence = array(1,2,4,5,4,6);
echo findSequenceLength($sequence);  // should return 3 [4,5,6]

You could then test that the «sequence length» is >= 4 to test for your «small straight»

answered May 12, 2009 at 2:25

gnarf's user avatar

gnarfgnarf

105k25 gold badges127 silver badges161 bronze badges

More precisely:

  function array_match($array, $target_array) {
  $offset = 0;
  $maxoffset = sizeof($target_array) - sizeof($array);
  for($y=0;$y<$maxoffset;$y++) {
    $result = true;
    for($x=0;$x<sizeof($array);$x++) {
      if ($array[$x] != $target_array[$x+$y] ) {
         $result = false;
         continue;
      }
    }
    if ($result)
       return "true";
  }
  return "false";
}
echo array_match(array(1,2,3), array(1,2,3,4,5)); //true
echo array_match(array(1,2,3), array(4,1,2,3,5)); //true
echo array_match(array(1,2,3), array(4,2,2,1,2)); //false

answered May 12, 2009 at 2:30

cgp's user avatar

cgpcgp

41k12 gold badges101 silver badges131 bronze badges

Here’s another idea, Use a generic isStraight() method and use it to test the two array slices.

$tests = array(
            array(1,2,3,4,5),
            array(1,1,2,3,4),
            array(4,3,2,1,4),
            array(3,4,5,6,1)
        );
foreach($tests as $test) {
    print_r($test);
    echo "Straight: "; 
    var_dump(isStraight($test));
    echo "Short Straight: "; 
    var_dump(isShortStraight($test));
    echo "n";
}

function isShortStraight($hand) {
    return isStraight(array_slice($hand, 0, 4)) || 
           isStraight(array_slice($hand, 1, 4));
}

function isStraight($hand) {
    $unique = array_unique($hand);
    if (count($hand) != count($unique)) {
        /* Has Duplicates, not a straight */
        return false;
    }

    sort($unique);
    if ($unique != $hand) {
        /* Sort order changed, not a straight */
        return false;
    }
    return true;
}

answered May 12, 2009 at 12:11

Reg.ru: домены и хостинг

Крупнейший регистратор и хостинг-провайдер в России.

Более 2 миллионов доменных имен на обслуживании.

Продвижение, почта для домена, решения для бизнеса.

Более 700 тыс. клиентов по всему миру уже сделали свой выбор.

Перейти на сайт->

Бесплатный Курс «Практика HTML5 и CSS3»

Освойте бесплатно пошаговый видеокурс

по основам адаптивной верстки

на HTML5 и CSS3 с полного нуля.

Начать->

Фреймворк Bootstrap: быстрая адаптивная вёрстка

Пошаговый видеокурс по основам адаптивной верстки в фреймворке Bootstrap.

Научитесь верстать просто, быстро и качественно, используя мощный и практичный инструмент.

Верстайте на заказ и получайте деньги.

Получить в подарок->

Бесплатный курс «Сайт на WordPress»

Хотите освоить CMS WordPress?

Получите уроки по дизайну и верстке сайта на WordPress.

Научитесь работать с темами и нарезать макет.

Бесплатный видеокурс по рисованию дизайна сайта, его верстке и установке на CMS WordPress!

Получить в подарок->

*Наведите курсор мыши для приостановки прокрутки.

Работа с последовательностями целых чисел

В этой заметке разберемся с тем, как управляться с последовательностями целых чисел в PHP-скриптах.

Первичная задача состоит в следующем: нам нужно выполнить некий фрагмент кода для каждого целого числа из некоего диапазона.

Начнем мы с простейшего цикла for и завершим чем-то гораздо более интересным и функциональным.

Итак, как наша задача решается с помощью цикла for?

$start = 3;
$end = 7;

for ($i = $start; $i <= $end; $i++)
{
    printf("%d в квадрате равно %d<br>", $i, $i * $i);
}

Понятно, что в качестве приращения можно использовать не только 1, например:

$start = 3;
$end = 7;

for ($i = $start; $i <= $end; $i += 2)
{
    printf("%d в квадрате равно %d<br>", $i, $i * $i);
}

Используя конструкцию «+= 2» мы говорим интерпретатору о том, что к текущему числу нужно прибавить значение 2.

В случае, если нам нужно сохранить числа для использования, помимо перебора нужно использовать метод range():

$numbers = range(3, 7);

foreach ($numbers as $n)
{
    printf("%d в квадрате равно %d<br>", $n, $n * $n);
}

foreach ($numbers as $n)
{
    printf("%d в кубе равно %d<br>", $n, $n * $n * $n);
}

Подобного плана циклы очень часто используются при создании программ и веб-приложений.

Практически в любых ситуациях, где мы имеем дело с массивами данных или некими последовательностями, мы столкнемся и с разного рода циклами.

В частности, цикл for использует один целочисленный счетчик, а произвольный выбор приращения (как в сторону увеличения, так и в сторону уменьшения), позволяет лучше контролировать ход выполнения цикла. Более того, значение счетчика можно изменять и внутри цикла.

В последнем примере функция range() возвращает массив значений от $start до $end. Преимуществом range() является лаконичность, однако не обошлось и без недостатков — большой массив может занимать много лишней памяти (а ведь память, как мы знаем, лишней не бывает:)).

Если вам нужно, чтобы range() использовала нестандартные приращения, нужно передать ей третий аргумент, которой и определит величину шага.

Например, вызов range(1,10,2) возвратит массив с элементами 1, 3, 5, 7, 9.

Обратите внимание, что значение $start, т.е. первый аргумент может быть больше значения $end (второго аргумента). В этом случае происходит вполне логичная вещь: числа, возвращаемые функцией range(), упорядочиваются по убыванию.

Еще одно из применений функции range — генерация символьных последовательностей.

Если мы пропишем такой код:

print_r(range('l', 'p'));

то на выходе получим массив:

Array
(
    [0] => l
    [1] => m
    [2] => n
    [3] => o
    [4] => p
)

При этом нужно учесть, что символьные последовательности, сгенерированные функцией range(),состоят из байтов ASCII, поэтому с многобайтовыми символами Юникода функция работать не будет.

Следующим момент. Начиная с PHP 5.5 для работы с сериями можно использовать так называемые генераторы. Это функции, которые вместо вызова return для возвращения значения вызывают yield (возможно, в цикле).

Вызов такой функции-генератора может быть применен всюду, где может использоваться массив, и вы работаете с сериями значений, передаваемых ключевому слову yield. В примере ниже мы используем генератор для построения списка квадратов:

function squares($start, $stop)
{
    if ($start < $stop)
    {
        for ($i = $start; $i <= $stop; $i++)
        {
            yield $i => $i * $i;
        }
    }

    else
    {
        for ($i = $stop; $i >= $start; $i--)
        {
            yield $i => $i * $i;
        }
    }
}

foreach (squares(3, 15) as $n => $square)
{
    printf("%d в квадрате равно %d<br>", $n, $square);
}

Смысл в том, что PHP продолжает вызывать функцию squares() до тех пор, пока та вызывает yield. Ключ и значение, передаваемое yield, могут использоваться в цикле foreach, как обычный элемент массива.

Генераторы удобны прежде всего тем, что в них можно реализовать произвольное поведение для создания каждого значения (то, что запрограммировано в вашей функции), но значения генерируются по требованию.

Кроме того, нам не нужно резервировать память для предварительного создания всего массива, как в случае с range(), прежде чем начать работать с ним.

Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!

Смотрите также:

PHP: Получение информации об объекте или классе, методах, свойствах и наследовании

PHP: Получение информации об объекте или классе, методах, свойствах и наследовании

CodeIgniter: жив или мертв?

CodeIgniter: жив или мертв?

Функции обратного вызова, анонимные функции и механизм замыканий

Функции обратного вызова, анонимные функции и механизм замыканий

Применение функции к каждому элементу массива

Применение функции к каждому элементу массива

Слияние массивов. Преобразование массива в строку

Слияние массивов. Преобразование массива в строку

Деструктор и копирование объектов с помощью метода __clone()

Деструктор и копирование объектов с помощью метода __clone()

Эволюция веб-разработчика или Почему фреймворк - это хорошо?

Эволюция веб-разработчика или Почему фреймворк — это хорошо?

Магические методы в PHP или методы-перехватчики (сеттеры, геттеры и др.)

Магические методы в PHP или методы-перехватчики (сеттеры, геттеры и др.)

PHP: Удаление элементов массива

PHP: Удаление элементов массива

Ключевое слово final (завершенные классы и методы в PHP)

Ключевое слово final (завершенные классы и методы в PHP)

50 классных сервисов, программ и сайтов для веб-разработчиков

50 классных сервисов, программ и сайтов для веб-разработчиков

Наверх

Привет,недавно начал изучать PHP,не совсем пойму как реализовать задачу:Напишите код на php, который найдет самую длинную возрастающую последовательность в массиве целых чисел из 100 элементов.Я понимаю что нужно написать цикл for и пройтись по всем элементам массива,но как выявить самую длинную возрастающую последовательность не пойму


  • Вопрос задан

    более года назад

  • 142 просмотра

У меня есть код, который находит 3 последовательных числа из массива и выводит их.

То, что я хотел бы сделать сейчас, это сказать, сколько чисел найти. Я думал о том, чтобы поместить цикл for внутрь цикла for, но я не вижу, чтобы он работал должным образом.

Как я могу заставить эту итерацию запускаться X раз, пока X не встретится?

 if(isset($arr[$i+1]))
if($arr[$i]+1==$arr[$i+1])
echo 'I found it:',$arr[$i],'|',$arr[$i+1],'|',$arr[$i+2],'|',$arr[$i+3],'<br>';
exit;

Это то, что я имею до сих пор

for($i=0; $i < sizeof($arr); $i++) {
if(isset($arr[$i+1]))
if($arr[$i]+1==$arr[$i+1])
{

if(isset($arr[$i+2]))
if($arr[$i]+2==$arr[$i+2])
{

if(isset($arr[$i+3]))
if($arr[$i]+3==$arr[$i+3])
{
echo 'I found it:',$arr[$i],'|',$arr[$i+1],'|',$arr[$i+2],'|',$arr[$i+3],'<br>';
exit;
}//if3

}//if 2

}//if 1
}

2

Решение

Вместо того, чтобы смотреть несколько раз вперед, вы можете просто пройтись по массиву, сравнивая текущее значение с предыдущим значением, чтобы увидеть, являются ли значения последовательными, при этом отслеживая текущий последовательный счет. Последовательные числа должны быть добавлены в массив, а непоследовательные числа должны повторно инициализировать массив. Когда вы достигнете желаемого количества последовательных чисел, вы можете вернуть результат.

function find_consecutive($array, $count) {
$consecutive = array();
$previous = null;
foreach ($array as $value) {
if ($previous !== null && $value == $previous + 1) {
$consecutive[] = $value;
if ($found == $count) {
return "I found it: " . implode("|", $consecutive) . "<br>";
}
} else {
$consecutive = array($value);
$found = 1;
}
$previous = $value;
$found++;
}
}

1

Другие решения

Других решений пока нет …

Понравилась статья? Поделить с друзьями:
  • Как исправить овраг
  • Как найти скорость через время расстояние
  • Как найти окончание глаголов правило
  • Система не обнаружила vcomp110 dll windows 10 как исправить
  • Как найти закрывшийся магазин