Recent

Author Topic: [SOLVED] Range over letters instead of numbers  (Read 640 times)

tudi_x

  • Hero Member
  • *****
  • Posts: 532
[SOLVED] Range over letters instead of numbers
« on: April 08, 2019, 06:20:13 pm »
hi All,
i need to write an algorithm to range over letters instead of numbers, for example:
-  "A"++ would return "B"
- "Z"++ would return "AA"
- "AA"++ would return "AB"

would you know the easiest way to implement this please?
i did not find code on internet, sorry if i skipped.
thank you
 
« Last Edit: April 09, 2019, 11:08:36 am by tudi_x »
Lazarus 2.0.2 64b on Debian LXDE 10

Thausand

  • Full Member
  • ***
  • Posts: 234
Re: Range over letters instead of numbers
« Reply #1 on: April 08, 2019, 07:08:49 pm »
hi hello,

I no think freepascal have ++ operator. Then can not change to make work as want.

c operators read https://www.freepascal.org/docs-html/prog/progsu10.html#x17-160001.2.10

Maybe can add helper type (or new type) then use
B := 'A'.plusplus
AA := 'Z'.plusplus
AB := 'AA'.plusplus

plusplus then method of helper. can name any. method plusplus is example.

lucamar

  • Hero Member
  • *****
  • Posts: 2397
Re: Range over letters instead of numbers
« Reply #2 on: April 08, 2019, 08:04:54 pm »
Sounds like homework, doesn't it?

This is a pretty basic algorithm: basically the same as you did additions in primary school only instead of having digits from "0" to "9" you have "digits" from "A" to "Z". That's all :)

Have fun!
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.4/2.0.6  - FPC 3.0.4 on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: Range over letters instead of numbers
« Reply #3 on: April 09, 2019, 07:16:08 am »
Define a new type:
Code: Pascal  [Select]
  1. Type
  2.  TAZ=String;

Your new system is base 26, and it starts with letter A:
Code: Pascal  [Select]
  1. const
  2.   CBASE = 26;
  3.   CSTART = 'A';

You need two functions to convert between your new type and Integer:
Code: Pascal  [Select]
  1. function AZToInt(AValue: TAZ): integer;
  2. var
  3.   i: integer;
  4. begin
  5.   Result := 0;
  6.   if AValue.Length=0 then
  7.     exit;
  8.   for i := 1 to AValue.Length-1 do
  9.     Result := Result*CBASE+Ord(AValue[i])-Ord(CSTART)+1;
  10.   Result := Result*CBASE+Ord(AValue[AValue.Length])-Ord(CSTART);
  11. end;

and

Code: Pascal  [Select]
  1. function IntToAZ(AValue: integer): TAZ;
  2. begin
  3.   Result := char(Ord(CStart)+(AValue mod CBASE));
  4.   while AValue>CBASE-1 do
  5.   begin
  6.     AValue := AValue div CBASE - 1;
  7.     Result := char(Ord(CStart)+(AValue mod CBASE)) + Result;
  8.   end;
  9. end;

A few operators to make life easier:
Code: Pascal  [Select]
  1. operator := (az:TAZ) i:integer; inline;
  2. begin
  3.   i := AZToInt(az);
  4. end;
  5.  
  6. operator := (i: integer) az:TAZ; inline;
  7. begin
  8.   az := IntToAZ(i);
  9. end;
  10.  
  11. operator + (az: TAZ; i: integer) raz:TAZ; inline;
  12. begin
  13.   raz := IntToAZ(AZToInt(az)+i);
  14. end;

Now you are good to go:
Code: Pascal  [Select]
  1. begin
  2.   WriteLn('A'+1);

Gives B.

Code: Pascal  [Select]
  1. begin
  2.   WriteLn('Z'+1);

Gives AA.

The whole thing:
Code: Pascal  [Select]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   Classes,
  7.   sysutils
  8.   { you can add units after this };
  9.  
  10. Type
  11.   TAZ=String;
  12.  
  13. const
  14.   CBASE = 26;
  15.   CSTART = 'A';
  16.  
  17. function AZToInt(AValue: TAZ): integer;
  18. var
  19.   i: integer;
  20. begin
  21.   Result := 0;
  22.   if AValue.Length=0 then
  23.     exit;
  24.   for i := 1 to AValue.Length-1 do
  25.     Result := Result*CBASE+Ord(AValue[i])-Ord(CSTART)+1;
  26.   Result := Result*CBASE+Ord(AValue[AValue.Length])-Ord(CSTART);
  27. end;
  28.  
  29. function IntToAZ(AValue: integer): TAZ;
  30. begin
  31.   Result := char(Ord(CStart)+(AValue mod CBASE));
  32.   while AValue>CBASE-1 do
  33.   begin
  34.     AValue := AValue div CBASE - 1;
  35.     Result := char(Ord(CStart)+(AValue mod CBASE)) + Result;
  36.   end;
  37. end;
  38.  
  39. operator := (az:TAZ) i:integer; inline;
  40. begin
  41.   i := AZToInt(az);
  42. end;
  43.  
  44. operator := (i: integer) az:TAZ; inline;
  45. begin
  46.   az := IntToAZ(i);
  47. end;
  48.  
  49. operator + (az: TAZ; i: integer) raz:TAZ; inline;
  50. begin
  51.   raz := IntToAZ(AZToInt(az)+i);
  52. end;
  53.  
  54. const
  55.   a: array[0..4] of TAZ=('A','B','C','Z','AA');
  56.  
  57. var
  58.   sAZ1, sAZ2: TAZ;
  59.   i, iAZ: Integer;
  60. begin
  61.   WriteLn('A'+1);
  62.   WriteLn('Z'+1);
  63.   ReadLn;
  64.  
  65.   for i := Low(a) to High(a) do
  66.   begin
  67.     sAZ1 := a[i];
  68.     iAZ := sAZ1; // convert AZ to integer
  69.     sAZ2 := iAZ; // convert integer to AZ
  70.     WriteLn(sAZ1, ':', iAZ,':',sAZ2);  // The conversions should give same results: sAZ1 and sAZ2
  71.   end;
  72.   ReadLn;
  73. end.

That was just to give you one possibility. Notice that the code is not bulletproof. For instance, it does not handle empty vars, or negative numbers..etc.

tudi_x

  • Hero Member
  • *****
  • Posts: 532
Re: Range over letters instead of numbers
« Reply #4 on: April 09, 2019, 11:08:22 am »
thank you very much engkin!
i am not familiar with the operator word, but Memo1.Append(IntToAZ( AZToInt('Z')+1)) added a 'AA'
Lazarus 2.0.2 64b on Debian LXDE 10