I want to try this sequence in PHP: 10 9 8 7 6 5 4 3 2 1 3 4 5 6 7 8 9 10. The condition is I can use only one loop.
I tried this code and I know it will infinite after it prints 0. But I do not find any way to fix it.
<?php
for($i = 10; $i >= 0; $i--){
echo $i;
if($i == 0){
echo $i++;
}
}
Now I can't test it but I think it works:
<?php
$x = 10;
$cond = "DESC";
for($i = 20; $i >= 0; $i--){
echo $x;
If ( $x == 1 ) $cond = "ASC";
$cond == "DESC" ? $x-- : $x++;
}
?>
If you want to have a more simple solution you can use array:
<?php
$arr = Array (10,9,8,7,6,5,4,3,2,1,2,3,4,5,6,7,8,9,10);
foreach ($arr as $int){
echo $int;
}
?>
You could do this with a one-liner, if you're looking for "simple":
foreach (array_merge(range(10, 1, 1), range(3, 10, 1)) as $i) {
echo "$i ";
}
Result:
10 9 8 7 6 5 4 3 2 1 3 4 5 6 7 8 9 10
This makes the two arrays, [ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ] and [ 3, 4, 5, 6, 7, 8, 9, 10 ], concatenates them, and then runs through the resultant array.
Related
How to use multi for loop with array.
I'm trying to iterate over the contents of an array.
This is the code I have tried.
<?php
$arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
for($i = 0; $i < 5; $i++){
echo $arr[$i];
for($j = 0; $j < $i; $j++){
echo $arr[$j];
}
echo "<br />";
}
echo "<br/>";
for ($i = 0; $i <= count($arr); $i++){
if ($i%3 == 0){
echo $arr[$i-1] . " " . "<br />";
} else {
echo $arr[$i-1] . " ";
}
}
this is the result i got
1
2 1
3 1 2
4 1 2 3
5 1 2 3 4
1 2 3
4 5 6
7 8 9
10 11 12
13 14 15
I want to display a result like this and how it works:
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
1 | 6 | 11
2 | 7 | 12
3 | 8 | 13
4 | 9 | 14
5 | 10 | 15
Thank you
Two separate questions:
The first one, I'd do like this:
$arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
$prev =0;
for ($i=1; $i<=5; $i++) {
print implode(" ", array_slice($arr, $prev, $i)) . "<br>\n";
$prev += $i;
}
You could replace the array_slice() with a for loop if that makes you happier. The second one:
$cols = 3;
$rows = floor(count($arr)/$cols);
for ($i = 0; $i < $rows; $i++) {
for ($j=0; $j<=$cols; $j++) {
print $arr[$i+$j*$rows] ?? ' ';
if ($j < ($cols-1)) print " | ";
}
print "<br>\n";
}
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
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);
?>
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
Normally, I'd be asking how to turn a 4-rowed, 3-columned array like this:
1 2 3
4 5 6
7 8 9
10 11 12
Into a 3-rowed, 4-columned array like: (I DON'T WANT THIS)
1 4 7 10
2 5 8 11
3 6 9 12
But actually, I want to turn it into this: (I WANT THIS)
1 5 9
2 6 10
3 7 11
4 8 12
In other words, I want to flip the rows and columns, but keep the same "width" and "height" of the new array. I've been stuck on this for over an hour.
This is the function I'm using to do a normal "flip" (the first example):
function flip($arr)
{
$out = array();
foreach ($arr as $key => $subarr)
{
foreach ($subarr as $subkey => $subvalue)
{
$out[$subkey][$key] = $subvalue;
}
}
return $out;
}
Just walk the array in the correct order. Assuming you have relatively small arrays, the easiest solution is just to create a brand new array during that walk.
A solution will be of the form:
$rows = count($arr);
$ridx = 0;
$cidx = 0;
$out = array();
foreach($arr as $rowidx => $row){
foreach($row as $colidx => $val){
$out[$ridx][$cidx] = $val;
$ridx++;
if($ridx >= $rows){
$cidx++;
$ridx = 0;
}
}
}
function flip_row_col_array($array) {
$out = array();
foreach ($array as $rowkey => $row) {
foreach($row as $colkey => $col){
$out[$colkey][$rowkey]=$col;
}
}
return $out;
}
First, what you don't want (which is half of the solution to what you do want)...
The term for "flipping rows and columns" is "transposing".
PHP has had a sleek native technique for this very action since the splat operator was added to the language.
The caveats to bear in mind are:
All keys must be numeric. The splat/spread operator will choke on non-numeric keys.
The matrix must be complete. If there are any gaps, you may not get the result that you desire.
Code: (Demo)
$matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12],
];
var_export(
array_map(null, ...$matrix)
);
Output:
[
[1, 4, 7, 10],
[2, 5, 8, 11],
[3, 6, 9, 12],
];
Now, for what you do want!
Here is a functional-style snippet that incorporates php's transposing technique while ensuring that the output has the same number of columns as the input.
Code: (Demo)
var_export(
array_map(
null,
...array_chunk(
array_merge(...$matrix),
count($matrix)
)
)
);
Output:
[
[1, 5, 9],
[2, 6, 10],
[3, 7, 11],
[4, 8, 12],
];
This approach flattens the input, then breaks it into rows with lengths equivalent to the original number of rows, then that result is transposed.
Late Edit: As a purely academic pursuit, I wanted to see what a pure mathematical technique would look like which didn't use any conditions and didn't maintain multiple "counters".
As it turns out, because php arrays will truncate float keys to integers, this can be done in a single loop.
// assuming the earlier mentioned 3x4 matrix:
i old pos new pos i%rows i/rows i/col i%col
0 : [0][0] => [0][0] 0 0 0 0
1 : [1][0] => [0][1] 1 0.25 0.3 1
2 : [2][0] => [0][2] 2 0.5 0.6 2
3 : [3][0] => [1][0] 3 0.75 1 0
4 : [0][1] => [1][1] 0 1 1.3 1
5 : [1][1] => [1][2] 1 1.25 1.6 2
6 : [2][1] => [2][0] 2 1.5 2 0
7 : [3][1] => [2][1] 3 1.75 2.3 1
8 : [0][2] => [2][2] 0 2 2.6 2
9 : [1][2] => [3][0] 1 2.25 3 0
10 : [2][2] => [3][1] 2 2.5 3.3 1
11 : [3][2] => [3][2] 3 2.75 3.6 2
Code: (Demo)
$rows = count($matrix);
$cols = count(current($matrix));
$cells = $rows * $cols;
$result = $matrix; // used to preserve original key orders
for ($i = 0; $i < $cells; ++$i) {
$result[$i % $rows][$i / $rows] = $matrix[$i / $cols][$i % $cols];
}
var_export($result);
here you go. It works. :)
Demonstration
$input = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12],
];
// flipping matrices
$output = array();
$intern = array();
for($row=0; $row < 4; $row++)
for($col=0;$col < 3;$col++)
$intern[] = $input[$row][$col];
// nesting the array
$count = 0;
$subcount = 0;
foreach($intern as $value)
{
$output[$count][$subcount] = $value;
$count++;
if($subcount == 3)
{
break;
}
if($count == 4)
{
$count = 0;
$subcount++;
}
}
echo "\n final output ";print_r($output);