question about merge sort under php - php

i'v been trying to implement merge sort under php. but seems unsuccessful :( couldn't find source of error. any kind of help is very much appreciated!
function merge_sort(&$input, $start, $end) {
if($start < $end) {
$mid = (int) floor($start + $end / 2);
merge_sort($input, $start, $mid);
merge_sort($input, $mid + 1, $end);
merge($input, $start, $mid, $end);
}
}
function merge(&$input, $p, $q, $r) {
$a = $q - $p + 1;
$b = $r - $q;
for($i = $p;$i <= $q;$i++) {
$arr1[] = $input[$i];
}
for($i = $q+1;$i <= $r;$i++) {
$arr2[] = $input[$i];
}
$c = $d = 0;
for($i = $p; $i <= $r; $i++) {
$s = $arr1[$c];
$t = $arr2[$d];
if($a && (($s <= $t) || !$b)) {
$input[$i] = $s;
$a--;$c++;
} else if($b) {
$input[$i] = $t;
$b--;$d++;
}
}
return true;
}
here's the info xdebug throw back:
Fatal error: Maximum function nesting level of '100' reached, aborting!

To reach a nesting level of 100 on a merge sort, you would need to have an input array of size 2^100(about 1e30), which is impossible. I suspect your recursion is incorrect. For instance, you wrote $start + $end / 2 instead of ($start + $end) / 2.

Set
xdebug.max_nesting_level=500
in my php.ini

Here's my working solution, feel free to compare...
/**
* #param array $items array to sort
* #param int $l left index (defaults to 0)
* #param int $r right index (defaults to count($items)-1)
*/
function mergeSort(&$items, $l = 0, $r = null)
{
if (!isset($r)) {
$r = count($items) - 1;
}
if ($l < $r) {
$m = floor(($r - $l) / 2) + $l;
mergeSort($items, $l, $m);
mergeSort($items, $m + 1, $r);
merge($items, $l, $m, $r);
}
}
/**
* #param array $items array to merge
* #param int $l left index
* #param int $m middle index
* #param int $r right index
*/
function merge(&$items, $l, $m, $r)
{
$itemsA = array_slice($items, $l, $m + 1 - $l);
$itemsB = array_slice($items, $m + 1, ($r + 1) - ($m + 1));
$a = 0;
$aCount = count($itemsA);
$b = 0;
$bCount = count($itemsB);
for ($i = $l; $i <= $r; $i++) {
if ($a < $aCount && ($b == $bCount || $itemsA[$a] <= $itemsB[$b])) {
$items[$i] = $itemsA[$a++];
} else {
$items[$i] = $itemsB[$b++];
}
}
}
$items = array(5,3,6,1,2,3,9,10,7,2,4,8);
mergeSort($items);
echo implode(',', $items) . "\n";
Outputs:
1,2,2,3,3,4,5,6,7,8,9,10

There is a maximum function nesting level of '100', and you have reached it. Your recursive function goes too deep.

From http://www.xdebug.org/docs/all_settings:
xdebug.max_nesting_level
Type: integer, Default value: 100
Controls the protection mechanism for infinite recursion protection. The value of this setting is the maximum level of nested functions that are allowed before the script will be aborted.
You are going too deep in your recursive function triggering this xdebug error. Try raising this limit and see if that helps.
Also, here is an interesting article about recursion and PHP: http://www.alternateinterior.com/2006/09/tail-recursion-in-php.html

PHP is not a good language for recursive algorithms. From the manual:
It is possible to call recursive
functions in PHP. However avoid
recursive function/method calls with
over 100-200 recursion levels as it
can smash the stack and cause a
termination of the current script.
If you need to do it in PHP, you'll probably have to find an iterative version of the algorithm. You've hit a hard-coded limit in the language.

Cosi dovrebbe funzionare!!!! www.dslpg.it
function merge ( &$a, $left, $center, $right ) { //left = p right = r center = q
$n1 = $center - $left + 1;
$n2 = $right - $center;
for ($i = 1; $i <= $n1; $i++) $L[$i] = $a[$left+$i-1];
for ($i = 1; $i <= $n2; $i++) $R[$i] = $a[$center+$i];
$L[$n1+1] = 99999;
$R[$n2+1] = 99999;
$i = 1;
$j = 1;
for ($k = $left; $k <= $right; $k++) {
if ($L[$i] <= $R[$j] ) {
$a[$k] = $L[$i];
echo $a[$k];
$i++;
}
else {
$a[$k] = $R[$j];
echo $a[$k];
$j++;
}
}
return $a;
}
function merge_sort ( &$a, $left, $right ) { //left = p right = r
if ( $left < $right ) {
$center = (int) floor(($left + $right) / 2 );
merge_sort ($a, $left, $center);
merge_sort ($a, $center+1, $right);
merge ($a, $left, $center, $right);
}
}
merge_sort ( $a, 1, $n );

Related

Calculate normal distribution probability in php

I need to use this table to get the probability from a given z value:
https://statistics.laerd.com/statistical-guides/img/normal-table-large.png
I'm sure there should be a better way to get those values on php but don't know how to calculate them.
Any help would be very appreciated.
Cumulative distribution function of the standard normal distribution with precision calculation:
function cumulativeNormalDensity($x, $mean = 0, $stddev = 1, $precision = 48) {
$result = 0;
$x -= $mean;
$x /= $stddev;
for ($i = 0, $k = 1; $i < $precision; $i++) {
$n = $i * 2 + 1;
$k *= $n;
$p = pow($x, $n) / $k;
if (is_nan($p) || is_infinite($p)) break;
$result += $p;
}
$result *= 1 / sqrt(2 * pi()) * exp(-pow($x, 2) / 2);
$result += 0.5;
return max(0, $result);
}
Table, I believe, is CDF of the normal distribution. I coded it using expression for
error function approximation.
Code is untested!
function sgn( $x ) {
if ( $x < 0 )
return -1;
return 1;
}
function erf( $x ) {
$e = exp(-$x*$x);
$e2 = exp(-$x*$x*2);
$q = sqrt(pi())/2 + 31*$e/200 - 341*$e2/8000;
return 2*sgn($x)*sqrt(1-$e)*$q/sqrt(pi());
}
function CDF( $x ) {
return (1 + erf($x / sqrt(2))) / 2;
}
print_r(CDF(0));
print_r(CDF(0.1));
....
UPDATE
Here is quick (untested!) code to compute erf() with up to 4 terms
function erf( $x ) {
$e = exp(-$x*$x);
$t = 1.0 - $e;
$s = 1. + $t*(-1./12. + $t*(-7./480. + $t*( -5./896. +$t * (-787./276480.))));
return 2.*sgn($x)*sqrt($t)*$s/sqrt(pi());
}

Looking for opposite of pow() in PHP

I am working on mathematical problem where the formula is: A[i] * (-2) power of i
where i=0,1,2,3,...
A is an array having values 0 or 1
Input array: [0,1,1,0,0,1,0,1,1,1,0,1,0,1,1]
Output is: 5730
Code
$totalA = 0;
foreach ($A as $i => $a) {
$totalA += $a * pow(-2, $i);
}
This is correct. Now I am looking for its opposite like:
Input is: 5730
Output will be: [0,1,1,0,0,1,0,1,1,1,0,1,0,1,1]
I am not asking for the exact code but looking for some logic from where I should start. I tried to use log() method but that did not return the desired output.
You were not looking for exact code, but I found this problem too interesting. This works:
function sign($n) {
return ($n > 0) - ($n < 0);
}
$target = -2396;
$i = 0;
$currentSum = 0;
// Look for max $i
while (true) {
$val = pow(-2, $i);
$candidate = $currentSum + $val;
if (abs($target) <= abs($candidate)) {
// Found max $i
break;
}
if (abs($target - $candidate) < abs($target - $currentSum)) {
// We are getting closer
$currentSum = $candidate;
}
$i++;
}
$result = [];
for ($j = $i; 0 <= $j; $j--) {
$val = pow(-2, $j);
$border = $val / 4;
if (sign($val) == sign($target) && abs($border) < abs($target)) {
array_unshift($result, 1);
$target -= $val;
} else {
array_unshift($result, 0);
}
}
echo json_encode($result);
First I look for the $i that gets me on or slightly above the $target. When found, I walk down and decide for each bit if it should be in the result.

Compare similarity between two string with PHP

Hey guys :) I want to ask for some solution. Now, I have dictionary words.txt, here some example:
happy
laugh
sad
And I have the slang string:
hppy
I want to search & match that slang string to my dictionary wich means it will return "happy" because those string refer to "happy" in dictionary.
Recently I've been using similar_text() but doesn't confident about its validity. Can you guys recommend better solution for my problem? Thank you :)
And here i put my codes:
function searchwords($tweet){
//echo $tweet;
$find = false;
$handle = #fopen("words.txt", "r");
if ($handle)
{
while (!feof($handle))
{
$buffer = fgets($handle);
similar_text(trim($tweet),trim($buffer),$percent);
if ($percent == 100){ // this exact match
$find = true;
}else if ($percent >= 90){ //there is the possibility of errors
$find = true;
}
}
fclose($handle);
}
if ($find == true){
unset($tweet);
}else{
return $tweet;
}
}
As answered here
I've found that to calculate a similarity percentage between strings,
the Levenshtein and Jaro Winkler algorithms work well for
spelling mistakes and small changes between strings, while the Smith
Waterman Gotoh algorithm works well for strings where significant
chunks of the text would be the same but with "noise" around the
edges. This answer to a similar question shows more detail on
this.
I included the php examples of using each of these three examples to return a similarity percentage between two strings:
Levenshtein
echo levenshtein("LEGENDARY","BARNEY STINSON");
Jaro Winkler
class StringCompareJaroWinkler
{
public function compare($str1, $str2)
{
return $this->JaroWinkler($str1, $str2, $PREFIXSCALE = 0.1 );
}
private function getCommonCharacters( $string1, $string2, $allowedDistance ){
$str1_len = mb_strlen($string1);
$str2_len = mb_strlen($string2);
$temp_string2 = $string2;
$commonCharacters='';
for( $i=0; $i < $str1_len; $i++){
$noMatch = True;
// compare if char does match inside given allowedDistance
// and if it does add it to commonCharacters
for( $j= max( 0, $i-$allowedDistance ); $noMatch && $j < min( $i + $allowedDistance + 1, $str2_len ); $j++){
if( $temp_string2[$j] == $string1[$i] ){
$noMatch = False;
$commonCharacters .= $string1[$i];
$temp_string2[$j] = '';
}
}
}
return $commonCharacters;
}
private function Jaro( $string1, $string2 ){
$str1_len = mb_strlen( $string1 );
$str2_len = mb_strlen( $string2 );
// theoretical distance
$distance = (int) floor(min( $str1_len, $str2_len ) / 2.0);
// get common characters
$commons1 = $this->getCommonCharacters( $string1, $string2, $distance );
$commons2 = $this->getCommonCharacters( $string2, $string1, $distance );
if( ($commons1_len = mb_strlen( $commons1 )) == 0) return 0;
if( ($commons2_len = mb_strlen( $commons2 )) == 0) return 0;
// calculate transpositions
$transpositions = 0;
$upperBound = min( $commons1_len, $commons2_len );
for( $i = 0; $i < $upperBound; $i++){
if( $commons1[$i] != $commons2[$i] ) $transpositions++;
}
$transpositions /= 2.0;
// return the Jaro distance
return ($commons1_len/($str1_len) + $commons2_len/($str2_len) + ($commons1_len - $transpositions)/($commons1_len)) / 3.0;
}
private function getPrefixLength( $string1, $string2, $MINPREFIXLENGTH = 4 ){
$n = min( array( $MINPREFIXLENGTH, mb_strlen($string1), mb_strlen($string2) ) );
for($i = 0; $i < $n; $i++){
if( $string1[$i] != $string2[$i] ){
// return index of first occurrence of different characters
return $i;
}
}
// first n characters are the same
return $n;
}
private function JaroWinkler($string1, $string2, $PREFIXSCALE = 0.1 ){
$JaroDistance = $this->Jaro( $string1, $string2 );
$prefixLength = $this->getPrefixLength( $string1, $string2 );
return $JaroDistance + $prefixLength * $PREFIXSCALE * (1.0 - $JaroDistance);
}
}
$jw = new StringCompareJaroWinkler();
echo $jw->compare("LEGENDARY","BARNEY STINSON");
Smith Waterman Gotoh
class SmithWatermanGotoh
{
private $gapValue;
private $substitution;
/**
* Constructs a new Smith Waterman metric.
*
* #param gapValue
* a non-positive gap penalty
* #param substitution
* a substitution function
*/
public function __construct($gapValue=-0.5,
$substitution=null)
{
if($gapValue > 0.0) throw new Exception("gapValue must be <= 0");
//if(empty($substitution)) throw new Exception("substitution is required");
if (empty($substitution)) $this->substitution = new SmithWatermanMatchMismatch(1.0, -2.0);
else $this->substitution = $substitution;
$this->gapValue = $gapValue;
}
public function compare($a, $b)
{
if (empty($a) && empty($b)) {
return 1.0;
}
if (empty($a) || empty($b)) {
return 0.0;
}
$maxDistance = min(mb_strlen($a), mb_strlen($b))
* max($this->substitution->max(), $this->gapValue);
return $this->smithWatermanGotoh($a, $b) / $maxDistance;
}
private function smithWatermanGotoh($s, $t)
{
$v0 = [];
$v1 = [];
$t_len = mb_strlen($t);
$max = $v0[0] = max(0, $this->gapValue, $this->substitution->compare($s, 0, $t, 0));
for ($j = 1; $j < $t_len; $j++) {
$v0[$j] = max(0, $v0[$j - 1] + $this->gapValue,
$this->substitution->compare($s, 0, $t, $j));
$max = max($max, $v0[$j]);
}
// Find max
for ($i = 1; $i < mb_strlen($s); $i++) {
$v1[0] = max(0, $v0[0] + $this->gapValue, $this->substitution->compare($s, $i, $t, 0));
$max = max($max, $v1[0]);
for ($j = 1; $j < $t_len; $j++) {
$v1[$j] = max(0, $v0[$j] + $this->gapValue, $v1[$j - 1] + $this->gapValue,
$v0[$j - 1] + $this->substitution->compare($s, $i, $t, $j));
$max = max($max, $v1[$j]);
}
for ($j = 0; $j < $t_len; $j++) {
$v0[$j] = $v1[$j];
}
}
return $max;
}
}
class SmithWatermanMatchMismatch
{
private $matchValue;
private $mismatchValue;
/**
* Constructs a new match-mismatch substitution function. When two
* characters are equal a score of <code>matchValue</code> is assigned. In
* case of a mismatch a score of <code>mismatchValue</code>. The
* <code>matchValue</code> must be strictly greater then
* <code>mismatchValue</code>
*
* #param matchValue
* value when characters are equal
* #param mismatchValue
* value when characters are not equal
*/
public function __construct($matchValue, $mismatchValue) {
if($matchValue <= $mismatchValue) throw new Exception("matchValue must be > matchValue");
$this->matchValue = $matchValue;
$this->mismatchValue = $mismatchValue;
}
public function compare($a, $aIndex, $b, $bIndex) {
return ($a[$aIndex] === $b[$bIndex] ? $this->matchValue
: $this->mismatchValue);
}
public function max() {
return $this->matchValue;
}
public function min() {
return $this->mismatchValue;
}
}
$o = new SmithWatermanGotoh();
echo $o->compare("LEGENDARY","BARNEY STINSON");
Hopefully it'll serve your purpose. But there are some things to keep in mind while working with similar_text().
matching percentage can differ depending on the order of parameters. ie: similar_text($a, $b, $percent) and similar_text($b, $a, $percent) here in both cases $percent may not be same.
Note that this function is case sensitive: so while passing $a and $b pass both either in uppercase or lowercase.
for more info check this page

Writing merge sort in PHP

I have tried to write a basic merge sort in PHP involving a small array, yet the problem is it takes about a minute or so to execute, and returns:
Fatal error: Allowed memory size of 536870912 bytes exhausted (tried
to allocate 35 bytes) in /Users/web/www/merge.php on line 39
Does anyone have an idea where the code might be going wrong (if at all)? I've been staring at this for a good hour now.
<?php
$array = array(8,1,2,5,6,7);
print_array($array);
merge_sort($array);
print_array($array);
function merge_sort(&$list){
if( count($list) <= 1 ){
return $list;
}
$left = array();
$right = array();
$middle = (int) ( count($list)/2 );
// Make left
for( $i=0; $i < $middle; $i++ ){
$left[] = $list[$i];
}
// Make right
for( $i = $middle; $i < count($list); $i++ ){
$right[] = $list[$i];
}
// Merge sort left & right
merge_sort($left);
merge_sort($right);
// Merge left & right
return merge($left, $right);
}
function merge(&$left, &$right){
$result = array();
while(count($left) > 0 || count(right) > 0){
if(count($left) > 0 && count(right) > 0){
if($left[0] <= $right[0]){
$result[] = array_shift($left);
} else {
$result[] = array_shift($right);
}
} elseif (count($left) > 0){
$result[] = array_shift($left);
} elseif (count($right) > 0){
$result[] = array_shift($right);
}
}
print_array($result);exit;
return $result;
}
function print_array($array){
echo "<pre>";
print_r($array);
echo "<br/>";
echo "</pre>";
}
?>
In your merge function, you call count on right instead of $right. PHP assumes this is a string constant (at least in 5.3.9) and when casted into an array that always has one element. So count(right) is always one, and you never exit the first merge.
Try this approach. Instead of shifting it, slice.
Also, for in while loop for the merge function, you need to do an and && comparison instead
of ||
function mergeSort($array)
{
if(count($array) == 1 )
{
return $array;
}
$mid = count($array) / 2;
$left = array_slice($array, 0, $mid);
$right = array_slice($array, $mid);
$left = mergeSort($left);
$right = mergeSort($right);
return merge($left, $right);
}
function merge($left, $right)
{
$res = array();
while (count($left) > 0 && count($right) > 0)
{
if($left[0] > $right[0])
{
$res[] = $right[0];
$right = array_slice($right , 1);
}
else
{
$res[] = $left[0];
$left = array_slice($left, 1);
}
}
while (count($left) > 0)
{
$res[] = $left[0];
$left = array_slice($left, 1);
}
while (count($right) > 0)
{
$res[] = $right[0];
$right = array_slice($right, 1);
}
return $res;
}
Have a look at this, the algorithm is already implemented, using array_push and array splice instead of just array_shift.
http://www.codecodex.com/wiki/Merge_sort#PHP
I implement merge sort this way
function mergeSort($Array)
{
$len = count($Array);
if($len==1){
return $Array;
}
$mid = (int)$len / 2;
$left = mergeSort(array_slice($Array, 0, $mid));
$right = mergeSort(array_slice($Array, $mid));
return merge($left, $right);
}
function merge($left, $right)
{
$combined = [];
$totalLeft = count($left);
$totalRight = count($right);
$rightIndex = $leftIndex=0;
while ($leftIndex < $totalLeft && $rightIndex < $totalRight) {
if ($left[$leftIndex] > $right[$rightIndex]) {
$combined[]=$right[$rightIndex];
$rightIndex++;
}else {
$combined[] =$left[$leftIndex];
$leftIndex++;
}
}
while($leftIndex<$totalLeft){
$combined[]=$left[$leftIndex];
$leftIndex++;
}
while ($rightIndex<$totalRight){
$combined[] =$right[$rightIndex];
$rightIndex++;
}
return $combined;
}
Here is the class in PHP to implement the Merge Sort -
<?php
class mergeSort{
public $arr;
public function __construct($arr){
$this->arr = $arr;
}
public function mSort($l,$r){
if($l===null || $r===null){
return false;
}
if ($l < $r)
{
// Same as ($l+$r)/2, but avoids overflow for large $l and $r
$m = $l+floor(($r-$l)/2);
// Sort first and second halves
$this->mSort($l, $m);
$this->mSort($m+1, $r);
$this->merge($l, $m, $r);
}
}
// Merges two subarrays of $this->arr[]. First subarray is $this->arr[$l..$m]. Second subarray is $this->arr[$m+1..$r]
public function merge($l, $m, $r)
{
if($l===null || $m===null || $r===null){
return false;
}
$n1 = $m - $l + 1;
$n2 = $r - $m;
/* create temp arrays */
$L=array();
$R=array();
/* Copy data to temp arrays $L[] and $R[] */
for ($i = 0; $i < $n1; $i++)
$L[$i] = $this->arr[$l + $i];
for ($j = 0; $j < $n2; $j++)
$R[$j] = $this->arr[$m + 1+ $j];
/* Merge the temp arrays back into $this->arr[$l..$r]*/
$i = 0; // Initial index of first subarray
$j = 0; // Initial index of second subarray
$k = $l; // Initial index of merged subarray
while ($i < $n1 && $j < $n2)
{
if($L[$i] <= $R[$j])
{
$this->arr[$k] = $L[$i];
$i++;
}
else
{
$this->arr[$k] = $R[$j];
$j++;
}
$k++;
}
/* Copy the remaining elements of $L[], if there are any */
while($i < $n1)
{
$this->arr[$k] = $L[$i];
$i++;
$k++;
}
/* Copy the remaining elements of $R[], if there are any */
while($j < $n2)
{
$this->arr[$k] = $R[$j];
$j++;
$k++;
}
}
}
$arr = array(38, 27, 43, 5, 9, 91, 12);
$obj = new mergeSort($arr);
$obj->mSort(0,6);
print_r($obj->arr);
?>
I was looking for a optimized Mergesort algorithm in PHP. There are 5 algorithms in the answers, so I tested those, and mine too. Using PHP 7.2.7, these are the times:
Sorting 1000 random numbers:
Avanche 1 0.0396 seconds
Avanche 2 0.0347 seconds
Kartik 0.0291 seconds
Kripa 0.0282 seconds
Samuel 0.0247 seconds
Mine 0.0144 seconds
Sorting 10 random numbers:
Avanche 1 0.000222 seconds
Kartik 0.000216 seconds
Kripa 0.000159 seconds
Avanche 2 0.000144 seconds
Samuel 0.000128 seconds
Mine 0.000098 seconds
So, although I encourage to whom read it to make it faster (that was I was looking for, and I believe it can be done), I let you my implementation too, cause seems to be faster than the other answers:
//This function needs start and end limits
function mergeSortRec(&$a,$start,$end){
if($start<$end){
$center=($start+$end)>>1; //Binary right shift is like divide by 2
mergeSortRec($a, $start, $center);
mergeSortRec($a, $center+1, $end);
//Mixing the 2 halfs
$aux=array();
$left=$start; $right=$center;
//Main loop
while($left<$center && $right<=$end){
if($a[$left]<$a[$right]){
$aux[]=$a[$left++];
}else{
$aux[]=$a[$right++];
}
}
//Copy the rest of the first half
while($left<$center) $aux[]=$a[$left++];
//Copy the rest of the second half
while($right<=$end) $aux[]=$a[$right++];
//Copy the aux array to the main array
foreach($aux as $v) $a[$start++]=$v;
}
}
//This is the function easier to call
function mergeSort(&$a) {
mergeSortRec($a,0,count($a)-1);
}
If you post a new answer, let me a comment to test it and add it.
Edit: I did some new optimizations, for those looking for a better implementation.
Your merge sort accepts a list by reference
function merge_sort(&$list)
So you need to assign it the new merged and sorted list. So instead of
return merge($left, $right);
do
$list = $this->merge($left, $right);
That should do it, just remove the exit and fix the count variable
MergeSort in PHP
<?php
class Solution
{
function mergeSort(&$arr)
{
if(count($arr) > 1) {
$mid = floor(count($arr)/2);
$left = array_slice($arr, 0, $mid);
$right = array_slice($arr, $mid);
$this->mergeSort($left);
$this->mergeSort($right);
// Merge the results.
$i = $j = $k = 0;
while(($i < count($left)) && ($j < count($right))) {
if($left[$i] < $right[$j]) {
$arr[$k] = $left[$i];
$i++;
} else {
$arr[$k] = $right[$j];
$j++;
}
$k++;
}
while($i < count($left)) {
$arr[$k] = $left[$i];
$i++;
$k++;
}
while($j < count($right)) {
$arr[$k] = $right[$j];
$j++;
$k++;
}
}
}
}
$s = new Solution();
$tmp = [12, 7, 11, 13, 5, 6, 7];
$s->mergeSort($tmp);
print_r($tmp);

PHP - Patterns within Arrays

I am trying to create a function which maps a recurring pattern of integers using an array.
As an example if I have a starting array of (0,1,3) and I know that I want to stop the pattern when I hit 15.
The pattern gets incremented by a fixed integer each time (lets say 4) so my final pattern should be..
0
1
3
4 (0 + 4)
5 (1 + 4)
7 (2 + 4)
8 (4 + 4)
9 (5 + 4)
11(7 + 4)
12(8 + 4)
13(9 + 4)
15(11+ 4)
Does anyone have any pointers on how this can be achieved?
My current implementation works but is stupidly inefficient which something like this...
$array = array(0,1,3);
$inc = 4;
$end = end($array);
$final = 15;
while($end < $final)
{
$tmp = array();
foreach($array AS $row)
{
$tmp = $row + $inc;
}
$array = merge($tmp, $array);
$end = end($array);
}
$array = array(0,1,3);
$inc = 4;
$final = 15;
$end = end($array);
while($end < $final)
{
$end += $inc;
$array[] = $end;
}
Or with a for loop:
$array = array(0,1,3);
$inc = 4;
$final = 15;
for($i = end($array) + $inc; $i <= $final; $i += $inc)
{
$array[] = $i;
}
Y'all are missing the fact that 4 is being added to the value in the array 2 keys back, not the last value.
This is the code you need (tested, and working)
$array = array(0,1,3);
$inc = 4;
$end = end($array);
$key = key($array);
$final = 15;
while ($end < $final) {
if ($array[$key-2] >= 0) {
$end = $array[$key-2] + $inc;
$array[] = $end;
$key++;
}
}
I also included in there a check to make sure the key being added to actually exists, though that may not be needed.
I assume that you want to have all the new values in the same array.
So:
//original array
$values = array(0, 1, 3);
//incremental value
$inc = 4;
//stop value
$stop = 15;
//set the index counter to the origin
$curr_index = 0;
//while the last value of the array is lower than the stop value
while($values[end($values)] < $stop)
{
//calculate the new value
$new_value = $values[$curr_index] + $inc;
//add the new value to the array
array_push($values, $new_value);
//update the index counter
$curr_index ++;
}
this code should work for any initial value in the array, any incremental value and any stop value.
<?php
function myArrayFunction(array $array, $inc = 4, $final = 15, $end = null)
{
if(!$end)
{
$end = end($array);
}
while($end < $final)
{
$end += $inc;
$array[] = $end;
}
return $array; //assume you're wanting $array back
}
This is minus any sort of testing or checking of injected values but you get the idea.
It would be better to know what you are trying to achieve here as the whole thing looks horribly overcomplicated, but...
$array = array(0,1,3);
$pattern = array();
$inc = 4;
$final = 15;
for ($base = 0; ; $base += $inc) {
foreach($array as $rem) {
if ($base + $rem > $final) break 2;
$pattern []= $base + $rem;
}
}
Alternatively,
$i = $v = 0;
while ($v < $final) {
$v = $pattern []= $pattern[$i++] + $inc;
}
(This assumes $final will be part of the pattern.)
If you can figure out how to calculate the number of elements will be in the array beforehand and assign that to $tum this should work.
<?php
$arr = array(0, 1, 3);
$inc = 4; // 6
$fin = 15; // 55
$num = count($arr);
$lum = 0;
$tum = 12; // 29
do
{
for($i = $lum; $i < $num; $i++)
{
$tar = $arr[$i] + $inc;
$arr[$tar] = $tar;
}
$lum = $num;
$num *= 2;
} while(end($arr) < $fin);
$arr = array_slice($arr, 0, $tum);
print_r($arr);
echo "\n";
?>

Categories