PHP, how to get every possible byte sequence in range? - php

i want every possible byte sequence between range(x,y), like range(0,0xFFFF) would give me 00...FF.0000.0001...FFFF ~
this works, but i suspect there's a much easier way to do it which escapes me, any suggestions?
<?php
function incbinstring(string $str): string
{
/*
if(strlen($str)===0){
return "\x00";
}
*/
$scanCurrent = strlen($str) - 1;
while ($scanCurrent >= 0) {
if ($str[$scanCurrent] !== "\xFF") {
break;
}
--$scanCurrent;
}
if ($scanCurrent < 0) {
// they're all \xFF... add new byte and all zeroes
return str_repeat("\x00", strlen($str) + 1);
}
if ($scanCurrent !== strlen($str) - 1) {
// preceeded by a bunch of \xFF\xFF\xFF , zero them out
// ps, this can be optimized to a substr()+str_repeat()
for ($i = strlen($str) - 1; $i > $scanCurrent; --$i) {
$str[$i] = "\x00";
}
}
// increment the first non-\xFF with 1
$str[$scanCurrent] = chr(ord($str[$scanCurrent]) + 1);
return $str;
}
$str = "\x00";
for ($i = 0; $i < 0xFFFF + 600; ++$i) {
echo bin2hex($str),"\n";
$str = incbinstring($str);
}
outputs, in part
00
01
02
03
04
05
06
07
(...)
f3
f4
f5
f6
f7
f8
f9
fa
fb
fc
fd
fe
ff
0000
0001
0002
0003
0004
(...)
fffb
fffc
fffd
fffe
ffff
000000
000001
000002
000003
000004
000005
000006
000007

<?php
function counterHex ($fromHex, $toHex ) {
$fromDec = hexdec($fromHex);
$toHex = hexdec($toHex);
for ($i = $fromHex; $i< $toHex; $i++){
echo dechex($i) .", ";
}
}
counterHex(1,'ff');
see: http://sandbox.onlinephpfunctions.com/code/d70d2766297c32039e01dd868e791b476bc92a87

Related

Number to Excel column name conversion

In Excel, column names are characters from A to Z, if there are more columns needed, it continues with AA, AB ...
I want to write a function, that converts integers to those excel column names.
0 .... A
25 ... Z
26 ... AA
702 ... AAA
.
.
.
The solution I came up with is working up to AZ, but I want it to work further.
function indexToXlxsColumn($index, $prefix="")
{
if($index < 26)
{
return $prefix.chr($index+65);
}else{
return indexToXlxsColumn($index % 26, "A");
}
}
How to adapt this function to work for every index without producing spaghetti code?
Here is the probleme
return indexToXlxsColumn($index % 26, "A");
You away set the next floor prefix to A , what happends when u have
input = 53 , the resultat should be "BB"
Code on paper
function indexToXlxsColumn($index, $prefix="")
{
if($index < 26) // 53 isnt less then 26
// second loop , 1 is less then 26
{
return $prefix.chr($index+65);
// $prefix = A
// chr($index+65) = B
// return "A"."B" ;
}else{
return indexToXlxsColumn($index % 26, "A");
// indexToXlxsColumn(53 % 26, "A") -> (1, "A")
}
}
---UPDATE---
Follow the ask here is the answer
function indexToXlxsColumn($index, $suffix ="")
{
if($index < 26){
return chr($index+65).$suffix ;
}
return indexToXlxsColumn(($index - $index%26)/26-1, chr($index%26+65).$suffix );
}
One of the implementations:
function indexToXlxsColumn($index)
{
$name = '';
while($index > 0) {
$mod = ($index - 1) % 26;
$name = chr(65 + $mod).$name;
$index = (int)(($index - $mod) / 26);
}
return $name;
}
// echo indexToXlxsColumn(26); // Z
echo indexToXlxsColumn(33); // AG
// echo indexToXlxsColumn(800); // ADT
I would do it a little differently. It bothered me to work with chr(). So I once stored the alphabet in a string and iterated over it until the index was successfully resolved.
max "zz"
<?php
function getIn($i) {
$str = 'abcdefghijklmnopqrstuvwxyz';
$r = (int) floor($i / 26) ;
$c = $i % 26;
return ($r) < 1 ? $str[$c] : $str[$r-1] . $str[$c];
}
echo getIn(52); // output: "ba"
Update with max "zzz"
function getIn($i) {
$str = 'abcdefghijklmnopqrstuvwxyz';
$r = (int) floor($i / 26);
$rr = $r >= 27 ? $r - 27 : null;
$c = $i % 26;
if ( $rr !== null) {
return $str[$c] : $str[$r-1] . $str[$c];
}
return ($r) < 1 ? $str[$c] : $str[$r-1] . $str[$c];
}
echo getIn(800); // ddu
echo getIn(1377); // zzz
PLACEHOLDER parts of the code return squiffy values! Needs review before using in the wild!!
In case anyone wants a utility function that does this, here's a python implementation:
n2AA performs the calculation from numeric to "AA" format.
def n2AA(n):
n=n-1
alphabet=["_"] + [chr(c+65) for c in range(0,26)]
w=len(alphabet)-1
accum=[]
for e in range(5,-1,-1):
expon=w**e
s=(n//expon)
r=n%expon
n=n-(s*expon)
if e>0:
accum.append(alphabet[s])
else:
accum.append(alphabet[s+1])
return "".join([a for a in accum if a != "_"])
And AA2n performs the inverse function, starting with "AA" format and returning the column number (starting at 1).
def AA2n(AA):
alphabet=["_"] + [chr(c+65) for c in range(0,26)]
w=len(alphabet)-1
accum=[]
for c in range(0,len(AA)):
expon=w**(len(AA)-1-c)
accum.append((alphabet.index(AA[c]))*expon)
return sum(accum)

face issues in loop and break in php

I've faced problem that I cant resolve in my simple code
foreach(file('num.txt') as $num) {
foreach(file('char.txt') as $char) {
echo $char.$num. "<br>";
if($char=="C"&&$num==3){
echo 'Found it<br>';
break;
}
}
echo '----------------------------<br>';
}
num.txt contains numbers like this
1
2
3
4
5 per line
char contains character Like A B C D per line
.
and as result
it dose not remove the C3 in text step after break
but i want it like this way without the founded C3
A1
B1
C1
D1
--------------
A2
B2
C2
D2
--------------
A3
B3
C3
Found it
D3
--------------
A4
B4
D4
--------------
A5
B5
D5
--------------
so C is no longer in the loop and continue if add B5 and so on
Please help i need this assignment
If you had regular array, you could remove "C" from it, but since you are getting data implicitly from file, this is the solution. Not the most elegant, but works:
// add flag for found value
$found = false;
foreach(file('num.txt') as $num) {
foreach(file('char.txt') as $char) {
// condition to show an entry
if(!$found || $char != "C") {
echo $char.$num. "<br>";
if($char == "C" && $num == 3) {
echo 'Found it<br>';
// you do not need 'break', remove it and set flag instead
$found = true;
}
}
}
echo '----------------------------<br>';
}
I think your code will be like this:
foreach(file('num.txt') as $num) {
foreach(file('char.txt') as $char) {
if($char=="C"&&$num==3){
echo 'Found it<br>';
break;
}
else{
echo $char.$num. "<br>";
}
}
echo '----------------------------<br>';
}
Hope this help.
<?php
$arr1 = ['A','B','C','D'];
$arr2 = [1,2,3,4,5];
for($i = 0; $i < count($arr1); $i++) {
for($j = 0; $j < count($arr2); $j++){
if($arr1[$i] == "C" && $arr2[$j] == 3){
echo "Found It<br/>";
break;
}
echo $arr1[$i]."".$arr2[$j]."<br/>";
}
echo "----------------------<br/>";
}
?>

Working with text-files in PHP

As mentioned before, I am a beginner when it comes to PHP coding. I have made a text file which has my students information, as per below - this includes their name, marks for subjects, e-mail address and date of registration:
Ann Thompson : 50,90,82,64,75 : ann#amuniversity.com: 2016-02-01
Jeremiah Hanson: 80, 75, 88 : jeremiah#amuniversity.com: 2016-03-02
Billy Jones: 89, 72, 46, 54 : billy#amuniversity.com: 2016-04-12
and I have also made a form which inputs a field which takes in the filename which the user wishes to read from and a field for the filename which the user wishes to write to.
Where do I start to get the output below?
Summary for students:
Ann Thompson enrolled in 2016-02-01, has an average of 48, with a symbol F.
Jeremiah Hanson enrolled in ....
Billy Jones enrolled in ....
It should also show the date at the bottom when it was last modified.
Please kindly help
Please check the following code. I commented on the code wherever I thought needed. Let me know if you don't understand something from it. And obviously, you need to update the checkGrade function as per your grade system, but you get the idea :)
<?php
// Read the input file line by line into "input" array
$filename = "input.txt";
$input = explode("\n", file_get_contents($filename));
// Go through each line
for($i = 0; $i < sizeOf($input); $i++){
// split line by :
$line = explode(":", $input[$i]);
// Initialize variables based on position
$name = $line[0];
$numbers = $line[1];
$email = $line[2];
$registration = $line[3];
// Calculate average
// Remove any spaces first from the numbers
$numbers = str_replace(' ', '', $numbers);
// Split the numbers by ,
$numbersArray = explode(",", $numbers);
$sum = 0;
// Calculate sum
for($j = 0; $j < sizeOf($numbersArray); $j++){
$num = (int)$numbersArray[$j];
$sum += $num;
}
$avg = $sum/sizeof($numbersArray);
// Print it
echo "$name enrolled in $registration, has an average of $avg, with a symbol ". checkGrade($avg) ."<br>";
}
// Last modified date of the input file
echo "<br><br><br>";
if (file_exists($filename)) {
echo "This file was last modified: " . date ("F d Y H:i:s.", filemtime($filename));
}
function checkGrade($num){
if ($num < 65){
$grad = 'F';
}
else if ($num<= 66 && $num >=65){
$grad = 'D';
}
else if ($num <= 69 && $num >=67){
$grad = 'D+';
}
else if ($num <= 73 && $num >=70){
$grad = 'C-';
}
else if ($num <= 76 && $num >=74){
$grad = 'C';
}
else if ($num<= 79 && $num >=77 ){
$grad = 'C+';
}
else if ($num <= 83 && $num >=80){
$grad = 'B-';
}
else if ($num <= 86 && $num >=84){
$grad = 'B';
}
else if ($num <= 89 && $num >=87){
$grad = 'B+';
}
else if ($num <= 93 && $num >=90){
$grad = 'A-';
}
else if ($num <= 96 && $num >=94){
$grad = 'A';
}
else if ($num >= 97){
$grad = 'A+';
}
return $grad;
}
?>
Here is the output:
Ann Thompson enrolled in 2016-02-01, has an average of 72.2, with a symbol C-
Jeremiah Hanson enrolled in 2016-03-02, has an average of 81, with a symbol B-
Billy Jones enrolled in 2016-04-12, has an average of 65.25, with a symbol D
This file was last modified: May 03 2017 13:12:13.

Shorten currency values like $20000 to $20k

I'd like to convert currency values like this:
4 000 000 000 => 4b
2 000 000 => 2m
2 250 000 => 2.25m
195 000 => 195k
10 000 => 10k
Anyone know of an existing library/function that does this, or do I need to write this myself by means of conditionals that cater for 0-9999, 10000-999999, and so on..?
You can create a custom function for this. The below one, firstly removes everything but numbers from string. Then it formats the number according how big is it and to the digit provided.
function shorten($num, $digits = 1) {
$num = preg_replace('/[^0-9]/','',$num);
if ($num >= 1000000000) {
$num = number_format(($num / 1000000000), $digits, '.', '') + 0;
$num = $num . "b";
}
if ($num >= 1000000) {
$num = number_format(($num / 1000000), $digits, '.', '') + 0;
$num = $num . 'm';
}
if ($num >= 1000) {
$num = number_format(($num / 1000), $digits, '.', '') + 0;
$num = $num . 'k';
}
return $num;
}
echo shorten("4 000 000 000");
echo shorten("3 200 000 000");
echo shorten("195 000");
Demo: http://codepad.org/K971MzVx
You can create a function like this to display shorten the values but it would miss the exact value
function shortifyCurrency($var){
$var=doubleval($var);
if($var>=1000000000){
$var=($var/1000000000)."b";
}else if($var>=1000000){
$var=($var/1000000)."m";
}else if($var>=1000){
$var=($var/1000)."k";
}
return $var;
}
//Output 4b
echo shortifyCurrency(4000000000);
Or you could use the following function to display more detailed information about the value
function shortifyCurrencyXtream($var){
$var=doubleval($var);
$print_str="";
if($var>=1000000000){
$print_str.=round($var/1000000000)."b";
$var=$var%1000000000;
}
if($var>=1000000){
if($print_str!="") $print_str.=" ";
$print_str.=round($var/1000000)."m";
$var=$var%1000000;
}
if($var>=1000){
if($print_str!="") $print_str.=" ";
$print_str.=($var/1000)."k";
}
return $print_str;
}
//Output 4b 101m 500.3k
echo shortifyCurrencyXtream(4100500300);

CRC Maxim/Dallas 1Wire Generation: translate Visual Basic to PHP

i Need a function that generates the Maxim/Dallas 1-Wire CRC 8bit-Code like this page:
http://www.datastat.com/sysadminjournal/maximcrc.cgi
For that problem I found an little Excel Calculator for solution.
It works correctly, but I got the Problem to translate it into PHP language.
Original VB Code:
Private Sub ROMCRC_Click()
Dim InHex, OutBinStr As String
Dim OutBinArr(1 To 56) As Integer
Dim OutDec, i, CRC(1 To 8), CRCTemp As Integer
InHex = Range("ROMByte1").Value & Range("ROMByte2").Value & Range("ROMByte3").Value & Range("ROMByte4").Value & Range("ROMByte5").Value & Range("ROMByte6").Value & Range("ROMByte7").Value
OutBinStr = HexToBin(InHex)
' Convert string to array, LSB = OutBinArr(1)
For i = 1 To 56
OutBinArr(57 - i) = Mid$(OutBinStr, i, 1) ' Split(OutBinStr)
Next i
'Initialize CRC
For i = 1 To 8
CRC(i) = 0
Next i
'Calculate CRC
For i = 1 To 56
CRCTemp = CRC(1) Xor OutBinArr(i)
CRC(1) = CRC(2)
CRC(2) = CRC(3)
CRC(3) = CRC(4) Xor CRCTemp
CRC(4) = CRC(5) Xor CRCTemp
CRC(5) = CRC(6)
CRC(6) = CRC(7)
CRC(7) = CRC(8)
CRC(8) = CRCTemp
Next i
DecCRC = BinToDec(CRC)
Range("ROMCRCValue").Value = DecCRC
End Sub
Private Function HexToBin(hstr)
'convert hex string to binary string
cnvarr = Array("0000", "0001", "0010", "0011", _
"0100", "0101", "0110", "0111", "1000", _
"1001", "1010", "1011", "1100", "1101", _
"1110", "1111")
bstr = ""
For i = 1 To Len(hstr)
hdgt = Mid(hstr, i, 1)
cix = CInt("&H" & hdgt)
bstr = bstr & cnvarr(cix)
Next
HexToBin = bstr
End Function
Function BinToDec(bstr)
'convert 8 bit Binary number to Decimal
Dim j, Out As Integer
Out = 0
For j = 1 To 8
Out = Out + bstr(j) * 2 ^ (j - 1)
Next j
BinToDec = Out
End Function
My PHP test code:
protected function HexToBin($hstr) {
//convert hex string to binary string
$cnvarr = array(
'0000',
'0001',
'0010',
'0011',
'0100',
'0101',
'0110',
'0111',
'1000',
'1001',
'1010',
'1011',
'1100',
'1101',
'1110',
'1111'
);
$bstr = "";
for ($i = 1; $i <= strlen($hstr); $i++) {
$hdgt = substr($hstr, $i, 1);
$cix = intval($hdgt);
echo $cix.'|';
$bstr .= $cnvarr[$cix];
}
return $bstr;
}
protected function createHash($data) {
//$OutBinStr = $this->HexToBin($data);
$OutBinStr = hex2bin($data);
$OutBinArr = array();
$crc = array();
//Convert string to array, LSB = OutBinArr(1)
for ($i = 1; $i <= 56; $i++) {
$OutBinArr[57 - $i] = substr($OutBinStr, $i - 1, 1);
}
//initialize crc
for ($i = 1; $i <= 8; $i++) {
$crc[$i] = 0;
}
// calculate
for ($i = 1; $i <= 56; $i++) {
$CRCTemp = $crc[1] ^ $OutBinArr[$i];
$crc[1] = $crc[2];
$crc[2] = $crc[3];
$crc[3] = $crc[4] ^ $CRCTemp;
$crc[4] = $crc[5] ^ $CRCTemp;
$crc[5] = $crc[6];
$crc[6] = $crc[7];
$crc[7] = $crc[8];
$crc[8] = $CRCTemp;
}
return implode('', $crc);
}
Example call:
$buttonId = '0000145D6E0F01';
echo $this->createHash($buttonId);
I thank you if you have any Ideas why the Script does not generate the correct crc.
Thank you, nice regards
Michael
Your HexToBin() was generating wrong string. The for loop for substr() started with 1 instead of 0. See substr manual.
Imploding $crc resulted an reverse bit order value.
<?PHP
function HexToBin($hstr){
$hstr = str_replace(' ','',$hstr);
$hArr = str_split($hstr);
$bstr = "";
foreach($hArr AS $c){
$cix = sprintf("0x0{$c}");
// echo sprintf("%04b|",hexdec($cix));
$bstr .= sprintf("%04b",hexdec($cix));
}
return $bstr;
}
function createHash($data){
$OutBinStr = HexToBin($data);
$crc = array_fill(0,8,0);
$OutBinArr = array_reverse(str_split($OutBinStr));
// calculate
foreach($OutBinArr AS $i){
$CRCTemp = $crc[0] ^ $i;
$crc[0] = $crc[1];
$crc[1] = $crc[2];
$crc[2] = $crc[3] ^ $CRCTemp;
$crc[3] = $crc[4] ^ $CRCTemp;
$crc[4] = $crc[5];
$crc[5] = $crc[6];
$crc[6] = $crc[7];
$crc[7] = $CRCTemp;
}
$crc = array_reverse($crc);
return implode('', $crc);
}
$buttonId = '00 00 14 5D 6E 0F 01'; // 59 => 3B
// $buttonId = '12 AA 12 5F 14 A2 12 12'; // 109 => 6D
$crc = bindec(createHash($buttonId));
printf("\n%d => %X",$crc,$crc);
?>

Categories