I have the following code
<?php
function randomGen($min, $max, $quantity) {
$numbers = range($min, $max);
shuffle($numbers);
$tmp = array_slice($numbers, 0, $quantity);
//sort($tmp);
return $tmp;
}
echo '<pre>';
$arr = randomGen(2,7,5);
//sort($arr);}
print_r($arr);
This code generates random n numbers between the specified range.
However, it returns the output similar to the following many times
Array
(
[0] => 3
[1] => 4
[2] => 7
[3] => 5
[4] => 2
)
Here, 2 3 4 5 are consecutive numbers. I am trying to modify the above code so that it does not return more than 3 consecutive numbers. The output should be similar to this
Array
(
[0] => 2
[1] => 3
[2] => 5
[3] => 6
[4] => 7
)
As you can see, it has just 3 consecutive numbers 5 6 7.
I have tried the following
<?php
function randomGen($min, $max, $quantity) {
$numbers = range($min, $max);
shuffle($numbers);
$tmp = array_slice($numbers, 0, $quantity);
sort($tmp);
return $tmp;
}
echo '<pre>';
$arr = randomGen(2,7,5);
$count = 0;
$first = $arr[0];
$i = 1;
//for($i = 1; $i < count($arr); $i++) {
while ($i < count($arr)) {
$ele = $arr[$i];
if ($counter >=3) {
$counter = 0;
$arr = randomGen(2,7,5);
$first = $arr[0];
$i = 1;
}
else {
if ($ele - $first === 1) {
$counter++;
//continue;
}
$first = $ele;
}
$i++;
}
print_r($arr);
But it doesn't provide the expected output.
Thanks in advance for any help.
Please see if we can do something like this
function randomGen($min, $max, $quantity,$rangestep) {
$numbers = range($min, $max,$rangestep);
$tmp = array_slice($numbers, 0, $quantity);
sort($tmp);
shuffle($tmp);
return $tmp;
}
echo '<pre>';
$arr = randomGen(2,7,5,1);
$count = 0;
$first = $arr[0];
$i = 1;
//for($i = 1; $i < count($arr); $i++) {
$counter = 0;
while ($i < count($arr)) {
$ele = $arr[$i];
if ($counter >=3) {
$counter = 0;
$arr = randomGen(2,7,8,2);
$first = $arr[0];
$i = 1;
}
else {
if ($ele - $first === 1) {
$counter++;
//continue;
}
$first = $ele;
}
$i++;
}
print_r($arr);
die;
second largest absolute value form array
input : array(13, -12, 8, 2, 5)
expected answer : 12
here is my code
<?php
function print2largest($arr, $arr_size)
{
if ($arr_size < 2)
{
echo(" Invalid Input ");
return;
}
$first = $second = PHP_INT_MIN;
for ($i = 0; $i < $arr_size ; $i++)
{
if ($arr[$i] > $first)
{
$second = $first;
$first = $arr[$i];
}
else if ($arr[$i] > $second &&
$arr[$i] != $first)
$second = $arr[$i];
}
if ($second == PHP_INT_MIN)
echo("There is no second largest element\n");
else
echo("The second largest element is " . $second . "\n");
}
$arr = array(13, -12, 8, 2, 5);
$n = sizeof($arr);
print2largest($arr, $n);
?>
output i got : 8
It can be easy done in "php-way":
$arr = array(13, -12, 8, 2, 5);
$absoluteArr = array_map('abs', array_unique($arr));
rsort($absoluteArr);
echo $absoluteArr[1];
No need to do that much code, do directly:
<?php
$array = array(13, -12, 8, 2, 5);
$final_array = array_unique(array_map('abs',$array)); // remove duplicates and apply abs() to all elements
rsort($final_array,SORT_NUMERIC); //reverse sort array numerically
echo $final_array[1]; //get second highest
Output:-https://3v4l.org/mgjaO
Reference:-
abs()
array_map()
array_unique()
rsort()
I'm not sure this needs a function, if you just rsort the array after each element has been updated with the absolute value with array_mapand look at the second position:
function print2largest($arr) {
if (count($arr) < 2) {
echo(" Invalid Input ");
return;
}
$arr = array_map("abs", $arr);
rsort($arr);
return $arr[1];
}
$arr = array(13, -11, 9, 2, 5);
print2largest($arr);
Just add abs() to the values here
function print2largest($arr, $arr_size)
{
if ($arr_size < 2)
{
echo(" Invalid Input ");
return;
}
$first = $second = PHP_INT_MIN;
for ($i = 0; $i < $arr_size ; $i++)
{
if (abs($arr[$i]) > $first)
{
$second = $first;
$first = abs($arr[$i]);
}
else if (abs($arr[$i]) > $second &&
abs($arr[$i]) != $first)
$second = abs($arr[$i]);
}
if ($second == PHP_INT_MIN)
echo("There is no second largest elementn");
else
echo("The second largest element is " . $second . "n");
}
$arr = array(13, -12, 8, 2, 5);
$n = sizeof($arr);
print2largest($arr, $n);
The second largest element is 12n
$array = [13, -12, 8, 2, 5];
echo getSecondLargestAbsolute($array); // 12
function getSecondLargestAbsolute($array)
{
$values = [];
if (count($array) == count($array, COUNT_RECURSIVE)) {
$values = $array;
} else {
foreach (new \RecursiveIteratorIterator(new \RecursiveArrayIterator($array)) as $item) {
$values[] = $item;
};
}
array_walk($values, function (&$val){
return $val = abs($val);
});
rsort($values);
return $values[1];
}
I have an array of 7 numbers (1,2,3,4,5,6,7) and I want to choose 5 of the numbers like
(1,2,3,4,5), (1,2,3,4,6), (1,2,3,4,7).
Note that (1,2,3,4,5) is equal to (4,5,3,1,2), so only one of those should be included in the output.
I would like to know if there is a function in PHP or any algorithm that can do this ?
I have no idea where to start from.
Can you help me ?
I want all the combinations of 7 given numbers ( they are taken from an array ) put into 5 slots, disregarding order.
You can use the solution found here http://stereofrog.com/blok/on/070910.
Incase the link goes down here's the code....
class Combinations implements Iterator
{
protected $c = null;
protected $s = null;
protected $n = 0;
protected $k = 0;
protected $pos = 0;
function __construct($s, $k) {
if(is_array($s)) {
$this->s = array_values($s);
$this->n = count($this->s);
} else {
$this->s = (string) $s;
$this->n = strlen($this->s);
}
$this->k = $k;
$this->rewind();
}
function key() {
return $this->pos;
}
function current() {
$r = array();
for($i = 0; $i < $this->k; $i++)
$r[] = $this->s[$this->c[$i]];
return is_array($this->s) ? $r : implode('', $r);
}
function next() {
if($this->_next())
$this->pos++;
else
$this->pos = -1;
}
function rewind() {
$this->c = range(0, $this->k);
$this->pos = 0;
}
function valid() {
return $this->pos >= 0;
}
protected function _next() {
$i = $this->k - 1;
while ($i >= 0 && $this->c[$i] == $this->n - $this->k + $i)
$i--;
if($i < 0)
return false;
$this->c[$i]++;
while($i++ < $this->k - 1)
$this->c[$i] = $this->c[$i - 1] + 1;
return true;
}
}
foreach(new Combinations("1234567", 5) as $substring)
echo $substring, ' ';
12345 12346 12347 12356 12357 12367 12456 12457 12467 12567 13456 13457 13467 13567 14567 23456 23457 23467 23567 24567 34567
<?php
echo "<pre>";
$test = array("test_1","test_2","test_3");
// Get Combination
$return = uniqueCombination($test);
//Sort
sort($return);
//Pretty Print
print_r(array_map(function($v){ return implode(",", $v); }, $return));
function uniqueCombination($in, $minLength = 1, $max = 2000) {
$count = count($in);
$members = pow(2, $count);
$return = array();
for($i = 0; $i < $members; $i ++) {
$b = sprintf("%0" . $count . "b", $i);
$out = array();
for($j = 0; $j < $count; $j ++) {
$b{$j} == '1' and $out[] = $in[$j];
}
count($out) >= $minLength && count($out) <= $max and $return[] = $out;
}
return $return;
}
?>
output
Array
(
[0] => test_1
[1] => test_2
[2] => test_3
[3] => test_1,test_2
[4] => test_1,test_3
[5] => test_2,test_3
[6] => test_1,test_2,test_3
)
The Math_Combinatorics in PEAR repository does exactly what you want:
A package that returns all the combinations and permutations, without
repetition, of a given set and subset size. Associative arrays are
preserved.
require_once 'Math/Combinatorics.php';
$combinatorics = new Math_Combinatorics;
$input = array(1, 2, 3, 4, 5, 6, 7);
$output = $combinatorics->combinations($input, 5); // 5 is the subset size
// 1,2,3,4,5
// 1,2,3,4,6
// 1,2,3,4,7
// 1,2,3,5,6
// 1,2,3,5,7
// 1,2,3,6,7
// 1,2,4,5,6
// 1,2,4,5,7
// 1,2,4,6,7
// 1,2,5,6,7
// 1,3,4,5,6
// 1,3,4,5,7
// 1,3,4,6,7
// 1,3,5,6,7
// 1,4,5,6,7
// 2,3,4,5,6
// 2,3,4,5,7
// 2,3,4,6,7
// 2,3,5,6,7
// 2,4,5,6,7
// 3,4,5,6,7
Another solution that bases on stack. It's quit fast but eats much memory.
Hope that helps someone.
In detail:
function _combine($numbers, $length)
{
$combinations = array();
$stack = array();
// every combinations can be ordered
sort($numbers);
// startup
array_push($stack, array(
'store' => array(),
'options' => $numbers,
));
while (true) {
// pop a item
$item = array_pop($stack);
// end of stack
if (!$item) {
break;
}
// valid store
if ($length <= count($item['store'])) {
$combinations[] = $item['store'];
continue;
}
// bypass when options are not enough
if (count($item['store']) + count($item['options']) < $length) {
continue;
}
foreach ($item['options'] as $index => $n) {
$newStore = $item['store'];
$newStore[] = $n;
// every combine can be ordered
// so accept only options which is greater than store numbers
$newOptions = array_slice($item['options'], $index + 1);
// push new items
array_push($stack, array(
'store' => $newStore,
'options' => $newOptions,
));
}
}
return $combinations;
}
Improved this answer to work with associative array as well:
function uniqueCombination($values, $minLength = 1, $maxLength = 2000) {
$count = count($values);
$size = pow(2, $count);
$keys = array_keys($values);
$return = [];
for($i = 0; $i < $size; $i ++) {
$b = sprintf("%0" . $count . "b", $i);
$out = [];
for($j = 0; $j < $count; $j ++) {
if ($b[$j] == '1') {
$out[$keys[$j]] = $values[$keys[$j]];
}
}
if (count($out) >= $minLength && count($out) <= $maxLength) {
$return[] = $out;
}
}
return $return;
}
Eg:
print_r(uniqueCombination([
'a' => 'xyz',
'b' => 'pqr',
]);
Result:
Array
(
[0] => Array
(
[b] => pqr
)
[1] => Array
(
[a] => xyz
)
[2] => Array
(
[a] => xyz
[b] => pqr
)
)
It will still work for non-associative arrays:
print_r(uniqueCombination(['a', 'b']);
Result:
Array
(
[0] => Array
(
[1] => b
)
[1] => Array
(
[0] => a
)
[2] => Array
(
[0] => a
[1] => b
)
)
New solution which optimizes speed and memory for combining algorithm
Mindset: generate combinations K numbers of Array of numbers. New solution will use K 'for' statements. One 'for' One number.
Such as: $K = 5 mean that 5 of 'for' statements is used
$total = count($array);
$i0 = -1;
for ($i1 = $i0 + 1; $i1 < $total; $i1++) {
for ($i2 = $i1 + 1; $i2 < $total; $i2++) {
for ($i3 = $i2 + 1; $i3 < $total; $i3++) {
for ($i4 = $i3 + 1; $i4 < $total; $i4++) {
for ($i5 = $i4 + 1; $i5 < $total; $i5++) {
$record = array();
for ($i = 1; $i <= $k; $i++) {
$t = "i$i";
$record[] = $array[$$t];
}
$callback($record);
}
}
}
}
}
And detail of code that generated the real code that will be execute by eval() function
function combine($array, $k, $callback)
{
$total = count($array);
$init = '
$i0 = -1;
';
$sample = '
for($i{current} = $i{previous} + 1; $i{current} < $total; $i{current}++ ) {
{body}
}
';
$do = '
$record = array();
for ($i = 1; $i <= $k; $i++) {
$t = "i$i";
$record[] = $array[$$t];
}
$callback($record);
';
$for = '';
for ($i = $k; $i >= 1; $i--) {
switch ($i) {
case $k:
$for = str_replace(['{current}', '{previous}', '{body}'], [$i, $i - 1, $do], $sample);
break;
case 1:
$for = $init . str_replace(['{current}', '{previous}', '{body}'], [$i, $i - 1, $for], $sample);
break;
default:
$for = str_replace(['{current}', '{previous}', '{body}'], [$i, $i - 1, $for], $sample);
break;
}
}
// execute
eval($for);
}
How to combine K numbers of Array
$k = 5;
$array = array(1, 2, 3, 4, 5, 6, 7);
$callback = function ($record) {
echo implode($record) . "\n";
};
combine($array, $k, $callback);
I found the other answers here confusing or overly complicated, so I wrote my own. I think this is a simple solution with a recursive method. The basic idea is that you go through your array and for each item decide whether or not it is in the combination (actually, you don't decide, you recursively try both ways). You make this choice for the first item and then combine it with the recursively generated combinations of the rest of the array. This solution fills a result array with every combination of your array as a sub-array. It uses the items in order and it preserves associations, including with numeric keys.
function combinations(array $items, int $numToChoose, array &$results, $comb = []): void {
if (count($items) < $numToChoose) {
throw new \Exception("Asked to choose $numToChoose items from an array of length ". count($items));
}
// if nothing left to choose, we have a complete combination
if ($numToChoose === 0) {
$results[] = $comb;
return;
}
// if we have to choose everything at this point, then we know what to do
if (count($items) == $numToChoose) {
$results[] = $comb + $items;
return;
}
// The recursive cases: either use the first element or not and find combinations of the rest
$val = reset($items);
$key = key($items);
unset($items[$key]);
// not using it
combinations($items, $numToChoose, $results, $comb);
// using it
$comb[$key] = $val;
combinations($items, $numToChoose - 1, $results, $comb);
}
// Do a test run
$combs = [];
combinations([1=>1, 2=>2, 3=>3], 2, $combs);
var_dump($perms);
This results in the output:
array(3) {
[0]=>
array(2) {
[2]=>
int(2)
[3]=>
int(3)
}
[1]=>
array(2) {
[1]=>
int(1)
[3]=>
int(3)
}
[2]=>
array(2) {
[1]=>
int(1)
[2]=>
int(2)
}
}
I needed a combining function that included subsets, so I took #Nguyen Van Vinh's answer and modified it for my needs.
If you pass [1,2,3,4] to the function, it returns every unique combination and subset, sorted:
[
[1,2,3,4], [1,2,3], [1,2,4], [1,3,4], [2,3,4], [1,2], [1,3], [1,4], [2,3], [2,4], [3,4], [1], [2], [3], [4]
]
Here's the function:
function get_combinations_with_length( $numbers, $length ){
$result = array();
$stack = array();
// every combinations can be ordered
sort($numbers);
// startup
array_push($stack, array(
'store' => array(),
'options' => $numbers,
));
while (true) {
// pop a item
$item = array_pop($stack);
// end of stack
if (!$item) break;
// valid store
if ($length <= count($item['store'])) {
$result[] = $item['store'];
continue;
}
// bypass when options are not enough
if (count($item['store']) + count($item['options']) < $length) {
continue;
}
foreach ($item['options'] as $i=>$n) {
$newStore = $item['store'];
$newStore[] = $n;
// every combine can be ordered, so accept only options that are greater than store numbers
$newOptions = array_slice($item['options'], $i + 1);
// array_unshift to sort numerically, array_push to reverse
array_unshift($stack, array(
'store' => $newStore,
'options' => $newOptions,
));
}
}
return $result;
}
function get_all_combinations( $numbers ){
$length = count($numbers);
$result = [];
while ($length > 0) {
$result = array_merge($result, get_combinations_with_length( $numbers, $length ));
$length--;
}
return $result;
}
$numbers = [1,2,3,4];
$result = get_all_combinations($numbers);
echo 'START: '.json_encode( $numbers ).'<br><br>';
echo 'RESULT: '.json_encode( $result ).'<br><br>';
echo '('.count($result).' combination subsets found)';
This question already has answers here:
PHP get the item in an array that has the most duplicates
(2 answers)
Closed 1 year ago.
I have an array of numbers like this:
$array = array(1,1,1,4,3,1);
How do I get the count of most repeated value?
This should work:
$count=array_count_values($array);//Counts the values in the array, returns associatve array
arsort($count);//Sort it from highest to lowest
$keys=array_keys($count);//Split the array so we can find the most occuring key
echo "The most occuring value is $keys[0][1] with $keys[0][0] occurences."
I think array_count_values function can be useful to you. Look at this manual for details : http://php.net/manual/en/function.array-count-values.php
You can count the number of occurrences of values in an array with array_count_values:
$counts = array_count_values($array);
Then just do a reverse sort on the counts:
arsort($counts);
Then check the top value to get your mode.
$mode = key($counts);
If your array contains strings or integers only you can use array_count_values and arsort:
$array = array(1, 1, 1, 4, 3, 1);
$counts = array_count_values($array);
arsort($counts);
That would leave the most used element as the first one of $counts. You can get the count amount and value afterwards.
It is important to note that if there are several elements with the same amount of occurrences in the original array I can't say for sure which one you will get. Everything depends on the implementations of array_count_values and arsort. You will need to thoroughly test this to prevent bugs afterwards if you need any particular one, don't make any assumptions.
If you need any particular one, you'd may be better off not using arsort and write the reduction loop yourself.
$array = array(1, 1, 1, 4, 3, 1);
/* Our return values, with some useless defaults */
$max = 0;
$max_item = $array[0];
$counts = array_count_values($array);
foreach ($counts as $value => $amount) {
if ($amount > $max) {
$max = $amount;
$max_item = $value;
}
}
After the foreach loop, $max_item contains the last item that appears the most in the original array as long as array_count_values returns the elements in the order they are found (which appears to be the case based on the example of the documentation). You can get the first item to appear the most in your original array by using a non-strict comparison ($amount >= $max instead of $amount > $max).
You could even get all elements tied for the maximum amount of occurrences this way:
$array = array(1, 1, 1, 4, 3, 1);
/* Our return values */
$max = 0;
$max_items = array();
$counts = array_count_values($array);
foreach ($counts as $value => $amount) {
if ($amount > $max) {
$max = $amount;
$max_items = array($value);
} elif ($amount = $max) {
$max_items[] = $value;
}
}
$vals = array_count_values($arr);
asort($vals);
//you may need this end($vals);
echo key($vals);
I cant remember if asort sorts asc or desc by default, you can see the comment in the code.
<?php
$arrrand = '$arr = array(';
for ($i = 0; $i < 100000; $i++)
{
$arrrand .= rand(0, 1000) . ',';
}
$arrrand = substr($arrrand, 0, -1);
$arrrand .= ');';
eval($arrrand);
$start1 = microtime();
$count = array_count_values($arr);
$end1 = microtime();
echo $end1 - $start1;
echo '<br>';
$start2 = microtime();
$tmparr = array();
foreach ($arr as $key => $value);
{
if (isset($tmparr[$value]))
{
$tmparr[$value]++;
} else
{
$tmparr[$value] = 1;
}
}
$end2 = microtime();
echo $end2 - $start2;
Here check both solutions:
1 by array_count_values()
and one by hand.
<?php
$input = array(1,2,2,2,8,9);
$output = array();
$maxElement = 0;
for($i=0;$i<count($input);$i++) {
$count = 0;
for ($j = 0; $j < count($input); $j++) {
if ($input[$i] == $input[$j]) {
$count++;
}
}
if($count>$maxElement){
$maxElement = $count;
$a = $input[$i];
}
}
echo $a.' -> '.$maxElement;
The output will be 2 -> 3
$arrays = array(1, 2, 2, 2, 3, 1); // sample array
$count=array_count_values($arrays); // getting repeated value with count
asort($count); // sorting array
$key=key($count);
echo $arrays[$key]; // get most repeated value from array
String S;
Scanner in = new Scanner(System.in);
System.out.println("Enter the String: ");
S = in.nextLine();
int count =1;
int max = 1;
char maxChar=S.charAt(0);
for(int i=1; i <S.length(); i++)
{
count = S.charAt(i) == S.charAt(i - 1) ? (count + 1):1;
if(count > max)
{
max = count;
maxChar = S.charAt(i);
}
}
System.out.println("Longest run: "+max+", for the character "+maxChar);
here is the solution
class TestClass {
public $keyVal;
public $keyPlace = 0;
//put your code here
public function maxused_num($array) {
$temp = array();
$tempval = array();
$r = 0;
for ($i = 0; $i <= count($array) - 1; $i++) {
$r = 0;
for ($j = 0; $j <= count($array) - 1; $j++) {
if ($array[$i] == $array[$j]) {
$r = $r + 1;
}
}
$tempval[$i] = $r;
$temp[$i] = $array[$i];
}
//fetch max value
$max = 0;
for ($i = 0; $i <= count($tempval) - 1; $i++) {
if ($tempval[$i] > $max) {
$max = $tempval[$i];
}
}
//get value
for ($i = 0; $i <= count($tempval) - 1; $i++) {
if ($tempval[$i] == $max) {
$this->keyVal = $tempval[$i];
$this->keyPlace = $i;
break;
}
}
// 1.place holder on array $this->keyPlace;
// 2.number of reapeats $this->keyVal;
return $array[$this->keyPlace];
}
}
$catch = new TestClass();
$array = array(1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 1, 2, 3, 1, 1, 2, 5, 7, 1, 9, 0, 11, 22, 1, 1, 22, 22, 35, 66, 1, 1, 1);
echo $catch->maxused_num($array);