wtorek, 25 lutego 2014

Ref parametry i wieża Hanoi w PowerShellu

Niestety, przekazywanie wartości przez referencję w PS nie jest wskazane. Postanowiłem troszkę poćwiczyć z tym typem danych. Jednym z zadań algorytmicznych, dla którego przydatne jest przekazywanie wartości przez referencje jest problem wieży Hanoi. Postanowiłem rozwiązać ten problem za pomocą obiektu z .NET. Stwórzmy klasę, która będzie reprezentowała stan wieży:
$HanoiRodsClassDefinition = @"
using System.Collections.Generic;
using System.Linq;

public class HanoiRods
{
    public List<int> RotA;
    public List<int> RotB;
    public List<int> RotC;
    public HanoiRods (int spots=1)
    {
        RotA =  Enumerable.Range(0,spots).ToList();
        RotB= new List<int>();
        RotC= new List<int>();
    }

    public int GetSpots()
    {
        return RotA.Count;
    }

    public HanoiRods New( List<int> rotA,  List<int> rotB, List<int> rotC)
    {
        return new HanoiRods{
        RotA = rotA,
        RotB = rotB,
        RotC = rotC,
        };
    }
}
"@

Aby dodać definicję klasy do PS to wystarczy:
Add-Type -Language CSharp -TypeDefinition $HanoiRodsClassDefinition

A sam algorytm rozwiązywania wieży Hanoi w PS jest następujący:
function Solve-Hanoi
{
    param(
    [Parameter(Mandatory=$true)]
    [HanoiRods]$rots,

    [Parameter(Mandatory=$false)]
    [int]$spots=$($rots.GetSpots()),

    [ref]$moves
    )

    if($spots -gt 0)
    {
        
        Solve-Hanoi -spots ($spots-1) -rots ($rots.New($rots.RotA, $rots.RotC, $rots.RotB)) -moves $moves

        $rots.RotC.Insert(0,$rots.RotA[0])
        $rots.RotA.RemoveAt(0)
        $moves.Value  +=1

        Write-Host ""
        Write-Host "Spot $spots"
        Write-Host "A $($rots.RotA)"
        Write-Host "B $($rots.RotB)"
        Write-Host "C $($rots.RotC)"

        Solve-Hanoi -spots  ($spots-1) -rots ($rots.New($rots.RotB, $rots.RotA, $rots.RotC)) -moves $moves
    }
}
Z ciekawych parametrów jest zmienna [ref]$moves, którą przekazujemy przez referencje.

Możemy teraz definiować parametry do rozwiązania wieży Hanoi:
$hanoi = new-object HanoiRods 5
[ref]$moves=0

A same wywołanie jest następujące:
Solve-Hanoi -rots $hanoi -moves $moves
$moves

Dla 5 krążków musimy wykonać 31 ruchów, aby rozwiązać problem wieży Hanoi.

Brak komentarzy:

Prześlij komentarz