From 43ae5ef9a197d11435c7d1ca4c8cd62686e38265 Mon Sep 17 00:00:00 2001 From: Thomas Vuille Date: Thu, 16 Dec 2021 11:43:38 +0100 Subject: [PATCH] domain content only Algorithm --- TowerOfHanoi.Domain/TowerOfHanoi.cs | 61 +++----- TowerOfHanoi.Test/TowerOfHanoiMoveShould.cs | 144 ++++++++++-------- TowerOfHanoi.UI.Console/Program.cs | 1 - .../TowerOfHanoiObserver.cs | 3 +- 4 files changed, 103 insertions(+), 106 deletions(-) diff --git a/TowerOfHanoi.Domain/TowerOfHanoi.cs b/TowerOfHanoi.Domain/TowerOfHanoi.cs index a3cdf7c..40e4856 100644 --- a/TowerOfHanoi.Domain/TowerOfHanoi.cs +++ b/TowerOfHanoi.Domain/TowerOfHanoi.cs @@ -4,41 +4,36 @@ namespace TowerOfHanoi.Domain; public class TowerOfHanoi : IObservable[]> { - private const string LevelSeparator = " - "; - private const string PlaceSeparator = " / "; - private static readonly Dictionary Places = new() { { 0, 'A' }, { 1, 'B' }, { 2, 'C' } }; - - private readonly Stack[] _levels = new Stack[3]; private static readonly int[] PlaceIndexes = { 0, 1, 2 }; + public Stack[] Levels { get; } = new Stack[3]; + private int _moveNumber; private readonly List[]>> _observers = new(); public TowerOfHanoi(int levelNumber) { - _levels[0] = new Stack(); - for (var currentLevel = levelNumber - 1; currentLevel >= 0; currentLevel--) _levels[0].Push(currentLevel); - _levels[1] = new Stack(); - _levels[2] = new Stack(); + Levels[0] = new Stack(); + for (var currentLevel = 0; currentLevel < levelNumber; currentLevel++) Levels[0].Push(currentLevel); + Levels[1] = new Stack(); + Levels[2] = new Stack(); } - public TowerOfHanoi(Stack levelsInA, Stack levelsInB, Stack levelsInC) + public TowerOfHanoi(IEnumerable levelsInA, IEnumerable levelsInB, IEnumerable levelsInC) { - _moveNumber = 0; - _levels[0] = levelsInA; - _levels[1] = levelsInB; - _levels[2] = levelsInC; + Levels[0] = new Stack(levelsInA); + Levels[1] = new Stack(levelsInB); + Levels[2] = new Stack(levelsInC); } - - - public void MoveLevels() => Move(_levels[0].Count, 0, 2); + + public void MoveLevels() => Move(Levels[0].Count, 0, 2); public void Move(int startPlaceIndex, int endPlaceIndex) { Console.WriteLine(this); - Move(_levels[0].Count, startPlaceIndex, endPlaceIndex); + Move(Levels[0].Count, startPlaceIndex, endPlaceIndex); } public void Move(int levelNumber, int startPlaceIndex, int endPlaceIndex) @@ -46,9 +41,8 @@ public void Move(int levelNumber, int startPlaceIndex, int endPlaceIndex) if (levelNumber == 1) { _moveNumber++; - var levelToMove = _levels[startPlaceIndex].Pop(); - _levels[endPlaceIndex].Push(levelToMove); - foreach (var observer in _observers) observer.OnNext(_levels); + Levels[endPlaceIndex].Push(Levels[startPlaceIndex].Pop()); + foreach (var observer in _observers) observer.OnNext(Levels); return; } @@ -65,31 +59,12 @@ public void Move(int levelNumber, int startPlaceIndex, int endPlaceIndex) Move(1, startPlaceIndex, endPlaceIndex); Move(levelNumber - 1, sidingPlaceIndex, endPlaceIndex); } - - public override string ToString() - { - var levelBuilder = new StringBuilder(); - levelBuilder.Append($"Move {_moveNumber} "); - for (var i = 0; i < _levels.Length; i++) levelBuilder.Append(PlaceToString(_levels[i], Places[i])); - var levelString = levelBuilder.ToString(); - levelString = PlaceSeparator.Aggregate(levelString, (current, separator) => current.TrimEnd(separator)); - return levelString; - } - - private static string PlaceToString(Stack levelStack, char placeName) - { - if (levelStack.Count == 0) return string.Empty; - var levelBuilder = new StringBuilder(); - levelBuilder.Append($"place {placeName}: "); - foreach (var level in levelStack) levelBuilder.Append(level + LevelSeparator); - levelBuilder.Remove(levelBuilder.Length - LevelSeparator.Length, LevelSeparator.Length); - levelBuilder.Append(PlaceSeparator); - return levelBuilder.ToString(); - } public IDisposable Subscribe(IObserver[]> observer) { - if (!_observers.Contains(observer)) _observers.Add(observer); + if (_observers.Contains(observer)) return new Unsubscriber(_observers, observer); + _observers.Add(observer); + observer.OnNext(Levels); return new Unsubscriber(_observers, observer); } diff --git a/TowerOfHanoi.Test/TowerOfHanoiMoveShould.cs b/TowerOfHanoi.Test/TowerOfHanoiMoveShould.cs index 8102faa..8fe505d 100644 --- a/TowerOfHanoi.Test/TowerOfHanoiMoveShould.cs +++ b/TowerOfHanoi.Test/TowerOfHanoiMoveShould.cs @@ -1,100 +1,124 @@ using Shouldly; using System.Collections.Generic; using Xunit; +// ReSharper disable CollectionNeverUpdated.Local namespace TowerOfHanoi.Test; public class TowerOfHanoiMoveShould { + private Stack _stackA = new(); + private Stack _stackB = new(); + private Stack _stackC = new(); + + private void FillStacks(IEnumerable levelsA, IEnumerable levelsB, IEnumerable levelsC) + { + _stackA = new Stack(levelsA); + _stackB = new Stack(levelsB); + _stackC = new Stack(levelsC); + } + [Fact] - public void Return1PlaceCWhenMoveOnly1LevelFrom0to2() + public void Return0Place2WhenMoveOnly0LevelFrom0to2() { - var stackA = new Stack(); - stackA.Push(1); - var stackB = new Stack(); - var stackC = new Stack(); - var towerOfHanoi = new Domain.TowerOfHanoi(stackA, stackB, stackC); - towerOfHanoi.Move(1,0,2); - towerOfHanoi.ToString().ShouldBe("Move 1 place C: 1"); + var levelsA = new List { 0 }; + var levelsB = new List(); + var levelsC = new List(); + + FillStacks(levelsA, levelsB, levelsC); + var stacksExpected = new[] {_stackC, _stackB, _stackA}; + var towerOfHanoi = new Domain.TowerOfHanoi(levelsA, levelsB, levelsC); + towerOfHanoi.Move(1, 0, 2); + towerOfHanoi.Levels.ShouldBe(stacksExpected); } + + [Fact] - public void Return1PlaceBWhenMoveOnly1LevelFrom0to1() + public void Return0Place1WhenMoveOnly0LevelFrom0to1() { - var stackA = new Stack(); - stackA.Push(1); - var stackB = new Stack(); - var stackC = new Stack(); - var towerOfHanoi = new Domain.TowerOfHanoi(stackA, stackB, stackC); + var levelsA = new List { 0 }; + var levelsB = new List(); + var levelsC = new List(); + + FillStacks(levelsA, levelsB, levelsC); + var stacksExpected = new[] { _stackB, _stackA, _stackC }; + var towerOfHanoi = new Domain.TowerOfHanoi(levelsA, levelsB, levelsC); towerOfHanoi.Move(1, 0, 1); - towerOfHanoi.ToString().ShouldBe("Move 1 place B: 1"); + towerOfHanoi.Levels.ShouldBe(stacksExpected); } [Fact] - public void Return1PlaceCWhenMoveOnly1LevelFrom1to2() + public void Return0Place2WhenMoveOnly0LevelFrom1to2() { - var stackA = new Stack(); - var stackB = new Stack(); - stackB.Push(1); - var stackC = new Stack(); - var towerOfHanoi = new Domain.TowerOfHanoi(stackA, stackB, stackC); + var levelsA = new List(); + var levelsB = new List { 0 }; + var levelsC = new List(); + + FillStacks(levelsA, levelsB, levelsC); + var stacksExpected = new[] { _stackA, _stackC, _stackB }; + + var towerOfHanoi = new Domain.TowerOfHanoi(levelsA, levelsB, levelsC); towerOfHanoi.Move(1, 1, 2); - towerOfHanoi.ToString().ShouldBe("Move 1 place C: 1"); + towerOfHanoi.Levels.ShouldBe(stacksExpected); } [Fact] - public void Return1PlaceAWhenMoveOnly1LevelFrom1to0() + public void Return0Place0WhenMoveOnly0LevelFrom1to0() { - var stackA = new Stack(); - var stackB = new Stack(); - stackB.Push(1); - var stackC = new Stack(); - var towerOfHanoi = new Domain.TowerOfHanoi(stackA, stackB, stackC); + var levelsA = new List(); + var levelsB= new List { 0 }; + var levelsC = new List(); + + FillStacks(levelsA, levelsB, levelsC); + var stacksExpected = new[] { _stackB, _stackA, _stackC }; + + var towerOfHanoi = new Domain.TowerOfHanoi(levelsA, levelsB, levelsC); towerOfHanoi.Move(1, 1, 0); - towerOfHanoi.ToString().ShouldBe("Move 1 place A: 1"); + towerOfHanoi.Levels.ShouldBe(stacksExpected); } [Fact] - public void Return1And2PlaceCWhenMove1And2From0To2() + public void Return0And1Place2WhenMove0And1From0To2() { - var stackA = new Stack(); - stackA.Push(2); - stackA.Push(1); - var stackB = new Stack(); - var stackC = new Stack(); - var towerOfHanoi = new Domain.TowerOfHanoi(stackA, stackB, stackC); - towerOfHanoi.ToString().ShouldBe("Move 0 place A: 1 - 2"); - towerOfHanoi.Move( 0, 2); - towerOfHanoi.ToString().ShouldBe("Move 3 place C: 1 - 2"); + var levelsA = new List { 0, 1 }; + var levelsB = new List(); + var levelsC = new List(); + + FillStacks(levelsA, levelsB, levelsC); + var stacksExpected = new[] { _stackC, _stackB, _stackA }; + + var towerOfHanoi = new Domain.TowerOfHanoi(levelsA, levelsB, levelsC); + towerOfHanoi.Move(0, 2); + towerOfHanoi.Levels.ShouldBe(stacksExpected); } [Fact] - public void Return1And2And3PlaceCWhenMove1And2And3From0To2() + public void Return0And1And2Place2WhenMove0And1And2From0To2() { - var stackA = new Stack(); - stackA.Push(3); - stackA.Push(2); - stackA.Push(1); - var stackB = new Stack(); - var stackC = new Stack(); - var towerOfHanoi = new Domain.TowerOfHanoi(stackA, stackB, stackC); - towerOfHanoi.ToString().ShouldBe("Move 0 place A: 1 - 2 - 3"); + var levelsA = new List { 0, 1, 2 }; + var levelsB = new List(); + var levelsC = new List(); + + FillStacks(levelsA, levelsB, levelsC); + var stacksExpected = new[] { _stackC, _stackB, _stackA }; + + var towerOfHanoi = new Domain.TowerOfHanoi(levelsA, levelsB, levelsC); towerOfHanoi.Move(0, 2); - towerOfHanoi.ToString().ShouldBe("Move 7 place C: 1 - 2 - 3"); + towerOfHanoi.Levels.ShouldBe(stacksExpected); } [Fact] - public void Return1To4PlaceCWhenMove1To4From0To2() + public void Return0To3Place2WhenMove0To3From0To2() { - var stackA = new Stack(); - stackA.Push(4); - stackA.Push(3); - stackA.Push(2); - stackA.Push(1); - var stackB = new Stack(); - var stackC = new Stack(); - var towerOfHanoi = new Domain.TowerOfHanoi(stackA, stackB, stackC); - towerOfHanoi.ToString().ShouldBe("Move 0 place A: 1 - 2 - 3 - 4"); + var levelsA = new List { 0, 1, 2, 3 }; + var levelsB = new List(); + var levelsC = new List(); + + FillStacks(levelsA, levelsB, levelsC); + var stacksExpected = new[] { _stackC, _stackB, _stackA }; + + var towerOfHanoi = new Domain.TowerOfHanoi(levelsA, levelsB, levelsC); towerOfHanoi.Move(0, 2); - towerOfHanoi.ToString().ShouldBe("Move 15 place C: 1 - 2 - 3 - 4"); + towerOfHanoi.Levels.ShouldBe(stacksExpected); } } \ No newline at end of file diff --git a/TowerOfHanoi.UI.Console/Program.cs b/TowerOfHanoi.UI.Console/Program.cs index 69eb962..58626f3 100644 --- a/TowerOfHanoi.UI.Console/Program.cs +++ b/TowerOfHanoi.UI.Console/Program.cs @@ -3,7 +3,6 @@ var towerOfHanoi = new TowerOfHanoi.Domain.TowerOfHanoi(6); var towerOfHanoiLevelsObserver = new TowerOfHanoiObserver(); - towerOfHanoiLevelsObserver.Subscribe(towerOfHanoi); towerOfHanoi.MoveLevels(); towerOfHanoiLevelsObserver.OnCompleted(); \ No newline at end of file diff --git a/TowerOfHanoi.UI.Console/TowerOfHanoiObserver.cs b/TowerOfHanoi.UI.Console/TowerOfHanoiObserver.cs index da7eb1d..1a2f7d6 100644 --- a/TowerOfHanoi.UI.Console/TowerOfHanoiObserver.cs +++ b/TowerOfHanoi.UI.Console/TowerOfHanoiObserver.cs @@ -27,9 +27,8 @@ public void OnError(Exception error) public void OnNext(Stack[] value) { - _moveNumber++; var levelBuilder = new StringBuilder(); - levelBuilder.Append($"Move {_moveNumber} "); + levelBuilder.Append($"Move {_moveNumber++} "); for (var i = 0; i < value.Length; i++) levelBuilder.Append(PlaceToString(value[i], Places[i])); var levelString = levelBuilder.ToString(); levelString = PlaceSeparator.Aggregate(levelString, (current, separator) => current.TrimEnd(separator));