Sziasztok,
Elsősorban PowerShell-ben szeretném megoldani az alábbi feladatot - de lassan ott járok bármi jó lesz:
Adottak:
tömb1: { "Egyes", "Kettes", "Hármas", "Négyes", "Ötös" }
tömb2: { "Alma", "Körte", "Dinnye" }
tömb3: { "Virág", "Kert", "Ásó", "Szilva", "Tök" }
tömb4: { "Valami", "Valami2", "Valami3" }
- Amint látható, mind a négy tömb változó méretű
- mind string lesz egyébként
- Term. nem ezekkel az adatokkal, ékezetekkel és változónevekkel persze.
A kérdés amit meg szeretnék oldani:
- Létrehozni egy n elemű tömböt, amely tömb mindegyik tömb legalább egy elemét a fentinek tartalmazza, de tömb3 elemei többször is szerepelhetnek.
Tehát pl. lehetséges az, hogy az egyik megoldás: { "Egyes", "Dinnye", "Virág", "Kert", "Tök", "Valami2" } - azaz csak a tömb3 elemei szerepelhetnek többször mint 1, a többi csak egyszer, de legalább egyszer szerepelj.
A C#-ban rátaláltam én a CartesianProduct class definíciójára, néztem is már, de kissé vakartam a fejem a feltétel és a nem egyező méret miatt
Valakinek van-e erre ötlete?
- 909 megtekintés
Hozzászólások
Nos egy olyan tömböt (listát) szeretnék létrehozni ami az összes lehetőséget permutációként tartalmazza, amit írtál az egyenként kiírja ugyan az eredményt de valamelyest ennél pragmatikusabban oldanám meg a feladatot.
Küldök egy kódrészletet amiben a több tömb permutálására egy jó példát hozott a CartesianProduct class és ahogy említettem felhasználtam C#-ban a példa illusztrálására.
Ezzel csak az a baj, hogy ez minden elemet egyszer használ fel, tehát a harmadik elemek csak egyszer kerülnek bele. Persze ennyi elemnél kézzel megcsinálhatnám az összes lehetőséget, az elég csúnya megoldás lenne.
Ráadásul ez a CartesianProduct C#-ban van és bár a .NET libeket lehet használni PowerShell alatt, megnehezítené a dolgokat ha forrást kéne buildezni és követni mondjuk hogy melyik VS-el buildezte az ember, stb., ennyiből jóval egyszerűbb lenne PSben.
Kód:
static void Main(string[] args)
{
var full = new CartesianProduct(
new string[] { "Egyes", "Kettes", "Harmas", "Negyes", "Otos", "Hatos"}
, new string[] { "Alma", "Korte", "Dinnye", "Cseresznye", "Szolo" }
, new string[] { "Virag", "Kert", "Aso", "Szilva", "Tok" }
, new string[] { "Valami", "Valami2", "Valami3" }
);
foreach (var i in full.Get())
{
List possibles = new List();
possibles.Add(i[0]);
possibles.Add(i[1]);
possibles.Add(i[2]);
possibles.Add(i[3]);
var possiblesArray = possibles.ToArray();
foreach (string c in possiblesArray)
{
Console.Write(c.ToString());
Console.Write(" ");
}
Console.WriteLine();
}
Console.ReadLine();
}
}
A CartesianProduct:
public class CartesianProduct
{
int[] lengths;
T[][] arrays;
public CartesianProduct(params T[][] arrays)
{
lengths = arrays.Select(k => k.Length).ToArray();
if (lengths.Any(l => l == 0))
throw new ArgumentException("Zero lenght array unhandled.");
this.arrays = arrays;
}
public IEnumerable Get()
{
int[] walk = new int[arrays.Length];
int x = 0;
yield return walk.Select(k => arrays[x++][k]).ToArray();
while (Next(walk))
{
x = 0;
yield return walk.Select(k => arrays[x++][k]).ToArray();
}
}
private bool Next(int[] walk)
{
int whoIncrement = 0;
while (whoIncrement < walk.Length)
{
if (walk[whoIncrement] < lengths[whoIncrement] - 1)
{
walk[whoIncrement]++;
return true;
}
else
{
walk[whoIncrement] = 0;
whoIncrement++;
}
}
return false;
}
}
- A hozzászóláshoz be kell jelentkezni
lehet ilyet is, ha lusta vagy...
$Assem = (
…add referenced assemblies here…
)
$Source = @”
…add C# source code here…
“@
Add-Type -ReferencedAssemblies $Assem -TypeDefinition $Source -Language CSharp
- A hozzászóláshoz be kell jelentkezni
"Létrehozni egy n elemű tömböt, amely tömb mindegyik tömb legalább egy elemét a fentinek tartalmazza, de tömb3 elemei többször is szerepelhetnek."
Íme:
PS > $tömb1[0], $tömb2[0], $tömb3[0], $tömb4[0]
Egyes
Alma
Virág
Valami
PS >
Szerintem pontosítsd, mit szeretnél, mert ez pontosan megfelel annak, amit kértél, de aligha ez volt a fejedben a feladvány.
Ez például véletlenszerűen állít elő egy, a fenti feltételeknek megfelelő tömböt:
(Get-Random -InputObject $tömb1), (Get-Random -InputObject $tömb2), (Get-Random -InputObject $tömb3 -Count (Get-Random -Minimum 1 -Maximum $tömb3.Count)), (Get-Random -InputObject $tömb4)
Üdv,
Marci
- A hozzászóláshoz be kell jelentkezni
Ami ebben érdekes, az az összes nemnulla részhalmaz generálása, például ennek alapján megoldható: http://stackoverflow.com/questions/936015/an-algorithm-to-generate-subs…
Üdv,
Marci
- A hozzászóláshoz be kell jelentkezni
Ezt keresed?
Function Generate-Subsets ($set)
{
$subsets=@()
for ($i=1;$i -lt [math]::pow(2,$set.Count);$i++)
{
$mask=[convert]::ToString($i,2)
$ss=@()
for ($j=0;$j -lt $mask.Length;$j++)
{
if ($mask[$j] -eq "1")
{
$ss+=$set[$mask.Length-$j-1]
}
}
$subsets+=,$ss
}
return $subsets
}
$tömb1= "Egyes", "Kettes", "Hármas", "Négyes", "Ötös"
$tömb2= "Alma", "Körte", "Dinnye"
$tömb3= "Virág", "Kert", "Ásó", "Szilva", "Tök"
$tömb4= "Valami", "Valami2", "Valami3"
foreach ($i1 in $tömb1)
{
foreach ($i2 in $tömb2)
{
foreach ($i3 in Generate-Subsets($tömb3))
{
foreach ($i4 in $tömb4)
{
$items=$i3
$items+=$i1,$i2,$i4
$items -join ","
}
}
}
}
Üdv,
Marci
- A hozzászóláshoz be kell jelentkezni
Szia!
Igen, erre gondoltam, ez egy jó megoldás, bár most épp azon szórakozom hogy na és akkor ezt hogyan rendezem mondjuk $tömb1 alapján, mivelhogy a $tömb3 néha 2, vagy akár 3 elem is lehet, nem mondhatom hogy akkor mindig rendezem a $item-et 2. elem alapján, mivel néha a 2. az épp tömb3-nak lesz egyik permutációja.
Arra gondoltam, hogy megszámolhatnám hogy hány elemű a subset előbb, majd utána a megfelelő column-ra hivatkoznék, ami mondjuk mindig igaz lesz hogy +1 mint ahány elemű a $tömb3 subset-je. Hmm?
- A hozzászóláshoz be kell jelentkezni
Pontosítsd előbb, kérlek, a rendezési elvárásokat!
Mi alapján kell rendezni a listát?
Ha a 3. tömb részhalmaza alapján is kell, ott mi a rendezési függvény?
Üdv,
Marci
- A hozzászóláshoz be kell jelentkezni
Köszi a segítséget, sikerült megoldanom.
A kód alapján amit küldtél, a rendezési elv $i4 alapján történt volna. Minekutána $i3 viszont több értéket is felvehet, $items[1] vagy $items[2] stb. nem minden esetben stimmelt volna, amire a rendezés épülhetne - ezért ahogy ötleteltem, gyakorlatilag külön függvénybe tettem a subset generálást ami visszaadja azt a subset-et amit $i3-ból készítünk először; ennek a returned value-nak megmértem a hosszát (mondjuk legyen ez $pLength) és gyakorlatilag ahhoz igazítom dinamikusan hogy $items[$pLength] hogy hol helyezkedik el $i3.
Ezzel rendeztem $i3 alapján így:
$blah = $items[$pLength]
majd amikor kiírom, ennyit adtam hozzá - a vesszőt a későbbi file-ba kiírt elemzés miatt három pipe-ra cseréltem.
$items -join " ||| " | Sort | ForEach-Object{$blah + " " + $_}
Ha érdekel szívesen elküldöm az egészet!
- A hozzászóláshoz be kell jelentkezni
Szívesen!
Üdv,
Marci
- A hozzászóláshoz be kell jelentkezni
Nagyon egyszerű.
Mivel csak a tömb3 többelemű, ezért:
- tömb1 alapján rendezi: az első elem szerint rendezni.
- tömb2 alapján rendezni: a második elem szerint rendezni
- tömb3 alapján rendezni: a harmadiktól utolsó előtti elem szerint rendezni
- tömb4 alapján rendezni: az utolsó elem szerint rendezni
Mindig pontosan definiált, hogy melyik elem melyik tömbből jön.
- A hozzászóláshoz be kell jelentkezni
LINQ-val tudsz Descartes-szorzatot csinálni.
Annyi a trükk, hogy kell egy új tömb3' tömb, aminek az elemei az eredeti tömb3 nemüres részhalmazai.
Példa LINQ-val:
http://stackoverflow.com/questions/4073713/is-there-a-good-linq-way-to-…
LINQ-t pedig tudsz hívni PowerShellből.
- A hozzászóláshoz be kell jelentkezni
Szerintem sem világos mit szeretnél pontosan, egy ilyet írtam:
- A hozzászóláshoz be kell jelentkezni