I have this array, I want to make conditional action based on the items hierarchy in the array. I'm going to compare between items based on their hierarchy and it will result a 2 dimensional array like this.
The comparison is : Imagine that there are 3 stair, in the highest stair is 5, the second stair is 3 and the last stair is 1.
If a number compared with the 1st lower floor then it'll be 3 and if a number compared with the 2nd lower floor then it'll be 5. Example : if 5 is compared with 3 then it'll be 3, if 5 is compared with 1 then it'll be 5. If a number compared with the 1st upper floor then it'll be 1/3 and if a number compared with the 2nd upper floor then it'll be 1/5. Example if 1 is compared with 3 then it'll be 1/3 and if 1 is compared with 5 then it'll be 1/5. And if 3 is compared with 5 then it'll be 1/3 and if 3 is compared with 1 then it'll be 3.
So far, this is my code
$weightvalue = array(5,3,1);
$numbers = count($weightvalue);
for ($row = 0; $row < $numbers; $row++) {
for ($column = 0; $column < $numbers; $column++) {
echo "$weightvalue[$row],$weightvalue[$column] ";
if ($weightvalue[$row]==$weightvalue[$column]) {echo "1";}
elseif ($weightvalue[$row]<$weightvalue[$column]) {echo "1/3";}
elseif ($weightvalue[$row]<$weightvalue[$column]) {echo "1/5";}
elseif ($weightvalue[$row]>$weightvalue[$column]) {echo "3";}
elseif ($weightvalue[$row]>$weightvalue[$column]) {echo "5";}
else {echo "false";};
echo ("\n");
}
}
So far this is the result, but there're some mistakes, I know what causes this but I don't know how to fix it. Please help, any suggestion will very much appreciated.
Related
I am adding in feed Ads to my website. I have a foreach statement that creates a list of posts. I have created a counter that is supposed to count every four posts and insert the Ad content then repeat.
I have tried some other iterations of this but this is the one I can actually get to do something. I can find a lot of info on this exact thing pertaining to wordpress. But I am running cake php and would prefer a pure php solution.
<?php
$count = 1;
foreach($stories as $story) {
echo '<h2>'.$story->title.'</h2>';
if(!empty($story->excerpt)) {
echo $story->excerpt;
} else {
echo limit_text($story->body);
}
if ($count % 4 == 1) {
echo AD_SENSE_INFEED;
}
}
$count++;
?>
This code is what I currently have but its not working the way I would like it to. As if now it basically goes every other. So POST, AD, POST AD...etc.
Your problem isn't a coding problem, its a math problem. What you're using is called modulos or remainders basically.
So that said:
if ($count % 4 == 1) {
For it to equal 1 we have to feed in something that goes in evenly once and leaves one more.
What you want to do is:
if ($count % 4 == 0) {
Aka it means there's no remainder, 4 goes into it evenly with nothing left over.
As #RiggsFolly mentioned and I completely missed this(Give his comment a up vote) your $count variable should be incremented inside the loop as well otherwise it will only increment once after the loop ends.
You can get rid of count all together (and just use the numeric index of the array)
//just some "test" data
$stories = array_fill(0, 100, []);
foreach( $stories as $count => $story) {
echo $count." ".($count % 4)."\n";
if ($count % 4 == 3) {
echo "--------------------------------------\n";
}
}
Output:
0 0
1 1
2 2
3 3
--------------------------------------
4 0
5 1
6 2
7 3
--------------------------------------
...
Sandbox
If your not sure if the keys are in proper order, you can reset them:
foreach(array_values($stories) as $count => $story) {
Obviously an array starts at 0, so you have to offset the % result a bit ... lol ... Yes I am to lazy to increment.
I am look to code a system by where a given number is given by the user and then a script will work out the total number of combinations using that number all the way down to one.
so if the number was 10 it would need to find all the combinatins of ten numbers, nine numbers, 8 numbers and so on down to one!
So say if the number is 3
then you have
3 number combinations (1,2,3) => 1
2 number combinations (1,2)(1,3)(2,3) => 3
1 number combinations (1)(2)(3) => 3
if the nuber is 4
then you would have
4 number combinations (1,2,3,4) => 1
3 number combinations (1,2,3)(1,2,4)(1,3,4)(2,3,4) => 4
2 number combinations (1,2)(1,3)(1,4)(2,3)(2,4)(3,4) => 6
1 number combinations (1)(2)(3)(4) => 4
and so on...
i wouldn't need different order combinations just the combinations itself and again the number could be anything though its unlikely to be over 10
does anyone know a way to code this so any given nubmer it will produce the combinations?
at the moment i have hard coded up to 5 numbers but its alot of coding, there has to be a simpler way of doing it :)
Hope this makes sense :)
Any help/directions to go woud be hugely appreciated
Thanks
If you just want to know how many combinations there are (regardless of the order of the elements within the combinations) use this formula:
n!/(k!(n-k)!) where n is how many numbers you have and k is how many numbers you have per combination. So if the number is 9 and you want to know how many combinations you can have grouping those numbers in pairs. it would give you: 9!/(2!(9-2)!) = 36
helpful:
http://en.wikipedia.org/wiki/Combination
And as for coding it in php
$n = $_GET['number'];
echo "Combinations for $n numbers:";
for ($k = 1; $k <= $n; $k++) {
$combinations = factorial($n)/(factorial($k)*factorial($n-$k));
echo "<br>Grouped by $k:" . $combinations;
}
function factorial($number) {
if ($number == 0) return 1;
return $number * factorial($number - 1);
}
Edit:
To print out all combinations:
combinations(range(1, $n), $k);
function combinations($numbers, $count, $prefix = ""){
if ($count == 0) {
echo "<br>". $prefix;
} else {
foreach ($numbers as $number) {
$offset = array_search ( $number , $numbers)+1;
combinations(array_slice($numbers, $offset), $count-1, $prefix . $number);
}
}
}
I have this logic written that loops out an array into <li>
and gives #1 and every 5th a class of "alpha".
$count = 0;
foreach($gallery->data as $row){
if ($count==0 || $count%4==0) {
echo '<li class="alpha"></li>'.PHP_EOL;
} else {
echo '<li></li>'.PHP_EOL;
}
$count++;
}
I need to add to this and get the code adding a class of "omega" to every 4th <li>
You do realize that as you describe it, there will be some overlap right? (example - item 30 is both a '5th' and a '6th') Brian gave you an answer for exactly what you described, but I'm not sure if its what you want. You want ALPHA, x, x, x, OMEGA, ALPHA, x, x, x, OMEGA, ALPHA.....
You seem to want Alpha on the 5*k + 1, and Omega on 5*k
conditions:
alpha - ($count + 1) % 5 == 1
omega - ($count + 1) % 5 == 0
I think grouping in the addition makes this easier to understand, since you're count starts at 0 but you seem to be thinking in terms of beginning at 1. If you don't like that, lose the addition and change the equivalences to 0 and 4, respectively - $count % 5 == 0 and $count % 5 == 4
i know this is better suited for a comment under the last answer, but I don't see how. Am i not allowed until my reputation is higher or am i just missing something?>
right now as it stands your code adds the "alpha" class to every fourth item beginning with the first, not every fifth. In other words, items 1, 5, 9, 13, etc. will have a class of "alpha" since your counter begins at 0.
I assume that you want to add the "omega" class then to items 4, 8, 12, etc. Here's what you need to do that:
$count = 0;
foreach($gallery->data as $row){
if ($count%4==0) {
echo '<li class="alpha"></li>'.PHP_EOL;
}
else if ($count%4==3) {
echo '<li class="omega"></li>'.PHP_EOL;
}
else {
echo '<li></li>'.PHP_EOL;
}
$count++;
}
Im trying to make dynamic column list that will be 4 columns total (PHP). Im echoing an array and after every time 4 array items are echod, I would like to wrap those 4 array items in a div called "column".
So basically, I thought I could do this with a self counting $i++ statement, but first off I'm having trouble starting the count from anything but zero (I tried setting the variable initially outside of the for each loop.)
Anyways, ya, if you could kindly show me how to check to see if the $++ is divisible by 4 in php, so that I can insert a if $i++ is divisible by 4 then echo "" , it would be much appreciated. But first I believe I need to figure out how to start the counting at 1 (so that the if $i++ is divisible by 4 would work... right??)
If you divide by 4 it will be integer division and the quotient will be the factor of 4. What you probably want is the modulus operator %. It will give you the remainder. So when $i is a multiple of 4 it will be 0.
if (($i % 4) == 0) {
// evenly divisible by 4 logic
}
Modulus can be inefficient. Since you are dividing by a multiple of 2, you could shift bits right by 2. It is the same as dividing by 4 and much more efficient. Check out bit shifting.
% is the modulus operator. It returns the remainder after a division, so 7 % 4 == 3.
You really should start from 0. This is because 0 % 4 == 0 and 4 % 4 == 0... AND you want the very first item to be a new row! So you want new rows on 0, 4, 8, etc... If you start at one, then 1, 2, and 3 would not be in a row.
Additionally, we have to remember to close the row on every item one before a new row.
Finally, if we exit our loop without closing the final row, we have to do that after we have exited the loop.
I'll show how to do this with tables, but you can use divs with classes just as easilly.
<table>
<?php
// Start at zero, so we start with a new row
// Since we start at 0, we have to use < number of items, not <=
for ($i = 0; $i < $numberOfItems; ++$i)
{
// if divisible by 0 start new row
if ($i % 4 == 0)
echo '<tr>';
// Always print out the current item
echo '<td>' . $item[$i] . '</td>';
// If the next $i is divisible by 4, we have to close the row
if ($i % 4 == 3)
echo '</tr>';
}
// If we didn't end on a row close, make sure to close the row
if ($i % 4 != 3)
echo '</tr>';
?>
</table>
Modulus!
$a % $b Remainder of $a divided by $b.
http://php.net/manual/en/language.operators.arithmetic.php
I have below a function (from a previous question that went unanswered) that creates an array with n amount of values. The sum of the array is equal to $max.
function randomDistinctPartition($n, $max) {
$partition= array();
for ($i = 1; $i < $n; $i++) {
$maxSingleNumber = $max - $n;
$partition[] = $number = rand(1, $maxSingleNumber);
$max -= $number;
}
$partition[] = $max;
return $partition;
}
For example: If I set $n = 4 and $max = 30. Then I should get the following.
array(5, 7, 10, 8);
However, this function does not take into account duplicates and 0s. What I would like - and have been trying to accomplish - is to generate an array with unique numbers that add up to my predetermined variable $max. No Duplicate numbers and No 0 and/or negative integers.
Ok, this problem actually revolves around linear sequences. With a minimum value of 1 consider the sequence:
f(n) = 1 + 2 + ... + n - 1 + n
The sum of such a sequence is equal to:
f(n) = n * (n + 1) / 2
so for n = 4, as an example, the sum is 10. That means if you're selecting 4 different numbers the minimum total with no zeroes and no negatives is 10. Now go in reverse: if you have a total of 10 and 4 numbers then there is only one combination of (1,2,3,4).
So first you need to check if your total is at least as high as this lower bound. If it is less there is no combination. If it is equal, there is precisely one combination. If it is higher it gets more complicated.
Now imagine your constraints are a total of 12 with 4 numbers. We've established that f(4) = 10. But what if the first (lowest) number is 2?
2 + 3 + 4 + 5 = 14
So the first number can't be higher than 1. You know your first number. Now you generate a sequence of 3 numbers with a total of 11 (being 12 - 1).
1 + 2 + 3 = 6
2 + 3 + 4 = 9
3 + 4 + 5 = 12
The second number has to be 2 because it can't be one. It can't be 3 because the minimum sum of three numbers starting with 3 is 12 and we have to add to 11.
Now we find two numbers that add up to 9 (12 - 1 - 2) with 3 being the lowest possible.
3 + 4 = 7
4 + 5 = 9
The third number can be 3 or 4. With the third number found the last is fixed. The two possible combinations are:
1, 2, 3, 6
1, 2, 4, 5
You can turn this into a general algorithm. Consider this recursive implementation:
$all = all_sequences(14, 4);
echo "\nAll sequences:\n\n";
foreach ($all as $arr) {
echo implode(', ', $arr) . "\n";
}
function all_sequences($total, $num, $start = 1) {
if ($num == 1) {
return array($total);
}
$max = lowest_maximum($start, $num);
$limit = (int)(($total - $max) / $num) + $start;
$ret = array();
if ($num == 2) {
for ($i = $start; $i <= $limit; $i++) {
$ret[] = array($i, $total - $i);
}
} else {
for ($i = $start; $i <= $limit; $i++) {
$sub = all_sequences($total - $i, $num - 1, $i + 1);
foreach ($sub as $arr) {
array_unshift($arr, $i);
$ret[] = $arr;
}
}
}
return $ret;
}
function lowest_maximum($start, $num) {
return sum_linear($num) + ($start - 1) * $num;
}
function sum_linear($num) {
return ($num + 1) * $num / 2;
}
Output:
All sequences:
1, 2, 3, 8
1, 2, 4, 7
1, 2, 5, 6
1, 3, 4, 6
2, 3, 4, 5
One implementation of this would be to get all the sequences and select one at random. This has the advantage of equally weighting all possible combinations, which may or may not be useful or necessary to what you're doing.
That will become unwieldy with large totals or large numbers of elements, in which case the above algorithm can be modified to return a random element in the range from $start to $limit instead of every value.
I would use 'area under triangle' formula... like cletus(!?)
Im really gonna have to start paying more attention to things...
Anyway, i think this solution is pretty elegant now, it applies the desired minimum spacing between all elements, evenly, scales the gaps (distribution) evenly to maintain the original sum and does the job non-recursively (except for the sort):
Given an array a() of random numbers of length n
Generate a sort index s()
and work on the sorted intervals a(s(0))-a(s(1)), a(s(1))-a(s(2)) etc
increase each interval by the
desired minimum separation size eg 1
(this necessarily warps their
'randomness')
decrease each interval by a factor
calculated to restore the series sum
to what it is without the added
spacing.
If we add 1 to each of a series we increase the series sum by 1 * len
1 added to each of series intervals increases sum by:
len*(len+1)/2 //( ?pascal's triangle )
Draft code:
$series($length); //the input sequence
$seriesum=sum($series); //its sum
$minsepa=1; //minimum separation
$sorti=sort_index_of($series) //sorted index - php haz function?
$sepsum=$minsepa*($length*($length+1))/2;
//sum of extra separation
$unsepfactor100=($seriesum*100)/($seriesum+sepsum);
//scale factor for original separation to maintain size
//(*100~ for integer arithmetic)
$px=series($sorti(0)); //for loop needs the value of prev serie
for($x=1 ; $x < length; $x++)
{ $tx=$series($sorti($x)); //val of serie to
$series($sorti($x))= ($minsepa*$x) //adjust relative to prev
+ $px
+ (($tx-$px)*$unsepfactor100)/100;
$px=$tx; //store for next iteration
}
all intervals are reduced by a
constant (non-random-warping-factor)
separation can be set to values other
than one
implementantions need to be carefuly
tweaked (i usualy test&'calibrate')
to accomodate rounding errors.
Probably scale everything up by ~15
then back down after. Intervals should survive if done right.
After sort index is generated, shuffle the order of indexes to duplicate values to avoid runs in the sequence of collided series.
( or just shuffle final output if order never mattered )
Shuffle indexes of dupes:
for($x=1; $x<$len; $x++)
{ if ($series($srt($x))==$series($srt($x-1)))
{ if( random(0,1) )
{ $sw= $srt($x);
$srt($x)= $srt($x-1);
$srt($x-1)= $sw;
} } }
A kind of minimal disturbance can be done to a 'random sequence' by just parting dupes by the minimum required, rather than moving them more than minimum -some 'random' amount that was sought by the question.
The code here separates every element by the min separation, whether duplicate or not, that should be kindof evenhanded, but overdone maybe. The code could be modified to only separate the dupes by looking through the series(sorti(n0:n1..len)) for them and calculating sepsum as +=minsep*(len-n) for each dupe. Then the adjustment loop just has to test again for dupe before applying adjustment.