In the php
wild wild west,
given that Most efficient way to get next letter in the alphabet using PHP is made by the pre increment ++
operator applied to a char
(i.e. one sized string):
$str = 'a';
echo ++$str; // prints 'b'
$str = 'z';
echo ++$str; // prints 'aa'
And that there is this crazyness in
for ($char='A'; $char<='Z'; $char++) {
echo $char;
}
that will print out
ABCDEFGHIJKLMNOPQRSTUVWXYZAAABACADAEAFAGAHAIAJAKALAMANAOAPAQARASATAUAVAWAXAYAZBABBBCBDBEBFBGBHBIBJBKBLBMBNBOBPBQBRBSBTBUBVBWBXBYBZCACBCCCDCECFCGCHCICJCKCLCMCNCOCPCQCRCSCTCUCVCWCXCYCZDADBDCDDDEDFDGDHDIDJDKDLDMDNDODPDQDRDSDTDUDVDWDXDYDZEAEBECEDEEEFEGEHEIEJEKELEMENEOEPEQERESETEUEVEWEXEYEZFAFBFCFDFEFFFGFHFIFJFKFLFMFNFOFPFQFRFSFTFUFVFWFXFYFZGAGBGCGDGEGFGGGHGIGJGKGLGMGNGOGPGQGRGSGTGUGVGWGXGYGZHAHBHCHDHEHFHGHHHIHJHKHLHMHNHOHPHQHRHSHTHUHVHWHXHYHZIAIBICIDIEIFIGIHIIIJIKILIMINIOIPIQIRISITIUIVIWIXIYIZJAJBJCJDJEJFJGJHJIJJJKJLJMJNJOJPJQJRJSJTJUJVJWJXJYJZKAKBKCKDKEKFKGKHKIKJKKKLKMKNKOKPKQKRKSKTKUKVKWKXKYKZLALBLCLDLELFLGLHLILJLKLLLMLNLOLPLQLRLSLTLULVLWLXLYLZMAMBMCMDMEMFMGMHMIMJMKMLMMMNMOMPMQMRMSMTMUMVMWMXMYMZNANBNCNDNENFNGNHNINJNKNLNMNNNONPNQNRNSNTNUNVNWNXNYNZOAOBOCODOEOFOGOHOIOJOKOLOMONOOOPOQOROSOTOUOVOWOXOYOZPAPBPCPDPEPFPGPHPIPJPKPLPMPNPOPPPQPRPSPTPUPVPWPXPYPZQAQBQCQDQEQFQGQHQIQJQKQLQMQNQOQPQQQRQSQTQUQVQWQXQYQZRARBRCRDRERFRGRHRIRJRKRLRMRNRORPRQRRRSRTRURVRWRXRYRZSASBSCSDSESFSGSHSISJSKSLSMSNSOSPSQSRSSSTSUSVSWSXSYSZTATBTCTDTETFTGTHTITJTKTLTMTNTOTPTQTRTSTTTUTVTWTXTYTZUAUBUCUDUEUFUGUHUIUJUKULUMUNUOUPUQURUSUTUUUVUWUXUYUZVAVBVCVDVEVFVGVHVIVJVKVLVMVNVOVPVQVRVSVTVUVVVWVXVYVZWAWBWCWDWEWFWGWHWIWJWKWLWMWNWOWPWQWRWSWTWUWVWWWXWYWZXAXBXCXDXEXFXGXHXIXJXKXLXMXNXOXPXQXRXSXTXUXVXWXXXYXZYAYBYCYDYEYFYGYHYIYJYKYLYMYNYOYPYQYRYSYTYUYVYWYXYYYZ
due to the fact that after 'Z' comes 'AA', and 'AA' is smaller than 'Z'.
and so the correct way is print the next char will be
foreach (range('A', 'Z') as $char) {
echo $char;
}
that will print out
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Assumed that we can get the next char with modulo operator and chr(ord())
$next=chr((((ord($c) - ord('A')) + 1) % 26) + ord('A'));
I need a way to do the ++$char
using ord()
and chr()
functions, and so doing
$cmax=ord('A');
$char='A';
foreach (range('A', 'z') as $c) {
++$char;
$next=chr((((ord($c) - $cmax) + 1) % 26) + $cmax);
echo ord($c)." ".$c." ".$next." ".$char."\n";
}
it will print out:
65 A B B
66 B C C
67 C D D
68 D E E
69 E F F
70 F G G
71 G H H
72 H I I
73 I J J
74 J K K
75 K L L
76 L M M
77 M N N
78 N O O
79 O P P
80 P Q Q
81 Q R R
82 R S S
83 S T T
84 T U U
85 U V V
86 V W W
87 W X X
88 X Y Y
89 Y Z Z
90 Z A AA
91 [ B AB
92 \ C AC
93 ] D AD
94 ^ E AE
95 _ F AF
96 ` G AG
97 a H AH
98 b I AI
99 c J AJ
since in $next
char are not being accumulated, just getting the next one.
So how to get the same value in the 3rd and 4th columns using only chr( ord() )
?
[EDIT]
I'm going to clarify that I need the same output of this for loop
for ($char='A'; $char<='Z'; $char++) {
echo $char."\n";
}
that is like
A
B
C
...
Y
Z
AA
AB
AC
AD
AE
AF
...
YW
YX
YY
YZ
but only using ord()
and chr()
and a modulo operator.
Now the last byte (first byte) is simply obtained by modulo %26
:
$byte_two=chr( ( ((ord($code) - ord('A')) + 1) % 26) + ord('A') );
that in a foreach
on the given range('A', 'z')
:
foreach (range('A', 'z') as $code) {
$byte_one=chr( ( ((ord($code) - ord('A')) + 1) % 26) + ord('A') );
echo ord($code)."\t".$byte_one."\n";
}
will print outs exactly the last byte there as the same byte position in ++$char
. So I think I'm missing the $byte_two
, the first byte here.
[SUGGESTED IMPLEMENTATION]
This is one of the suggested implementation, and the most simple I was able to come out using a lookup table as suggested:
function lookupNextChar($c)
{
static $lookup_table=null;
if ($lookup_table === null) {
$lookup_table=explode(",","A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR,AS,AT,AU,AV,AW,AX,AY,AZ,BA,BB,BC,BD,BE,BF,BG,BH,BI,BJ,BK,BL,BM,BN,BO,BP,BQ,BR,BS,BT,BU,BV,BW,BX,BY,BZ,CA,CB,CC,CD,CE,CF,CG,CH,CI,CJ,CK,CL,CM,CN,CO,CP,CQ,CR,CS,CT,CU,CV,CW,CX,CY,CZ,DA,DB,DC,DD,DE,DF,DG,DH,DI,DJ,DK,DL,DM,DN,DO,DP,DQ,DR,DS,DT,DU,DV,DW,DX,DY,DZ,EA,EB,EC,ED,EE,EF,EG,EH,EI,EJ,EK,EL,EM,EN,EO,EP,EQ,ER,ES,ET,EU,EV,EW,EX,EY,EZ,FA,FB,FC,FD,FE,FF,FG,FH,FI,FJ,FK,FL,FM,FN,FO,FP,FQ,FR,FS,FT,FU,FV,FW,FX,FY,FZ,GA,GB,GC,GD,GE,GF,GG,GH,GI,GJ,GK,GL,GM,GN,GO,GP,GQ,GR,GS,GT,GU,GV,GW,GX,GY,GZ,HA,HB,HC,HD,HE,HF,HG,HH,HI,HJ,HK,HL,HM,HN,HO,HP,HQ,HR,HS,HT,HU,HV,HW,HX,HY,HZ,IA,IB,IC,ID,IE,IF,IG,IH,II,IJ,IK,IL,IM,IN,IO,IP,IQ,IR,IS,IT,IU,IV,IW,IX,IY,IZ,JA,JB,JC,JD,JE,JF,JG,JH,JI,JJ,JK,JL,JM,JN,JO,JP,JQ,JR,JS,JT,JU,JV,JW,JX,JY,JZ,KA,KB,KC,KD,KE,KF,KG,KH,KI,KJ,KK,KL,KM,KN,KO,KP,KQ,KR,KS,KT,KU,KV,KW,KX,KY,KZ,LA,LB,LC,LD,LE,LF,LG,LH,LI,LJ,LK,LL,LM,LN,LO,LP,LQ,LR,LS,LT,LU,LV,LW,LX,LY,LZ,MA,MB,MC,MD,ME,MF,MG,MH,MI,MJ,MK,ML,MM,MN,MO,MP,MQ,MR,MS,MT,MU,MV,MW,MX,MY,MZ,NA,NB,NC,ND,NE,NF,NG,NH,NI,NJ,NK,NL,NM,NN,NO,NP,NQ,NR,NS,NT,NU,NV,NW,NX,NY,NZ,OA,OB,OC,OD,OE,OF,OG,OH,OI,OJ,OK,OL,OM,ON,OO,OP,OQ,OR,OS,OT,OU,OV,OW,OX,OY,OZ,PA,PB,PC,PD,PE,PF,PG,PH,PI,PJ,PK,PL,PM,PN,PO,PP,PQ,PR,PS,PT,PU,PV,PW,PX,PY,PZ,QA,QB,QC,QD,QE,QF,QG,QH,QI,QJ,QK,QL,QM,QN,QO,QP,QQ,QR,QS,QT,QU,QV,QW,QX,QY,QZ,RA,RB,RC,RD,RE,RF,RG,RH,RI,RJ,RK,RL,RM,RN,RO,RP,RQ,RR,RS,RT,RU,RV,RW,RX,RY,RZ,SA,SB,SC,SD,SE,SF,SG,SH,SI,SJ,SK,SL,SM,SN,SO,SP,SQ,SR,SS,ST,SU,SV,SW,SX,SY,SZ,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR,TS,TT,TU,TV,TW,TX,TY,TZ,UA,UB,UC,UD,UE,UF,UG,UH,UI,UJ,UK,UL,UM,UN,UO,UP,UQ,UR,US,UT,UU,UV,UW,UX,UY,UZ,VA,VB,VC,VD,VE,VF,VG,VH,VI,VJ,VK,VL,VM,VN,VO,VP,VQ,VR,VS,VT,VU,VV,VW,VX,VY,VZ,WA,WB,WC,WD,WE,WF,WG,WH,WI,WJ,WK,WL,WM,WN,WO,WP,WQ,WR,WS,WT,WU,WV,WW,WX,WY,WZ,XA,XB,XC,XD,XE,XF,XG,XH,XI,XJ,XK,XL,XM,XN,XO,XP,XQ,XR,XS,XT,XU,XV,XW,XX,XY,XZ,YA,YB,YC,YD,YE,YF,YG,YH,YI,YJ,YK,YL,YM,YN,YO,YP,YQ,YR,YS,YT,YU,YV,YW,YX,YY,YZ");
echo implode($lookup_table,',')."\n";
echo count($lookup_table)."\n";
}
$idx=( ((ord($c) - ord('A')) + 1 ) % count($lookup_table));
return $lookup_table[ $idx ];
}
To prove it, just get the next $char
from the range('A','z')
:
$sum=$n='A';
foreach (range('A','z') as $c) {
$n=lookupNextChar($c,$lookup_table);
++$sum;
echo "$c\t$n\t$sum\n";
}
and then I get
A B B
B C C
C D D
D E E
E F F
F G G
.. .. ..
X Y Y
Y Z Z
Z AA AA
[ AB AB
\ AC AC
] AD AD
^ AE AE
.. .. ..
x CD BD
y DE BE
z EF BF
that is want I wanted to achieve as output, even if using a different way.
NOTE. Of course, the lookup table was generated using the ++
operator then:
$lookup_table=array();
for ($char='A'; $char<='Z'; $char++) {
array_push($lookup_table,$char);
}
that does not imply to be used programmatically in the javascript porting (see comments).