I'm new to php so please take it easy.
I have created an array of integers. 1-100. What I want to do is shuffle the array and remove random numbers from it leaving only lets say 15 numbers.
This is what I have done so far, can't figure out how to remove the random numbers. I know I could possibly use unset function but I'm unsure how could I use it in my situation.
// Create an Array using range() function
$element = range(1, 100);
// Shuffling $element array randomly
shuffle($element);
// Set amount of number to get rid of from array
$numbersOut = 85;
// Remove unnecessary items from the array
var_dump($element);
Just try with:
$element = range(1, 100);
shuffle($element);
$output = array_slice($element, 0, 15);
var_dump($output);
Output:
array (size=15)
0 => int 78
1 => int 40
2 => int 10
3 => int 94
4 => int 82
5 => int 16
6 => int 15
7 => int 57
8 => int 79
9 => int 83
10 => int 32
11 => int 13
12 => int 96
13 => int 48
14 => int 62
Or if you want to use $numbersOut variable:
$numbersOut = 85;
$output = array_slice($element, $numbersOut);
It will slice an array from 85 to the end. Remember - if you will have 90 elements in the array, this method will return just 5 elements.
Related
I am trying to build a function which decodes a CS:GO match sharing code. I have seen enough examples but everyhting is in JS or C# but nothing in PHP.
I took the akiver demo manager as an example and i tried to replicate it in PHP. I am going bit blind because i have no idea what is the output on a certain points so i can only hope that the result will be what i expect it to be. I think i am on the right path, the problem comes when the bytes have to be created/interpeted/converted to the desire outcome.
The code that should be decoded is the following: 'CSGO-oPRbA-uTQuR-UFkiC-hYWMB-syBcO' ($getNextGame variable)
The result should be 3418217537907720662
My code so far:
/**
* #param $getNextGame
* #return array
*/
public function decodeDemoCode(string $getNextGame): array
{
$shareCodePattern = "/CSGO(-?[\w]{5}){5}$/";
if (preg_match($shareCodePattern, $getNextGame) === 1) {
$result = [];
$bigNumber = 0;
$matchIdBytes = $outcomeIdBytes = $tvPortIdBytes = [];
$dictionary = "ABCDEFGHJKLMNOPQRSTUVWXYZabcdefhijkmnopqrstuvwxyz23456789";
$dictionaryLength = strlen($dictionary);
$changedNextGame = str_replace(array("CSGO", "-"), "", $getNextGame);
$chars = array_reverse(str_split($changedNextGame));
foreach ($chars as $char) {
$bigNumber = ($bigNumber * $dictionaryLength) + strpos($dictionary, $char);
}
}
}
This brings me back something like that:
1.86423701402E+43 (double)
Then i have the following:
$packed = unpack("C*", $bigNumber);
$reversedPacked = array_reverse($packed);
and this brings the following back:
array(17 items)
0 => 51 (integer)
1 => 52 (integer)
2 => 43 (integer)
3 => 69 (integer)
4 => 50 (integer)
5 => 48 (integer)
6 => 52 (integer)
7 => 49 (integer)
8 => 48 (integer)
9 => 55 (integer)
10 => 51 (integer)
11 => 50 (integer)
12 => 52 (integer)
13 => 54 (integer)
14 => 56 (integer)
15 => 46 (integer)
16 => 49 (integer)
Now here i am not really sure what to do because i do not completely understand C# and i have never worked with bytes in PHP before.
Generally the return type should be an array and would look something like that:
$result = [
matchId => 3418217537907720662,
reservationId => 3418217537907720662,
tvPort => 55788
];
Thanks in advance. Any help is deeply appreciated
I have created a PHP class which makes that possible:
CS:GO ShareCode Decoder PHP
The first problem you have to solve is the returned double value. PHP has limitation when it comes to big integers. More to that here What is the maximum value for an integer in PHP.
Because of this limitation you are losing precision leading to inaccurate results. In order to solve this problem you will have to use one of these libraries GMB, BC Math. What these libraries do, is to give you back the result as a string which solves the double value you got.
So your code has to look something like that:
foreach ($chars as $char) {
$bigNumber = gmp_add(
gmp_mul($bigNumber,$dictionaryLength),
strpos($dictionary,$char)
);
}
json_encode($bigNumber);
$result = json_decode($bigNumber, true, 512, JSON_BIGINT_AS_STRING);
This will give you back the following "18642370140230194654275126136176397505221000"
You do not really need the PHP pack and unpack functions since the results can be generated without them. The next step is to convert your number to hexadecimal. You can do that with the following:
$toHex = gmp_strval(gmp_init($number, 10), 16);
Again you need to use the gmp library in order to get the desired value. What you do, is to make sure that the result is a string and then you convert your number's base from 10 to 16 which is the equivalent of hexadecimal. The results is the following:
"d6010080bdf26f2fbf0100007cf76f2f5188"
The next step is to convert the hex value to an array of byte integers. It looks like this:
$bytes = [];
$byteArray= str_split($toHex, 2);
foreach ($byteArray as $byte) {
$bytes[] = (int)base_convert($byte, 16, 10);
}
What you do here is to split the array to every two chars. The $byteArray variable looks like this (before it enters the foreach loop)
array(18 items)
0 => 'd6' (2 chars) 1 => '01' (2 chars) 2 => '00' (2 chars) 3 => '80' (2 chars)
4 => 'bd' (2 chars) 5 => 'f2' (2 chars) 6 => '6f' (2 chars) 7 => '2f' (2 chars)
8 => 'bf' (2 chars) 9 => '01' (2 chars) 10 => '00' (2 chars) 11 => '00' (2 chars)
12 => '7c' (2 chars) 13 => 'f7' (2 chars) 14 => '6f' (2 chars) 15 => '2f' (2 chars)
16 => '51' (2 chars) 17 => '88' (2 chars)
Now you will have to convert each entry into integer. Since the results are not that big anymore you can change the base of your values with the base_convert function. The base is 16 (hex) and you will have to change it back to 10. The results $bytes after the foreach loop looks like this:
array(18 items)
0 => 214 (integer) 1 => 1 (integer) 2 => 0 (integer) 3 => 128 (integer)
4 => 189 (integer) 5 => 242 (integer) 6 => 111 (integer) 7 => 47 (integer)
8 => 191 (integer) 9 => 1 (integer) 10 => 0 (integer) 11 => 0 (integer)
12 => 124 (integer) 13 => 247 (integer) 14 => 111 (integer) 15 => 47 (integer)
16 => 81 (integer) 17 => 136 (integer)
Now you have to define which bytes are responsible for each result.
$matchIdBytes = array_reverse(array_slice($bytes, 0, 8));
$reservationIdBytes = array_reverse(array_slice($bytes, 8, 8));
$portBytes = array_reverse(array_slice($bytes, 16, 2));
For the match id you will have to get the first 8 entries and the reverse the array
For the reservation id you will have to get the next 8 entries starting from the 8th entry and reverse the array
For the port you will have to get the last 2 entries and reverse the array
Now you will have to return the value
return [
'matchId' => $this->getResultFromBytes($matchIdBytes),
'reservationId' => $this->getResultFromBytes($reservationIdBytes),
'tvPort' => $this->getResultFromBytes($portBytes)
];
The getResultFromBytes() function:
**
* #param array $bytes
* #return string
*/
public function getResultFromBytes(array $bytes): string
{
$chars = array_map("chr", $bytes);
$bin = implode($chars);
$hex = bin2hex($bin);
return gmp_strval($this->gmp_hexDec($hex));
}
/**
* #param $n
* #return string
*/
public function gmp_hexDec($n): string
{
$gmp = gmp_init(0);
$multi = gmp_init(1);
for ($i=strlen($n)-1;$i>=0;$i--,$multi=gmp_mul($multi, 16)) {
$gmp = gmp_add($gmp, gmp_mul($multi, hexdec($n[$i])));
}
return $gmp;
}
Best regards
I have a site with a search feature but am trying to improve the search for a fuzzy search.
So far what I've done is query all of my products and use similar_text() to see how close they are to the actual search term
I then create an array where the key is how similar it is and the value is the product id. I then sort this by the key/similarity.
$term = $_GET['search_term'];
$similar_array = [];
$sql = "SELECT * FROM products";
$stmt = DB::run($sql);
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$id = $row["pro_id"];
$result = $row['product'];
similar_text($term,$result,$similarity);
$similar_array[$similarity][] = $id;
}
$closest_match = array_keys($similar_array);
rsort($closest_match);
$match_count = count($closest_match);
for($i=0; $i<$match_count; $i++){
var_dump($similar_array[$closest_match[$i]]);
}
This gives me something like:
array (size=9)
0 => int 28
1 => int 1628
2 => int 1665
3 => int 1666
4 => int 1667
5 => int 1668
6 => int 1669
7 => int 1670
8 => int 1671
C:\wamp64\www\V2\search.php:65:
array (size=2)
0 => int 37
1 => int 38
C:\wamp64\www\V2\search.php:65:
array (size=1)
0 => int 481
C:\wamp64\www\V2\search.php:65:
array (size=3)
0 => int 27
1 => int 1009
2 => int 1620
C:\wamp64\www\V2\search.php:65:
array (size=14)
0 => int 30
1 => int 104
2 => int 131
3 => int 134
4 => int 168
5 => int 169
6 => int 170
7 => int 557
8 => int 1011
9 => int 1014
10 => int 1661
11 => int 1662
12 => int 1663
13 => int 1664
I have a show_products() function that I just need to pass an array of ID's, so what I want to do now is take the multiple arrays of ID's from above and merge it in this specific order and then crop the array to a certain number so it won't have every product but will cut off after so many results.
As per your query you can use follow below steps
you merge all array by array_merge
sort the array using rsort (highest merge come first);
for display you can use array_slice or array_chunk
I'm beginner in PHP scripting. As per my knowledge, array means collection of same types of elements but PHP violating that rule.
Here is my code:
<!DOCTYPE html>
<html>
<body>
<?php
$a = 10;
echo $a;
$arr = array();
for($i = 0; $i < 10; $i++){
$arr[$i] = $i * $i; // Integer values
}
$arr[10]="Rohit"; // string value
$arr[11] = 10.15; // float value
$arr[12] = true; // boolean value
for($i = 0; $i < COUNT($arr); $i++){
echo "<br>".$arr[$i];
}
echo "<br>Length of array: ".COUNT($arr);
echo "var_dump output: ".var_dump($arr);
?>
</body>
</html>
and here is what I got result:
10
0
1
4
9
16
25
36
49
64
81
Rohit
10.15
1
Length of array: 13
C:\wamp\www\phpModules\check16_6_18_study.php:28:
array (size=13)
0 => int 0
1 => int 1
2 => int 4
3 => int 9
4 => int 16
5 => int 25
6 => int 36
7 => int 49
8 => int 64
9 => int 81
10 => string 'Rohit' (length=5)
11 => float 10.15
12 => boolean true
var_dump output:
You can notice first 10 elements are integers, 10th element is string, 11th element is float and 12th element is boolean.
Please anyone explain me why PHP has such confusing behavior?
PHP is a language with a dynamic type system. Like most dynamic languages such as Python, Javascript, Ruby don't check types for anything by default. It's really just emergent behavior from how everything else works.
I have an array like this one:
array (size=1)
0 =>
array (size=33)
0 => int 126
1 => int 43
2 => int 4
3 => int 0
4 => int 3
5 => int 3
6 => int 30
7 => int 15
8 => int 22
9 => int 27
10 => int 22
11 => int 46
12 => int 0
13 => int 8
14 => int 14
15 => int 8
array (size=1)
1 =>
array (size=33)
0 => int 273
1 => int 3
2 => int 4
3 => int 28
4 => int 36
5 => int 19
6 => int 142
7 => int 81
8 => int 59
9 => int 71
10 => int 88
11 => int 47
12 => int 42
13 => int 0
14 => int 12
15 => int 97
(of course it is way longer)
and I need both to sum all the value with the same key and count how many values with the same key are >0 (cause I have to find the avarage of all the numbers >0
My expected result is
0=>
'sum' => 399
'count'=>2
1=>
'sum' =>46
'count'=>2
how can I create this array?
There's an inbuilt function in PHP to count the sum of all the elements of an array. Here, this will give you your expected output :
<?php
$arr = [[10, 20, 30, 40], [10, 20, 30], [10, 20, 30, 4]];
// Let the magic happen...
$yourArray = array_map(function ($el){ return ["sum" => array_sum($el), "count" => count($el)]; }, $arr);
print_r($yourArray);
?>
I have thought about this, and came up with a solution (I think...), it comes in the form of a function and it goes like this:
function getSumAndCount(array $arr)
{
$sum = 0;
$count = 0;
foreach ($arr as $v)
{
$count++;
if (is_array($v))
{
$next = getSumAndCount($v);
$count += $next['count'];
$sum += $next['sum'];
}
else
{
!is_numeric($v) ?: $sum += $v;
}
}
return [ 'sum' => $sum, 'count' => $count ];
}
It has a recursive check to if the array is multidimensional, checks if the value is numeric and sets the count and sum in a return array.
I haven't tested this properly as yet, but please test and let me know if you get the desired output.
EDIT
I will extend this to count dupe keys soon
I want to convert the byte array from a webservice to image. The webservice response array looks like the following but I could not figure out how to render this array back to an image. Please help me
'MemberImage' =>
array (size=151745)
0 => int 255
1 => int 216
2 => int 255
3 => int 224
4 => int 0
5 => int 16
6 => int 74
7 => int 70
8 => int 73
9 => int 70
10 => int 0
11 => int 1
12 => int 1
13 => int 1
14 => int 0
15 => int 72
16 => int 0
17 => int 72
18 => int 0
19 => int 0
20 => int 255 ...
Use pack to convert data into binary string, es:
$data = implode('', array_map(function($e) {
return pack("C*", $e);
}, $MemberImage));
// header here
// ...
// body
echo $data;
If you want to convert that array to an actual byte array (i.e. a binary string in PHP) you could use the following function...
function arrayToBinaryString(Array $arr) {
$str = "";
foreach($arr as $elm) {
$str .= chr((int) $elm);
}
return $str;
}
You could also use pack instead of the above function to do the same thing like so...
call_user_func_array('pack', array_merge(['C*'], $arr));
or in PHP 5.6+
pack('C*', ...$arr);
With that you could then - in theory - use the binary string as an image. So, for example, assuming you want to output the raw image data, and that the image is say a PNG, you would do something like the following, in conjunction with the above code...
header('Content-type: image/png');
echo arrayToBinaryString($myArray);
Just be sure to edit the Content-type header with whatever type the actual image is. If you don't know you could use something like getimagesize on the binary string to extract the MIME type from the image data.
$tmpFile = tempnam("/tmp");
$image = arrayToBinaryString($myArray);
file_put_conetnts($tmpFile, $image);
$imageData = getimagesize($tmpFile);
header("Content-type: {$imageData['mime']}");
echo $image;
unlink($tmpFile);