I have a multidimentionnal array like this example
$arr = array (
range(9,4),
range(8,0),
range(2,7),
range(-1,17)
);
after showing its content I get this
9 8 7 6 5 4
8 7 6 5 4 3 2 1 0
2 3 4 5 6 7
-1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Now the result I want to get is this
-1 0 0 1 1 2
2 2 3 3 3 4 4 4 4
5 5 5 5 6 6
6 6 7 7 7 7 8 8 8 9 9 10 11 12 13 14 15 16 17
I defined a function that sorts the array and returns the result I need, but I want to know if there is a simple way to do it using predefined functions or a simple and fast algorithm
this is my function
function sort_multi($arr)
{
$length = 0;
foreach ($arr as $value)
$length += count($value);
$sorted = false;
while(!$sorted)
{
$x = 0;
$y = 0;
$sorted = true;
while(($x+$y)<($length-1) && isset($arr[$x][$y]))
{
$new_x = isset($arr[$x][$y+1])?$x:($x+1);
$new_y = isset($arr[$x][$y+1])?($y+1):0;
if(($new_x+$new_y)<$length && isset($arr[$new_x][$new_y]))
if($arr[$x][$y] > $arr[$new_x][$new_y])
{
perm($arr[$x][$y], $arr[$new_x][$new_y]);
$sorted=false;
}
$x = $new_x;
$y = $new_y;
}
}
return $arr;
}
the definition of perm is
function perm(&$a,&$b)
{
$inter = $a;
$a = $b;
$b = $inter;
}
I think array_walk_recursive could work well for something like this.
// Fill a temp array with all the values from the multidimensional array...
$temp = array();
array_walk_recursive($arr, function($item) use (&$temp) {
$temp[] = $item;
});
sort($temp); // sort it...
// refill the multidimensional array with the sorted values.
array_walk_recursive($arr, function(&$item) use (&$temp) {
$item = array_shift($temp);
});
I don't know which is the best way. But you can do it brute force: Sample Output
$arr = array (
range(9,4),
range(8,0),
range(2,7),
range(-1,17),
);
// simple checking of number of items per batch (since this is sort of like array_chunk, but jagged)
$chunks = array_map(function($batch){ return count($batch); }, $arr);
foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($arr)) as $v) {
$values[] = $v; // simple flattening
}
sort($values); // sort ascending (prepping)
foreach($chunks as $key => $batch) {
// number of items in a batch
// simple cutting (i can't find the function for this, i think there is)
for($x = 0; $x < $batch; $x++) {
$final[$key][] = $values[$x];
unset($values[$x]);
}
$values = array_values($values); // reindex again (resetter)
}
echo '<pre>';
print_r($final);
I Usually prefer a Bubble Sort, because at longest it will take the same as brute force. Usually it is slightly more efficient though.
Related
in an N numbers of array a number is a X-number if it is divisible by atleast one other number in the array. Program to find how many such numbers exists in an given array
example 1 : in array [1,2,3] , number of x-numbers is 2 ( 2 and 3 as they are divisible by number 1 )
example 2 : in array [2,3,5,8] , number of x-numbers is 1 ( 8 is divisible by 2 )
example 3 : in array [2,3,6,12] , number of x-numbers is 2 ( 6 is divisible by 2 and 3 , 12 is divisible by 2 and 3 and 6 )
I am using the below code, but i want to optimize it in a way if the array size increase the performance should not hamper :
$arr = array(2,3,6,12);
$count = 0;
function check_special_num($tnum, $tarr){
sort($tarr);
for($i=0;$i<sizeof($tarr);$i++){
if( $tnum % $tarr[$i] == 0 ){
return true;
}
}
return false;
}
for($i=0;$i<sizeof($arr);$i++){
$temp = $arr;
$num = $arr[$i];
array_splice($temp, $i, 1);
if( check_special_num( $num, $temp ) ){
$count += 1;
}
}
echo $count;
Coding language is PHP
It might be faster this way:
$arr = array(2,3,6,12);
function x_numbers_count($arr) {
$count = 0;
sort($arr);
foreach ($arr as $i => $number) {
for ($j = 0; $j < $i; $j++) {
if ($number % $arr[$j] == 0) {
$count++;
break;
}
}
}
return $count;
}
echo x_numbers_count($arr);
The main differences, which can be expected to improve performance:
the array is sorted only once, before beginning to work (this could also improve your own method, without changing anything else)
the search loop stops as soon as it is to reach the current investigated number
less variables are used
Lets say, I have an array with 1000 values (integers). And I need from this array to have an array with f.e. 400 values (the number can be changed, f.e. 150, etc.).
So I need to return each 2.5th array value, i.e. 1st, 3rd, 6th, 8th, 11th, etc.
Is this somehow possible?
I dont need a code, I just need some way, how to do it.
EDITED:
My array is array of elevations (from another array with GPS coordinates). And I want to draw a 2D model of elevation. Lets say, my map will always have 400px width. 1px = 1 point of elevation. Thats why I need each 2.5th elevation value...
Like this:
You don't want the 2.5th one. You effectively want to divide the set into blocks of five and get the first and third from each set.
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
You want the first and third columns.
This is PHP, so we've got 0-based arrays.
We can divide it into groups of 5 using the modulo operator %. We can then see if the return value is 0 (i.e. it's in the first column) or 2 (i.e. it's in the third column).
I'm going to presume your array has numeric keys starting from 0.
// PHP 5.6
$filtered = array_filter($array, function($value, $key) {
$mod = $key % 5;
return ($mod === 0) || ($mod === 2);
}, ARRAY_FILTER_USE_BOTH);
// pre-PHP 5.6
$filtered = array();
foreach ($array as $key => $value) {
$mod = $key % 5;
if (($mod === 0) || ($mod === 2)) {
$filtered[$key] = $value;
}
}
var_dump($filtered);
How about using the modulo % operator?
Say you want to make 1000 into 200 values, loop through all the items in the array and keep a counter, if the counter % 5 == 0 then put that value into a new array, or if != 0 then remove from array. We use modulo 5 because 1000 / 200 = 5.
Below is the way to start with. It does not ensure that first and last elements are included in the output and, probably, has some other glitches. But since you requested the idea, here you go—array_reduce:
$a=[1,2,3,4,5,6,7,8,9,10,11,12]
$step = 2.5;
$i = 0;
$r = array_reduce($a, function($memo, $curr) use(&$i, $step) {
if($i === round($step * count($memo))) {
$memo[] = $curr;
}
$i++;
return $memo;
}, []);
print_r($r);
/*
Array
(
[0] => 1
[1] => 4
[2] => 6
[3] => 9
[4] => 11
)
*/
Hope it helps.
This should be pretty close to what you seem to be looking for. It will collect whichever values are closest (rounding down) to the float values.
$list = range(1,1000);
$targetSize = 300;
$new = array();
$step = count($list) / $targetSize;
$curStep = 0;
for( $i = 0; $i < count($list); $i++ ) {
$curStep++;
if( $curStep > $step ) {
$new[] = $list[ floor($i) ];
$curStep -= $step;
}
}
So this is it:
$arr = range(1, 1387); // f.e.
$cnt = 296; // f.e.
$new = array();
$max = count($arr);
$step = $max / $cnt;
for ($i = 0; $i < $max; $i += $step) {
$new[] = round($arr[(int)$i]);
}
I am trying to figure out how I can loop out possible combinations of a x amount of integers to sum a specifik number.
Let's say, I have number 7 and I need to figure out how I can sum that number with integers in pairs 3.
1+2+4 = 7
3+3+1 = 7
5+1+1 = 7
2+2+3 = 7
Repeated combinations of numbers doesn't interest me, e.g.:
1+2+4 = 7
2+4+1 = 7
4+2+1 = 7
Anyone got any ideas of how I should proceed to reach this result?
Thanks.
Here is the solution for your problem.
function printPartitions($target, $max, $s){
if($target === 0 )
echo $s;
else
{
if($max > 1)
{
printPartitions($target, $max-1, $s);
}
if($max <= $target)
{
printPartitions($target-$max, $max, $max . " " . $s);
}
}
}
printPartitions(5, 5, "<br/>");
You have to specify the $target Value, $max value.
e.g.
printPartitions(7, 7, "<br/>");
It will give you output like:
1 1 1 1 1 1 1
1 1 1 1 1 2
1 1 1 2 2
1 2 2 2
1 1 1 1 3
1 1 2 3
2 2 3
1 3 3
1 1 1 4
1 2 4
3 4
1 1 5
2 5
1 6
7
I've got a solution to my problem. I feel I should defientely share it here, if anyone would ever need it. My solutions is based on this post: https://stackoverflow.com/a/19067884/3293843
<?php
function sampling($chars, $size, $combinations = array()) {
# if it's the first iteration, the first set
# of combinations is the same as the set of characters
if (empty($combinations)) {
$combinations = $chars;
}
# we're done if we're at size 1
if ($size == 1) {
return $combinations;
}
# initialise array to put new values in
$new_combinations = array();
# loop through existing combinations and character set to create strings
foreach ($combinations as $combination) {
foreach ($chars as $char) {
$new_combinations[] = $combination .'#'. $char;
}
}
# call same function again for the next iteration
return sampling($chars, $size - 1, $new_combinations);
}
// example
$chars = array('1', '2', '3','4');
$target = 7;
$maxLengthOfIntegers = 3;
$output = sampling($chars, $maxLengthOfIntegers);
$repeatedEntries = array();
//presenting the output
foreach($output as $out){
$explodeOut = explode('#',$out);
sort($explodeOut);
if(array_sum($explodeOut) == $target){
$sortedPattern = implode('',$explodeOut);
if(!in_array($sortedPattern,$repeatedEntries)){
echo $sortedPattern.'<br/>';
$repeatedEntries[] = $sortedPattern;
}
}
}
?>
Thank you for your time and efforts.
Regards,
Jacob
you can try this algorithm
$ans = array();
for($i=1;$i<=5;$i++)
{
$i1 = 7-$i;
$i2 = intval($i1 - $i);
$value = $i."+".$i1."+".$i2;
$ans = array_unshift($ans,$value);
}
print_r($ans);
hope this helps.. PLease let me know
what i want to do is something like memory game, but I keep cannot get the same number with the out put
$numbers = range(1, 15);
shuffle($numbers);
foreach($numbers as $key){
echo $numbers[array_rand($numbers)];
break;
}
now the out put will be something like this
4 2 3 3
1 5 3 6
2 3 4 5
10 9 8 10
but how to I do it as rand array and with same 2 array number, which is i can match the number.
what i want in out put is
2 3 1 4
3 4 2 1
5 6 9 7
7 9 6 5
so like this i can get the match in 2 same number
any idea how to do it?
thanks
Your question is a bit confusing and vague. I extrapolate that you want to shuffle and display an array of numbers, two of each, in random order. To do that:
<?php
$numbers = range(1, 5);
$numbers = array_merge($numbers, $numbers);
shuffle($numbers);
echo implode(' ', $numbers);
This outputs, for instance, 3 5 1 5 1 2 3 4 2 4.
The array_rand() call in the foreach in your code makes absolutely no sense. If the above isn't what you wanted, please revise your question to be clearer.
First you have to do an array with couple values
// Generate array with values from 1 to 8
$arNumbers = range(1, 8);
// Duplicate the array so get copy of each number
$arNumbers = array_merge($arNumbers, $arNumbers);
// Shuffle the array
shuffle($arNumbers);
// And now display them
foreach($arNumbers as $nNumber)
{
// Do some business
}
Hope it helps :)
Try this. It is a simple way.
$numbers=range(1, 15);
//Get 4 unique random keys from $numbers array.
$rand_keys = array_rand($numbers, 4);
//print out the random numbers using the
//random keys.
foreach ($rand_keys as $k=>$i) {
echo $numbers[$i]." ";
}
Hope this will helps you...
If I get you correctly, you can achieve what you want to do with the following:
// make sure these are even numbers
$rows = 4;
$cols = 4;
$set = range(1, ($rows * $cols) / 2);
$numbers = array_merge($set, $set);
shuffle($numbers);
foreach (array_chunk($numbers, $cols) as $row) {
foreach ($row as $col) {
printf('%-5d', $col);
}
echo "\n";
}
Outputs:
3 7 2 1
4 6 8 5
6 3 8 4
2 5 7 1
Do something like:
$numbers = range(1, 15);
shuffle($numbers);
$used_numbers = array();
foreach($numbers as $key){
$this_number = $numbers[array_rand($numbers)];
$used_numbers[] = $this_number;
echo $this_number;
break;
}
$_SESSION['numbers'] = $used_numbers;
Then you can use the $_SESSION to access the numbers on another page (after reload perhaps), or use the same $used_numbers array to access them.
If you try:
$numbers = range(1, 15);
shuffle($numbers);
$used_numbers = array();
foreach($numbers as $key){
$this_number = $numbers[array_rand($numbers)];
$used_numbers[] = $this_number;
echo $this_number;
break;
}
echo '<br />';
foreach($used_numbers AS $number) {
echo $number;
}
You will see it returns the same number.
I need this output..
1 3 5
2 4 6
I want to use array function like array(1,2,3,4,5,6). If I edit this array like array(1,2,3), it means the output need to show like
1 2 3
The concept is maximum 3 column only. If we give array(1,2,3,4,5), it means the output should be
1 3 5
2 4
Suppose we will give array(1,2,3,4,5,6,7,8,9), then it means output is
1 4 7
2 5 8
3 6 9
that is, maximum 3 column only. Depends upon the the given input, the rows will be created with 3 columns.
Is this possible with PHP? I am doing small Research & Development in array functions. I think this is possible. Will you help me?
For more info:
* input: array(1,2,3,4,5,6,7,8,9,10,11,12,13,14)
* output:
1 6 11
2 7 12
3 8 13
4 9 14
5 10
You can do a loop that will automatically insert a new line on each three elements:
$values = array(1,1,1,1,1);
foreach($values as $i => $value) {
printf('%-4d', $value);
if($i % 3 === 2) echo "\n";
}
EDIT: Since you added more information, here's what you want:
$values = array(1,2,3,4,5);
for($line = 0; $line < 2; $line++) {
if($line !== 0) echo "\n";
for($i = $line; $i < count($values); $i+=2) {
printf('%-4d', $values[$i]);
}
}
And if you want to bundle all that in a function:
function print_values_table($array, $lines = 3, $format = "%-4d") {
$values = array_values($array);
$count = count($values);
for($line = 0; $line < $lines; $line++) {
if($line !== 0) echo "\n";
for($i = $line; $i < $count; $i += $lines) {
printf($format, $values[$i]);
}
}
}
EDIT 2: Here is a modified version which will limit the numbers of columns to 3.
function print_values_table($array, $maxCols = 3, $format = "%-4d") {
$values = array_values($array);
$count = count($values);
$lines = ceil($count / $maxCols);
for($line = 0; $line < $lines; $line++) {
if($line !== 0) echo "\n";
for($i = $line; $i < $count; $i += $lines) {
printf($format, $values[$i]);
}
}
}
So, the following:
$values = range(1,25);
print_array_table($values);
Will output this:
1 10 19
2 11 20
3 12 21
4 13 22
5 14 23
6 15 24
7 16 25
8 17
9 18
One solution is to cut the array into chunks, representing the columns, and then print the values in row order:
$cols = array_chunk($arr, ceil(count($arr)/3));
for ($i=0, $n=count($cols[0]); $i<$n; $i++) {
echo $cols[0][$i];
if (isset($cols[1][$i])) echo $cols[1][$i];
if (isset($cols[2][$i])) echo $cols[2][$i];
}
If you don’t want to split your array, you can also do it directly:
for ($c=0, $n=count($arr), $m=ceil($n/3); $c<$m; $c++) {
echo $arr[$c];
for ($r=$m; $r<$n; $r+=$m) {
echo $arr[$c+$r];
}
}
$a = array(1,2,3,4,5);
"{$a[0]} {$a[1]} {$a[2]}\n{$a[3]} {$a[4]}";
or
$a = array(1,2,3,4,5);
"{$a[0]} {$a[1]} {$a[2]}".PHP_EOL."{$a[3]} {$a[4]}";
or
$a = array(1,2,3,4,5);
$second_row_start = 3; // change to vary length of rows
foreach( $a as $index => $value) {
if($index == $second_row_start) echo PHP_EOL;
echo "$value ";
}
or, perhaps if you want a longer array split into columns of 3?
$a = array(1,2,3,4,5,6,7,8,9,10,11,12,13);
$row_length = 3; // change to vary length of rows
foreach( $a as $index => $value) {
if($index%$row_length == 0) echo PHP_EOL;
echo "$value ";
}
which gives
1 2 3
4 5 6
7 8 9
10 11 12
13
one solution is :
your array has N elements, and you want 3 columns, so you can get the value of each cell with $myarray[ column_index + (N/3) + line_index ] (with one or two loops for columns and lines, at least for lines)
I hope this will help you
Bye
Here's something I whipped up. I'm pretty sure this could be more easily accomplished if you were using HTML lists, I've assumed you can't use them.
$arr = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14, 15, 16);
$max = count($arr);
$cols = 3;
$block = ceil($max / $cols);
for ($i = 0; $i < $block ; $i++) {
echo $arr[$i] . ' ';
for ($j = 1; $j < $cols; $j++) {
$nexKey = $i + $block * $j;
if (!isset($arr[$nexKey])) break;
echo $arr[$nexKey] . ' ';
}
echo '<br>';
}
NOTE : You can easily refactor the code inside the loop that uses $nexkey variable by making it into a loop itself so that it works for any number of columns. I've hardcoded it.
Uses loops now.