user1484634
user1484634

Reputation: 13

Combination without Repetition using powershell?

I am new in powershell but was wondering how do you get combination of given numbers without repetition ?

for e.g

$a = (1,2,3,4)
$n = 4
$k = 2

output :-

12
13
14
23
24
34

if K = 3 then

123
124
134
234

Upvotes: 1

Views: 1727

Answers (3)

Jon
Jon

Reputation: 1

I thought of this as binary strings with 1's and 0's, generated each binary string from 1 to Length of the array, and then use the value at the same index if there is a 1.

$items = 1,2,3,4;
$k = 3;

$output = @();
for ($i = 1; $i -lt [Math]::Pow(2, $items.Count); $i++) {
    $binary = [Convert]::ToString($i, 2).PadLeft($items.Count, "0");

    # if number of 1's in the entire string is not equal to "1" * $k, then skip
    if (($binary -replace "0", "") -ne ("1" * $k)) {
        continue;
    }

    #foreach char in binary
    $outputSet = @()
    $outputSet += $items | ForEach-Object {
        if ($binary[$items.IndexOf($_)] -eq "1") {
            $_
        }
    }
    $output += [PSCustomObject]@{
        Set = $outputSet;
        Binary = $binary;
        Count = $outputSet.Count;
        Concatenated = $outputSet -join "";
    }
}

$output | Sort-Object -Property Count, Set


#SAMPLE OUTPUT
Set       Binary Count Concatenated
---       ------ ----- ------------
{1, 2, 3} 1110       3 123
{1, 2, 4} 1101       3 124
{1, 3, 4} 1011       3 134
{2, 3, 4} 0111       3 234

Upvotes: 0

JPBlanc
JPBlanc

Reputation: 72610

You can try this :

$List = "A","B","C","D","E","F","G","H"
$k = 3

Add-Type @"
public class Shift {
     public static int   Right(int x,   int count) { return x >> count; }
     public static uint  Right(uint x,  int count) { return x >> count; }
     public static long  Right(long x,  int count) { return x >> count; }
     public static ulong Right(ulong x, int count) { return x >> count; }
     public static int    Left(int x,   int count) { return x << count; }
     public static uint   Left(uint x,  int count) { return x << count; }
     public static long   Left(long x,  int count) { return x << count; }
     public static ulong  Left(ulong x, int count) { return x << count; }
  }                    
"@

function CombinationWithoutRepetition ([int]$k, $List)
{
  Function IsNBits ([long]$value, $k, $length)
  {
    $count = 0
    for ($i = 0 ; $i -le $length ; $i++)
    {
      if ($value -band 1)
      {
        $count++
      }
      $value = [shift]::Right($value,1)
    }

    if ($count -eq $k)
    {
      return $true
    }
    else
    {
      return $false
    }
  }

  Function BitsToArray ([long]$value, $List)
  {
    $res = @()
    for ($i = 0 ; $i -le $List.length ; $i++)
    {
      if ($value -band 1)
      {
        $res += $List[$i]
      }
      $value = [shift]::Right($value,1)
    }  

    return ,$res
  }

  [long]$i = [Math]::Pow(2, $List.Length)
  $res = @()
  for ([long]$value=0 ; $value -le $i ; $value++)
  {
    if ((IsNBits $value $k $List.Length) -eq $true)
    {
      #write-host $value
      $res += ,(BitsToArray $value $List)
    }
  }
  return ,$res
}

Clear-Host
$res = CombinationWithoutRepetition $k $List
$res.count
$res | %{$_ |% {}{Write-Host -NoNewline $_}{Write-Host ""}}

Upvotes: 0

BartekB
BartekB

Reputation: 8650

Just a quick solution for that particular case, I don't see much value in it because I feel there are tools designed for such exercises... ;)

$a = (1,2,3,4)

$rest = New-Object Collections.ArrayList
$a[1..($a.Length - 1)] | foreach { $rest.Add($_) | Out-Null }

$prefix = $a[0]

$(while ($rest) {
    foreach ($suffix in $rest) {
        -join ($prefix, $suffix)
    }
    $prefix = $rest[0]
    $rest.RemoveAt(0)
}) -join ', '

Upvotes: 1

Related Questions