Solving Towers of Hanoi in C# using recursion - c#

I'm facing the Towers of Hanoi problem, I read the concept and the recursive way of solving it from wikipedia, but I can not see what I'm missing in the implementation of the steps mentioned in wikipedia.
I have seen many examples here but I don't want my program to print the steps, I want the program solves the problem moving the "discs" between 3 collections, in my code I'm using 3 Stacks to simulate the pegs.
Here is my current code:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main(string[] args)
{
var hs = new HanoiSolver(discs: 3);
hs.Solve();
Console.ReadKey();
}
}
class HanoiSolver
{
private int TotalDiscs { get; set; } = 0;
private Stack<int> FirstPeg { get; set; } = new Stack<int>();
private Stack<int> SecondPeg { get; set; } = new Stack<int>();
private Stack<int> ThirdPeg { get; set; } = new Stack<int>();
public HanoiSolver(int discs = 3)
{
TotalDiscs = discs;
//Create list of items (discs)
var discList = Enumerable.Range(1, TotalDiscs).Reverse();
//Add items (discs) to first peg
foreach (var d in discList)
{
FirstPeg.Push(d);
}
}
public void Solve()
{
if (ThirdPeg.Count != TotalDiscs)
{
PrintPegs();
//Move first item from firstpeg to secondpeg
if (FirstPeg.Any())
{
var fp_f = FirstPeg.Pop();
SecondPeg.Push(fp_f);
}
PrintPegs();
//Move second item from firstpeg to thirdpeg
if (FirstPeg.Any())
{
var fp_s = FirstPeg.Pop();
ThirdPeg.Push(fp_s);
}
PrintPegs();
//Move first item from secondpeg to thirdpeg
if (SecondPeg.Any())
{
var sp_f = SecondPeg.Pop();
ThirdPeg.Push(sp_f);
}
PrintPegs();
Solve();
}
}
private void PrintPegs()
{
var fp = FirstPeg.Select(x => x.ToString()).ToList();
if (fp.Count < TotalDiscs)
{
fp.AddRange(Enumerable.Repeat(string.Empty, (TotalDiscs - fp.Count)));
}
var sp = SecondPeg.Select(x => x.ToString()).ToList();
if (sp.Count < TotalDiscs)
{
sp.AddRange(Enumerable.Repeat(string.Empty, (TotalDiscs - sp.Count)));
}
var tp = ThirdPeg.Select(x => x.ToString()).ToList();
if (tp.Count < TotalDiscs)
{
tp.AddRange(Enumerable.Repeat(string.Empty, (TotalDiscs - tp.Count)));
}
Console.WriteLine($"{"[First Peg]",10}" + $"{"[Second Peg]",10}" + $"{"[Third Peg]",10}");
for (var i = 0; i < TotalDiscs; i++)
{
Console.WriteLine($"{fp[i],10}" +
$"{sp[i],10}" +
$"{tp[i],10}");
}
}
}

In order to make a recursive method you need one or more base cases where the recursion will end and then one or more recursive calls that break the problem down closer to one of the base cases. For Towers of Hanoi the idea is that moving n discs from Peg A to Peg C is just moving n-1 from Peg A to Peg B, then moving the nth from A to C and finally moving the n-1 discs from C to B. That will eventually get you down to moving no discs which is your base case. That can be done in a recursive method very simply like this.
private static void Move(
int discs,
Stack<int> fromPeg,
Stack<int> toPeg,
Stack<int> otherPeg)
{
if (discs == 0)
{
return;
}
Move(discs - 1, fromPeg, otherPeg, toPeg);
toPeg.Push(fromPeg.Pop());
Move(discs -1, otherPeg, toPeg, fromPeg);
}

When you are implementing TOH, this means you are new to DS and data types. So one must use the data type which is not present in DS like stack and queue. So the below approach is using array.
using System;
using static System.Console;
namespace TOH
{
class Program
{
// Problem statement
//Create an array tower(a) containing all element in ascending order
public static int[] towerSource = new int[] { 1, 3, 5,6,7,9,11,12,13,14,15,16,17};
//solution statement
//we have two more towers with same capacity, tower(b) as auxiliary and tower(c) as destination
public static int[] towerAuxiliary;
public static int[] towerDestination;
public static void CreateTowers()
{
towerAuxiliary = new int[towerSource.Length];
towerDestination = new int[towerSource.Length];
}
public static void Print(int[] tower)
{
for (int i = 0; i < tower.Length; i++)
Write(tower[i].ToString());
WriteLine("--------next run-------------");
}
//start operation
public static void TOH(int numberOfDisks, int[] source,int[] auxiliary,int[] destination)
{
//check if there is only one disk in source
if(numberOfDisks == 1)
{
//move to destination and come out
towerDestination[numberOfDisks-1] = towerSource[numberOfDisks-1];
Print(towerDestination);
return;
}
//move n-1 disks from source to auxiliary
TOH(numberOfDisks - 1, towerSource, towerAuxiliary, towerDestination);
towerDestination[numberOfDisks-1] = towerSource[numberOfDisks-1];
//move nth disc from source to dest
//this is being handeled by if condition
//move n-1 disks from auxiliary to dest
TOH(numberOfDisks - 1, towerAuxiliary, towerSource, towerDestination);
return;
}
static void Main(string[] args)
{
CreateTowers();
TOH(towerSource.Length, towerSource, towerAuxiliary, towerDestination);
}
}
}

Related

ref list isn't modified outside command class

I would like one class to modify the list fields of another class. I pass both list fields as references. The problem is, one list is modified in the end, and second is not. I don't understand why. I wanted to check my idea with a minimal working example, where everything works fine:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _20190424_ref_list_del
{
class Program
{
static void Main(string[] args)
{
ListManager testObj = new ListManager();
testObj.startJob();
}
}
class ListManager
{
private List<int> ListToExpand;
private List<int> ListToShorten;
public ListManager()
{
ListToExpand = new List<int>() { 1, 2, 3 };
ListToShorten = new List<int>() { 1, 2, 3 };
}
public void startJob()
{
EditList editObj = new EditList(ref ListToExpand, ref ListToShorten);
editObj.doJob();
System.Diagnostics.Debug.Print("List to expand:");
foreach (int x in ListToExpand)
{
System.Diagnostics.Debug.Print(x.ToString());
}
System.Diagnostics.Debug.Print("List to shorten:");
foreach (int x in ListToShorten)
{
System.Diagnostics.Debug.Print(x.ToString());
}
}
}
class EditList
{
private List<int> ListToExpand;
private List<int> ListToShorten;
public EditList(ref List<int> listToExpand, ref List<int> listToShorten)
{
ListToExpand = listToExpand;
ListToShorten = listToShorten;
}
public void doJob()
{
ListToExpand.Add(4);
ListToShorten.RemoveAt(0);
}
}
}
The main idea is:
Init two lists
Expand first and shorten another.
Check if there is an effect outside the working class, which modifies lists.
For this reason, I'm using ref. But the same approach in my real app fails. I have two lists too. One to be expanded, second to be shortened.
Let me explain what part of my code does: There is a list of samples from a Modbus device. Some of the samples require to be joined into bigger ones (because some of the values are so large that have values of int32 which need to be stored in two int16 registers).
I have a class with the Command design pattern which works as follows:
Create a Command object which takes:
(ref) input list of single samples
list of samples to be joined
(ref) list of samples joined to double ones
Build double samples
Remove single samples which have been joined
While testing, the list of double samples are filled, but the list of single ones isn't shortened. I don't understand why, because it looks like I'm using the same approach as in the minimal working example. Can you tell me what's wrong?
Test Case:
namespace put_samples_into_dbTests.Unit.Commands
{
[TestClass]
public class GetDoubleSamples
{
List<Sample> SingleSamples;
List<PatternSample32> SamplesPattern;
List<Sample32> ResultSamples;
int MaxSources = 2;
int MaxObjects = 3;
[TestInitialize]
public void TestInit()
{
SingleSamples = new List<Sample>();
SamplesPattern = new List<PatternSample32>();
ResultSamples = new List<Sample32>();
for (byte i = 1; i <= MaxSources; i++)
{
for (byte k = 2; k <= MaxObjects; k++)
{
SamplesPattern.Add(new PatternSample32(i, k, 1, 2));
}
}
}
[TestMethod]
public void BuildFrom1Set()
{
int howManySamples32 = MaxSources * (MaxObjects-1);
int howManySamples = MaxSources* ((1 + MaxObjects) * MaxObjects / 2) - howManySamples32 *2;
DateTime dateTime = DateTime.Now;
for (byte i = 1; i <= MaxSources; i++)
{
for (byte k = 1; k <= MaxObjects; k++)
{
for (byte l = 1; l <= k; l++)
{
SingleSamples.Add(new Sample(dateTime, i, k, l, 1, true));
}
}
}
Command command = new GetDoubleSamples(ref SingleSamples, SamplesPattern , ref ResultSamples );
command.Execute();
Assert.AreEqual(howManySamples, SingleSamples.Count); // [!]
Assert.AreEqual(howManySamples32, ResultSamples.Count);
}
Now, do take a look at my GetDoubleSamples command:
public class GetDoubleSamples : Command
{
private List<Sample> SingleSamples;
private List<PatternSample32> DoubleSamplesPattern;
private List<Sample32> ResultSamples;
private List<Sample> ProcessedSamples;
public GetDoubleSamples (ref List<Sample> singleSamples, List<PatternSamples32> doubleSamplesPattern, ref List<Sample32> resultSamples)
{
SingleSamples = singleSamples;
doubleSamplesPattern = doubleSamplesPattern;
ResultSamples = resultSamples;
ProcessedSamples = new List<Sample>();
}
public void Execute()
{
SortSamples();
foreach (List<Sample> samplesSet in GenerateSets())
{
ResultSamples.AddRange(BuildDoubles(samplesSet ));
}
DeleteProcessedSamples();
}
private void DeleteProcessedSamples()
{
SingleSamples = SingleSamples.Except(ProcessedSamples).ToList();
}
}
And the problem is, when I check for the amount of created double samples - it's okay. But the same (I suppose) kind of list of simple samples isn't reduced of processed samples. When I debug the code, I see that inside the class the mentioned list is modified. But once I get outside Execute methods and get outside Command class, I lose that modified list and get back to the original one. Just as if my list wasn't passed as a reference.
Do you have any idea what might be wrong?
Any suggestions, also about rearranging my test method, will be appreciated! :-)

C#: Game mechanism issue?

I am trying to calculate the amount of links between one destination and another in my game, the first method that gets called is CalculateRoute and it returns a list of map routes.
At this point you're probably thinking "so whats wrong with the code you've shown?".
When the link is further than 1 room away, it doesn't take into account that it needs to get the links from the first two rooms and just ignores the rest...
Better explain, it only gets the link instructions from the room it starts from inside of the method GetRoutesForRoom and this causes a big problem for the whole mechanism.
I'm already confused by this code so I'm just asking for some help to make it count the first parts of the link inside of the GetRoutesForRoom method.
internal class MapRoute
{
private List<int> _arrowLinks;
public MapRoute(List<int> arrowLinks)
{
_arrowLinks = arrowLinks;
}
}
Here is the CalculateRoute method...
public Dictionary<int, MapRoute> CalculateRoute(Player player, Room startLocation, Room endLocation)
{
var possibleRoutes = new Dictionary<int, MapRoute>();
var arrowsAtStart = startLocation.GetRoomItemHandler().GetFloor.Where(
x => x.GetBaseItem().InteractionType == InteractionType.ARROW);
foreach (var arrow in arrowsAtStart)
{
if (!ItemTeleporterFinder.IsTeleLinked(arrow.Id, startLocation))
{
continue;
}
var linkedRoomId = ItemTeleporterFinder.GetTeleRoomId(arrow.Id, startLocation);
if (linkedRoomId == endLocation.RoomId)
{
possibleRoutes.Add(possibleRoutes.Count + 1, new MapRoute(new List<int> { arrow.Id }));
}
else if (PlusEnvironment.GetGame().GetRoomManager().TryGetRoom(linkedRoomId, out var secondRoom))
{
foreach (var mapRoute in GetRoutesForRoom(secondRoom, startLocation.RoomId))
{
possibleRoutes.Add(possibleRoutes.Count + 1, mapRoute);
}
}
}
return possibleRoutes;
}
For calculating rooms further down the link, I use another method...
public List<MapRoute> GetRoutesForRoom(Room room, int destination)
{
var possibleRoutes = new List<MapRoute>();
var arrowsInRoom = room.GetRoomItemHandler().GetFloor.Where(
x => x.GetBaseItem().InteractionType == InteractionType.ARROW);
foreach (var arrow in arrowsInRoom)
{
if (!ItemTeleporterFinder.IsTeleLinked(arrow.Id, room))
{
continue;
}
var linkedRoomId = ItemTeleporterFinder.GetTeleRoomId(arrow.Id, room);
if (linkedRoomId == destination)
{
possibleRoutes.Add(new MapRoute(new List<int> { arrow.Id }));
}
else if (PlusEnvironment.GetGame().GetRoomManager().TryGetRoom(linkedRoomId, out var secondRoom))
{
foreach (var mapRoute in GetRoutesForRoom(secondRoom, destination))
{
possibleRoutes.Add(mapRoute);
}
}
}
return possibleRoutes;
}

fastest starts with search algorithm

I need to implement a search algorithm which only searches from the start of the string rather than anywhere within the string.
I am new to algorithms but from what I can see it seems as though they go through the string and find any occurrence.
I have a collection of strings (over 1 million) which need to be searched everytime the user types a keystroke.
EDIT:
This will be an incremental search. I currently have it implemented with the following code and my searches are coming back ranging between 300-700ms from over 1 million possible strings. The collection isnt ordered but there is no reason it couldnt be.
private ICollection<string> SearchCities(string searchString) {
return _cityDataSource.AsParallel().Where(x => x.ToLower().StartsWith(searchString)).ToArray();
}
I've adapted the code from this article from Visual Studio Magazine that implements a Trie.
The following program demonstrates how to use a Trie to do fast prefix searching.
In order to run this program, you will need a text file called "words.txt" with a large list of words. You can download one from Github here.
After you compile the program, copy the "words.txt" file into the same folder as the executable.
When you run the program, type a prefix (such as prefix ;)) and press return, and it will list all the words beginning with that prefix.
This should be a very fast lookup - see the Visual Studio Magazine article for more details!
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
var trie = new Trie();
trie.InsertRange(File.ReadLines("words.txt"));
Console.WriteLine("Type a prefix and press return.");
while (true)
{
string prefix = Console.ReadLine();
if (string.IsNullOrEmpty(prefix))
continue;
var node = trie.Prefix(prefix);
if (node.Depth == prefix.Length)
{
foreach (var suffix in suffixes(node))
Console.WriteLine(prefix + suffix);
}
else
{
Console.WriteLine("Prefix not found.");
}
Console.WriteLine();
}
}
static IEnumerable<string> suffixes(Node parent)
{
var sb = new StringBuilder();
return suffixes(parent, sb).Select(suffix => suffix.TrimEnd('$'));
}
static IEnumerable<string> suffixes(Node parent, StringBuilder current)
{
if (parent.IsLeaf())
{
yield return current.ToString();
}
else
{
foreach (var child in parent.Children)
{
current.Append(child.Value);
foreach (var value in suffixes(child, current))
yield return value;
--current.Length;
}
}
}
}
public class Node
{
public char Value { get; set; }
public List<Node> Children { get; set; }
public Node Parent { get; set; }
public int Depth { get; set; }
public Node(char value, int depth, Node parent)
{
Value = value;
Children = new List<Node>();
Depth = depth;
Parent = parent;
}
public bool IsLeaf()
{
return Children.Count == 0;
}
public Node FindChildNode(char c)
{
return Children.FirstOrDefault(child => child.Value == c);
}
public void DeleteChildNode(char c)
{
for (var i = 0; i < Children.Count; i++)
if (Children[i].Value == c)
Children.RemoveAt(i);
}
}
public class Trie
{
readonly Node _root;
public Trie()
{
_root = new Node('^', 0, null);
}
public Node Prefix(string s)
{
var currentNode = _root;
var result = currentNode;
foreach (var c in s)
{
currentNode = currentNode.FindChildNode(c);
if (currentNode == null)
break;
result = currentNode;
}
return result;
}
public bool Search(string s)
{
var prefix = Prefix(s);
return prefix.Depth == s.Length && prefix.FindChildNode('$') != null;
}
public void InsertRange(IEnumerable<string> items)
{
foreach (string item in items)
Insert(item);
}
public void Insert(string s)
{
var commonPrefix = Prefix(s);
var current = commonPrefix;
for (var i = current.Depth; i < s.Length; i++)
{
var newNode = new Node(s[i], current.Depth + 1, current);
current.Children.Add(newNode);
current = newNode;
}
current.Children.Add(new Node('$', current.Depth + 1, current));
}
public void Delete(string s)
{
if (!Search(s))
return;
var node = Prefix(s).FindChildNode('$');
while (node.IsLeaf())
{
var parent = node.Parent;
parent.DeleteChildNode(node.Value);
node = parent;
}
}
}
}
A couple of thoughts:
First, your million strings need to be ordered, so that you can "seek" to the first matching string and return strings until you no longer have a match...in order (seek via C# List<string>.BinarySearch, perhaps). That's how you touch the least number of strings possible.
Second, you should probably not try to hit the string list until there's a pause in input of at least 500 ms (give or take).
Third, your queries into the vastness should be async and cancelable, because it's certainly going to be the case that one effort will be superseded by the next keystroke.
Finally, any subsequent query should first check that the new search string is an append of the most recent search string...so that you can begin your subsequent seek from the last seek (saving lots of time).
I suggest using linq.
string x = "searchterm";
List<string> y = new List<string>();
List<string> Matches = y.Where(xo => xo.StartsWith(x)).ToList();
Where x is your keystroke search text term, y is your collection of strings to search, and Matches is the matches from your collection.
I tested this with the first 1 million prime numbers, here is the code adapted from above:
Stopwatch SW = new Stopwatch();
SW.Start();
string x = "2";
List<string> y = System.IO.File.ReadAllText("primes1.txt").Split(' ').ToList();
y.RemoveAll(xo => xo == " " || xo == "" || xo == "\r\r\n");
List <string> Matches = y.Where(xo => xo.StartsWith(x)).ToList();
SW.Stop();
Console.WriteLine("matches: " + Matches.Count);
Console.WriteLine("time taken: " + SW.Elapsed.TotalSeconds);
Console.Read();
Result is:
matches: 77025
time taken: 0.4240604
Of course this is testing against numbers and I don't know whether linq converts the values before, or if numbers make any difference.

Creating multiple array using a foreach loop and a select statement

I have a database that I call select all of its contents of a table. It has 18000+ items. I have a method uses a web service that can have an array of up to ten element pass into it. Right now I am doing item by item instead of by an array. I want to create an array of ten and then call the function. I could make an array of ten and then call the function be what is I have an extra three records?
public static void Main()
{
inventoryBLL inv = new inventoryBLL();
DataSet1.sDataTable dtsku = inv.SelectEverything();
foreach (DataSet1.Row row in dtsku)
{
webservicefunction(row.item);
}
}
My question is how would I transform this?
Generic solution of your problem could look like this:
static class LinqHelper
{
public static IEnumerable<T[]> SplitIntoGroups<T>(this IEnumerable<T> items, int N)
{
if (items == null || N < 1)
yield break;
T[] group = new T[N];
int size = 0;
var iter = items.GetEnumerator();
while (iter.MoveNext())
{
group[size++] = iter.Current;
if (size == N)
{
yield return group;
size = 0;
group = new T[N];
}
}
if (size > 0)
yield return group.Take(size).ToArray();
}
}
So your Main function become
public static void Main()
{
inventoryBLL inv = new inventoryBLL();
DataSet1.sDataTable dtsku = inv.SelectEverything();
foreach (var items in dtsku.Select(r => r.item).SplitIntoGroups(10))
{
webservicefunction(items);
}
}
var taken = 0;
var takecount = 10;
while(list.Count() >= taken)
{
callWebService(list.Skip(taken).Take(takecount));
taken += takecount;
}
Generic Extension Method version:
public static void AtATime<T>(this IEnumerable<T> list, int eachTime, Action<IEnumerable<T>> action)
{
var taken = 0;
while(list.Count() >= taken)
{
action(list.Skip(taken).Take(eachTime));
taken += eachTime;
}
}
Usage:
inv.SelectEverything().AtATime<Row>(10, webservicefunction);

How can I shuffle my list of strings? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Randomize a List<T> in C#
I thought I had my code working but now it seems not. Here's what I have:
public class NoteDetail
{
public NoteDetail()
{
_noteDetails = new List<string>();
}
public IList<string> NoteDetails { get { return _noteDetails; } }
private readonly List<string> _noteDetails;
}
I populate my details like this:
var noteDetail = new NoteDetail ();
noteDetail.NoteDetails.Add("aaa");
noteDetail.NoteDetails.Add("bbb");
noteDetail.NoteDetails.Add("ccc");
Now I want to shuffle so I used this routine:
public static void ShuffleGenericList<T>(IList<T> list)
{
//generate a Random instance
var rnd = new Random();
//get the count of items in the list
var i = list.Count();
//do we have a reference type or a value type
T val = default(T);
//we will loop through the list backwards
while (i >= 1)
{
//decrement our counter
i--;
//grab the next random item from the list
var nextIndex = rnd.Next(i, list.Count());
val = list[nextIndex];
//start swapping values
list[nextIndex] = list[i];
list[i] = val;
}
}
My problem is that I am not sure how to do the shuffle. I have tried the following but it gives:
Error 237 Argument 1: cannot convert from 'System.Collections.Generic.IList' to 'System.Collections.Generic.IList<.Storage.Models.NoteDetail>'
Sort.ShuffleGenericList<NoteDetail>(noteDetail.NoteDetails);
Can anyone see what I am doing wrong. It all looks okay to me and I can't see why I should get this error :-(
You should change this:
Sort.ShuffleGenericList<NoteDetail>(noteDetail.NoteDetails);
To:
Sort.ShuffleGenericList<string>(noteDetail.NoteDetails);
Because noteDetail.NoteDetails is a List<string>, not a List<NoteDetail>.
You are using the wrong type to parametrize your generic method, do this instead:
Sort.ShuffleGenericList(noteDetail.NoteDetails);
or more explicit (but unneccessary):
Sort.ShuffleGenericList<string>(noteDetail.NoteDetails);
You were passing NoteDetail as type, rather than string - that won't work.
I took your code and threw it into VS. The below execustes okay with a few small modifications:
using System;
using System.Collections.Generic;
using System.Linq;
namespace MsgBaseSerializeationTest
{
class StackOverflow
{
public void Test()
{
var noteDetail = new NoteDetail<string>();
noteDetail.NoteDetails.Add("aaa");
noteDetail.NoteDetails.Add("bbb");
noteDetail.NoteDetails.Add("ccc");
NoteDetail<string>.ShuffleGenericList(noteDetail);
}
}
public class NoteDetail<T> : List<T>
{
public NoteDetail()
{
_noteDetails = new List<string>();
}
public IList<string> NoteDetails { get { return _noteDetails; } }
private readonly List<string> _noteDetails;
public static void ShuffleGenericList(IList<T> list)
{
//generate a Random instance
var rnd = new Random();
//get the count of items in the list
var i = list.Count();
//do we have a reference type or a value type
T val = default(T);
//we will loop through the list backwards
while (i >= 1) {
//decrement our counter
i--;
//grab the next random item from the list
var nextIndex = rnd.Next(i, list.Count());
val = list[nextIndex];
//start swapping values
list[nextIndex] = list[i];
list[i] = val;
}
}
}
}

Categories