Add tower models

This commit is contained in:
Andrew Cooper
2021-10-30 23:52:13 +11:00
parent db11f064e9
commit 882f51057d
2 changed files with 91 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Tower.Models
{
internal class Needle : IEnumerable<int>
{
private readonly Stack<int> _disks = new Stack<int>();
public int Top => _disks.TryPeek(out var disc) ? disc : default;
public bool TryPut(int disc)
{
if (_disks.Count == 0 || disc < _disks.Peek())
{
_disks.Push(disc);
return true;
}
return false;
}
public bool TryGetTopDisk(out int disk) => _disks.TryPop(out disk);
public IEnumerator<int> GetEnumerator() =>
Enumerable.Repeat(1, 7 - _disks.Count).Concat(_disks).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}

View File

@@ -0,0 +1,60 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Tower.Models
{
internal class Towers : IEnumerable<(int, int, int)>
{
private readonly Needle[] _needles = new[] { new Needle(), new Needle(), new Needle() };
public bool TryFindDisk(int disk, out int needle)
{
for (needle = 1; needle <= 3; needle++)
{
if (_needles[needle].Top == disk) { return true; }
}
return false;
}
public bool TryMoveDisk(int from, int to)
{
if (!_needles[from].TryGetTopDisk(out var disk))
{
throw new InvalidOperationException($"Needle {from} is empty");
}
if (_needles[to].TryPut(disk)) { return true; }
_needles[from].TryPut(disk);
return false;
}
public IEnumerator<(int, int, int)> GetEnumerator() => new TowersEnumerator(_needles);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
private class TowersEnumerator : IEnumerator<(int First, int Second, int Third)>
{
private readonly List<IEnumerator<int>> _enumerators;
public TowersEnumerator(Needle[] needles)
{
_enumerators = needles.Select(n => n.GetEnumerator()).ToList();
}
public (int First, int Second, int Third) Current =>
(_enumerators[0].Current, _enumerators[1].Current, _enumerators[2].Current);
object IEnumerator.Current => Current;
public void Dispose() => _enumerators.ForEach(e => e.Dispose());
public bool MoveNext() => _enumerators.All(e => e.MoveNext());
public void Reset() => _enumerators.ForEach(e => e.Reset());
}
}
}