combination without repetition of N elements without use for..to..do

前端 未结 6 1225
野的像风
野的像风 2020-12-29 11:08

i want load in a list the combination of N number without repetition, giving to input the elements and group. For example, with 4 elements [1,2,3,4], i have for:

<         


        
6条回答
  •  北荒
    北荒 (楼主)
    2020-12-29 11:24

    Here's a rather fun solution reliant on bitsets. As it stands it's limited to sets of size not greater than 32. I don't think that's a practical limitation since there are a lot of subsets for a set of cardinality greater than 32.

    The output is not in the order that you want, but that would be easy enough to remedy if it matters to you.

    program VisitAllSubsetsDemo;
    
    {$APPTYPE CONSOLE}
    
    procedure PrintBitset(Bitset: Cardinal; Size: Integer);
    var
      i: Integer;
      Mask: Cardinal;
      SepNeeded: Boolean;
    begin
      SepNeeded := False;
      Write('{');
      for i := 1 to Size do begin
        Mask := 1 shl (i-1);
        if Bitset and Mask<>0 then begin
          if SepNeeded then begin
            Write(',');
          end;
          Write(i);
          SepNeeded := True;
        end;
      end;
      Writeln('}');
    end;
    
    procedure EnumerateSubsets(Size: Integer);
    var
      Bitset: Cardinal;
    begin
      for Bitset := 0 to (1 shl Size)-1 do begin
        PrintBitset(Bitset, Size);
      end;
    end;
    
    begin
      EnumerateSubsets(4);
    end.
    

    Output

    {}
    {1}
    {2}
    {1,2}
    {3}
    {1,3}
    {2,3}
    {1,2,3}
    {4}
    {1,4}
    {2,4}
    {1,2,4}
    {3,4}
    {1,3,4}
    {2,3,4}
    {1,2,3,4}
    

    And here is a variant that just lists the subsets of a specified cardinality:

    function SetBitCount(Bitset: Cardinal; Size: Integer): Integer;
    var
      i: Integer;
      Mask: Cardinal;
    begin
      Result := 0;
      for i := 1 to Size do begin
        Mask := 1 shl (i-1);
        if Bitset and Mask<>0 then begin
          inc(Result);
        end;
      end;
    end;
    
    procedure EnumerateSubsets(Size, NumberOfSetBits: Integer);
    var
      Bitset: Cardinal;
    begin
      for Bitset := 0 to (1 shl Size)-1 do begin
        if SetBitCount(Bitset, Size)=NumberOfSetBits then begin
          PrintBitset(Bitset, Size);
        end;
      end;
    end;
    
    begin
      EnumerateSubsets(4, 2);
    end.
    

    Output

    {1,2}
    {1,3}
    {2,3}
    {1,4}
    {2,4}
    {3,4}
    

提交回复
热议问题