$ar is a sock of pairs. $n is the number of items in $ar. I have to match each number in the array with another if any of them match, its a pair. I have to then return the count of matched items. I have done it below but the answer is one less than what it should be. Example
n:9
ar: 10 20 20 10 10 30 50 10 20
I get output 2 instead of 3.
function sockMerchant($n, $ar) {
$pair =0;
$j=0;
for($i=0; $i< count($ar); $i++)
{
for($j=$i+1; $j< count($ar); $j++)
{
if ( isset( $ar[$j]) && isset( $ar[$i])) {
if ($ar[$i]== $ar[$j])
{
unset($ar[$i]);
unset($ar[$j]);
$pair+=1;
$i=0;
break;
}
}
}
}
return count($ar);
}
Instead of what you are doing there is shortcut to achieve the same,
$temp = array_count_values($arr); // count number of occurences
echo count(array_filter($temp, function($value){ // filter in not greater than 1
return $value > 1;
}));
The above snippet will give you all the pairs which are not only once.
Here is an one more alternative for your snippet,
$temp = array_count_values($arr); // count number of occurences
$e = array_reduce($temp, function ($carry, $item) {
$carry += ($item > 1 ? intval($item / 2) : 0);
return $carry;
});
echo $e;die;
Working demo.
$ar = [10, 20, 20, 10, 10, 30, 50, 10, 20];
$pairIndex = [];
$count = 0;
foreach ($ar as $key => $item) {
// Start comparing from the next element
for ($i = ($key + 1); $i < count($ar); $i++) {
if ($item == $ar[$i] && !in_array($key, $pairIndex)) {
$pairIndex[] = $key;
$pairIndex[] = $i;
$count++;
}
}
}
echo "Pairs: " . $count;
This will give you the number of pairs.
$arr = array(10, 20, 20, 10, 10, 30, 50, 10, 20);
$counts = array_count_values($arr); // count number of occurences
array_walk($counts, function(&$x) {$x = intdiv($x, 2);}); //divide each element
//by 2 (integer division), so now you have pairs of each element
echo array_sum($counts); //sum the pairs
Using your initial array, it echoes 3.
simple example what happens to your array:
$ar = array(0, 10, 20, 30, 40, 50 , 60, 70, 80, 90);
$lnPointer = 2;
print_r($ar);
// Array ( [0] => 0 [1] => 10 [2] => 20 [3] => 30 [4] => 40 [5] => 50 [6] => 60 [7] => 70 [8] => 80 [9] => 90 )
echo "<HR>";
echo $ar[$lnPointer];
echo "<HR>";
unset( $ar[$lnPointer]);
print_r($ar);
// Array ( [0] => 0 [1] => 10 [3] => 30 [4] => 40 [5] => 50 [6] => 60 [7] => 70 [8] => 80 [9] => 90 )
echo "<HR>";
echo $ar[$lnPointer];
after unsetting you get an undefined index
If you want total matched pair count then you should return $pair. But you are returning count($ar) which can not be correct in all the possible scenarios. Check the below code with output and new set of data:
<?php
function sockMerchant($n, $ar) {
$pair =0;
$j=0;
for($i=0; $i< $n; $i++)
{
for($j=$i+1; $j< $n; $j++)
{
if ( isset( $ar[$j]) && isset( $ar[$i])) {
if ($ar[$i]== $ar[$j])
{
unset($ar[$j]);
unset($ar[$i]);
$pair+=1;
$i=0;
break;
}
}
}
}
echo '<pre>'; print_r($ar);
return $pair.'--'.count($ar);
}
$a = [10, 20, 20, 10, 10, 30, 50, 10, 20, 80, 40];
$n = 11;
$b = sockMerchant($n, $a);
var_dump($b);
// Output:
/*
Array
(
[5] => 30
[6] => 50
[8] => 20
[9] => 80
[10] => 40
)
string(4) "3--5"
*/
?>
Demo
Related
foreach($manualsArray as $manuls){
for($i=0;$i<=count($manuls);$i++){
if($i/2 == 0){
$manuls = 23;
print($manuls);
}
else{
$manualsArray= 98;
print($manualsArray);
}
print($manualsArray);
}
}
I want to create key value pairs according to index like 0 is key 1 is value 2 is key 3 is value and so on.
the sample input is write below
Array
(
[0] => Array
(
[0] => Faucet Centers
[1] => 6, 4, 13, 12, 7, 10, 14, 16, 8, 5, 9, 15, 11 in.
[2] => Flow Rate (GPM)
[3] => 1.2
[4] => Height
[5] => 5.875 in.
[6] => Max Deck Thickness
[7] => 2.25 in.
[8] => Spout Height
[9] => 3.625 in.
[10] => Spout Reach
[11] => 5 in.
)
)
You can achieve this by changing your loop to increment by 2 each time and take $i as the key and $i+1 as the value...
$output = [];
foreach($manualsArray as $manual){
$m = [];
for ( $i = 0; $i < count($manual); $i+=2 ) {
$m [$manual[$i]] = $manual[$i+1];
}
$output [] = $m;
}
print_r($output);
you can use array_chunk()
foreach($manualsArray as $manuls){
foreach( array_chunk($manuls, 2) as $pair) {
echo 'key: ' . $pair[0] . ' is value: '. $pair[1] . "<br>/n";
}
}
or if you want an associative array
$result_array = [];
foreach($manualsArray as $manuls){
foreach( array_chunk($manuls, 2) as $pair) {
$result_array[] = [$pair[0] => $pair[1]];
}
}
var_export($result_array);
https://www.php.net/manual/en/function.array-chunk.php
Use modulo for that:
<?php
$newarray = array();
foreach($yourarray[0] as $id => $val){
if($id % 2 == 0){
$last_index = $val;
}else{
$newarray[$last_index] = $val;
}
}
?>
I assume that your array is the one you have given, so it's 2-dimensional.
If not, use $yourarray instead of $yourarray[0].
<?php
$array = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
$result = [];
for ($i=0; $i < count($array) ; $i++) {
if (($i >=3 AND $i <= 6) OR $i=8){
array_push($result, $array[$i]*2);
} else {
array_push($result, $array[$i]*10);
}
}
var_dump($result);
?>
I want to multiply value in array that have key 3, 4, 5, 6, and 8 by 2, other than that key I want to multiply it by 10.
Tried change memory limit even to -1 (unlimited) but still give same error.
It seems the only problem is: you are changing the value of $i inside the if clause because of a missing =, it should be $i==8 instead of $i=8, a working script with some minor changes would be:
<?php
$array = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
$result = [];
$length = count($array);
for($i=0; $i < $length ; $i++) {
if (($i >=3 AND $i <= 6) OR $i==8){
$val = $array[$i] * 2;
} else {
$val = $array[$i] * 10;
}
array_push($result, $val);
}
// output
echo "<pre>";
print_r($result);
echo "</pre>";
?>
This outputs:
Array
(
[0] => 100
[1] => 200
[2] => 300
[3] => 80
[4] => 100
[5] => 120
[6] => 140
[7] => 800
[8] => 180
[9] => 1000
)
change your if condition from: if (($i >=3 AND $i <= 6) OR $i=8){
to : if (($i >=3 AND $i <= 6) OR $i==8){
***You are not assigning a value to $i. You are checking its value. That's why you must use ==.
If I have an associative array like
3 => 50
4 => 12
5 => 45
6 => 89
7 => 5
8 => 1
Now I want to sort only the values of odd keys in ascending order.
The output should be:
7 => 5
4 => 12
5 => 45
6 => 89
3 => 50
8 => 1
To maintain original keys, you have to first separate even and odd elements:
$odd = $even = array();
array_walk( $array, function( $val, $key ) use ( &$odd, &$even ) { ( $key % 2 ) ? $odd[$key] = $val : $even[$key] = $val; });
Then, sort $odd array:
asort( $odd );
At the end, you reconstruct the array:
$array = array();
while( current( $odd ) || current( $even ) )
{
if( current( $odd ) ) $array[key($odd)] = current( $odd );
if( current( $even ) ) $array[key($even)] = current( $even );
next( $odd );
next( $even );
}
print_r( $array );
eval.in demo
Note that your question is a bit ambiguous: it's not totally clear if you base odd/even on key value or key position: this solution consider key values and — trough while and if checks — guarantee that all values are preserved, even if you have more even than odd keys (or vice-versa).
Try this:
<?php
$array = array(
3 => 50,
4 => 12,
5 => 45,
6 => 89,
7 => 5,
8 => 1
);
$oddElems = array();
$evenElems = array();
$i = 0;
foreach($array as $index => $value)
{
if($i % 2 == 0)
$oddElems[$index] = $value;
else
$evenElems[$index] = $value;
$i++;
}
//sort odd elements
asort($oddElems);
$result = array();
while(!empty($oddElems) || !empty($evenElems))
{
$lastEvenElemKey = array_keys($evenElems, end($evenElems))[0];
$evenElem = array_pop($evenElems);
if($evenElem !== null)
$result[$lastEvenElemKey] = $evenElem;
$lastOddElemKey = array_keys($oddElems, end($oddElems))[0];
$oddElem = array_pop($oddElems);
if($oddElem !== null)
$result[$lastOddElemKey] = $oddElem;
}
echo '<pre>';
$result = array_reverse($result, true);
print_r($result);
Result is:
Array
(
[7] => 5
[4] => 12
[5] => 45
[6] => 89
[3] => 50
[8] => 1
)
This is how you could do this in PHP, is this what you are looking for ?
$array(3 => 50, 4 => 12, 5 => 45, 6 => 89, 7 => 5, 8 => 1);
function sort_it($array) {
$final_array[];
$array_only_odd_keys[];
$array_only_odd_stuff[];
$array_only_even_keys[];
$array_only_even_stuff[];
foreach($array as $key => $value) {
if($key & 1) {
//Key is odd
array_push($array_only_odd_stuff, $key => $value);
array_push($array_only_odd_keys, $key);
}
else {
// Key is even
array_push($array_only_even_stuff, $key => $value);
array_push($array_only_even_keys, $key);
}
}
$array_only_odd_keys = asort($array_only_odd_keys);
for ($x = 0; $x <= count($array)/2; $x++) {
if ($x & 1) {
array_push($final_array, $array_only_odd_keys[$x], $array_only_odd_stuff[$array_only_odd_keys[$x]]);
}
else {
array_push($final_array, $array_only_even_keys[$x], $array_only_odd_stuff[$array_only_even_keys[$x]]);
}
}
return $final_array;
This is how i'd do it in PHP though only if you want the final array to switch between even and odd keys like in your example.
The easiest way is probably to separate the array into even and odd arrays, sort the odd array, and then glue them back together:
$odd = $even = [];
foreach (array_chunk($myArray, 2, true) as $pair) {
$odd += array_slice($pair, 0, 1, true);
$even += array_slice($pair, 1, 1, true);
}
asort($odd);
$result = [];
for ($i = 0; $i < count($odd); $i++) {
$result += array_slice($odd, $i, 1, true);
$result += array_slice($even, $i, 1, true);
}
This rather naïve implementation assumes there is an equal number of odd and even numbers, they're always alternating and the array starts with an odd number.
For each element in the array, I need to add value of previous element to it's current element. Example:
Array
(
[0] => 460
[1] => 25
[2] => 25
[3] => 25
[4] => 25
[5] => 25
[6] => 25
)
How can I get like following:
Array
(
[0] => 460
[1] => 485
[2] => 510
[3] => 535
[4] => 560
[5] => 585
[6] => 610
)
Any ideas?
Here's a quicker solution compared to the rest:
foreach ($a as $i => $val) {
// make sure the current item is not the first one.
// because the first one is the base number
if ($i > 0) {
// Update current $i (INDEX) by
// adding the previous value ($a[$i -1]) with the current value ($val)
$a[$i] = $a[$i - 1] + $val;
}
}
As 0 is the first value, we can't increment before it :) hence the if statement
And here is a demo: Example
It doesn't matter about what looping method you use, it's how you apply it. Look, here's the exact same thing done in a for loop:
for($i = 0; $i < count($a); $i++) {
if($i > 0) {
$a[$i] = $a[$i - 1] + $a[$i];
}
}
It all comes down to the preference of the coder using it.
Both of those loops return the correct data:
Array
(
[0] => 460
[1] => 485
[2] => 510
[3] => 535
[4] => 560
[5] => 585
[6] => 610
)
Like this?
$source = array(460, 25, 25, 25, 25, 25, 25);
$result = array();
$last = 0;
foreach($source as $s){
$last = $result[] = $s+$last;
}
$previous = 0;
foreach ($a as $key => &$value)
$previous = $value = $previous + $value;
or
$sum = 0;
foreach ($a as $key => &$value)
{
$sum += $value;
$value = $sum;
}
Get the value of the previous index (do check if index > 0), and add it to the current value.
$values = array(
460,
25,
25,
25,
25,
25,
25
);
foreach($values as $key => &$value){
if($key > 0){
$prev_value = $values[$key-1];
$value += $prev_value;
}
}
echo print_r($values);
$array1 = (460, 25, 25, 25, 25, 25, 25);
function calculateAdjecentSum($array1)
{
$array2 = array();
$pointer = 0;
foreach ($array1 as $number) {
$sum = $pointer + $number;
$array2[] = $sum;
$pointer = $sum;
}
return $array2;
}
It's enough to use for loop:
<?php
$array = array
(
0 => 460,
1 => 25,
2 => 25,
3 => 25,
4 => 25,
5 => 25,
6 => 25,
);
for ($i=1, $c = count($array); $i<$c; ++$i) {
$array[$i] += $array[$i-1];
}
var_dump($array);
I have no idea why all other answers use foreach loop in this case as for in my opinion is better to do that (no conditions, no temporary variables, no unset references from foreach).
You can do like this
<?php
$yourarray = array(460, 25, 25, 25, 25, 25, 25);
$l = 0;
foreach($yourarray as $b){
$l = $b+$l;
echo $last;
}
Outputs 460485510535560585610
Try this :
<?php
$array = array( 460, 25, 25, 25, 25, 25, 25);
$result = array();
for ($i=count($array);$i>0; $i--){
$result[($i-1)] = array_sum($array);
array_pop($array);
}
echo "<pre>";
ksort($result);
print_r($result);
?>
Output :
Array
(
[0] => 460
[1] => 485
[2] => 510
[3] => 535
[4] => 560
[5] => 585
[6] => 610
)
I try to write a script and a problem. Can you let me know if you know how i can do this or ask someone if they know how can this be possibe.
Max numbers which can be selected 1 to 20 numbers. it can loop and select any number between 1-20
ignore these numbers e.g. 1,2,4,6,9,12 this will be array which can change.
each array line can have upto 4 numbers
Each array line needs to be unique
5.I need to have around 10 arrays unique
Max 2 numbers can match previous numbers see below.
How can i go about doing this. Any help would be great.
e.g.
Array(
[0] => Array
(
[0] => 3
[1] => 16
[2] => 22
[3] => 24
)
[1] => Array
(
[0] => 3
[1] => 16
[2] => 7
[3] => 13
)
[2] => Array
(
[0] => 20
[1] => 17
[2] => 10
[3] => 18
)
)
This not allow as some array match each other
Array(
[0] => Array
(
[0] => 3
[1] => 16
[2] => 22
[3] => 24
)
[1] => Array - cant have this as 3 of the numbers matchs the previous array.only two numbers can match.
(
[0] => 3
[1] => 16
[2] => 22
[3] => 13
)
[2] => Array
(
[0] => 20
[1] => 17
[2] => 10
[3] => 18
)
)
Thank you.
This seems to satisfy your conditions: http://codepad.viper-7.com/WHkQeD
<?php
$num_arrays = 10; $num_elements = 4;
$min = 1; $max = 20;
$exclude_numbers = array( 1, 4, 6); // Add numbers here to exclude
$answer = array();
for( $i = 0; $i < $num_arrays; $i++)
{
$answer[$i] = array();
for( $j = 0; $j < $num_elements; $j++)
{
do
{
$current = rand( $min, $max);
// If the previous array exists and there are more than two common elements when we add the $current element, continue
if( isset( $answer[$i-1]) && count( array_intersect( $answer[$i-1], array_merge( $answer[$i], array( $current))) > 2)
{
continue;
}
} while( in_array( $current, $exclude_numbers) || in_array( $current, $answer[$i]));
$answer[$i][$j] = $current;
}
}
var_dump( $answer);
Edit: Here is a complete solution that satisfies all of your criteria.
Demo
<?php
$num_arrays = 10; $num_elements = 4;
$min = 1; $max = 20;
$exclude_numbers = array( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
$answer = array();
for( $i = 0; $i < $num_arrays; $i++)
{
$answer[$i] = array();
for( $j = 0; $j < $num_elements; $j++)
{
do
{
// Get a random element
$current = rand( $min, $max);
$new_array = array_merge( $answer[$i], array( $current));
// If the previous array has more than two common elements (because of the added $current), get a new $current
if( isset( $answer[$i-1]) && count( array_intersect( $answer[$i-1], $new_array)) > 2)
{
$answer[$i] = array_diff( $new_array, $answer[$i-1]);
$j = count( $answer[$i]) - 1;
continue;
}
} while( in_array( $current, $exclude_numbers) || in_array( $current, $answer[$i]));
$answer[$i][$j] = $current;
// If the array is complete, we need to check for unique arrays
if( count( $answer[$i]) == $num_elements)
{
$k = $i - 1;
while( $k >= 0)
{
if( count( array_diff( $answer[$k], $answer[$i])) == 0)
{
// This array is the same as a previous one, start over
$answer[$i] = array();
$j = -1;
break;
}
$k--;
}
// Optionally sort each array
sort( $answer[$i]);
}
}
}
var_dump( $answer);
somthing like:
function generate_list($max, $forbidden)
{
$list = array();
while(count($list) < 4)
{
$new = rand(1, $max);
if(in_array($new, $forbidden))
{
continue;
}
$list[] = $new;
$forbidden[] = $new;
}
return $list;
}
function count_max_same($new_list, $old_lists)
{
$max_same = 0;
foreach($old_lists as $current_list)
{
$max_same = max($max_same, count(array_intersect($new_list, $old_lists)));
}
return $max_same;
}
function generate_unique_lists($count_of_lists, $max, $forbidden, $max_same = 2, $max_tries = 1000)
{
$lists = array();
while($max_tries-- AND count($lists) < $count_of_lists)
{
$new_list = generate_list($max, $forbidden);
if(count_max_same($new_list, $lists) <= $max_same)
{
$lists[] = $new_list;
}
}
return $lists;
}