You are not logged in.
Hehe. The idea of the ALPHA_FORMAT was to allow exactly that... mixing of character sets. It depends on what you're aiming for, but if you don't need to mix and match, that's fine.
As far as your current IsNumber, IsUpperCaseLetter, etc., you could probably substitute those with the built-in functions IsWideCharDigit, IsWideCharUpper, etc. Minor point of cleanup, entirely up to you.
As far as how it works... the array SerialCount is a blob of integers, one integer per character in the resulting serialization. You increment index 0, which corresponds to the lowest position in the serialization. CheckCarries() checks if each number is actually within the bounds of the character set for that position. If it is, great; if not, it does like what you were taught in elementary school.... add a carry to the next column over.
Once the values are all updated, AlphaSerialize() translates each integer to a matching letter, collects them all together, and returns the resulting serialization string. The remaining critters are helper functions which are hopefully instructive by their name.
Offline
I suspected that there might be such built-in functions in Pascal, but programming these again was faster than looking up manuals :) Thank you for the background explanations; this will make it easier to understand the semantics!
Offline
OK, I hope it's final version.
I went for a small unification with your scripts, guys. So now we have same letterset's constant names. Just for case that someone want's to use both scripts. It will be less confusing.
I did some cleaning. And there it is.
If the letterset is 'abc', serialization goes like this:
a
b
c
aa
ab
ac
ba... and so on.
The main difference between mine and prologician's script is that mine goes only through the defined (but only one) letterset. No number-padding when you exceed the pattern.
BTW, prologician, maybe you should give user a possibility to chose padding from any given letterset,
eg. PADDING = LETTERS_U;
I think, I will give up tweaking it now. It was nice exercise.
Cheers.
CONST
LETTERS_L = 'abcdefghijklmnopqrstuvwxyz';
LETTERS_U = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
NUMBERS = '0123456789';
BOTH_NL = '0123456789abcdefghijklmnopqrstuvwxyz';
BOTH_NU = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
TEST = 'abcde';
//CONTROLS FOR THE SCRIPT:
SERIALIZE = LETTERS_L; //setting the letterset for serialization
START_PATTERN = 'a'; //anything you want to start with, eg. 'bba'
STEP = 1; //step MUST be lower than length of SERIALIZE string
var
i, k: Integer;
Pad: Array of Integer; //Pad array is 0 based, but it stores values only from index 1
Initialized: Boolean;
Start, Serialization : WideString;
procedure Initialize;
begin
Initialized := True;
Start:='';
Start:=Start+START_PATTERN;
SetLength(Pad, Length(Start)+1);
Pad[0] := -1; // just in case, we won't use that cell
if Length(Pad) < 2 then
ShowMessage('Error:'+#13+'START_PATTERN constant not defined.'+#13+'Set START_PATTERN constant to '+#39+'a'+#39)
else if Length(Pad) = 2 then
begin
Pad[1] := WidePos(Start[1], SERIALIZE);
If Pad[1] = 0 then
ShowMessage('Error:'+#13+'START_PATTERN constant contains a char ('+#39+Start[1]+#39+'), that is not present in SERIALIZE constant!');
end
else
for k:=1 to Length(Pad)-1 do
begin
Pad[k] := WidePos(Start[k], SERIALIZE);
if Pad[k] = 0 then
ShowMessage('Error:'+#13+'START_PATTERN constant contains a char ('+#39+Start[k]+#39+'), that is not present in SERIALIZE constant!');
end;
;
i := WidePos(Start[Length(Pad)-1], SERIALIZE);
end;
procedure CheckZ(p:Integer);
begin
if Pad[p] > Length(SERIALIZE) then
begin
Pad[p]:=1;
if p > 1 then
begin
Pad[p-1]:=Pad[p-1]+1;
CheckZ(p-1);
end
else
SetLength(Pad, Length(Pad)+1);
end;
end;
begin
if not Initialized then Initialize;
Pad[Length(Pad)-1]:=i;
if i > Length(SERIALIZE) then
begin
CheckZ(Length(Pad)-1);
i:=i-Length(SERIALIZE);
Pad[Length(Pad)-1]:=i;
end;
Serialization:='';
for k:=1 to Length(Pad)-1 do
Serialization:=Serialization + SERIALIZE[Pad[k]];
FileName := WideStripExtension(FileName)+ Serialization + WideExtractFileExt(FileName);
i := i + STEP;
end.
Regular Expressions are not as hard to understand as you may think. Check ReNamer's manual or nice Regular Expressions tutorial for more info and start to use full power of applications that use them (like ReNamer, Mp3Tag and so on).
Offline
Strictly speaking, the capacity to change the overflow padding already there, I was just too lazy to make it an explicit constant.... In the NthInFormatToLetterset() function:
if (I >= length(Format)) then
begin
result := NUMBERS;
exit
end;
Change 'NUMBERS' to whatever other alphabet set you want will get you there. Or, if you REALLY want it, you could pull out another constant for handling this. Entirely up to you.
Last edited by prologician (2009-02-16 21:54)
Offline
the capacity to change the overflow padding is already there
I thaught so
Frankly speaking I can hardly believe I will ever use mine or yours script for actual renaming. I prefer numbers for serialization.
But it was nice exercise.
Last edited by krtek (2009-02-17 07:03)
Regular Expressions are not as hard to understand as you may think. Check ReNamer's manual or nice Regular Expressions tutorial for more info and start to use full power of applications that use them (like ReNamer, Mp3Tag and so on).
Offline
krtek, in your script above, if I specify START_PATTERN = 'Z9x', then after 'Z9z', it shows 'ZA0'.
prologician's script on the other hand shows '0A0a' or 'aA0a' (depending on whether result := NUMBERS; or result := LETTERS_L as discussed just above).
When I was independently thinking of the logic, I too thought that 'Z9z' should be followed by 'aA0a'. Anyway, it all depends on what the user wants. Both scripts are simply fantastic!
BTW, since I too felt that this would be a nice programming exercise and a way to improve my PascalScript skills, here's my contribution:
{ Alphanumeric Serialization Script }
// v1 - Original script by Andrew
const
digit_low = 48; // 0
digit_high = 57; // 9
ucase_low = 65; // A
ucase_high = 90; // Z
lcase_low = 97; // a
lcase_high = 122; // z
initstr = 'a'; // Set initial string here
overflow = lcase_low; // Set overflow char here
step = 1; // Set step value here
append = True; // Append serialized string?
skipext = True; // Skip file extension?
var
s1,s2: String;
i,low,high,val: Integer;
initialized,carry: Boolean;
procedure SetFileName;
begin
if(append) then
begin
if(skipext) then
FileName := WideExtractBaseName(FileName) + s2 + WideExtractFileExt(FileName)
else
FileName := FileName + s2;
end
else
FileName := s2 + FileName;
end;
begin
if(Not initialized) then
begin
s2 := initstr;
for i := 1 to Length(s2) do
s1 := s2[i] + s1;
SetFileName;
initialized := True;
Exit;
end;
for i := 1 to Length(s1) do
begin
if((i>1) And (Not carry)) then
Break;
val := Ord(s1[i]);
if(val >= lcase_low) then // Lower-case
begin
low := lcase_low;
high := lcase_high;
end
else if(val >= ucase_low) then // Upper-case
begin
low := ucase_low;
high := ucase_high;
end
else if(val >= digit_low) then // Digit
begin
low := digit_low;
high := digit_high;
end;
if(Not carry) then
val := val + step;
carry := False;
if(val > high) then
begin
while(val > high) do
val := low + (val mod high) - 1;
if(i = Length(s1)) then
begin
SetLength(s1, Length(s1)+1);
s1[i+1] := Chr(overflow);
end
else
begin
s1[i+1] := Chr(Ord(s1[i+1]) + 1);
carry := True;
end;
end;
s1[i] := Chr(val);
end;
s2 := '';
for i := 1 to Length(s1) do
s2 := s1[i] + s2;
SetFileName;
end.
If someone can, please stress test it and give your comments. Thanks!
Last edited by Andrew (2009-02-18 20:04)
Offline
krtek, in your script above, if I specify START_PATTERN = 'Z9x', then after 'Z9z', it shows 'ZA0'.
prologician's script on the other hand shows '0A0a' or 'aA0a' (depending on whether result := NUMBERS; or result := LETTERS_L as discussed just above).
To be honest I haven't notice the difference... Just tested, and prologician's script (with pattern 'BBb' and initial string 'Z9x') gives ZA0 after Z9z...
And about the logic... It's quite hard to aknowledge that... I haven't thought about logic. Mainly, because I can't find any particular use of such (letters+numbers) serialization (I prefer numbers). My main goal was to recreate the list created by report at the very beginning.
BOTH_NL and BOTH_NU serialization strings were taken by me from prologician's script to give user some unification of interface.
The cold truth is that anyone who decides to use one of BOTH type serialization strings, have to decide what was first (egg or hen?). And make adjustments to these strings. They can start with 0 with 1 or with a (and then after z can be 0 or 1)...
Do it like you like it
If someone can, please stress test it and give your comments.
It looks to work fine if overflow char is a letter of same case as in initial string.
It looks a bit funny with 'a' as initial string and 'A' as overflow char (or other way round).
It's quite strange with digits as overflow... It seems to work the other work round then. x,y,z, 0a, 0b, 0c... 9x, 9y, 9z, 00a, 00b, 00c...
Nice idea with append and skipext constants. But I guess you should explain "append" a bit better in comments eg. true - at the beggining, false - at the end... (I hate naming const and vars and adding comments, I never know how to make all that meaningful enough for user). Overflow char is quite mystic and not very well explained const, too.
Just few first thoughts.
It has started as an example of hard typing work and ended as PascalScript self-e-learning course
Cheers,
Konrad
Last edited by krtek (2009-02-18 21:46)
Regular Expressions are not as hard to understand as you may think. Check ReNamer's manual or nice Regular Expressions tutorial for more info and start to use full power of applications that use them (like ReNamer, Mp3Tag and so on).
Offline
Just some motivation for why one one might serialize alphanumeric:
My most frequent application is to have countless media files. Different contents gets different file numbers. However, I also want to group almost-same contents (like a picture with same motif but edited for brightness or like a music track but edited to be without scratches). Then I use the same file number but append serialized letters.
It does sometimes happen though that I need speaking filenames plus counter. Like MySpeakingNameNNN. Then it is fast to do that in one step by starting from MySpeakingName000.
Of course, I try to avoid w0I1l2D3 file names. But, from a programming POV, it has been the almost same work to allow both MySpeakingName000 or w0I1l2D3 as starting values. So there is no reason not to offer it in all generality. And there is no reason to require two rules (Insert MySpeakingName + Append Serialize From 000) when one rule (Serialize from MySpeakingName000) suffices! File renaming must be as efficient as anyhow possible because in practice one wants to work with contents rather than spending lots of time on file renaming:)
Offline
Andrew, your script (and its straightforward design) seems to work as well. How many roads are there to Rome...? However, if one restricts the letterset to, say, {a, b} by lcase_high = 98 and then uses an initstring with also other letters, say, MyNamea, then one is reminded of Pacman: The name is eaten up in a peculiar manner:( Such does not happen with prologician's or my scripts.
I agree though that more options for where to insert or the extension should be added but do not like your selective choice here. It is more a proof of concept so far.
Practically speaking, users will find editing letterset strings easier than ascii code numbers. But... when alphaserialize becomes hardcoded, such does not matter any longer.
Offline
As far as the script is concerned, I'm with krtek on this one. It was a rather interesting exercise, though it's not something I myself would use on any regular basis at all. But, if it makes your life easier, report, then by all means. *^_^*
I do wonder, in a way, if such a thing will get built into Renamer itself, though. I mean, one way to look at all our scripts is as a proof-of-concept. Another way is that they are functional code, doing the job to a (hopefully reasonable) degree. Combining this with my belief that, due to the inclusion of PascalScript within a program like ReNamer, that you really can do virtually anything (I mean, we got a couple scripts here that call actual DLLs.... if that's not power in your hands, I don't know what is)... any of the answers proposed in this thread are probably more than enough for most folks' needs.
Of course, this isn't to say that den4b ~couldn't~ include an AlphaSerialize function into some future version. I'm figuring it's more likely that using one of these scripts will be more likely to happen.
Offline