Can we insert those values without if statements? - php

Hello here is an array of all values possibilities that should be an instance of the int we have as rank. But I would like this array to be empty first and find those values without if statements, so with a smart mathematical relation.
Example: a player who has the rank 3 would have those rewards: First time: At pos 0: 10 keys; pos 1: 13 keys; pos 2: 13 keys; 8 lives and 2 keys at pos 0 if he already registered their first time rewards.
(In fact there would be if satement only if the player never registered their rewards).
So I've tried to do this with digital sequences that I learned to school but it does not seems working.
Thank you for your time... and your help !
P.S.: I'm quite new here, sorry for any mistake.
Here is the schema of all possibilities stored in this array:
$rewards = [
1 => [
"count" => [7, 7, 7],
"lives" => 8,
"count_back" => [2, 2]
],
2 => [
"count" => [7, 10, 10],
"lives" => 10,
"count_back" => [1]
],
3 => [
"count" => [10, 13, 13],
"lives" => 13,
"count_back" => [2]
],
4 => [
"count" => [10, 13, 13],
"lives" => 15,
"count_back" => [2]
],
5 => [
"count" => [14, 15, 15],
"lives" => 18,
"count_back" => [2]
],
6 => [
"count" => [16, 18, 18],
"lives" => 20,
"count_back" => [2, 2]
]
];
So the only input we have for this command is the player rank (int). Starting to it I would like to find without if statements, that will be too big or this complete array we have above that would take too much datas in memory for nothing (because the player doesn't have several ranks) ; the specific reward.
For example: I have the input 1. So the output should be ["count" => [7, 7, 7], "lives" => 8] if the player never used the command. If he already used it so the output should be only ["count" => [2, 2]]

Related

Get dense rank and gapped rank for all items in array

I want to calculate and store the dense rank and gapped rank for all entries in an array using PHP.
I want to do this in PHP (not MySQL because I am dealing with dynamic combinations 100,000 to 900 combinations per week, that’s why I cannot use MySQL to make that many tables.
My code to find the dense ranks is working, but the gapped ranks are not correct.
PHP code
$members = [
['num' => 2, 'rank' => 0, 'dense_rank' => 0],
['num' => 2, 'rank' => 0, 'dense_rank' => 0],
['num' => 3, 'rank' => 0, 'dense_rank' => 0],
['num' => 3, 'rank' => 0, 'dense_rank' => 0],
['num' => 3, 'rank' => 0, 'dense_rank' => 0],
['num' => 3, 'rank' => 0, 'dense_rank' => 0],
['num' => 3, 'rank' => 0, 'dense_rank' => 0],
['num' => 5, 'rank' => 0, 'dense_rank' => 0],
['num' => 9, 'rank' => 0, 'dense_rank' => 0],
['num' => 9, 'rank' => 0, 'dense_rank' => 0],
['num' => 9, 'rank' => 0, 'dense_rank' => 0]
];
$rank=0;
$previous_rank=0;
$dense_rank=0;
$previous_dense_rank=0;
foreach($members as &$var){
//star of rank
if($var['num']==$previous_rank){
$var['rank']=$rank;
}else{
$var['rank']=++$rank;
$previous_rank=$var['num'];
}//end of rank
//star of rank_dense
if($var['num']===$previous_dense_rank){
$var['dense_rank']=$dense_rank;
++$dense_rank;
}else{
$var['dense_rank']=++$dense_rank;
$previous_dense_rank=$var['num'];
}
//end of rank_dense
echo $var['num'].' - '.$var['rank'].' - '.$var['dense_rank'].'<br>';
}
?>
My flawed output is:
num
rank
dynamic rank
2
1
1
2
1
1
3
2
3
3
2
3
3
2
4
3
2
5
3
2
6
5
3
8
9
4
9
9
4
9
9
4
10
Notice when the error happens and there is a higher number in the number column it corrects the error in that row. See that when the number goes from 3 to 5.
Given that your results are already sorted in an ascending fashion...
For dense ranking, you need to only increment your counter when a new score is encountered.
For gapped ranking, you need to unconditionally increment your counter and use the counter value for all members with the same score.
??= is the "null coalescing assignment" operator (a breed of "combined operator"). It only allows the right side operand to be executed/used if the left side operand is not declared or is null. This is a technique of performing conditional assignments without needing to write a classic if condition.
Code: (Demo)
$denseRank = 0;
$gappedRank = 0;
foreach ($members as &$row) {
$denseRanks[$row['num']] ??= ++$denseRank;
$row['dense_rank'] = $denseRanks[$row['num']];
++$gappedRank;
$gappedRanks[$row['num']] ??= $gappedRank;
$row['rank'] = $gappedRanks[$row['num']];
// for better presentation:
echo json_encode($row) . "\n";
}
Output:
{"num":2,"rank":1,"dense_rank":1}
{"num":2,"rank":1,"dense_rank":1}
{"num":3,"rank":3,"dense_rank":2}
{"num":3,"rank":3,"dense_rank":2}
{"num":3,"rank":3,"dense_rank":2}
{"num":3,"rank":3,"dense_rank":2}
{"num":3,"rank":3,"dense_rank":2}
{"num":5,"rank":8,"dense_rank":3}
{"num":9,"rank":9,"dense_rank":4}
{"num":9,"rank":9,"dense_rank":4}
{"num":9,"rank":9,"dense_rank":4}
For the record, if you are dealing with huge volumes of data, I would be using SQL instead of PHP for this task.
It seems like you want the dynamic rank to be sequential?
Your sample data appears to be sorted, if this remains true for your real data then you can remove the conditional and just increment the variable as you assign it:
//start of rank_dense
$var['dense_rank']=++$dense_rank;
//end of rank_dense
It sounds like you're saying you won't be implementing a database.
Databases like MySQL can easily handle the workload numbers you outlined and they can sort your data as well. You may want to reconsider.

php array and recursive function

hello stackoverflow :),
I block on this problem for a few days I think that the solution is with a recursive function but I cannot create it.
my main problem is that the source data is random, I can not determine neither the order nor the amount of data.
I would like to combine several array to be able to prepare my request in db
for example I can receive a table
array: {
color_id: [3,4],
size_id: [11, 6, 7]
}
and I would like to convert it to
color_id[
3 => size_id[11, 6, 7],
4 => size_id[11, 6, 7],
],
to simplify nothing it is possible to have x array, example
array: {
color_id: [3,4],
size_id: [11, 6, 7],
x_id: [8, 9],
}
to
color_id[
3 => size_id[
11 => x_id[8, 9],
6 => x_id[8, 9],
7 => x_id[8, 9]
],
4 => size_id[
11 => x_id[8, 9],
6 => x_id[8, 9],
7 => x_id[8, 9]
],
],
I have to be able to cover all possibilities,
Thanks for your help

Print unique values from an array column as a comma-separated string

I want to print all unique Department values from a multidimensional array as a comma-separated string, but not all rows have a Department value.
The boiled down version of my array looks like this:
$employee = [
["employee_id" => 1, "Department" => "Tech"],
["employee_id" => 2, "Department" => "Tech"],
["employee_id" => 3],
["employee_id" => 4, "Department" => "Tech"],
["employee_id" => 5],
["employee_id" => 6, "Department" => "Crm"],
["employee_id" => 7],
["employee_id" => 8, "Department" => "Crm"],
["employee_id" => 9, "Department" => "Crm"],
["employee_id" => 10],
["employee_id" => 11, "Department" => "Crm"],
["employee_id" => 12, "Department" => "Crm"]
];
I tried with:
for ($i=0; $i < count($employee); $i++) {
print_r(array_unique($employee[$i]['Department']));
}
But I generate Warnings when I try to access a non-existent Department value.
Expected output:
Tech,Crm
<?php
echo implode(",",array_unique(array_column($employee,'Department')));
Use array_column to filter values of Department column and use array_unique() to have unique values of Department. Now, just implode() them based on ,.
You can avoid calling array_unique() after array_column() by repeating its second parameter as its third parameter. PHP does no allow duplicate kays on the same level as an array. When a repeated Department is encountered, the old value is replaced with its newer, identical value.
Code: (Demo)
echo implode(',', array_column($employee, 'Department', 'Department'));
// Tech,Crm

Merge Two Arrays to Have an Integer Value be an near equal as possible

Application to Distribute Stock between Warehouses
I have two arrays,
One has list of Warehouses along with the Current Quantity: (This can be Dynamic with one or more locations)
[
['location_name' => 'Toronto', 'current_qty' => 3],
['location_name' => 'Mississauga','current_qty' => 7],
['location_name' => 'London', 'current_qty' => 5],
]
The Other array has the Amount of Stock that would be Comming in:
[
'qty' => 5
]
And want to distribute the Qty among the locations so that the current qty of each of the locations would be near equal to each other. So want to return an array with the number that needs to be added to each location. Like: Here , of the 5, 3 went to Toronto and 2 to London. So it can be seen then after the nearest equalization, rest of the distribution can be done randomly.
[
['location_name' => 'Toronto', 'add_qty' => 3],
['location_name' => 'Mississauga','add_qty' => 0],
['location_name' => 'London', 'add_qty' => 2],
]
And Just cannot figure out the logic of this algorithm. Would really appreciate any pointers. Many Thanks.
I would do it like this, not really sure about any performance issues. I don't know how big your data set is.
$locations = [
['location_name' => 'Toronto', 'current_qty' => 3, 'add_qty' => 0],
['location_name' => 'Mississauga', 'current_qty' => 7, 'add_qty' => 0],
['location_name' => 'London', 'current_qty' => 5, 'add_qty' => 0],
];
$supplies = 5;
// This function sorts locations, by comparing the sum of the current quantity and the quantity the location will get.
$locationsByQuantityAscending = function ($locationA, $locationB) {
return ($locationA['current_qty'] + $locationA['add_qty']) - ($locationB['current_qty'] + $locationB['add_qty']);
};
// Sort the locations, getting the ones with the lowest quantity first.
usort($locations, $locationsByQuantityAscending);
// Keep dividing, until we're out of supplies
while ($supplies > 0) {
$locations[0]['add_qty']++; // Add one to the location with the lowest supplies
$supplies--; // Decrease the supplies by one
usort($locations, $locationsByQuantityAscending); // Sort the locations again.
}
print_r($locations);
At the end, this will output:
Array
(
[0] => Array
(
[location_name] => Toronto
[current_qty] => 3
[add_qty] => 3
)
[1] => Array
(
[location_name] => London
[current_qty] => 5
[add_qty] => 2
)
[2] => Array
(
[location_name] => Mississauga
[current_qty] => 7
[add_qty] => 0
)
)
If you really need to be performant, you could also just sort the locations once by their current quantity. Then keep adding to the first location, until its stock will be higher than the second location. Then, until the quantity at the second location is higher than the third location, add one to the first and second location, etc.
I think this will be more performant, since you don't have to sort all your locations X times (X being the number of supplies to divide). I'll leave that implementation to you.
Hint: have a look at recursive functions
If performance is critical, and the input data is usually bigger then shown here (e.g. a lot more locations or a lot more quantity to distribute). You might want to consider using SplMinHeap:
For example:
<?php
$helper = new class extends SplMinHeap
{
public function compare($a, $b): int
{
return ($b['current_qty'] + $b['add_qty']) <=> ($a['current_qty'] + $a['add_qty']);
}
};
$locations = [
['location_name' => 'Toronto', 'current_qty' => 3, 'add_qty' => 0],
['location_name' => 'Mississauga', 'current_qty' => 7, 'add_qty' => 0],
['location_name' => 'London', 'current_qty' => 5, 'add_qty' => 0],
];
foreach ($locations as $entry) {
$helper->insert($entry);
}
$qty = 10000;
while ($qty-- > 0) {
$min = $helper->extract();
$min['add_qty']++;
$helper->insert($min);
}
print_r(iterator_to_array($helper));
https://3v4l.org/nDOY8

Find matching equal orders using arrays and PHP

I am cracking my brain and can't find a good solution for my problem. I am trying to design a system that I can use for batch picking in our order system.
The point is that from a set of orders I want to pick 6 orders that are most equal to each other. In our warehouse most orders are them so we can safe a lot of time by picking some orders at the same time.
Assume I have the following array:
<?php
$data = [
156 => [
1,
2,
7,
9,
],
332 => [
3,
10,
6
],
456 => [
1,
],
765 => [
7,
2,
10,
],
234 => [
1,
9,
3,
6,
],
191 => [
7,
],
189 => [
7,
6,
3,
],
430 => [
10,
9,
1,
],
482 => [
1,
2,
7,
],
765 => [
1,
5,
9,
]
];
?>
The array key is the order id, and the values are the product ID's it contains. If I want to pick the top 3 orders which look at much like each other, where do I start?
Any help would be much appreciated!
1. Step
Sort productId inside order (ASC)
2. Step
In loop check difference (array_diff) in each order to each other.
Create array with defference. For example:
$diff = [
'156' => [ //order id
'234' => 4, // with order 234 has 4 differences
'332' => 7, // with order 332 has 7 differences
// and so on...
],
]
3. Step
Order $diff by ASC and receive order with less differences.
Improvement
Also you could add total size of products in order for compare with difference. For example, If you have an order with 100 products and 10 diffs - it's better than order with 10 products and 9 diffs.
Here is what i would do if I had the problem :
$topOrders = [];
foreach($data as $value):
foreach($value as $order):
if(isset($$order)):
$$order++;
else:
$$order = 1;
endif;
$topOrders[$order] = $$order;
endforeach;
endforeach;
print_r($topOrders);
In $topOrders, you have an array that contains as key the ID, and as value you got the number of orders. All you have to do is to sort your array to get your top 3.

Categories