I have a function where is checks on two arrays and returns the common minimum value in both the arrays. IT returns the correct answer when both the arrays have equal number of elements. But is the other other is bigger it does not return the correct one. How to overcome this?
<?php
$A = array(0);
$B= array(1,0);
$n = sizeof($A);
$m = sizeof($B);
sort($A);
sort($B);
$i = 0;
for ($k = 0; $k < $n; $k++) {
if ($i < $m - 1 AND $B[$i] < $A[$k])
$i += 1;
if ($A[$k] == $B[$i])
echo $A[$k];
}
echo "end";
?>
Thanks
A way simpler way would be to take the minimum value of the intersection of your arrays :
$array = array (5,6,7,8,9);
$array2 = array (9,7,5,3,4,1);
$min = min(array_intersect($array, $array2));
echo $min; // 5
Leverage PHP function array_intersect() to extract common values in two arrays, then fetch the minumum value by using min()
Like so:
<?php
$arrayOne = [1, 3, 5, 6, 7];
$arrayTwo = [0, 9, 2, 3, 4, 5];
echo min(array_intersect($arrayOne, $arrayTwo)); // 3
I would use array_intersect. It will give you an array with only values that are present in both arrays you are looking through, then you can find the lowest value in the array
$A = array(0,5,4,3,2,1,4);
$B = array(0,1,3,4);
$C = array_intersect($A, $B);
$low = $C[0];
for($i = 0; $i < count($C); $i++) {
if($C[$i] < $low)
$low = $C[$i];
}
echo "Lowest shared number is $low";
Related
I have two arrays which I want to multiply and get the final sum. First one is fixed but the second one could have missing elements. For example:
$array1 = array(1, 2, 3, 4, 5);
$array2 = array(1, 3, 5);
Lets say I've got missing elements $array2[1] and $array2[3]. I want to be able to multiply and sum up the rest as:
$sum = array_sum($array1[0] * $array2[0] + $array1[1] * $array2[1] + $array1[2] * $array2[2] + $array1[3] * $array2[3] + $array1[4] + $array2[5]);
Length of arrays may also vary so can't do it the way I've written it above. Any suggestions?
You can complete the array2 missing values as 1, then make the two array have the same length.
$missingKeys = [1,3];
foreach($missingKeys as $k)
{
$array2[$k] = 1;
}
$sum = 0;
foreach($array1 as $k => $v)
{
$sum += $v * $array1[$k];
}
Ok, I didn't use my own advise, but I think this might work?
$total = 0;
foreach ($array1 as $index => $value)
{
if (isset($array2[$index])) $total += $value*$array2[$index];
else $total += $value;
}
echo $total;
The assumption is that all elements of $array2 are present in $array1, but not necessarily the other way around.
As you wrote in your question that the first array is leading (has all the indexes) you only need to iterate over it and eventually multiply with the value from the second array or one:
$sum = 0;
foreach ($array1 as $k => $v) {
$sum += $v * ($array2[$k] ?? 1);
}
Different to the accepted answer, there is no need to manipulate the second array.
If I understood your question properly, and your looking for array multiplication, you could use 2 for loops, iterating one of them and multiplying. Your probably looking for something like this:
for ($i = 0; $i < count($array1); $i++) {
for ($j = 0; $j < count($array2); $j++) {
$sum += $array1[$i] * $array2[$j];
}
}
I am trying to write a function that will check if the array can be sorted with a single swap of the values in the array.
For example: array(1,3,5,3,7) must return true, but array(1,3,5,3,4) must return false.
I tried the following code below, but I'm stuck with it:
$noOfIterations = 0;
for($x = 0; $x < count($a)-2; $x++) {
if($a[$x] > $a[$x+1]) {
$noOfIterations ++;
}
}
return $noOfIterations >1;
// The below solution helped as well.
//$arr = [1, 3, 5, 3, 7]; //[1, 3, 5, 3, 4]
$arr = [1, 3, 5, 3, 4];
$sortedArr = $arr;
sort($sortedArr);
print_r(array_intersect_assoc($arr,$sortedArr));
This should work for you:
(Here I first make a copy of the original array to then sort() it. After this I loop through both arrays with array_map() and look how many position has changed. With array_filter() I sort the elements out where no position has changed. Then you can simply check if 2 or more position has changed and print either FALSE or TRUE)
<?php
$arr = [1, 3, 5, 3, 7]; //[1, 3, 5, 3, 4]
$sortedArr = $arr;
sort($sortedArr);
$filtered = array_filter(
array_map(function($v1, $v2){
return ($v1 == $v2 ?FALSE:TRUE);
}, $arr, $sortedArr)
);
var_dump(count($filtered) > 2 ? FALSE : TRUE);
?>
output:
TRUE //FALSE
Execute the sort, then compare the original array with the sorted array using array_intersect_assoc().... if the difference is more than two elements, then the answer is 'no'
If you really wanna do it with a loop, you can do it with a double loop comparing each value to one another. You need to get a little creative with the comparing. From what I see, your code succeeds on the first array but fails on the second. It fails on the second one because you are only checking 2 adjacent entries and 3 is always less than 4. Or you can keep track of the largest number and count how many numbers are less than that value past it. Also make sure to add to the count if you encounter another bigger value. Hope all this makes sense.
What if array is sorted and no swap is needed?
It might help if I knew Why.
Try this, it works for your two example arrays.
function swap($array){
$prev = 0;
$count = 0;
foreach($array as $val){
if($val < $prev){
$count++;
}
else{
$prev = $val;
}
}
if($count < 2){return(true);}else{return(false);}
}
My answer in php.
function oneSwap($A){
$count=count($A);
$swaps=0;
$curr_max = 0;
$res = false;
for($i = 0; $i <= $count; $i++) {
if(isset($A[$i+1])){
if(($A[$i] >= $A[$i + 1]) && $curr_max >= $A[$i+1]){
$swaps++;
}
if($A[$i] >= $A[$i +1]){
$curr_max = $A[$i];
}
}
}
if(($swaps == 1) || ($swaps == 0 && $curr_max ==0)){
$res = true;
echo $res;
}
}
oneSwap([3,1,2,8]);
oneSwap([1,2,3]);
oneSwap([1,5,3,3,7]);
oneSwap([3,2,1,8]);
oneSwap([2,1,1,2]);
Given the following array:
$arr = array(0,0,1,2,2,5,6,7,7,9,10,10);
And assuming $n = 2, what is the most efficient way to get a count of each value in the array within $n of each value?
For example, 6 has 3 other values within $n: 5,7,7.
Ultimately I'd like a corresponding array with simply the counts within $n, like so:
// 0,0,1,2,2,5,6,7,7,9,10,10 // $arr, so you can see it lined up
$count_arr = array(4,4,4,4,4,3,3,4,4,4, 2, 2);
Is a simple foreach loop the way to go? CodePad Link
$arr = array(0,0,1,2,2,5,6,7,7,9,10,10);
$n = 2;
$count_arr = array();
foreach ($arr as $v) {
$range = range(($v-$n),($v+$n)); // simple range between lower and upper bound
$count = count(array_intersect($arr,$range)); // count intersect array
$count_arr[] = $count-1; // subtract 1 so you don't count itself
}
print_r($arr);
print_r($count_arr);
My last answer was written without fully groking the problem...
Try sorting the array, before processing it, and leverage that when you run through it. This has a better runtime complexity.
$arr = array(0,0,1,2,2,5,6,7,7,9,10,10);
asort($arr);
$n = 2;
$cnt = count($arr);
$counts = array_pad(array(), $cnt, 0);
for ($x=0; $x<$cnt; $x++) {
$low = $x - 1;
$lower_range_bound = $arr[$x]-$n;
while($low >= 0 && ($arr[$low] >= $lower_range_bound)) {
$counts[$x]++;
$low--;
}
$high = $x + 1;
$upper_range_bound = $arr[$x]+$n;
while($high < $cnt && $arr[$high] <= $upper_range_bound) {
$counts[$x]++;
$high++;
}
}
print_r($arr);
print_r($counts);
Play with it here: http://codepad.org/JXlZNCxW
Suppose I have two arrays:
$a1 = array(0, 1, 2);
$a2 = array(3, 4, 5);
I want to be able to do a merge technique that alternates the array values and not just concatenate them. I want this result:
array(0, 3, 1, 4, 2, 5);
Is there a native way to do this as performance is an issue here since I need to do this thousands of times
Please note, I know I can do it like this:
for (var $i = 0; $i < count($a1); $i++) {
newArray[] = $a1[$i];
newArray[] = $b1[$i];
}
I'm looking for a built in way if there is a faster one.
$count = count($a1);
for ($i = 0; $i < $count; $i++) {
$newArray[] = $a1[$i];
$newArray[] = $b1[$i];
}
My work here is done.
$a1 = array(0,1,2);
$a2 = array(3,4,5);
$start = microtime(TRUE);
for($t = 0; $t < 100000; $t++)
{
$newArray = array();
$count = count($a1);
for ($i = 0; $i < $count; $i++)
{
$newArray[] = $a1[$i];
$newArray[] = $a2[$i];
}
}
echo round(microtime(TRUE) - $start, 2); # 0.6
$a1 = array(0,1,2);
$a2 = array(3,4,5);
$start = microtime(TRUE);
for($t = 0; $t < 100000; $t++)
{
$newArray = array();
for ($i = 0; $i < count($a1); $i++)
{
$newArray[] = $a1[$i];
$newArray[] = $a2[$i];
}
}
echo round(microtime(TRUE) - $start, 2); # 0.85
So pre-counting array size will be ~1/4 [citation needed] (on freakin' 100.000 iterations you will gain 0.2 in total) faster. If you put count() inside loop, it will recount on every iteration. 1/4 seems to me a reasonably faster. If you are looking for compiled function, you can stop.
P.S. Benchmark is like bikini, it shows you everything, and nothing.
Since you are "zippering" two indexed arrays, you can "transpose and flatten". I expect that this will not be quite as fast as using a for() or foreach(), but on small input arrays, there will be no noticeable drag on performance. In other words, when coding style or minimal declared variables is sought, then the following technique should be considered.
Code: (Demo)
$a1 = [0, 1, 2];
$a2 = [3, 4, 5];
var_export(
array_merge(...array_map(null, $a1, $a2))
);
Output:
array (
0 => 0,
1 => 3,
2 => 1,
3 => 4,
4 => 2,
5 => 5,
)
As a funky little function-less approach, you can push the $a1 value from the foreach() value declaration and inside the loop's body, you can push the $a2 value. Feast your eyes... (Demo)
$result = [];
foreach ($a1 as $index => $result[]) {
$result[] = $a2[$index];
}
var_export($result);
// same output as earlier snippet
For anyone that is hunting for an associative-safe technique, you could make looped slice or splice calls. Be aware that splice() will mutate/consume the input arrays in the process. (Slice Demo) (Splice Demo)
$result = [];
for ($i = 0, $count = count($a1); $i < $count; ++$i) {
$result += array_slice($a1, $i, 1)
+ array_slice($a2, $i, 1);
}
or
$result = [];
while($a1 && $a2) {
$result += array_splice($a1, 0, 1)
+ array_splice($a2, 0, 1);
}
p.s. I even build this utility snippet to offer more dynamic tooling of how many elements should be inserted and how frequently from each array while merging. See Insert elements from one array (one-at-a-time) after every second element of another array (un-even zippering).
I want to know if it is possible to take an array and insert the array's values into a bigger array, multiple times, so that the values of the smaller array fill up the bigger array.
Say array1 has values ([0 => 'a'],[1 => 'b'],[2 => 'c']), and array2 can hold 8 values. So, how would I take the values of array1 and insert them into array2 continuously until array2 runs out of space, so that array2 would have the values 'a','b','c','a','b','c','a','b'?
Thanks in advance,
~Hussain~
Essentially, you want to loop over and over the small array, adding each element to the new array until it has reached the desired size.
Consider this:
$max = 8;
$Orig_Array = array('a', 'b', 'c');
$Next_Array = array();
while True
{
foreach($Orig_Array as $v)
{
$Next_Array[] = $v;
if(count($Next_Array) >= $max)
break 2;
}
}
Assuming that your input array is indexed sequentially:
$len = count($input);
$output = array();
for ($i = 0; $i < MAX_SIZE; ++$i)
$output[] = $input[$i % $len];
$a = array('a','b','c');
$desired = 8;
$b = array();
for($i=0;$i<($desired/count($a))+1;++$i) $b = array_merge($b,$a);
array_splice($b,$desired);
Or
$a = array('a','b','c');
$desired = 8;
$b = array();
for($i=0;$i<$desired/count($a);++$i) $b = array_merge($b,$a);
for($i=0;$i<($desired-count($b)-1);++$i) $b[] = $a[$i];
The first one fills up an array so that it has at least desired number of elements and cuts off the rest. The second one fills up an array up the desired number of elements modulo original array size and adds up the rest.
Here's one using the input array's internal pointer, to keep things conceptually simple:
$input = array(1, 2, 3);
$size = 32;
$output = array();
for ( $i = 0; $i < $size; $i++ ) {
$curr = current($input);
if ( $curr === false ) {
reset($input);
$curr = current($input);
}
$output[] = $curr;
next($input);
}
print_r($output);die;