From 882f51057d5cdca3d559eb2451b7fe7b369af3c5 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sat, 30 Oct 2021 23:52:13 +1100 Subject: [PATCH] Add tower models --- 90 Tower/csharp/Tower/Models/Needle.cs | 31 +++++++++++++ 90 Tower/csharp/Tower/Models/Towers.cs | 60 ++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 90 Tower/csharp/Tower/Models/Needle.cs create mode 100644 90 Tower/csharp/Tower/Models/Towers.cs diff --git a/90 Tower/csharp/Tower/Models/Needle.cs b/90 Tower/csharp/Tower/Models/Needle.cs new file mode 100644 index 00000000..e373efe9 --- /dev/null +++ b/90 Tower/csharp/Tower/Models/Needle.cs @@ -0,0 +1,31 @@ +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace Tower.Models +{ + internal class Needle : IEnumerable + { + private readonly Stack _disks = new Stack(); + + 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 GetEnumerator() => + Enumerable.Repeat(1, 7 - _disks.Count).Concat(_disks).GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } +} \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Models/Towers.cs b/90 Tower/csharp/Tower/Models/Towers.cs new file mode 100644 index 00000000..830fa631 --- /dev/null +++ b/90 Tower/csharp/Tower/Models/Towers.cs @@ -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> _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()); + } + } +} \ No newline at end of file