PHP : Combinations without permutations - php

This code gives me every possible combination of n values with a length of x, to have a sum of n.
function GETall_distri_pres($n_valeurs, $x_entrees, $combi_presences = array()) {
if ($n_valeurs == 1) {
$combi_presences[] = $x_entrees;
return array($combi_presences);
}
$combinaisons = array();
// $tiroir est le nombre de chaussettes dans le tiroir suivant
for ($tiroir = 0; $tiroir <= $x_entrees; $tiroir++) {
$combinaisons = array_merge($combinaisons, GETall_distri_pres(
$n_valeurs - 1,
$x_entrees - $tiroir,
array_merge($combi_presences, array($tiroir))));
}
return $combinaisons;
}
I need to generate only unique distributions for example not having [2,1,1,0] and [1,2,1,0], only [2,1,1,0].
var_dump(GETall_distri_pres(3,3)) will give :
array (size=10)
0 =>
array (size=3)
0 => int 0
1 => int 0
2 => int 3
1 =>
array (size=3)
0 => int 0
1 => int 1
2 => int 2
2 =>
array (size=3)
0 => int 0
1 => int 2
2 => int 1
3 =>
array (size=3)
0 => int 0
1 => int 3
2 => int 0
4 =>
array (size=3)
0 => int 1
1 => int 0
2 => int 2
5 =>
array (size=3)
0 => int 1
1 => int 1
2 => int 1
6 =>
array (size=3)
0 => int 1
1 => int 2
2 => int 0
7 =>
array (size=3)
0 => int 2
1 => int 0
2 => int 1
8 =>
array (size=3)
0 => int 2
1 => int 1
2 => int 0
9 =>
array (size=3)
0 => int 3
1 => int 0
2 => int 0
Do you have any ideas?

This would be an approach: before returning the computed set you filter them by creating a fresh associative array, using the normalized permutations as keys. That will result in permutations overwriting themselves, so that only one will get preserved:
<?php
function GETall_distri_pres($n_valeurs, $x_entrees, $combi_presences = array()) {
if ($n_valeurs == 1) {
$combi_presences[] = $x_entrees;
return array($combi_presences);
}
$combinaisons = array();
// $tiroir est le nombre de chaussettes dans le tiroir suivant
for ($tiroir = 0; $tiroir <= $x_entrees; $tiroir++) {
$combinaisons = array_merge($combinaisons, GETall_distri_pres(
$n_valeurs - 1,
$x_entrees - $tiroir,
array_merge($combi_presences, array($tiroir))));
}
// filter out permutations
$filteredCombinations = [];
array_walk($combinaisons, function($entry) use(&$filteredCombinations) {
arsort($entry);
$filteredCombinations[join('', $entry)] = $entry;
});
return array_values($filteredCombinations);
}
$result = GETall_distri_pres(3, 3);
print_r($result);
The output obviously is:
Array
(
[0] => Array
(
[0] => 3
[1] => 0
[2] => 0
)
[1] => Array
(
[0] => 2
[1] => 1
[2] => 0
)
[2] => Array
(
[0] => 1
[1] => 1
[2] => 1
)
)

Related

PHP - sorting and merging arrays

I have a site with a search feature but am trying to improve the search for a fuzzy search.
So far what I've done is query all of my products and use similar_text() to see how close they are to the actual search term
I then create an array where the key is how similar it is and the value is the product id. I then sort this by the key/similarity.
$term = $_GET['search_term'];
$similar_array = [];
$sql = "SELECT * FROM products";
$stmt = DB::run($sql);
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$id = $row["pro_id"];
$result = $row['product'];
similar_text($term,$result,$similarity);
$similar_array[$similarity][] = $id;
}
$closest_match = array_keys($similar_array);
rsort($closest_match);
$match_count = count($closest_match);
for($i=0; $i<$match_count; $i++){
var_dump($similar_array[$closest_match[$i]]);
}
This gives me something like:
array (size=9)
0 => int 28
1 => int 1628
2 => int 1665
3 => int 1666
4 => int 1667
5 => int 1668
6 => int 1669
7 => int 1670
8 => int 1671
C:\wamp64\www\V2\search.php:65:
array (size=2)
0 => int 37
1 => int 38
C:\wamp64\www\V2\search.php:65:
array (size=1)
0 => int 481
C:\wamp64\www\V2\search.php:65:
array (size=3)
0 => int 27
1 => int 1009
2 => int 1620
C:\wamp64\www\V2\search.php:65:
array (size=14)
0 => int 30
1 => int 104
2 => int 131
3 => int 134
4 => int 168
5 => int 169
6 => int 170
7 => int 557
8 => int 1011
9 => int 1014
10 => int 1661
11 => int 1662
12 => int 1663
13 => int 1664
I have a show_products() function that I just need to pass an array of ID's, so what I want to do now is take the multiple arrays of ID's from above and merge it in this specific order and then crop the array to a certain number so it won't have every product but will cut off after so many results.
As per your query you can use follow below steps
you merge all array by array_merge
sort the array using rsort (highest merge come first);
for display you can use array_slice or array_chunk

Why an array key-value sets in the end of an array instead of a specific place?

to be precise I have:
$foo = [1, 4, 1, 5, 8, 1, 3, 5, 1, 4, 1, 3, 7, 2];
sort($foo);
$bar = array_count_values($foo);
for ($i = 1; $i < count($bar); $i++) {
if (!isset($bar[$i])) {
$bar[$i] = 0;
}
}
Actual result:
array (size=8)
1 => int 5
2 => int 1
3 => int 2
4 => int 2
5 => int 2
7 => int 1
8 => int 1
6 => int 0
Expected result:
array (size=8)
1 => int 5
2 => int 1
3 => int 2
4 => int 2
5 => int 2
6 => int 0
7 => int 1
8 => int 1
Why my key value pair 6 => 0 appears in the bottom of an array instead of a specific place?
It's because you are appending a new value to the array.
To "fix" that, use ksort($bar);.
As #Rob Ruchte wrote in comments, the array returned by array_count_values() is associative, which means there is no order with the keys.
http://php.net/manual/en/function.array-count-values.php
Returns an associative array of values from array as keys and their count as value.

Sort array of months with laravel collection

My array is
$array = [
1 => 0
2 => 0
3 => 0
4 => 0
5 => 0
6 => 0
7 => 2
8 => 0
9 => 0
10 => 1
11 => 0
12 => 1
];
As a result i want it to be
$array = [
10 => 1
11 => 0
12 => 1
1 => 0
2 => 0
3 => 0
4 => 0
5 => 0
6 => 0
7 => 2
8 => 0
9 => 0
];
And my logic for now is
$sorted = collect($array)
->sortBy(function ($count, $month) {
return $month <= 9;
});
But the result is not what I expected :(
Basically i want last index to be current month and so on back.
Please help me!
You can do it like this:
$sorted = collect($array)->sortBy(function ($count, $month) {
$currentMonth = (int) \Carbon\Carbon::now()->month;
return ($month + (12 - $currentMonth - 1)) % 12;
});
You can function form php that
krsort();
krsort can sort associative arrays in descending order, according to the key. So
ksort($array);

PHP - How to count all the values of an array with limited ranges?

I have an array like this:
$array = array(10,25,47,14,45,58,25,29,15,36,45,15,25,27,34);
is there a way to output a new array of 10 ranges with key that tells me which is used and frequency as values?
$result = array(
[x0] => frequency // number of values <= x0
[x1] => frequency // number of values > x0 and <=1
etc..., [x2], ...., [x7], x[8]
[x9] => frequency // number of values >= x9
)
use this for 10 equal segments
$array = array(10,25,47,14,45,58,25,29,15,36,45,15,25,27,34);
$step = (max($array) - min($array)) / 10;
$result = [];
for ($i = min($array); $i < max($array) - $step; $i += $step) {
$res = array_filter($array, function($v) use ($i, $step) {
return ($i <= $v) && $v < $i +$step;
});
$result[$i . '-' . ($i + $step)] = $res;
}
Return:
"10 - 14.8" => 2
"14.8 - 19.6" => 2
"19.6 - 24.4" => 0
"24.4 - 29.2" => 5
"29.2 - 34" => 0
"34 - 38.8" => 2
"38.8 - 43.6" => 0
"43.6 - 48.4" => 3
"48.4 - 53.2" => 0
"53.2 - 58" => 0
You can use array_count_values() to count values
$array = array(10,25,47,14,45,58,25,29,15,36,45,15,25,27,34);
$vals = array_count_values($array);
echo "<pre>"; print_r($vals);
This will give you
Array
(
[10] => 1
[25] => 3
[47] => 1
[14] => 1
[45] => 2
[58] => 1
[29] => 1
[15] => 2
[36] => 1
[27] => 1
[34] => 1
)
I've used an array for the range boundaries. Here with an example of 4 irregular ranges. And dumped the sorted array to make it easier to see if the results are as you'd expect.
<?php
$array = array(10,25,47,14,45,58,25,29,15,36,45,15,25,27,34);
$bounds = array(0,10,25,50,100);
$lower = array_shift($bounds);
$range_frequencies = array();
sort($array);
var_dump($array);
foreach($bounds as $upper) {
$range_frequencies[$lower . '-' . $upper] = 0;
foreach($array as $k => $v) {
if($v > $lower && $v <= $upper) {
$range_frequencies[$lower . '-' . $upper]++;
unset($array[$k]);
}
}
$lower = $upper;
}
var_dump($range_frequencies);
Output:
array (size=15)
0 => int 10
1 => int 14
2 => int 15
3 => int 15
4 => int 25
5 => int 25
6 => int 25
7 => int 27
8 => int 29
9 => int 34
10 => int 36
11 => int 45
12 => int 45
13 => int 47
14 => int 58
array (size=4)
'0-10' => int 1
'10-25' => int 6
'25-50' => int 7
'50-100' => int 1
Based on Manjeet Barnala's answer:
$array = array(10,25,47,14,45,58,25,29,15,36,45,15,25,27,34);
$vals = array_count_values($array);
arsort($vals);
$vals = array_slice($vals,0,10,true);
var_dump($vals);

Count and sum multidimensional array php

I have an array like this one:
array (size=1)
0 =>
array (size=33)
0 => int 126
1 => int 43
2 => int 4
3 => int 0
4 => int 3
5 => int 3
6 => int 30
7 => int 15
8 => int 22
9 => int 27
10 => int 22
11 => int 46
12 => int 0
13 => int 8
14 => int 14
15 => int 8
array (size=1)
1 =>
array (size=33)
0 => int 273
1 => int 3
2 => int 4
3 => int 28
4 => int 36
5 => int 19
6 => int 142
7 => int 81
8 => int 59
9 => int 71
10 => int 88
11 => int 47
12 => int 42
13 => int 0
14 => int 12
15 => int 97
(of course it is way longer)
and I need both to sum all the value with the same key and count how many values with the same key are >0 (cause I have to find the avarage of all the numbers >0
My expected result is
0=>
'sum' => 399
'count'=>2
1=>
'sum' =>46
'count'=>2
how can I create this array?
There's an inbuilt function in PHP to count the sum of all the elements of an array. Here, this will give you your expected output :
<?php
$arr = [[10, 20, 30, 40], [10, 20, 30], [10, 20, 30, 4]];
// Let the magic happen...
$yourArray = array_map(function ($el){ return ["sum" => array_sum($el), "count" => count($el)]; }, $arr);
print_r($yourArray);
?>
I have thought about this, and came up with a solution (I think...), it comes in the form of a function and it goes like this:
function getSumAndCount(array $arr)
{
$sum = 0;
$count = 0;
foreach ($arr as $v)
{
$count++;
if (is_array($v))
{
$next = getSumAndCount($v);
$count += $next['count'];
$sum += $next['sum'];
}
else
{
!is_numeric($v) ?: $sum += $v;
}
}
return [ 'sum' => $sum, 'count' => $count ];
}
It has a recursive check to if the array is multidimensional, checks if the value is numeric and sets the count and sum in a return array.
I haven't tested this properly as yet, but please test and let me know if you get the desired output.
EDIT
I will extend this to count dupe keys soon

Categories