PHP Specific sort of numbers - php

I have the following type of array :
$foo = array(
"a" => 1,
"b" => 1,
"c" => 2,
"d" => 2,
"e" => 3,
"f" => 3,
"g" => 4,
"h" => 4,
"i" => 5,
"j" => 5,
"k" => 10,
"l" => 12,
"m" => 15,
"n" => 20
);
I need to sort the array in this way :
$foo = array(1,2,3,4,5,12,20,15,10,5,4,3,2,1);
As you can see, the best value needs to be in the middle of the array. And the min-values in the start/end of array. The key needs to be linked to the original value.
Thank's for the help! sorry for my English.

If the input is already sorted, you can use two loops to first push every item with an odd offset in ascending order and then every item with an even offset in descending order into your array:
$keys = array_keys($foo);
$n = count($keys);
$result = array();
for ($i=0; $i<$n; $i+=2) {
$result[$keys[$i]] = $foo[$keys[$i]];
}
for ($i=$n-$n%2-1; $i>0; $i-=2) {
$result[$keys[$i]] = $foo[$keys[$i]];
}

First arrange all the integers in ascending order.
Lets say $foo_as is the new array you got in ascending order.
$a=a new empty array of size $n
$n=number of integers.
$c=0;
for ($i=$n-1;$i>0;$i--){
if (i%2==0){
$a(i/2)+c=$foo_as($n-$c)
}
else{
$a(i+1/2)-c=$foo_as($n-$c)
}
$c++
}
Explanation: I'm putting the largest integer in the middle. After that I'm filling the alternate indexes around the middle one with the integers in descending order.
- - - - - 11 - - - - -
- - - - 10 11 - - - - -
- - - - 10 11 9 - - - -
- - - 8 10 11 9 - - - -
- - - 8 10 11 9 7 - - -
- - 6 8 10 11 9 7 - - -
- - 6 8 10 11 9 7 5 - -
- 4 6 8 10 11 9 7 5 - -
- 4 6 8 10 11 9 7 5 3 -
2 4 6 8 10 11 9 7 5 3 -
2 4 6 8 10 11 9 7 5 3 1
I have used a basic algorithm to demonstrate this. If at some point, my php syntax is incorrect, please omit that.

A overkill version:
<?php
$foo = array(
"a" => 1,
"b" => 1,
"c" => 2,
"d" => 2,
"e" => 3,
"f" => 3,
"g" => 4,
"h" => 4,
"i" => 5,
"j" => 5,
"k" => 10,
"l" => 12,
"m" => 15,
"n" => 20
);
$arrayKeys = array_keys($foo);
$arrayValues = array_values($foo);
$array_count = count($foo);
for ($idx =0; $idx < round($array_count/2); $idx+=2) {
$tmpA = $arrayKeys[$idx];
$arrayKeys[$idx] = $arrayKeys[$array_count - $idx -1];
$arrayKeys[$array_count - $idx -1] = $tmpA;
$tmpB = $arrayValues[$idx];
$arrayValues[$idx] = $arrayValues[$array_count - $idx -1];
$arrayValues[$array_count - $idx -1] = $tmpB;
}
$tmpArray = array_combine($arrayKeys, $arrayValues);
$ascent = array_slice($tmpArray, 0, round($array_count/2));
$descent = array_slice($tmpArray, round($array_count/2));
asort($ascent);
arsort($descent);
$foobar = array_merge($ascent, $descent);
var_dump($foo, $foobar);
?>

Related

How can I shift all keys one position forward from a starting and end point in an array? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
So I have an array like this:
[
543 => 1,
22 => 3,
65 => 4,
10 => 5,
50 => 6,
]
Now I get a key and a value as input. For example 22 as key and 5 as value.
Now I want to use those two inputs as start and end point in my array and want to shift all keys one forward between those two positions.
[
543 => 1,
22 => 3, ─┐ ┌─ 65 => 3,
65 => 4, ├ Shift all those keys one forward to: ┤ 10 => 4,
10 => 5, ─┘ └─ 22 => 5,
50 => 6,
]
So the expected output would be:
[
543 => 1,
65 => 3,
10 => 4,
22=> 5,
50 => 6,
]
Figure out the start and end offset from your inputs in your array:
$startIndex = array_search(22, array_keys($arr));
$endIndex = array_search(5 , array_values($arr));
//↑ Your input
So for your example array this would look like this:
[
543 => 1, //Offset: 0
22 => 3, //Offset: 1 ← 22 found; offset: 1
65 => 4, //Offset: 2
10 => 5, //Offset: 3 ← 5 found; offset: 3
50 => 6, //Offset: 4
]
Split your array into three parts:
$before = array_slice($arr, 0, $startIndex, true);
$data = array_slice($arr, $startIndex, ($endIndex - $startIndex) + 1, true);
$after = array_slice($arr, $endIndex, null, true);
Visualized this would look like this:
[
543 => 1, → $before; Where you do NOT want to shift your keys
22 => 3, ┐
65 => 4, ├ $data; Where you want to shift your leys
10 => 5, ┘
50 => 6, → $after; Where you do NOT want to shift your keys
]
Rotate the data part keys, just by merging the last key at the start with the other keys at the end:
$keys = array_keys($data);
$keys = array_merge(array_slice($keys, -1), array_slice($keys, 0, -1));
$data = array_combine($keys, $data);
Put it all back together:
$arr = $before + $data + $after;

How to right align numbers from an array in php?

I have a problem with aligning numbers from a multidimensional array. I want to print the following result:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
And I want all of the numbers to be aligned with the second digit of the next rows. However my result is that:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
I did this in C# by using:
for (int col = 0; col < matrix.GetLength(1); col++)
{
Console.Write("{0,4}", matrix[row, col]);
}
But how can I receive this result in PHP?
You can use str_pad
$arr = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
$test = '';
foreach ($arr as $key => $value) {
if ($key % 4 == 0) {
$test .= "\n";
}
$test .= str_pad($value, 4, ' ', STR_PAD_LEFT);
}
echo "<pre>$test</pre>";
The result would be:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16

How to make a graphic using numbers with PHP [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I need to break a number in a table field and turn it into an array.
input_table
+------+---------+
| id | number |
+------+---------+
| 1 | 7 |
| 2 | 8 |
+------+---------+
for the id 1 (which has 7 number) the output what I need in php is:
1 2 3 4 5 6 7
2 3 4 5 6
3 4 5
4
How to do this?
for ($q=1; $q <= $obj->number ; $q++) {
echo "$q";
//This only turn 1, 2, 3, 4, 5, 6, 7
}
try something like this.
$set = array( 7, 8 );
echo '<pre>';
foreach( $set as $number ){
//assuming number is your INT
$array = range( 1, $number );
while( count( $array ) ){
echo "\n";
var_export( $array );
//remove first element
array_shift( $array );
//remove last element
array_pop($array);
}
}
Outputs:
For 7
array (
0 => 1,
1 => 2,
2 => 3,
3 => 4,
4 => 5,
5 => 6,
6 => 7,
)
array (
0 => 2,
1 => 3,
2 => 4,
3 => 5,
4 => 6,
)
array (
0 => 3,
1 => 4,
2 => 5,
)
array (
0 => 4,
)
For 8
array (
0 => 1,
1 => 2,
2 => 3,
3 => 4,
4 => 5,
5 => 6,
6 => 7,
7 => 8,
)
array (
0 => 2,
1 => 3,
2 => 4,
3 => 5,
4 => 6,
5 => 7,
)
array (
0 => 3,
1 => 4,
2 => 5,
3 => 6,
)
array (
0 => 4,
1 => 5,
)
I'll leave it to you to build a multi-dimensional array out of that.
If you just want the output, than use echo implode(' ', $array ); in place of var_export(). Such as this:
$set = array( 7, 8 );
echo '<div style="text-align:center">';
foreach( $set as $number ){
//assuming number is your INT
$array = range( 1, $number );
while( count( $array ) ){
echo implode(' ', $array );
//remove first element
array_shift($array);
//remove last element
array_pop($array);
echo '<br>';
}
echo '<br>';
}
echo '</div>';
Outputs:
1 2 3 4 5 6 7
2 3 4 5 6
3 4 5
4
1 2 3 4 5 6 7 8
2 3 4 5 6 7
3 4 5 6
4 5
<?php
$n = 7; //or whatever you want
echo '<div style="text-align:center">';
for($i=0;$i<=round($n/2,0);$i++){
for($j=$i; $j<$n-$i;$j++){
echo ($j+1).' ';
}
echo "<br />\n";
}
echo '</div>';

How does this code generate the proper sequence of characters?

The code in question comes from MathGuard, a PHP anti-spam CAPTCHA script that requires the user to answer a simple math problem. It displays the digits and operator symbols as 3x5 matrices of random characters. I understand how the code works in the sense that I can follow the code and understand what it's doing; I just don't understand how one would come to this solution.
This function takes an integer that describes one line of the 3x5 matrix and converts it into a line of random characters:
function decToBin($dec) {
$pattern = "123456789ABCDEFGHIJKLMNOPQRTSTUWXYZ";
$output = " ";
$i = 0;
do {
if ($dec % 2) {
$rand = rand() % 34;
$output { 2 - $i } = $pattern { $rand };
} else {
$output { 2 - $i } = " ";
}
$dec = (int) ($dec / 2);
$i++;
} while ($dec > 0);
$output = str_replace(" ", " ", $output);
return $output;
}
Here are the digit descriptors:
$number = array (
array ( 7, 5, 5, 5, 7 ), // 0
array ( 2, 6, 2, 2, 7 ), // 1
array ( 7, 1, 7, 4, 7 ), // 2
array ( 7, 1, 7, 1, 7 ), // 3
array ( 4, 5, 7, 1, 1 ), // 4
array ( 7, 4, 7, 1, 7 ), // 5
array ( 7, 4, 7, 5, 7 ), // 6
array ( 7, 1, 1, 1, 1 ), // 7
array ( 7, 5, 7, 5, 7 ), // 8
array ( 7, 5, 7, 1, 7 ) // 9
);
My question is: how does one come to this conclusion and method of generation and know that, for example, 7 will generate a full line of random characters, and 5 only the outermost characters?
Is this just a form of code obfuscation? What makes this method better than, say, storing the digits as a string (111101101101111 as 0, for example) and replacing each 1 with a random character?
Looks like a simple bitmap to me.
7 = 1 1 1
5 = 1 0 1
5 = 1 0 1
5 = 1 0 1
7 = 1 1 1
2 = 0 1 0
6 = 1 1 0
2 = 0 1 0
2 = 0 1 0
7 = 1 1 1

Autogenerate array values with a loop?

I know this doesn't work but is there any way of autogenerating values? It can be pretty tedious to put so many values in specially if it's 50 or maybe 100 numbers...
Here's the code so you get my idea:
for ($num = 1; $num <= 20; $num++){
$arr = array($num);
echo $arr[2];
};
Solved: It was the range() and arrayfill(). :)
Take a look at the range() function.
>> $a = range(1, 10);
array (
0 => 1,
1 => 2,
2 => 3,
3 => 4,
4 => 5,
5 => 6,
6 => 7,
7 => 8,
8 => 9,
9 => 10,
)
>>
Or maybe array_fill()?
Are you talking about the rand() function? That surely exist ;)
PHP Rand Function

Categories