{$A+,B+,D+,E-,F+,G+,I+,L+,N-,O+,P+,Q+,R+,S+,T+,V-,X+,Y+}
{$M 65520,100000,655360}
{
Program compiled and tested With BP 7.0
WARNING since this Program is not using the fastest algorithm to
find it's Anagrams, long Delays can be expected For large
input-Strings.
Test have shown the following results:
Length of Input Number of anagrams found
2 2
3 6
4 24
5 120
6 720
7 5040
As can plainly be seen from this, the number of Anagrams For a
String of length N is a direct Function of the number of Anagrams
For a String of N-1. In fact the result is f(N) = N * f(N-1).
You might have recognised the infamous FACTORIAL Function!!!
Type
MyType = LongInt;
Function NumberOfAnagrams(Var InputLen : MyType) : MyType;
Var
Temp : MyType;
begin
Temp := InputLen;
if Temp >1 then
begin
Temp := Temp - 1;
NumberOfAnagrams := InputLen * NumberOfAnagrams(Temp);
end else
NumberOfAnagrams := InputLen;
end;
The above Function has been tested and found to work up to an input
length of 12. After that, Real numbers must be used. As a side note
the Maximum value computable was 1754 With MyType defined as
Extended and Numeric-Coprocessor enabled of course. Oh and BTW, the
parameter is passed as a Var so that the Stack doesn't blow up when
you use Extended Type!!!! As a result, you can't pass N-1 to the
Function. You have to STORE N-1 in a Var and pass that as parameter.
The net effect is that With Numeric Copro enabled, at 1754 it blows
up because of a MATH OVERFLOW, not a STACK OVERFLOW!!!
Based on these findings, I assume the possible anagrams can be
computed a lot faster simply by Realising that the possible Anagrams
For an input length of (N) can be found by finding all anagrams for
an input Length of (N-1) and inserting the additional letter in each
(N) positions in those Strings. Since this can not be done
recursively in memory, the obvious solution would be to to output
the anagrams strating With the first 4 or 5 caracters to a File,
because those can be found quickly enough, and then to read in each
String and apply the following caracters to each and Repeat this
process Until the final File is produced.
Here is an example:
Anagrams For ABCD
Output Anagrams For AB to File
Giving AB and BA
read that in and apply the next letter in all possible positions
Giving
abC
aCb
Cab
&
baC
bCa
Cba
Now Apply the D to this and get
abcD
abDc
aDbc
Dabc
&
acbD
acDb
aDcb
Dacb
Etc... YOU GET THE POINT!!!
BTW Expect LARGE Files if you become too enthousiastic With this!!!
An Input of just 20 caracters long will generate a File of
2,432,902,008,176,640,000 Anagrams
That's
2.4 Quintillion Anagrams
Remember that each of those are 20 caracters long,
add Carriage-return and line-feeds and you've got yourself a
HUGE File ;-)
In fact just a 10 Caracter input length will generate 3.6 Million
Anagrams from a 10 Caracter input-String. Again add Cr-LFs and
you've got yourself a 43.5 MEGAByte File!!!!!! but consider you
are generating it from the previous File which comes to 3.5 MEG
For an Input Length of 9 and you've got yourself 45 MEG of DISK in
use For this job.
}
Uses
Strings, Crt;
Const
MaxAnagram = 1000;
Type
AnagramArray = Array[0..MaxAnagram] of Word;
AnagramStr = Array[0..MaxAnagram] of Char;
Var
Target : AnagramStr;
Size : Word;
Specimen : AnagramArray;
Index : Word;
AnagramCount : LongInt;
Procedure working;
Const
CurrentCursor : Byte = 0;
CursorArray : Array[0..3] of Char = '|/-\';
begin
CurrentCursor := Succ(CurrentCursor) mod 4;
Write(CursorArray[CurrentCursor], #13);
end;
Procedure OutPutAnagram(Target : AnagramStr;
Var Specimen : AnagramArray; Size : Word);
Var
Index : Word;
begin
For Index := 0 to (Size - 1) do
Write(Target[Specimen[Index]]);
Writeln;
end;
Function IsAnagram(Var Specimen : AnagramArray; Size : Word) : Boolean;
Var
Index1,
Index2 : Word;
Valid : Boolean;
begin
Valid := True;
Index1 := 0;
While (Index1<Pred(Size)) and Valid do
begin
Index2 := Index1 + 1;
While (Index2 < Size) and Valid do
begin
if Specimen[Index1] = Specimen[Index2] then
Valid := False;
inc(Index2);
end;
inc(Index1);
end;
IsAnagram := Valid;
end;
Procedure FindAnagrams(Target : AnagramStr;
Var Specimen : AnagramArray; Size : Word);
Var
Index : Word;
Carry : Boolean;
begin
Repeat
working;
if IsAnagram(Specimen, Size) then
begin
OutputAnagram(Target, Specimen, Size);
inc(AnagramCount);
end;
Index := 0;
Repeat
Specimen[Index] := (Specimen[Index] + 1) mod Size;
Carry := not Boolean(Specimen[Index]);
Inc(Index);
Until (not Carry) or (Index >= Size);
Until Carry and (Index >= Size);
end;
begin
ClrScr;
Write('Enter anagram Target: ');
readln(Target);
Writeln;
AnagramCount := 0;
Size := Strlen(Target);
For Index := 0 to MaxAnagram do
Specimen[Index] := 0;
For Index := 0 to Size - 1 do
Specimen[Index] := Size - Index - 1;
FindAnagrams(Target, Specimen, Size);
Writeln;
Writeln(AnagramCount, ' Anagrams found With Source ', Target);
end.