Autogenerate array values with a loop? - php

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

Related

Negative value of $step in range(), PHP

This is taken from the php.net manual for json_decode(), Example 4, 5th line from the bottom there:
foreach (range(4, 3, -1) as $depth)
I am not sure what is the purpose of that -1 there. I tried range(4, 3, 1) and range (4, 3, -1) and it gives the same results. The 1 in the first example is the default so it could be range(4, 3). I was only trying it with something like print_r(range(4, 3, -1); so the example on the php.net may be a different thing. I was looking on the Net and there is no info about it, or not right away.
It will actually ignore the sign of the $step argument, and determine whether to increment or decrement based purely on whether $start > $end or $end > $start. For example:
<?php print_r( range( 20, 11, 3 ) ); ?>
Array
(
[0] => 20
[1] => 17
[2] => 14
[3] => 11
)
<?php print_r( range( 11, 20, -3 ) ); ?>
Array
(
[0] => 11
[1] => 14
[2] => 17
[3] => 20
)
Step is automatically cast to a positive number (yes, the manual is incorrect here)
So all of these will work:
var_dump(
range(1, 5, 1), // positive integer
range(1, 5, -1), // negative integer
range(1, 5, 2),
range(1, 5, .5), // positive fractional number
range(1, 5, "-0.1") // negative fractional number passed as string
);
Also, if you use a float value as $step, all the values will be float too, even if they are whole numbers.

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 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

php importance of a number in a set of numbers

I have a set of numbers e.g.
$input = array(1, 4, 7, 4, 9, 4, 8, 6, 2, 8, 7, 7, 4, 5, 3);
I am trying to work out the importance of each number based on the following rule:
As the sequence gets longer the numbers get less significant, and each time a number is mentioned then it will improve the relevance (how much depends on its position in the
sequence).
I am expecting something like:
Array(
'4' => 90%
'1' => 75%
'7' => 60%
....
)
So 4 is the most inportant, followed by 1 and then 7 etc. Note that the output is completely fabricated but gives in indication that 4 should be the most important. I believe I want some kind of linear solution.
Is this more of what you were thinking? Answer based on stillstanding
$numbers = array(1, 4, 7, 4, 9, 4, 8, 6, 2, 8, 7, 7, 4, 5, 3);
$weight = array();
$count = count($numbers);
for ($i=0; $i<$count; $i++) {
if (!isset($weight[$numbers[$i]])) $weight[$numbers[$i]] = 1;
$weight[$numbers[$i]] += $count + pow($count - $i, 2);
}
$max = array_sum($weight);
foreach ($weight as &$w) {
$w = ($w / $max) * 100;
}
arsort($weight);
result:
Array
(
[4] => 34.5997286296
[7] => 17.3677069199
[1] => 16.3500678426
[8] => 10.0407055631
[9] => 9.29443690638
[6] => 5.42740841248
[2] => 4.40976933514
[5] => 1.35685210312
[3] => 1.15332428765
)
$numbers=array(1, 4, 7, 4, 9, 4, 8, 6, 2, 8, 7, 7, 4, 5, 3);
$weight=array();
$count=count($numbers);
for ($i=0; $i<$count; $i++) {
if (!isset($weight[$numbers[$i]]))
$weight[$numbers[$i]]=1;
$weight[$numbers[$i]]*=$count-$i;
}
var_dump($weight);
Result:
Array
(
[1] => 15
[4] => 5040
[7] => 260
[9] => 11
[8] => 54
[6] => 8
[2] => 7
[5] => 2
[3] => 1
)
This algorithm is fairly simplistic, but I think it accomplishes what you're looking for.
Given that you have the sequence you described above and it is stored in an array called $sequence
$a = array();
for($i=0;$i<count($sequence);$i++)
{
//calculate the relevance = 1/position in array
$relevance = 1/($i+1);
//add $relevance to the value of $a[$sequence[$i]]
if(array_key_exists((string)$sequence[$i],$a))
$a[(string)$sequence[$i]] += $relevance;
else
$a[(string)$sequence[$i]] = $relevance;
}
return $a;

Flip (transpose) the rows and columns of a 2D array without changing the number of columns

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);

Categories