First, I have been programming in PHP for all of two weeks. So, please excuse my ignorance.
Here is my problem. I am trying to find essentially the running average of multiple difference values within an array. I think I have figured out how to get what I want, but the code is really inefficient and takes several seconds in a small test array (n = 20). My production array will be around n = 1000. I suspect that there is a much more efficient way to get what I want.
Here is what I am conceptually trying to do:
array = (20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1);
newarray = (20-19, 19-18, 18-17, 17-16, 16-15, ... 2-1);
newarray2 = (20-18, 19-17, 18-16, 17-15, 16-14 ... 3-1);
newarray3 = (20-17, 19-16, 18-15, 17-14, ... 4-1);
differenceaverage = (sum of (20-19, 20-18, 20-17)/3, sum of (19-18, 19-17, 19-16)/3, etc.)
Here is the code that I used to generate the average:
$n=count($appArrayqb);
for($i = 1; $i<=($n-1); $i++){
$diff[]= $appArrayqb[$i-1]-$appArrayqb[$i];
}
for($i = 1; $i<=($n-2); $i++){
$diff2[]= $appArrayqb[$i-1]-$appArrayqb[$i+1];
}
for($i = 1; $i<=($n-3); $i++){
$diff3[]= $appArrayqb[$i-1]-$appArrayqb[$i+2];
}
$VOcomb = array($diff,$diff2,$diff3)
$sumVO = array_map ("sum", $VOcomb[0], $VOcomb[1], $VOcomb[2])
function sum ($arr1, $arr2, $arr3){
return($arr1+$arr2+$arr3);
}
$counts = array();
foreach($VOcomb as $item){
foreach($item as $k=>$v){
if(isset($item[$k])){
$counts[$k]++;
}
}
}
$VOarray=array($sumVO,$counts);
$VO = array_map("VO", $VOarray[0],$VOarray[1]);
function VO($arr1, $arr2) {
return($arr1/$arr2);
}
Incidentally, while the code works, I get an undefined offset notice when I run the count loop because it is trying to count values that don't exist in $item array. So I have three related questions:
1.) Is there a better way to calculate the differences?
2.) Is there a better way to get the count of the differences so I don't wind up with an undefined offset?
3.) Is the array_map function the best function to use to get the sums and averages?
Thanks!
Try this simplified code that seems to give the same result as yours:
It works by building the result array element by element, calculating the differences and averages as needed instead of creating arrays of differences and mapping over them.
// Calculate average differences between E(n) and E(n+1), E(n+2), and E(n+3)
// in an array
function diffaverages($appArrayqb) {
$n = count($appArrayqb);
$diffAvg = array();
for($i = 0; $i+1 < $n; $i++){
$diffsum = 0;
$count = 0;
for($j = 1; $j <= 3 && $i+$j < $n; $j++){
$diffsum += $appArrayqb[$i] - $appArrayqb[$i+$j];
$count++;
}
$diffAvg[] = $diffsum / $count;
}
return $diffAvg;
}
Related
Im looking for a way to get an array of points between 2 points that are 3d.
What I’ve found
So far while looking ive not found anything that is 3d, when I look for 3d it only returns a bunch of things of How to get distance between 2 points And thats not what im looking for!
I have found 1 good one about 2d points - here
However Ive found nothing about 3d, so sorry if this is duplicate.
Ive also tried search Stack Exchange Mathematics, and multiple other webpages, and still cant find anything that can answer my question.
More Details
Im going to give an example so that its more clear what I am looking for. Say I have 2 3d vectors (x1, y1, z1) and (x2, y2, z2). My points in this example will be (0, 0, 0) and (10, 10, 10).
After I have run these through the function I would want it to return an array of points something like this:
[1, 1, 1],
[2, 2, 2],
[3, 3, 3]
All the way up to 10.
Have you tried a 'for' loop?
function myFunction() {
$arr = array();
for ($i = 1; $i < 11; $i++) {
$arr[] = array($i, $i, $i);
}
return $arr;
}
$myArr = myFunction();
The result will be an array with each key having an array value incremented.
you can use see complete array...
print_r($myArr);
Or each individual value by using its key value...
echo $myArr[0][2]
Answer
I have now found the answer to my question above.
function logPointsOnLine(array $point1, array $point2, int $points) {
$vecs = [];
$delX = $point2[0] - $point1[0];
$delY = $point2[1] - $point1[1];
$delZ = $point2[2] - $point1[2];
for($i = 0; $i < $points; $i++) {
$newX = $point1[0] + $delX / ($points - 1) * $i;
$newY = $point1[1] + $delY / ($points - 1) * $i;
$newZ = $point1[2] + $delZ / ($points - 1) * $i;
array_push($vecs, array($newX, $newY, $newZ));
}
}
If you want to run it one way you could do it is:
$vec1 = array(10, 12, 32);
$vec2 = array(15, 60, 25);
$amt = 10;
$points = logPointsOnLine($vec1, $vec2, $amt);
print_r($points);
QUESTION:
Given an array of integers, find the pair of adjacent elements that has the largest product and return that product.
Example:
https://app.codesignal.com/arcade/intro/level-2
For inputArray = [3, 6, -2, -5, 7, 3], the output should be
adjacentElementsProduct(inputArray) = 21.
7 and 3 produce the largest product.
Input/Output
Input:
inputArray: [3, 6, -2, -5, 7, 3]
Expected Output:
21
SOLUTION: My code that doesn't work:
function adjacentElementsProduct($inputArray) {
$total = 0;
$temp = 0;
$maxProduct = 0;
$var = 0;
if ($inputArray.count == 1) return 0;
for ($i = 0; $i < $inputArray[$inputArray.count-1]; $i++) {
if ($inputArray[i] + $inputArray[i+1] > $maxProduct) {
$maxProduct = $inputArray[i] * $inputArray[i+1];
}
}
return $maxProduct;
}
As with any programming task, the trick is to tackle it piece by piece. You tend to find your code is more readable when you break problems down into small components.
You need to:
Find the product of adjacent elements in an array
Find the largest product in that group of values
You can approach this without a large number of variables, nesting, etc.
function adjacentElementsProduct(array $inputs) {
$products = [];
for ($i = 1; $i < count($inputs); $i++) {
$products[] = $inputs[$i - 1] * $inputs[$i];
}
return max($products);
}
All we're doing is looping through the input array, starting with the second element. Calculating the product of the previous element and the current element then putting the result into an array of products. Finally we run that through max() which is going to handle finding the largest value for us.
Important to note: there's no validation taking place here. Can you trust that your array will only ever contain numerical values? Will it always contain at least two elements? If not you'll want to account for that.
Here is how I would do it
$inputArray = [3, 6, -2, -5, 7, 3];
function adjacentElementsProduct($inputArray) {
$max = 0;
for($i = 0; $i < (sizeof($inputArray) - 1); $i++){
$b = $i+1;
if($inputArray[$i] > 0 && $inputArray[$b] > 0){
$max = (($inputArray[$i] * $inputArray[$b]) > $max) ? ($inputArray[$i] * $inputArray[$b]) : $max;
}
}
return $max;
}
echo adjacentElementsProduct($inputArray); // Outputs 21
function adjacentElementsProduct($inputArray) {
$res = [];
for($j=0;$j<count($inputArray);$j++){
$res[] = $inputArray[$j]*$inputArray[$j+1];
}
return (max($res) < 0) ? 0 : max($res);
}
As with any programming task, the trick is to tackle it piece by piece. You tend to find your code is more readable when you break problems down into small components.
You need to:
Find the product of adjacent elements in an array
Find the largest product in that group of values
In PHP its as below:
function adjacentElementsProduct($inputArray) {
$res = [];
for($j=1;$j<count($inputArray);$j++){
$res[] = $inputArray[$j-1]*$inputArray[$j];
}
return max($res);
}
$a = [3, 6, -2, -5, 7, 3]
echo adjacentElementsProduct($a); //21
When iterating through a loop, I've used the modulus operator in an if statement to obtain nth results pretty easily like this:
// Get 5th item in series
if ($variable->array_item % 5 == 0) {
echo $variable->array_item;
}
How do you do get the 5th item in a series with an offset of 3 (ie, 3,8,13,18,23,etc.)?
I've seen a couple of methods but I'm looking for a canonical answer and I really don't see one on S.O. right now.
Your code specifically requests numbers that are evenly divisible by 5, whereas what you want are numbers 3, 8, 13, 18, 23, etc. This is easy enough to do using almost identical code to what you have:
// set up some test data
$testArray = [];
for ($i = 1; $i <= 30; ++$i) {
$testArray[$i] = "Testing {$i}";
}
// here's where the actual work happens
foreach ($testArray as $key => $value) {
if ($key % 5 == 3) { // <-- note 3, not 0
echo "Found $value\n";
}
}
$iterator = 0;
$step = 3;
while($iterator < count($collection))
{
echo $collection[$iterator]
$iterator += $step
}
I'm a beginner with PHP (and programming in general).
To test what I've learned so far I wrote this code, which prints all the possibile combinations of a set number of dice with a certain number of faces. (you'll find the code at the end).
What I want to do is dynamically change the number of nested for loops according to the $dicenumber variable. Right now it can only process 3 dice, since the code is:
for ($d1=1; $d1 <= $d1value ; $d1++) {
for ($d2=1; $d2 <= $d2value ; $d2++) {
for ($d3=1; $d3 <= $d3value ; $d3++) {
array_push(${sum.($d1+$d2+$d3)}, "$d1"."$d2"."$d3");
}
}
}
But I want to change it so that, for example, if $dicenumber were 2, it would produce something like:
for ($d1=1; $d1 <= $d1value ; $d1++) {
for ($d2=1; $d2 <= $d2value ; $d2++) {
array_push(${sum.($d1+$d2)}, "$d1"."$d2");
}
}
I want the code to process for whatever number $dicenumber may be, without limits. Looking around, it seems like I have to add some kind of recursive code, but I don't know how to do that. Any tips? Also, any feedback on what I did wrong in general, would be extremely helpful! thanks!
<?php
//defines the number and type of dice
$dicenumber = 3;
$dtype = 6;
//defines the maximum value of every die
for ($i=1; $i <=$dicenumber ; $i++) {
${d.$i.value} = $dtype;
}
//defines and array for each possible sum resulting from the roll of the given number of dice.
for ($i=$dicenumber; $i <= ($dtype*$dicenumber) ; $i++) {
${sum.$i} = array();
}
//the troublesome piece of code I want to change
for ($d1=1; $d1 <= $d1value ; $d1++) {
for ($d2=1; $d2 <= $d2value ; $d2++) {
for ($d3=1; $d3 <= $d3value ; $d3++) {
array_push(${sum.($d1+$d2+$d3)}, "$d1"."$d2"."$d3");
}
}
}
//prints all the possible roll combinations, each line lists combination that share the same sum
for ($i=$dicenumber; $i <= ($dtype*$dicenumber); $i++) {
print join(" ", ${sum.$i})."<br />";
}
?>
Here we have a two-function process. The first function, buildArrays, creates arrays in the proper format to feed into the second function, allCombinations. So, for this example with 3 d6's in play, buildArrays will produce an array equivalent to this:
$data = array(
array(1, 2, 3, 4, 5, 6),
array(1, 2, 3, 4, 5, 6),
array(1, 2, 3, 4, 5, 6));
I will warn you that as you increase the number of dice and the number of sides, the number of possible combinations increases exponentially! This means that you could place a very large demand on the server, and both timeout and max memory limits will quickly come into play. The arrays generated could be very, very large and quickly consume more than the max memory limit. That said, here we go:
function buildArrays($dicenumber, $dtype){
for ($i = 0; $i<$dicenumber; $i++){
$tmp = array();
for ($j = 1; $j<=$dtype; $j++){
$tmp[] = $j;
}
$data[$i] = $tmp;
}
return $data;
}
function allCombinations($data){
$result = array(array()); //this is crucial, dark magic.
foreach ($data as $key => $array) {
$new_result = array();
foreach ($result as $old_element){
foreach ($array as $element){
if ($key == 0){
$new_result[] = $element;
} else {
$new_result[] = $old_element.$element;
}
}
$result = $new_result;
}
}
return $result;
}
//set variables
$dicenumber = 3;
$dtype = 6;
//set_time_limit(0); //You may need to uncomment this for large values.
//call functions
$data = buildArrays($dicenumber, $dtype);
$results = allCombinations($data);
//print out the results
foreach ($results as $result){
echo $result."<br/>";
}
N.B. This answer is a variant of the cartesian product code
If you have learned functions, you can do a recursive call and keep track of what dicenumber you're on, then increment it each call to the function (and end the loop once you've hit your #).
understanding basic recursion
My question:
I got a phpmyadmin database ( and using php 5),
with 2 tables to compare a football toto tournament.
the strings that i must compaire are like the following :
1|2|3|1|1|2|3|1|2|3|3
( in total 43 numbers) i know that i must use explode for taking out the "|" between them (because its saved as a string)
but the final score is also saved like that. so i must compare all (guessed outcomes from matches with the final score string. how do it do it so that i can see who has got the most guessed right?
And that it would be shown as 1e place, 2e place, 3e place and so on?
Would be a great help,
sorry if i lack at something.
I'm not entirely certain that I understand the question correctly, but if the two arrays are of the same length, you can use the same iterator for both of them.
After you've explode()d the strings into arrays:
$one = array(1, 2, 3, 4, 5);
$two = array(8, 2, 3, 6, 1);
$results = array();
for ($i = 0; $i < count($one); $i++) {
$results[$i] = $one[$i] - $two[$i];
}
Note that the above code is untested, and instead of whatever calculation you use, I just subtract the value of each $two element from each $one element.
Hope it helps.
if i understand the question well...
$guess = array(1, 2, 1, 3, 1, 2, 3);
$real = array(2, 2, 1, 2, 2, 1, 1);
$score = 0;
$length = count($real);
for($i = 0; $i < $length; $i++) {
if($guess[$i] == $real[$i])
++$score;
}
echo $score;