Reputation: 13
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
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
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
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