PHP dynamic creation of alphabet - php

I would like to create some arrys. First of all I would like to tell you what it is about so that you understand why I am doing this:
Cryptography.
I want create an array with the alphabet.
such as
$a1 = array("a"=>"b", "b"=>"c",....,"z"=>a");
Alright, that is just a bit of typing so now I want to do it a bit more often. In this case it is x+1=y or in other words for the decoding x=y-1
So lets say I would like to do that with a position change from 1 to 26 - I would have 26 arrays than.
The encryption and decryption itself is not that problem in php and not what I am asking for as it is simple string replacement. But I was wondering if there is anything like this possible to create in an dynamic way by telling:
createAlphabets(1,12)
and it creates me a multidimensional array with 12 alphabet keys?
This is the second part of my question:
is there mathematically figure of more possibilities to swap characters by calculation?
I mean, x+5-3=y is the same like x+2=y so however I calculate it is covered by my 26 arrays? so even if I say: x-5+3=y =? x-2=y it is the same like x+24=y ? isnt it? Please dont bother telling me it might be +25 or +23 and that I am not going to have 24 arrays - its 8am and I didnt sleep - I am just asking about the principle - I dont want you to do my work - I am just looking for some comfirmation and an idea.

$chars = range('a', 'z');
$shift = 5;
$shifted = array_merge(array_slice($chars, $shift), array_slice($chars, 0, $shift));
$alphabet = array_combine($chars, $shifted);
Since there are 26 characters in your alphabet you can only shift them by 26 characters, meaning there are 26 possible combinations.

Related

Making a coinflip in php (Provably fair)

so I'm trying to create website with a coinflip system (Its just a small project I'm doing in my free time) but I don't really know where to begin. I need to make it in php (so its in the backend) and I need it to be provably fair (so I can prove that it is legit). What I've found out is that I need to use something like sh256 but I also heard that its pretty out dated and can be easily cracked. Also if it matters it's a site with a steam login system so I plan on being able to join 1v1's with others steam users not just a person sitting besides me or something (not just 1 button is what I mean hehe).
EDIT: I have googled it and tried asking people I know and etc if they knew anything but nothing was any good.
Thanks in advance
-EirĂ­kur
This is a simple way to get a random coin toss result:
$result = array("heads", "tails")[random_int(0,1)];
First, we make an array, which will be our choices. array("heads, "tails") means we will always get one of those 2 results. Next, in the same line, we can select a single element to actually assign to the $result variable from the array we made previously. We can use random_int(min, max) to generate that number.
Note: random_int() generates cryptographic random integers that are
suitable for use where unbiased results are critical, such as when
shuffling a deck of cards for a poker game.
http://php.net/manual/en/function.random-int.php
As a bonus, you could add more elements to this array, and then just increase the max value in random_int(), and it will work. You could make this more dynamic as-well by doing it like this:
$choices = ["heads", "tails", "Coin flew off the table"];
$result = $choices[random_int(0, count($choices)-1];
With the above code, you can have as many choices as you'd like!
Testing
I ran this code 50,000 times, and these were my results.
Array
(
[heads] => 24923
[tails] => 25077
)
And I ran this code 100,000 times, these were my results:
Array
(
[tails] => 49960
[heads] => 50040
)
You can play around with this here, to check out results:
https://eval.in/894945
The answer above might be the best for most of the scenarios.
In commercial usage, you might want to make sure that the results can be recalculated to prove fairness.
In the following code, you need to calculate a seed for the server. Besides, you also might want to create a public seed that users can see. Those can be anything but I do recommend using some kind of a hash. Each time you get a new result just increase the round, it will generate a new truly random result.
$server_seed = "96f3ea4d221ca1b2048cc3b3b844e479f2bd9c80a870628072ee98fd1aa83cd0";
$public_seed = "460679512935";
for($round = 0;$round < 10;$round++) {
$hash = hash('sha256', $server_seed . "-" . $public_seed . "-" . $round);
if (hexdec(substr($hash, 0, 8)) % 2) {
echo 'heads', PHP_EOL;
} else {
echo 'tails', PHP_EOL;
}
}
This code will loop through 10 times using for loop, each time generating a new result. In the code, we assign a SHA256 hash to the $hash variable. Then we can calculate the decimal value from the $hash using PHP inbuilt function hexdec. We take the remainder from the decimal value and give the result based on it whether it's 0 or not.
NOTE You can play around with the values. Changing the substring to substr($hash, 0, 14) will get you a different way of generation to the results. Keep in mind that this will not change the final results in any way.
Average results of 1 000 000 runs were the following:
Heads: 50.12%
Tails: 49.88%
You can experiment with the code above at here.

10 digit mt_rand() with unbiased first digit

I want to generate the profile ids in my software. The mt_rand function works well but I need the ids to be a fixed 10 digit long. Currently I am looping through mt_rand outputs until I get a 10 digit number. But the problem I am facing now is that most of the profile ids start from 1 and some from 2. None from any of the other single digit numbers. I understand this happens because of mt_rand's range and it can't produce 10 digit numbers that start with 3 or more.
This is what I am currently doing
for($i = 0; $i < 200; $i++){
$num = mt_rand();
if(strlen($num) == 10) echo $num."<br>";
}
If you run the above code you will see all numbers start from either 1 or 2. Any way to fix this?
Edit: I guess I can just flip the numbers but some numbers end with zero and this seems like a bit of a hack anyways. But then again, random number generation is a hack in itself I guess.
just start your IDs at 1000000001 , then ID 2 at 1000000002 , ID 543 at 1000000543 , and so on?
alternatively, keep calling mt_rand(1000000001,min((PHP_INT_SIZE>4 ? intval("9999999999",10): PHP_INT_MAX),mt_getrandmax())) until you get an ID which does not already exist in your database? (this will be more and more cpu intesive as your db grows larger and larger.. when its almost full, i wouldn't be surprised if it took billions of iterations and several minutes..)
To elaborate on Rizier's suggestion, the only way to ensure any string (even a string of numbers) fits a given mold for length and rules is to generate it one character at a time and then fit them together
$str = '';
for($loop = 0; $loop < 10; $loop++) {
$str .= mt_rand(0,9);
}
echo $str;
You can then add rules to this. Maybe you don't want a leading 0 so you can add a rule for that. Maybe you want letters too. This will always give you a random string with the rules you want.
You can see this in action here http://3v4l.org/kIRdV

Can regex be used to validate numbers OUTSIDE a range of specific numbers?

I have referred to several SO webpages for the answer to my question, but I keep reading that regex should not be used for validating numbers which are less than or greater than a certain range. I want to ensure that a user enters numbers within the following ranges: 11--20 and 65-100. Anything less than 11 will not be allowed, anything between 21 and 64 will not be allowed and anything from 101 above will not be allowed. I realize I can write something like
if ($num <=10 and $num >= 21 and $num <=64 and $num >=101) {
$num = "";
$numErr = "Number must be within specified ranges";
}
But what I really want is to use regex to preclude the range of numbers I do not want from being entered but I have not seen any satisfactory answers on SO. Can someone please help?
The regex would be less readable but like
/^(1[1-9]|20|6[5-9]|[7-9][0-9]|100)$/
Regex Demo

filling an array with array_pad

I am currently working on a site where I have an array that must contain 8 values.
I generate a random number and write it into my array, after that i would liek to check if this number was infact 8 character long. If this was not the case it should be filled with leading zero's.
Here is the code i am using
$number=rand(0,255);
// convert the number to binary and store it as an array
$states=str_split(decbin($number),1);
echo '<pre>'.print_r($states,true).'</pre>';
// in case the number is not 8 bit long make it an 8 bit number using array_pad
if(count($states)<8){
$states = array_pad($states,count($states)-8,"0");
}
The problem is now that it never fills up the array even if the array only consists of 3 or 4 entrys.
Thanks for the help.
Edit :Thanks to everyone for awnsering so quickly the solution provided by Suresh Kamrushi is working.
instead of
$states = array_pad($states,count($states)-8,"0");
Try like this:
$number=rand(0,255);
// convert the number to binary and store it as an array
$states=str_split(decbin($number),1);
echo '<pre>'.print_r($states,true).'</pre>';
// in case the number is not 8 bit long make it an 8 bit number using array_pad
if(count($states)<8){
$states = array_pad($states,8,"0");
}
print_r($states);
PHP fiddle: http://phpfiddle.org/main/code/a1d-m97
If I understand correctly you don't need count($states) - 8:
$states = array_pad($states, -8, "0");
Which will pad the array to a size of 8, with leading zeroes
For array_pad the second argument is the size you want the array to be, not the number of items you want to add to it.
So just do:
if(count($states)<8){
$states = array_pad($states,8,"0");
}
Or, as array_pad has no effect if your array is already big enough, you don't even need the if(count($states)<8) part.

What is the best algorithm to see if my number is in an array of ranges?

I have a 2 dimensional arrays in php containing the Ranges. for example:
From.........To
---------------
125..........3957
4000.........5500
5217628......52198281
52272128.....52273151
523030528....523229183
and so on
and it is a very long list. now I want to see if a number given by user is in range.
for example numbers 130, 4200, 52272933 are in my range but numbers 1, 5600 are not.
of course I can count all indexes and see if my number is bigger than first and smaller than second item. but is there a faster algorithm or a more efficient way of doing it using php function?
added later
It is sorted. it is actually numbers created with ip2long() showing all IPs of a country.
I just wrote a code for it:
$ips[1] = array (2,20,100);
$ips[2] = array (10,30,200);
$n=11;// input ip
$count = count($ips);
for ($i = 0; $i <= $count; $i++) {
if ($n>=$ips[1][$i]){
if ($n<=$ips[2][$i]){
echo "$i found";
break;
}
}else if($n<$ips[1][$i]){echo "not found";break;}
}
in this situation numbers 2,8,22,and 200 are in range. but not numbers 1,11,300
Put the ranges in a flat array, sorted from lower to higher, like this:
a[0] = 125
a[1] = 3957
a[2] = 4000
a[3] = 5500
a[4] = 5217628
a[5] = 52198281
a[6] = 52272128
a[7] = 52273151
a[8] = 523030528
a[9] = 523229183
Then do a binary search to determine at what index of this array the number in question should be inserted. If the insertion index is even then the number is not in any sub-range. If the insertion index is odd, then the number falls inside one of the ranges.
Examples:
n = 20 inserts at index 0 ==> not in a range
n = 126 inserts at index 1 ==> within a range
n = 523030529 inserts at index 9 ==> within a range
You can speed things up by implementing a binary search algorithm. Thus, you don't have to look at every range.
Then you can use in_array to check if the number is in the array.
I'm not sure if I got you right, do your arrays really look like this:
array(125, 126, 127, ..., 3957);
If so, what's the point? Why not just have?
array(125, 3957);
That contains all the information necessary.
The example you give suggests that the numbers may be large and the space sparse by comparison.
At that point, you don't have very many options. If the array is sorted, binary search is about all there is. If the array is not sorted, you're down to plain, old CS101 linear search.
The correct data structure to use for this problem is an interval tree. This is, in general, much faster than binary search.
I am assuming that the ranges do not overlap.
If that is the case, you can maintain a map data structure that is keyed on the lower value of the range.
Now all you have to do (given the number N) is to find the key in the map that is just lower than N (using binary search - logarithmic complexity) and then check if the number is lesser than the right value.
Basically, it is a binary search (logarithmic) on the constructed map.
From a pragmatic point of view, a linear search may very well turn out to be the fastest lookup method. Think of page faults and hard disk seek time here.
If your array is large enough (whatever "enough" actually means), it may be wise to stuff your IPs in a SQL database and let the database figure out how to efficiently compute SELECT ID FROM ip_numbers WHERE x BETWEEN start AND end;.

Categories