I have Win98 and D4. A previously asked question on displaying combinations was done sometime during the month of May 99. I would like to see the solution again. Comment : This newEE system is so slow leafing backwards through the previous solutions offered that it may take me days to get back to there. And yes I have used the NEW search engine but no solution to this topic is offered in Delphi.
RWilson's contribution was, as I have copied from the locked Question:
var
I : integer;
Count : Integer;
CombinationSize : Integer;
Combinations : TStringlist;
TheItems : TStringList; // Set of items;
procedure OutputCombination(Depth : Integer; state : string);
var
I : integer;
begin
if depth > 0 then
begin
for I := CombinationSize - Depth to Count - Depth + 1 do
OutputCombination(Count, Depth - 1, State + ','+TheItems[I]);
end
else
Combinations.add(state);
end;
begin
Count := 10;
CombinationSize := 4;
Combinations := TStringList.Create;
TheItems := TStringList.Create;
AddItemsToSet(TheItems); // fill the set here...
for I := 1 to Count - CombinationSize + 1 do
OutputCombination(CombinationSize - 1, TheItems[i]);
end;
here's another implementation for your problem. I hope it is what you are looking for as I don't know the original question. I also don't know what you consider as being better. The code below takes a range of characters and constructs all possible combinations from these chars.
begin
if Level > 0 then
begin
for I := #0 to #255 do
if I in (Range - Exclusion) then
begin
Include(Exclusion, I);
ConstructLevel(Level - 1, I + Item);
Exclude(Exclusion, I);
end;
end
else List.Add(Item);
end;
begin
List.Clear;
if Depth > 0 then
begin
Exclusion := [];
ConstructLevel(Depth, '');
end;
end;
begin
CreateCombinations(['A'..'Z'], 3, ListBox1.Items);
end;
The Depth parameter determines the length of the result strings. This parameter must be less or equal the number of elements in the range of characters. If you want to allow duplicates in the result then replace:
My answer to the question, which is still waiting to graded, takes a string, and builds a combination of that string according to an index.
For instance permutestring('ABC',1) would return 'ABC', while
('ABC',2) would return 'ACB', up to ('ABC',6) which would return 'CBA'.
It has advantages and disadvantages over the other offers. It requires very little memory, as it doesn't store all the possible combinations (on large strings, very, as there are lots of combinations on very large numbers). On the other hand, for small numbers, it takes more time, especially when up against lookups in pre-calculated combination tables.
It lacks error checking (don't call it with ('ABC',7) for instance), and is limited to 21 digits long strings (the limit imposed by the size of INT64).
function excited_n(n : int64) : int64;
var
i : integer;
begin
result := 1;
if n < 2 then
exit;
for i:=2 to n do
result := result*i;
end;
function permutestring(originalstring : string;
whichperm : Int64) : string;
var
numperms : int64;
takechar : integer;
begin
numperms := excited_n(length(originalstring)-1);
result := '';
repeat
takechar := ((whichperm-1) div numperms) + 1;
result := result + originalstring[takechar];
Delete(originalstring,takechar,1);
if (length(originalstring) > 1) then
begin
whichperm := ((whichperm-1) mod numperms)+1;
numperms := numperms div (length(originalstring));
end;
until (length(originalstring) = 1);
result := result + originalstring;
end;
0
Be seen. Boost your questionâ€™s priority for more expert views and faster solutions
unfortunately, you are not accepting what you got so far. We gave you several solutions but you came up with more and more new requirements. Perhaps you should pick and accept one solution and work out the rest you need yourself...
Oops, sorry sbruck. This was a bad mistake! I couldn't find the question (there are soooo many) so I just wrote my comment without lookup. Sorry again!
Hi EE Commentors To My Question,
I do not know what part of the world you are in but as I read your notes I sse that you are restless for my approval. FYI I wrote the Q at 1AM my time and it is now 7AM my time. I know that some of you miss your sleep period as that is your work period. I do not miss my sleep period as it is a necessary thing.
Please forgive me for sleeping and I'll get around to checking out, grading your response.
It may be another 24 hours before I get to it. Thanks for responding.
How do you declare this in the forward declaration at the start of the program and why not add the Sender: TObject to these procedures as you did in the Button5Click?
Right Delphi3! Socalled local functions are a speciality of PASCAL. I used them only when I need to carry out an action which is only needed in one function but this function is already so complex that it is clearer to use a local routine. Another valid situation is given here as the local function is recursive. No problem to make a regular function from it, though...
The Sender parameter in the outer function is there because I have put the call to the combination function into a button click handler. You could call it from everywhere you like. Usually you don't need to declare the combination function with "forward" as it is a standalone function. Just place it so near to the implementation keyword that it can be access from all code which needs it. But if you, for whatever reason, need to declare it forward then go ahead and write:
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
CreateCombinations(['A'..'Z'], 3, ListBox1.Items,Self);
end;
procedure TForm1.CreateCombinations(Range: TCharRange; Depth: Cardinal;List: TStrings;Sender:Tobject);
var
Exclusion: TCharRange;
procedure ConstructLevel(Level: Cardinal; Item: String);
var
I: Char;
begin // start of ConstructLevel
if Level > 0 then
begin
for I := #65 to #68 do
if I in (Range - Exclusion) then
begin
Include(Exclusion, I);
ConstructLevel(Level - 1, I + Item);
Exclude(Exclusion, I);
end; //end if I
end //end for loop
else
List.Add(Item);
end;//if Level
begin // start procedure createcombinations
List.Clear;
if Depth > 0 then
begin
Exclusion := [];
ConstructLevel(Depth, '');// recursively
end; //end if Depth
end; //end procedure
procedure TForm1.Button2Click(Sender: TObject);
begin
Application.Terminate;
end;
end.
{Notes:
a Permutation of 4 things taken 3 at a time is given by the
Formula P(n,r) and for this sample is calculated by 4! divided by
(4-3)! = 24 In the problem of letters of the alphabet:
Q: how many 'meaningless words' can be constructed
using 4 letters,using 3 at a time? For this problem
there are 24 items in the output.
a Combination of 4 things taken 3 at a time is give by the
Formula C(n,r) and for this sample is calculated by 4! divided by
((4-3)!* 3!) = 4 . In the problem of committees:
Q: how many committees can be selected from a group of 4 people,
3 at a time? For this kind of problem there are only
4 different name arrangements in the output.
The distinction between permutation and combination is
an important one. If order is important then a permutation
is the desired outcome. On the other hand if order is NOT
important then it is a combination.
I need a program for showing Combinations as a listing
not Permutations. Can you help me? Thank you. Delphi3 }
Okay, you made me clear a point I wasn't aware of. Sure, what I gave you was code to create permutations. While thinking about a new algo I realized that Ray's solution is what I also would use (the code in your question). What's wrong with it that you want another one?
Hi Lischke,
His procedure within the procedure does not call a consistant set of variables. His list of is unspecified.
Can that be fixed? or replaced within yours?
oh well, this took me 3 hours to work out this so simple looking function. I hope this is now what you need. Next time, I'd suggest, you declare such a question as being hard (by assigning more points to it) ;-).
procedure P(N, Elements: Integer; Current: array of Integer);
var
I, J: Integer;
S: String;
A: array of Integer;
begin
if Length(Current) = Elements then
begin
S := '';
for I := 0 to High(Current) do S := S + IntToStr(Current[I]);
List.Add(S);
end
else
begin
if Length(Current) > 0 then J := Current[High(Current)]
else J := 0;
// create a new array which can be extended with one value
SetLength(A, Length(Current) + 1);
for I := 0 to High(Current) do A[I] := Current[I];
for I := 1 to N - (Elements - Length(Current)) - J + 1 do
begin
A[High(A)] := I + J;
P(N, Elements , A);
end;
end;
end;
begin
CreateCombinations(5, 3, ListBox1.Items);
end;
The core function P takes three arguments. The first one is the upper limit of a range of integer numbers (going so from 1..N). The second parameter is the number of elements the results should comprise and the third parameter can be empty to start output with the first possible combination or any combination (or part of combination) to start output with.
Hi Lischke,
Nice job. I placed your answer in a program that takes your combination number lists and converts it to lists of combinations using names/words.
As for making the program difficulty level as a hard one. Well, that is how prepared you were to answer. I had no idea as to how prepared you were. But I increased the points.
procedure P(N, Elements: Integer; Current: array of Integer);
var
I, J: Integer;
S: String;
A: array of Integer;
begin
if Length(Current) = Elements then
begin
S := '';
for I := 0 to High(Current) do S := S + IntToStr(Current[I]);ListBox1.Add(S);
end
else
begin
if Length(Current) > 0 then J := Current[High(Current)]
else J := 0;
// create a new array which can be extended with one value
SetLength(A, Length(Current) + 1);
for I := 0 to High(Current) do
A[I] := Current[I];
for I := 1 to N - (Elements - Length(Current)) - J + 1 do
begin
A[High(A)] := I + J;
P(N, Elements , A);
end;
end;
end;
begin
P(Range, Elements, []);
end;
procedure TForm1.ReadAndTransfer(Sender: TObject);
var
ListArra:Array[0..20] of String; // more than enough
FName:Array[0..20] of String; //more than enough
Itm:String;
I,I1,I2,Num,C,D :Integer;
Data:Textfile;
begin
C := ListBox1.Items.Count;
for I := 0 to C-1 do
ListArra[I]:= Form1.ListBox1.Items.Strings[I];
//Reading File with names
//List of names/words MUST contain AT LEAST a number of elements N
Reset(Data,'MyNameList.txt');
Num := 0;
Readln(Data,FName[Num]);
while not EOF(Data) do
begin
Num:= Num + 1;
Readln(Data,FName[Num]);
end;
CloseFile(Data);
If StrToInt(Edit1.Text) > Num + 1 then Exit;
For I1 := 1 to C do
begin
Itm:= ListArra[I1-1];
for I2 := 1 to Length(Itm) do
begin
D := StrToInt(Itm[I2]);
Form1.Listbox2.Items.Add(FName[D-1]);
end;
Form1.Listbox2.Items.add (' '); //a blank separator
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Application.Terminate;
end;
Yes indeed, the difficultness can be considered as function of preparedness. Honestly, I was nearly going to give up to provide a solution as I haven't done this kind of maths a few years now, but somehow I'd like to find a solution primarily to see whether I still can it :-)
Well, finally you got what you needed and that is what counts.
Ciao, Mike
0
Featured Post
A positive customer journey is important in attracting and retaining business. To improve this experience, you can use Google Maps APIs to increase checkout conversions, boost user engagement, and optimize order fulfillment. Learn how in this webinar presented by Dito.