Automate sum in array - php

I will try to explain the problem that I have with this code.
This script works well to up to three persons ($numRows = 3).
$z=0;
$i=0;
$x=0;
do {
$total[] = (
${'contaH'.$z}[$i+0]*$final[$x+0]+
${'contaH'.$z}[$i+1]*$final[$x+1]+
${'contaH'.$z}[$i+2]*$final[$x+2]
);
$z++;
} while ($z<$numRows); //3
But if I have only four persons ($numRows = 4), I need something like this:
$z=0;
$i=0;
$x=0;
do {
$total[] = (
${'contaH'.$z}[$i+0]*$final[$x+0]+
${'contaH'.$z}[$i+1]*$final[$x+1]+
${'contaH'.$z}[$i+2]*$final[$x+2]+
${'contaH'.$z}[$i+3]*$final[$x+3]
// if they are 5 persons ($numRows=5), here, should exists another row
);
$z++;
} while ($z<$numRows); //4
So the problem is to automate these changes in relation of $numRows.
Here is a demo of matrix algebra:
The only thing that I want is put my code dynamically in a function of number of persons.
A | B | C | D
Person1
Person2
Person3
Person4
...
What can be different in my case is just the number of persons.
More information here.

$z=0;
$i=0;
$x=0;
$numRows = 5;
do{
$currentSum = 0;
for($c = 0; $c < $numRows; $c++){
$currentSum += (${'contaH'.$z}[$i+$c] * $final[$x+$c]);
}
$total[] = $currentSum;
$z++;
}while($z < $numRows);

$subtotal = 0;
for ($i = 0; $i < $numRows; $i++) {
$subtotal += ${'contaH'.$z}[$i] * $final[$i];
}
$total[] = $subtotal;

You might be interested in the Math_Matrix library which will help you do all sorts of matrix arithmetic.
The following code, however, automates your solution:
function mat_mult($matrix, $vector) {
$result = array();
$matrixWidth = count($matrix[0]);
for ($z = 0; $z < $matrixWidth; $z++) {
$value = 0;
for ($y = 0; $y < $matrixWidth; $y++) {
$value += $matrix[$z][$y]*$vector[$y];
}
$result[] = $value;
}
return $result;
}
$matrix = array(
array(1, 1/3.0, 2, 4),
array(3, 1, 5, 3),
array(1/2.0, 1/5.0, 1, 1/3.0),
array(1/4.0, 1/3.0, 3, 1)
);
$vector = array(0.26, 0.50, 0.09, 0.16);
$v2 = mat_mult($matrix, $vector);
print_r($v2);
Also, to tie it more into your existing matrix structure:
$matrix = array();
for ($z = 0; $z < $numRows; $z++) {
$matrix[] = ${'contaH'.$z};
}

Related

Create two-dimensional array by using 2 loops

I need to create two-dimensional array by using 2 loops.
Array must look like this: [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
This is what I tried, but I wanted to see better solution and to know is my solution bad.
<?php
$arr = [];
$elem = 1;
for ($i = 0; $i <= 2; $i++) {
for ($j = 1; $j <= 3; $j++) {
$arr[$i][] = $elem++;
}
}
?>
$number = range(1,9);
print_r (array_chunk($number,3));
Others have shown you some clever ways, but keeping it simple in case you are just starting out with programming.... In the inner loop, create a temporary array, then outside the inner loop but inside the outer, add it to your main array.
$arr = [];
$elem = 1;
for ($i = 0; $i <= 2; $i++) {
$t = []; #Init empty temp array
for ($j = 1; $j <= 3; $j++) {
$t[] = $elem++;
}
$arr[] = $t;
}
One of hundreds options:
$arr = [
range(1, 3),
range(4, 6),
range(7, 9),
];
print_r($arr);
one method: this method use "temp variables".
<?php
$arr_inner = [];
$arr_main = [];
$elem=1;
for ($i = 0; $i <= 2; $i++) {
for ($j = 0; $j <= 2; $j++) {
$elem =$elem +1;
$arr_inner[$j] = $elem;
}
$arr_main[$i] = $arr_inner;
unset($arr_inner);
}
?>

How to calculate Diagonal difference in PHP?

I have a N*N Matrix.Now i want to know the diagonal difference of this Matrix.What will be the best approach of this solution?
I am trying with given approach:
Such as it is 3*3 Matrix say it is:
11 15 85
66 72 21
14 21 47
the diagonal simple formula will be:
firstD= (11+72+47) = 130
secondD = (85+72+14)= 171
diagonalDiff = |firstD - secondD| = |130-171| = 41
If I count every row such as first to find out firstD (First row's first value + Sec row's Sec value + Third row's third value+..).This is my thinking.
Can anyone tell me best approaches?
Try this:
$arr = array(
array(11, 15, 85),
array(66, 72, 21),
array(14, 21, 47),
);
$arrDiag = count($arr);
$firstD = 0;
$secondD = 0;
$i = 0;
for($j = 0; $j < $arrDiag; $j++){
$firstD += $arr[$i++][$j];
$secondD += $arr[$arrDiag - $i][$j];
}
echo abs($firstD - $secondD);//41
Model your matrix with a multi-dimensional array and iterate through it. The easiest way should be the following:
<?
$matrix = array(array(1,2,3),array(4,5,6),array(7,8,9)); //Insert or define your matrix here..
$n = count($matrix); //Size of matrix, thanks to VolkerK
$firstD = 0;
$lastD = 0;
for($i = 0; $i < $n; $i++){
$firstD += $matrix[$i][$i];
$lastD += $matrix[$i][$n-$i-1];
}
echo $firstD."\n";
echo $lastD;
Here is a pseudo code for your problem using one simple loop:
// $array - predefined 2 dimentional array with $N rows and $N columns
$result = 0;
for ($i=0;$i<$N;$i++) {
$result += ($array[$i,$i] - &array[$i,$N-$i-1]);
}
return echo abs($result);
that way you can do the calculation in one pass, and do a diff between two elements in each row insead of calculation the sum of each diagonal
Try this:
function diagonalDifference($arr) {
$left = 0;
$right = 0;
$i = 0;
foreach($arr as $ar){
$left+= $ar[0+$i];
$right+= $ar[count($ar) - (1+$i)];
$i++;
}
return abs($left - $right);
}
Try this
$result=0;
for($i=0;$i<=count($arr)-1;$i++){
$result= $result+($arr[$i][$i])-($arr[(count($arr)-1-$i)] [$i]);
}
return abs($result);
This is the code you need:
$first = 0;
$second = 0;
for($i = 0; $i < N; $i++) {
for($j = 0; $j < N; $j++) {
if($i == $j) {
$first += $matrix[$i][$j];
} else if($i + $j == N) {
$second += $matrix[$i][$j];
}
}
}
$diagonalDiff = abs($first - $second);
Where $matrix is a N*N array
Just using the function array_reduce:
function diagonalDifference($arr) {
$i = 0;
$n = count($arr);
return abs(array_reduce($arr,
function ($c, $str) use (&$i, $n ) {
$i++;
return $c + $str[$i-1] - $str[$n-$i];
}, 0));
}
demo
you can try this :
$first_diag=$second_diag=0;
$matrix=array(array(11,15,85),array(66,72,21),array(14,21,47));
foreach($matrix as $index=>$sub_array){
$first_diag +=$sub_array[$index];
$second_diag +=$sub_array[count($matrix)-1-$index];
}
print abs ($first_diag-$second_diag);
For one you can use a matrix library like Math_Matrix. But if this is the only operation you are gona need then it's best to write a generalized function for this using the same method you quoted yourself.
function diagonalDiff($n){
$firstD = 0;
$secondD = 0;
for($i=0;$i<$n;$i++){
for($j=0;$j<$n;$j++){
if($i == $j) {
$first += $matrix[$i][$j];
} else if($i + $j == $n) {
$secondD += $matrix[$i][$j];
}
}
}
return abs($firstD-$secondD);
}
Should give you the answer you need for a matrix of a given size $n. (Only square Matrixes ofcourse :) )
Another better solution and it's easy to understand:
<?php
$arr = array(
array(11, 15, 85),
array(66, 72, 21),
array(14, 21, 47),
);
$arrDiag = count($arr);
$firstD = 0;
$secondD = 0;
$i = 0;
for($j = 0; $j < $arrDiag; $j++){
$i++;
$firstD += $arr[$j][$j];
$secondD += $arr[$arrDiag - $i][$j];
}
echo abs($firstD - $secondD);
?>
DEMO
Recently solved this question in Hacker Rank.
<?php
$m=array(array(3,4,-1,11,2),
array(-3,2,1,6,9),
array(3,4,6,5,-2),
array(1,9,9,7,-3),
array(12,9,16,7,-3));
echo count($m)."<br>";
$i=0;
$j=0;
$ek=0;
$k=0;
$n=1;
$es=count($m)-1;
for($i=0;$i<count($m);$i++)
{
for($j=0;$j<count($m);$j++)
{
echo $m[$i][$j]." ";
}
echo "<br>";
}
echo "<br>";
for($k=0;$k<count($m);$k++)
{
for($n=0;$n<count($m);$n++)
{
if($k==$n){
$ek=$ek+$m[$k][$n];
}
}
echo "<br>";
}
echo "<hr>";
$p=0;
for($k=0;$k<count($m);$k++)
{
echo $m[$k][$es-$p]."<br> ";
$p++;
}
?>
Sorry I used different variable names, I had to take this to my vs code.
$b = array(
array(1,2,5),
array(3,4,5),
array(3,4,5)
);
//So for each diag
echo $b[0][0] + $b[1][1] + $b[2][2]; //to sum the first diag
echo $b[0][2] + $b[1][1] + $b[2][0]; //to sum the second diag
//notice the pattern 00, 11, 22 vs 02,11, 20. hence why I have written the function below
function difference($b){
$d1 = 0;
$d2 = 0;
$count = count($b);
for($i=0; $i<$count; $i++){
$d1 += $b[$i][$i];
$d2 += $b[$i][$count-1-$i];
}
return abs($d1 - $d2);
}
I had the same issue, the instructions was given by the site, mislead me. However, I solved it in this way,
$n = count and store the length of input array
//define variables to store first diagonals and second diagonals
$fd = 0;
$sd = 0;
//loop through the 2D array with $i increment
$j = get an array from the main array
//in each iteration
$pd += get the values from the left to the right and add;
$sd += get the values from the right to the left and add;
}
find absolute difference between the sums using built in abs function and return it;
I think this would help someone

Divide integer number into dynamic number of parts using php

I want to divide a number into n number of parts like follows
Input : $n = 4;$m =14;
Output should as : array(1=>4,2=>4,3=>3,4=>3);
i.e :
$n $m
1 1+1+1+1
2 1+1+1+1
3 1+1+1
4 1+1+1
Any suggestions or links would help a lot.
Here is one way to do it - this works in phpfiddle:
$n = 4;
$m =14;
$array = distribute($m,$n);
print_r($array);
function distribute($m,$n) {
$div = floor($m / $n);
$mod = fmod($m, $n);
$result = array();
for ($i = 1;$i <= $n;$i++) {
$result[$i] = $div;
}
if ($mod > 0) {
for ($i = 1;$i <= $mod;$i++) {
$result[$i] = $result[$i] + 1;
}
}
return $result;
}

How to create a 2D array that values BA and AB are treated as the same

I am trying to create function that allows me to get all combinations of an array to later generate a list.
But my problem is that currently my function treat "ab" as different from "ba". I dont know how to explain it in words but I guess the picture below exemplify what I try to achieve.
function everyCombination($array) {
$arrayCount = count($array);
$maxCombinations = pow($arrayCount, $arrayCount);
$returnArray = array();
$conversionArray = array();
foreach ($array as $key => $value) {
$conversionArray[base_convert($key, 10, $arrayCount)] = $value;
}
for ($i = 0; $i < $maxCombinations; $i++) {
$combination = base_convert($i, 10, $arrayCount);
$combination = str_pad($combination, $arrayCount, "0", STR_PAD_LEFT);
$returnArray[] = strtr($combination, $conversionArray);
}
return $returnArray;
}
$a = everyCombination(array('a', 'b', 'c','d'));
print_r($a);
The desired ouput would be
a
ab
abc
abcd
b
bc
bcd
c
cd
d
What you need to do is iterate through the array recursively, for each recursion you should only iterate through all the greater elements. Like so:
function everyCombination($arr) {
$combos = array();
$len = count($arr);
for( $i=0; $i<$len; $i++) {
for( $j=$i+1; $j<=$len; $j++) {
$combos[] = implode("",array_slice($arr,$i,$j-$i));
}
}
return $combos;
}
Example call:
everyCombination(['a','b','c','d']);
Returns:
['a','ab','abc','abcd','b','bc','bcd','c','cd','d']
It seems that you're after consecutive results, so a double loop would be a better choice here; recursion requires more control.
function combos($array)
{
if (!$array) {
return [];
}
$n = count($array);
$r = [];
for ($i = 0; $i < $n; ++$i) {
$prefix = '';
for ($j = $i; $j < $n; ++$j) {
$r[] = $prefix . $array[$j];
$prefix .= $array[$j];
}
}
return $r;
}
print_r(combos([1, 2, 3, 4]));

Populate 4 arrays evenly distributed as much as possible from top to bottom

This question is in relation to this post
How to distribute mysql result set in an multidimensional array of 4 arrays
I got the accepted answer but now i want to make a change to the code and i'm not having a lot of success...
Basically, from a mysql result set, i need to populate 4 arrays evenly distributed as much as possible from top to bottom...
Chris Hayes provided a solutuon that works, but when i tested it today, i realize that it populates the array from left to rigth, and not from top to bottom...
How do i change the code so it populates the 4 arrays as much as possible from top to bottom ?
$i = 0;
$array_r = array( array(), array(), array(), array() );
while ($stmt->fetch()) {
array_push($array_r[$i], array(... values ...));
$i = ($i + 1) % 4;
}
final version without manipulating the input array at all:
for ($num = count($input), $offset = 0; $numBuckets > 0; $numBuckets -= 1, $num -= $bucketSize, $offset += $bucketSize) {
$bucketSize = ceil($num / $numBuckets);
$output[] = array_slice($input, $offset, $bucketSize);
}
pervious answer:
Try the following:
<?php
$input = range('A', 'Z'); // test input data
$output = array(); // the output container
$numBuckets = 4; // number of buckets to fill
for (; $numBuckets > 0; $numBuckets -= 1) {
$output[] = array_splice($input, 0, ceil(count($input) / $numBuckets));
}
print_r($output);
alternative version, without constant rechecking the length of the array
for ($num = count($input); $numBuckets > 0; $numBuckets -= 1, $num -= $bucketSize) {
$bucketSize = ceil($num / $numBuckets);
$output[] = array_splice($input, 0, $bucketSize);
}
This snippet should work for you:
<?php
$array= [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17];
$strays = count($array)%4;
$offset = 0;
$results = array();
for($x = 0; $x < 4; $x++){
if ($x < $strays){
$size = (floor(count($array)/4) + 1);
} else {
$size = (floor(count($array)/4));
}
$results[] = array_slice($array, $offset, $size);
$offset+=$size;
}
print_r($results);
I've tested something and it seems to work... but it looks very spaghetti... please feel free to optimize the code. Thanks.
$num_rows = $stmt->num_rows; //number of records returned by the result set
$min_per_column = (int)($num_rows/4); //minimum records per column
$remainder = $num_rows % 4; //the remainder
$array_r = array(array(), array(), array(), array());
$i = 1;
$col = 0;
//how many records to populate before moving to the next array?
$rows = ($col < $remainder) ? $min_per_column + 1 : $min_per_column;
while ($stmt->fetch()) {
array_push($array_r[$col], array($r_recordingid, $r_title, $r_subtitle, $r_seourl));
$i++;
//initialize values for new array
if ($i > $rows) {
$i = 1;
$col++;
$rows = ($col < $remainder) ? $min_per_column + 1 : $min_per_column;
}
}

Categories