Filter an array based on density - php

I have a sample graph like one below.., which I plotted with set of (x,y) values in an array X.
http://bubblebird.com/images/t.png
As you can see the image has dense peak values between 4000 to 5100
My exact question is can I programmatically find this range where the graph is most dense?
ie.. with Array X how can I find range within which this graph is dense?
for this array it would be 4000 - 5100.
Assume that the array has only one dense region for simplicity.
Thankful if you can suggest a pseudocode/code.

You can use the variance of the signal on a moving window.
Here is an example (see the graph attached where the test signal is red, the windowed variance is green and the filtered signal is blue) :
:
test signal generation :
import numpy as np
X = np.arange(200) - 100.
Y = (np.exp(-(X/10)**2) + np.exp(-((np.abs(X)-50.)/2)**2)/3.) * np.cos(X * 10.)
compute moving window variance :
window_length = 30 # number of point for the window
variance = np.array([np.var(Y[i-window_length / 2.: i+window_length/2.]) for i in range(200)])
get the indices where the variance is high (here I choose the criterion variance superior to half of the maximum variance... you can adapt it to your case) :
idx = np.where(variance > 0.5 * np.max(variance))
X_min = np.min(X[idx])
# -14.0
X_max = np.max(X[idx])
# 15.0
or filter the signal (set to zero the points with low variance)
Y_modified = np.where(variance > 0.5 * np.max(variance), Y, 0)

you may calculate the absolute difference between the adjacent values, then maybe smooth things a little with sliding window and then find the regions, where the smoothed absolute difference values are at 50% of maximum value.
using python (you have python in tags) this would look like this:
a = ( 10, 11, 9, 10, 18, 5, 20, 6, 15, 10, 9, 11 )
diffs = [abs(i[0]-i[1]) for i in zip(a,a[1:])]
# [1, 2, 1, 8, 13, 15, 14, 9, 5, 1, 2]
maximum = max(diffs)
# 15
result = [i>maximum/2 for i in diffs]
# [False, False, False, True, True, True, True, True, False, False, False]

You could use classification algorithm (for example k-means), to split data into clusters and find the most weighted cluster

Related

Find the coin change (Greedy Algorithm) when coins are in decimals and returned amount in coins is larger then original return value

I need to find the number of coins that make a given value where coins are in decimals and there is a possibility that the algorithm will return more coins (money) because there is no way to return the exact value where the returned amount is close to the given value.
For example:
Coins: [23, 29.90, 34.50]
Value: 100
Possible solutions:
Solution 1: 34.60, 34.50, 29.90, 23 (122)
Solution 2: 29.90, 29.90, 29.90 ,29.90 (119.90)
Solution 3: 23, 23, 23, 23, 23 (115)
Solution 4: 23, 23, 23, 34.50 (103.5)
Based on the possible solutions, the clear winner is "Solution 4" and I am looking for an algorithm that will help me to solve this issue. I don't care how many coins are used I just need to be sure that returned values in coins are as close as passed/desired value.
Does someone know the solution or algorithm for this case?
Best Regards.
Greedy algorithm assumes that you get the largest possible coin, then the next possible and so on until you reach the sum. But it does not provide the best solution in general case.
So consider using of table containing possible sums:
Multiply sum and all nominals by 100 to work in integers.
Make array A[] of length 1 + sum + largest_coin, filled with zeros, set A[0] into -1.
For every coin nominal C walk through array. If A[i-C] is not zero, put value C into A[i]
After all scan array range A[sum]..A[max] to find the first non-zero item. It's index K represents the best sum. This cell contains the last coin added - so you can unwind the whole combination, walking down until index 0: A[k] => A[k - A[k]] an so on
Python code
def makesum(lst, summ):
mx = max(lst)
A = [-1] + [0]*(mx+summ)
for c in lst:
for i in range(c, summ + c + 1):
if A[i - c]:
A[i] = c
print(A)
#look for the smallest possible combination >= summ
for k in range(summ, summ + mx + 1):
if A[k]:
break
if (k == summ + mx + 1):
return
# unwind combination of used coins
while (k > 0):
print(A[k])
k = k - A[k]
makesum([7, 13, 21], 30)
Array for reference. Non-zero entries - for possible sums.
[-1, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 13, 7, 0, 0, 0, 0, 0, 13, 21, 0, 0,
0, 0, 13, 13, 21, 0, 0, 0, 0, 13, 21, 21, 0, 0, 0, 13, 13, 21, 21, 0, 0, 0,
0, 21, 21, 21, 0, 0]
Combination:
13
13
7
Getting started
I do not have enough reputation to ask in comments I wanted to ask you further questions but here it goes.I believe this can get you started
-Assuming we are not sure how many coins a user is going to pick
-Any of the coins can be the same amount as the others but have to be treated as different inputs
-Any number of coins can be added together so that the sum closest to the desired max can be accepted
What exactly is the script intended to achieve
A user picks random number of coins which are recorded then put into array.Any random number of coins can be picked and added and if the sum gets closer to a specific threshold those coins are accepted
Concept
<?php
$arrX = array("1.1","20.1","3.5","4","5.7","6.8","7.3","8.6","9","10"); //random coins from user
$minthresh = "30";
$desired = "33";
$maxthresh = "35"; //A threshold is necessary if the desired amount is not enforced
$randIndex = array_rand($arrX, 2); //Pick any random two coins avoid the same coin twice
$sumofpair = $arrX[$randIndex[0]] + $arrX[$randIndex[1]]." Possible acceptable sum<br>"; //Debug to see which two
coins are picked and how much they give
print_r($randIndex[0]);
echo " pair with ";
print_r($randIndex[1]);
echo " = ".$sumofpair; //Debug to see which two coins are picked and how much they give
if (($sumofpair >= "30") && ($sumofpair <= "35")){ //Check if the sum is within the threshold
echo "<br>found something<br>";
echo "<br>This ".$arrX[$randIndex[0]]."+".$arrX[$randIndex[1]]." Gets you this ".$sumofpair." Which is very close to
".$desired;
//if a pair is found show which pair exactly and how much did the pair make
} else { echo "<br>No match so far.Refresh again</br>"; //If the pair do not match refresh until a pair is found...See
below for more info on this }
?>
If you were to solve the need for refresh.You will run this in a loop until the pair that gives you the desired is found
You can expand this to check for 3 random and 4 random and so on.
randIndex = array_rand($arrX, 3)...randIndex = array_rand($arrX, 4)....
Php.net does not say array_rand function cannot pick the same keys.Personally never seen two picked at the same time.If that does happen.
The code should be expanded to record coins that are already picked,which should also prevent adding a coin against itself.
Here is a clean code...run this any sum that return amount between 29 and 35 should return found.
<?php
$arrX = array("1.1","20.1","3.5","4","5.7","6.8","7.3","8.6","9","10");
$desired = "32";
$randIndex = array_rand($arrX, 2);
$sumofpair = $arrX[$randIndex[0]] + $arrX[$randIndex[1]];
echo $arrX[$randIndex[0]];
echo " pair with ";
echo $arrX[$randIndex[1]];
echo " = ".$sumofpair;
if (($sumofpair >= "30") && ($sumofpair <= "35")){
echo "<br>This coin ".$arrX[$randIndex[0]]."+ This coin ".$arrX[$randIndex[1]]." = ".$sumofpair." This amount ~ equal
to ".$desired;
} else { echo "<br>Not a match so far.Refresh again</br>"; }
?>

Iterate through 2d array of booleans and leave only the largest contiguous "2D blob of ones"

Ok, so the question is kind of awkwardly phrased, but I hope this will clear things up.
I have this sample 2d array.
$array = array(
array(1, 0, 0, 0, 1, 0, 0, 1),
array(0, 0, 1, 1, 1, 1, 0, 1),
array(0, 1, 1, 0, 1, 0, 0, 0),
array(0, 1, 1, 0, 0, 0, 1, 0),
array(1, 0, 0, 0, 1, 1, 1, 1),
array(0, 1, 1, 0, 1, 0, 1, 0),
array(0, 0, 0, 0, 0, 0, 0, 1)
);
When iterated by rows (and terminating each row with \n), and for every row then iterated by column, it will echo something like this: (░░ = 0, ▓▓ = 1)
▓▓░░░░░░▓▓░░░░▓▓
░░░░▓▓▓▓▓▓▓▓░░▓▓
░░▓▓▓▓░░▓▓░░░░░░
░░▓▓▓▓░░░░░░▓▓░░
▓▓░░░░░░▓▓▓▓▓▓▓▓
░░▓▓▓▓░░▓▓░░▓▓░░
░░░░░░░░░░░░░░▓▓
But what I'd like to do is to "analyse" the array and only leave 1 contiguous shape (the one with the most "cells"), in this example, the result would be:
░░░░░░░░▓▓░░░░░░
░░░░▓▓▓▓▓▓▓▓░░░░
░░▓▓▓▓░░▓▓░░░░░░
░░▓▓▓▓░░░░░░░░░░
▓▓░░░░░░░░░░░░░░
░░▓▓▓▓░░░░░░░░░░
░░░░░░░░░░░░░░░░
My initial approach was to:
Assign each ▓▓ cell a unique number (be it completely random, or the current iteration number):
01 02 03
04050607 08
0910 11
1213 14
15 16171819
2021 22 23
24
Iterate through the array many, MANY times: every iteration, each ▓▓ cell assumes the largest unique number among his neighbours. The loop would go on indefinitely until there's no change detected between the current state and the previous state. After the last iteration, the result would be this:
01 21 08
21212121 08
2121 21
2121 24
21 24242424
2121 24 24
24
Now it all comes down to counting the value that occurs the most. Then, iterating once again, to turn all the cells whose value is not the most popular one, to 0, giving me the desired result.
However, I feel it's quite a roundabout and computationally heavy approach for such a simple task and there has to be a better way. Any ideas would be greatly appreciated, cheers!
BONUS POINTS: Divide all the blobs into an array of 2D arrays, ordered by number of cells, so we can do something with the smallest blob, too
Always fun, these problems. And done before, so I'll dump my code here, maybe you can use some of it. This basically follows every shape by looking at a cell and its surrounding 8 cells, and if they connect go to the connecting cell, look again and so on...
<?php
$shape_nr=1;
$ln_max=count($array);
$cl_max=count($array[0]);
$done=[];
//LOOP ALL CELLS, GIVE 1's unique number
for($ln=0;$ln<$ln_max;++$ln){
for($cl=0;$cl<$cl_max;++$cl){
if($array[$ln][$cl]===0)continue;
$array[$ln][$cl] = ++$shape_nr;
}}
//DETECT SHAPES
for($ln=0;$ln<$ln_max;++$ln){
for($cl=0;$cl<$cl_max;++$cl){
if($array[$ln][$cl]===0)continue;
$shape_nr=$array[$ln][$cl];
if(in_array($shape_nr,$done))continue;
look_around($ln,$cl,$ln_max,$cl_max,$shape_nr,$array);
//SET SHAPE_NR to DONE, no need to look at that number again
$done[]=$shape_nr;
}}
//LOOP THE ARRAY and COUNT SHAPENUMBERS
$res=array();
for($ln=0;$ln<$ln_max;++$ln){
for($cl=0;$cl<$cl_max;++$cl){
if($array[$ln][$cl]===0)continue;
if(!isset($res[$array[$ln][$cl]]))$res[$array[$ln][$cl]]=1;
else $res[$array[$ln][$cl]]++;
}}
//get largest shape
$max = max($res);
$shape_value_max = array_search ($max, $res);
//get smallest shape
$min = min($res);
$shape_value_min = array_search ($min, $res);
// recursive function: detect connecting cells
function look_around($ln,$cl,$ln_max,$cl_max,$nr,&$array){
//create mini array
$mini=mini($ln,$cl,$ln_max,$cl_max);
if($mini===false)return false;
//loop surrounding cells
foreach($mini as $v){
if($array[$v[0]][$v[1]]===0){continue;}
if($array[$v[0]][$v[1]]!==$nr){
// set shape_nr of connecting cell
$array[$v[0]][$v[1]]=$nr;
// follow the shape
look_around($v[0],$v[1],$ln_max,$cl_max,$nr,$array);
}
}
return $nr;
}
// CREATE ARRAY WITH THE 9 SURROUNDING CELLS
function mini($ln,$cl,$ln_max,$cl_max){
$look=[];
$mini=[[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]];
foreach($mini as $v){
if( $ln + $v[0] >= 0 &&
$ln + $v[0] < $ln_max &&
$cl + $v[1] >= 0 &&
$cl + $v[1] < $cl_max
){
$look[]=[$ln + $v[0], $cl + $v[1]];
}
}
if(count($look)===0){return false;}
return $look;
}
Here's a fiddle
I can only think of a few minor improvements:
Keep a linked list of the not empty fields. In step 2 you do not need to touch n² matrix-elements, you only need to touch the ones in your linked list. Which might be much less depending how sparse your matrix is.
You only need to compare to the right, right-down, left-down and down directions. Otherwise The other directions are already checked from the former row/column. What I mean: When I am greater that my right neighbour, I can already change the number of the right neighbour. (same for down and right-down). This halfs the number of compairs.
If your array size isn't huge and memory won't be a problem maybe a recursive solution would be faster. I found a c++ algorithm that does this here:
https://www.geeksforgeeks.org/find-length-largest-region-boolean-matrix/

How to distribute values across an array according to percentages

I'm making a DBZ Xenoverse 2 stat distribution guide according to build so you receive consistent gameplay in your attributes. The thought is that if by level 80 you have a total of 332 stat/attribute points to distribute, and you want to keep a consistent point allocation while creating your build, you would need to gather the percentages of the attributes from the total points gathered and assign them according to those percentages for each level. So if I wanted a character build that looked like:
Health - 30
Ki - 42
Stamina - 42
Basic Attacks - 93
Strike Supers - 0
Ki Blast Supers - 125
Total - 332
The percentages would look like:
Health - 9.03614457831325%
Ki - 12.65060240963855%
Stamina - 12.65060240963855%
Basic Attacks - 28.01204819277108%
Strike Supers - 0%
Ki Blast Supers -37.65060240963855%
So on level 2 (since you don't get stats for level one) you get two stat points and your Attributes would look like this:
Health - 0
Ki - 0
Stamina - 0
Basic Attacks - 1
Strike Supers - 0
Ki Blast Supers - 1
Whereas on level 20 your stats would look like this:
Health - 5
Ki - 7
Stamina - 7
Basic Attacks - 16
Strike Supers - 0
Ki Blast Supers - 22
Total - 57
So the end result would look like:
LVL 1
stat array
LVL 2
stat array
...
LVL 80
stat array
Since the character receives a variable number of stats per level we have to have a hardcoded array and change our distribution based on that, along with what has already been used and what should be used.
<?php
class Stats {
public function show_level_proportions( $build_stats ) {
$build_stat_labels = [ 'max_health', 'max_ki', 'max_stamina', 'basic_attack', 'strike_supers', 'ki_blast_supers' ];
$build = array_combine($build_stat_labels, $build_stats);
$stat_percents = $this->calculate_stat_percents($build);
$get_stats_per_lvl = $this->get_stats_per_lvl($stat_percents, $build);
return $get_stats_per_lvl;
}
//Stats given from levels 1-20
private $incremental_points = [
0, //1
2, //2
3, //3
3, //4
3, //5
3, //6
3, //7
3, //8
3, //9
3, //10
3, //11
3, //12
3, //13
3, //14
3, //15
3, //16
3, //17
3, //18
3, //19
4, //20 total: 57
];
private function calculate_stat_percents( $build_stats ) {
$stat_sum = array_sum( $build_stats );
foreach ( $build_stats as $key => $value ) {
$calculated_stat = $this->calc_percents($stat_sum, $value);
$stat_percentages[$key] = $calculated_stat;
}
return $stat_percentages;
}
private function calc_percents($sum, $stat){
$product = ( $stat / $sum );
return round( $product, 8, PHP_ROUND_HALF_UP );
}
/*================
* This is the problem area
* I can get the percentages for the inputted stats,
* but I don't even know how to start getting and
* distributing the percentages for each level. So
* right now, it's static, only works with the input,
* and doesn't incorporate the $incremental_stats.
================*/
private function get_stats_per_lvl($percentages, $stats){
$stats_total = array_sum($this->incremental_points);
foreach( $percentages as $key => $value ){
$lvl_twenty_stats[$key] = $stats_total * $value;
$rounded_lvl_twenty_stats[$key] = round( $lvl_twenty_stats[$key], 0, PHP_ROUND_HALF_UP );
}
return $rounded_lvl_twenty_stats;
}
}
$stat_tracker = new Stats();
print_r( $stat_tracker->show_level_proportions([5, 0, 5, 20, 7, 20]) );
Okay, so, to answer this, I'll first go over the theory, then the actual implementation in PHP.
Theory
So, for any given moment, you have your current attribute values, and your ideal attribute values.
For both collections of attributes, you can compute the percentage of the total each attribute represents.
So, for example, given an attribute collection like:
{
"foo": 2,
"baz": 1,
"bar": 3,
"foobar": 0
}
The total points here is 6, so the percentage of the total for each as computed would be (in pseudo-JSON):
{
"foo": 33.3%,
"baz": 16.6%,
"bar": 50.0%,
"foobar": 0.0%
}
If you compute this percentage list for each attribute collection (the desired and the current), you can then subtract each value of the desired from the current to get the percentage offset that each current value is off by.
So, a negative offset percentage indicates that the given stat that is associated with that offset is below where it should be, a 0 offset means it is exactly distributed evenly for that level, and a positive offset percentage indicates that the offset is above where it should be.
Since we can't distribute parts of a point, there will always be added points that knock it too high, so we can safely ignore the attributes that have a positive percentage offset.
Similarly, attributes with exactly 0 as their percentage offset can also be ignored, as at least at the current moment, that attribute is correctly distributed.
So, we're only really concerned with attributes that have a negative offset percentage, as those are the ones that need to be incremented.
To wrap it all together, for each point assigned, we need to compute the percentage offsets of the current attributes, assign a point to the attribute with the lowest offset percentage, and repeat the process until we are out of points, recording where, and how many, points we assigned in the process.
Example
Let's use the same example as in OP's question. The ideal distribution attributes collection is (attribute names truncated):
{
basic: 93,
ss: 0,
kbs: 125,
health: 30,
ki: 42,
stamina: 42
}
And the current is a collection of zeroes (because no points have been assigned yet):
{
basic: 0,
ss: 0,
kbs: 0,
health: 0,
ki: 0,
stamina: 0
}
And we have 2 points to assign.
Point 1
For the first point, we compute the percentage offsets, which looks like:
{
basic: -0.28012048192771083,
ss: 0,
kbs: -0.37650602409638556,
health: -0.09036144578313253,
ki: -0.12650602409638553,
stamina: -0.12650602409638553
}
If we ignore all zeroes/positive values (as described before), and sort the negatives by the lowest negative, we get this result:
[
{ name: 'kbs', value: -0.37650602409638556 },
{ name: 'basic', value: -0.28012048192771083 },
{ name: 'ki', value: -0.12650602409638553 },
{ name: 'stamina', value: -0.12650602409638553 },
{ name: 'health', value: -0.09036144578313253 }
]
With kbs (Ki Blast Supers) as the lowest offset, so, we assign one point to that, and then move on to the next point.
Point 2
Again, let's compute the percentage offsets, with the increased KBS value. Note that KBS is now positive due to the increase.
{
basic: -0.28012048192771083,
ss: 0,
kbs: 0.6234939759036144,
health: -0.09036144578313253,
ki: -0.12650602409638553,
stamina: -0.12650602409638553
}
And then, again, sort by lowest negative, throwing out zeroes and positive values. Note that KBS is now not eligible because it is slightly too high compared to the other values.
[
{ name: 'basic', value: -0.28012048192771083 },
{ name: 'ki', value: -0.12650602409638553 },
{ name: 'stamina', value: -0.12650602409638553 },
{ name: 'health', value: -0.09036144578313253 }
]
So now basic (Basic Attacks) has the lowest negative, and so we assign the final point to it.
So, our total points assigned looks like:
{
kbs: 1,
basic: 1
}
Which is correctly assigned based on OP's expected results.
Implementation
As for implementation in PHP, I won't give a 100% working example, but the basic idea is you want a function called something like getPointsDistributionForTarget which takes the current attribute scores, the target attribute score distributions, and the amount of points to assign.
function getPointsDistributionForTarget(current, target, pointsToSpend) { ... }
Within that function, you'll want to loop the amount of times there is points to spend, doing the following each loop:
Computing the sorted array of offset percentages
Take the top (0th index) value and:
Increasing the associated current attribute value and increasing it by one, and
Note down that you increased that attribute by one, in a running list of totals per attribute
Hopefully this helps! Let me know if you have any issues. I have a working implementation in Node (Javascript) I can provide that I used to test this theory and produce the numbers in the example, or I can try to convert that example to PHP if it helps.

Divide a two dimensional array into surfaces

For a project it's required to arrange a two dimensional array into planes that are in proportion to each other based on a the percentage of each plane. (I hope this make sense, else see example below). In this 2D array the 'first' level represents the rows and the 'second' level, the columns. For example;
array(
// row 1
array(
// items
number1
number2
numberN
),
// row 2
array(
// items..
),
// row N
array(
// items..
)
)
The numbers in this array has te be added/arranged in such a way that they form panels. The panels together form one grid. Each digit is representing a item (doesn't matter for the question what this is). I came up with a solution myself. Click here for print of the 2D array (The groups are color coded.).
Lets say, there are three groups (listed below). The groups do represent the panels, introduced above. Each group has some percentage between zero and hundred. The sum of the percentage of the planes is required to be hundred percent. The maximum amount of group is seven. Example group info;
Group 1 (Panel A): 70%
Group 2 (Panel B): 20%
Group 3 (Panel C): 10%
Again this arrangement should result in one large panel with (sub)panels in it. As shown in this schematic figure.
I came up whit the idea to divide the end result into 4 corners. Each corner will be calculated by the rules. These corners should than be mirror (horizontally and/or vertically) based on what corner it is (Upper left, Upper right, Lower left, Lower right).
List of rules;
The number of items should be te same for each row
The aspects ratio of the complete grid should be 2 to 1. So the width is two times the hight.
The amount of rows are based on the total items, since the aspect is known.
After some days of work I was able to come up with a working script. But this does act weird (weird as in, not as expected) in some cases. See current solution above.
So, my question is; How do lever designers this? Is this a known problem and are there solution (like algorithm) what solve this (kind of) questions? I am struggling with the following problem for a long time now. Searching on the internet, trying to find similar problems. But I did not succeed.
I am not asking for a ready made solution. Just a pointer in the right direction would be much appreciated.
Assuming the planes should have approximately the same "aspect ratio" as the complete matrix, you could use this algorithm:
Calculate for each percentage what would be the coefficient to apply to the width and height to get the exact area that would be left over after subtracting the percentage of the available area. This coefficient is the square root of the coefficient that needs to be applied to the area (related to the percentage).
As this coefficient will in general be a non-integer number, check which way of rounding the width and height yields an area that comes closest to the desired area.
Repeat this for each plane.
Here is the code:
function createPlanes($width, $height, $groupPercentages) {
$side = 0;
$area = $width * $height;
$planeWidth = $width;
$planeHeight = $height;
$sumPct = 0;
$coefficient2 = 1;
foreach ($groupPercentages as $i => $pct) {
$plane = [
"column" => floor(($width - $planeWidth) / 2),
"row" => floor(($height - $planeHeight) / 2),
"width" => $planeWidth,
"height" => $planeHeight,
];
$coefficient2 -= $pct / 100;
$coefficient = sqrt($coefficient2);
$planeArea = $coefficient2 * $area;
$planeWidth = $coefficient * $width;
$planeHeight = $coefficient * $height;
// determine all possible combinations of rounding:
$deltas = [
abs(floor($planeWidth) * floor($planeHeight) - $planeArea),
abs(floor($planeWidth) * min(ceil($planeHeight), $plane["height"]) - $planeArea),
abs(min(ceil($planeWidth), $plane["width"]) * floor($planeHeight) - $planeArea),
abs(min(ceil($planeWidth), $plane["width"]) * min(ceil($planeHeight), $plane["height"]) - $planeArea)
];
// Choose the one that brings the area closest to the required area
$choice = array_search(min($deltas), $deltas);
$planeWidth = $choice & 2 ? ceil($planeWidth) : floor($planeWidth);
$planeHeight = $choice & 1 ? ceil($planeHeight) : floor($planeHeight);
$newSumPct = ($area - $planeWidth * $planeHeight) / $area * 100;
$plane["pct"] = $newSumPct - $sumPct;
$sumPct = $newSumPct;
$planes[] = $plane;
}
return $planes;
}
// Example call for a 2D array with 20 columns and 32 rows, and
// three percentages: 10%, 20%, 70%:
$planes = createPlanes(20, 32, [10, 20, 70]);
The $planes variable will get this content:
array (
array (
'column' => 0,
'row' => 0,
'width' => 20,
'height' => 32,
'pct' => 10.9375,
),
array (
'column' => 0,
'row' => 1,
'width' => 19,
'height' => 30,
'pct' => 20,
),
array (
'column' => 1,
'row' => 3,
'width' => 17,
'height' => 26,
'pct' => 69.0625,
),
)
The inner attributes define where the plane starts (row, column), and how large it is (height, width), and which is the actual percentage that plane is in relation to the total area.
Note that the actual 2D does not need to be part of the algorithm, as its values don't influence it.

Get number by knowing chance

I don't think the article title is correct so I will try to explain what I need.
ATM I have array:
array(
'start' => 1,
'end' => 10,
'lucky_numbers' => 6
);
and knowing this array I can define that chance to win is 60% out of 100%. The next part is the second array:
array(0, 1.25, 0.5, 1.25, 0, 3, 0, 1, 0.5, 1.25, 0.5, 1.25, 0, 2, 0.5, 2)
and this is the hard part. I don't have any clue how to pick one number knowing that chance to pick not a zero is 60%. Any ideas?
EDIT
this is the wheel numbers. when user spins the wheel i need to give him 60% chance to win. So 60% chance to spin not the 0
Let me see if i understand:
-This is a "slots like" winnings multiplier minigame for a game where you roll a "wheel" showing the possibles multipliers the player can win, this wheel is the second array, this array is variable in lenght.
-You want to give the player a variable chance to win (sometimes 60%, sometimes 80%, sometimes 20%).
If you only want to be sure the player doesn't get a "0%" multiplier, do the opposite, take the possibility of a "0%" to appear and put them the equivalent in the array and then fill the array with random multipliers and shuffle it.
$multipliers = [0.5, 1.25, 2, 3];
$wheel = [];
for ($i = 0; $i < $arraylenght; $i++) {
if ($i < floor($arraylenght * (1 - ((float)$luckyNumbers/10)))){
$wheel[] = 0;
} else {
$wheel[] = array_rand($multipliers);
}
}
shuffle($wheel);
Now if you also want to control the probabilities of each multiplier... That's another beast.

Categories