Related
I am new to c# (or coding in general) and I guess this question is really stupid and confusing (I know I'm doing it a hard way) but please help me.
I'm trying to make a minesweeper with form app. I made a 10 x 10 of buttons and if you click it, number of mines around it will be revealed. If a mine is there "F" (the first letter of "False") will appear.
There's a constructor that contains the button, x and y position, list of surrounding blocks, number of mines around it, and a boolean that indicates if there's a mine or not.
What I tried to do was to make the 8 surrounding blocks (from the list) cleared when the player clicked a block with no mine around it and if the block surrounding that block also doesn't have any mine around it, these blocks that surrounding that block will also be cleared. The method uses foreach to reveal and check the number of mines around that block. If there's no mines, same method will be applied to that block (calling the method recursively). The problem is that I keep getting System.StackOverflowException.
I somehow understand why it's happening but I just can't come up with the other way.
//scroll to the bottom for the method with the problem
private void Form1_Load(object sender, EventArgs e)
{
Random random = new Random();
Button[,] buttons = new Button[10, 10]
{
{ r0c0, r0c1, r0c2, r0c3, r0c4, r0c5, r0c6, r0c7, r0c8, r0c9 },
{ r1c0, r1c1, r1c2, r1c3, r1c4, r1c5, r1c6, r1c7, r1c8, r1c9 },
{ r2c0, r2c1, r2c2, r2c3, r2c4, r2c5, r2c6, r2c7, r2c8, r2c9 },
{ r3c0, r3c1, r3c2, r3c3, r3c4, r3c5, r3c6, r3c7, r3c8, r3c9 },
{ r4c0, r4c1, r4c2, r4c3, r4c4, r4c5, r4c6, r4c7, r4c8, r4c9 },
{ r5c0, r5c1, r5c2, r5c3, r5c4, r5c5, r5c6, r5c7, r5c8, r5c9 },
{ r6c0, r6c1, r6c2, r6c3, r6c4, r6c5, r6c6, r6c7, r6c8, r6c9 },
{ r7c0, r7c1, r7c2, r7c3, r7c4, r7c5, r7c6, r7c7, r7c8, r7c9 },
{ r8c0, r8c1, r8c2, r8c3, r8c4, r8c5, r8c6, r8c7, r8c8, r8c9 },
{ r9c0, r9c1, r9c2, r9c3, r9c4, r9c5, r9c6, r9c7, r9c8, r9c9 }
};
Square[,] squares = new Square[10, 10];
for (int i = 0, ii = 0, iii = 0; i < 100; i++, ii++)
{
if (ii == 10)
{
ii = 0;
iii++;
}
squares[ii, iii] = new Square(i, buttons[ii, iii], ii, iii, 0, true);
}
List<int> randoms = new List<int>();
for (int i = 0; i < 10; i++)
{
int ii = random.Next(100);
if (!randoms.Contains(ii))
{
squares[ii % 10, ii / 10].setSafe(false);
}
else
{
i--;
}
randoms.Add(ii);
}
for (int i = 0; i < 10; i++)
{
for (int ii = 0; ii < 10; ii++)
{
for (int iii = -1; iii < 2; iii++)
{
for (int iiii = -1; iiii < 2; iiii++)
{
try
{
if (squares[i + iii, ii + iiii].getSafe() == false)
squares[i, ii].addNumber();
}
catch (System.IndexOutOfRangeException)
{
}
}
//if (squares[i, ii].getSafe() == false) squares[i, ii].getButton().Text = squares[i, ii].getSafe().ToString();
//else squares[i, ii].getButton().Text = squares[i, ii].getNumber().ToString();
}
}
}
for (int i = 0; i < 10; i++)
{
for (int ii = 0; ii < 10; ii++)
{
for (int iii = -1; iii < 2; iii++)
{
for (int iiii = -1; iiii < 2; iiii++)
{
try
{
squares[i, ii].addList(squares[i + iii, ii + iiii]);
}
catch (System.IndexOutOfRangeException)
{
}
}
}
}
}
}
Here's the Square class:
public class Square
{
int id;
Button button;
int x;
int y;
int number;
bool safe;
List<Square> list = new List<Square>();
public Square(int id, Button button, int x, int y, int number, bool safe)
{
this.id = id;
this.button = button;
this.x = x;
this.y = y;
this.number = number;
this.safe = safe;
button.Text = "";
button.Click += button_Click;
}
public int getId()
{
return id;
}
public void setId(int i)
{
id = i;
}
public Button getButton()
{
return button;
}
public void setButton(Button b)
{
button = b;
}
public int getX()
{
return x;
}
public void setX(int i)
{
x = i;
}
public int getY()
{
return y;
}
public void setY(int i)
{
y = i;
}
public int getNumber()
{
return number;
}
public void setNumber(int i)
{
number = i;
}
public void addNumber()
{
number++;
}
public bool getSafe()
{
return safe;
}
public void setSafe(bool b)
{
safe = b;
}
private void button_Click(object sender, EventArgs e)
{
if (getSafe() == false) button.Text = getSafe().ToString();
else button.Text = getNumber().ToString();
if (getNumber() == 0) zeroReveal();
}
//---------------------------------------------------
// this is the method that reveals surrounding blocks
//---------------------------------------------------
private void zeroReveal()
{
foreach (Square s in list)
{
//revealing the blocks
s.getButton().Text = s.getNumber().ToString();
//call the same method if there's no mine
//this is the line that keeps giving me exception
if (s.getNumber() == 0) s.zeroReveal();
}
}
//-----------------------------------------------------
public List<Square> getList()
{
return list;
}
public void setList(List<Square> sl)
{
list = sl;
}
public void addList(Square s)
{
list.Add(s);
}
}
I am new to c# (or coding in general) and I guess this question is really stupid and confusing (I know I'm doing it a hard way)
This topic confuses many a new developer; don't stress out about it!
If there's no mines, same method will be applied to that block (calling the method recursively).
Recursive methods can be confusing but if you design them using the standard pattern, you will avoid SO exceptions. You have not designed yours using the standard pattern.
The standard pattern for successful recursive methods is:
Am I in a case that requires no recursion?
If yes, do the necessary computations to produce the desired effect and return. The problem is now solved.
If no, then we're going to recurse.
Break the current problem down into some number of smaller problems.
Solve each smaller problem by recursing.
Combine the solutions of the smaller problem to solve the current problem.
The problem is now solved, so return.
The most important thing about designing a recursive method is that each recursion must be solving a smaller problem, and the sequence of smaller problems must bottom out at a case that does not require recursion. If those two conditions are not met, then you will get a stack overflow.
Internalize that pattern, and every time you write a recursive method, actually write it out:
int Frob(int blah)
{
if (I am in the base case)
{
solve the base case
return the result
}
else
{
find smaller problems
solve them
combine their solutions
return the result
}
}
Fill in that template with your real code, and you will be much more likely to avoid stack overflows. I've been writing recursive methods for decades, and I still follow this pattern.
Now, in your example, what is the case that does not require recursion? There must be one, so write down what it is. Next, how will you guarantee that the recursion solves a smaller problem? That is often the hard step! Give it some thought.
The stack overflow is occurring because zeroReveal is recursively calling itself forever. To fix this we need to find ways where we do not need it to make further calls to itself.
The name of the method gives us a clue. If the square has already been revealed, then surely the method does not need to do anything, since it has already been revealed.
It looks like the button's Text property is an empty string if it has not yet been revealed. So change the foreach so that it doesn't process squares that have already been revealed:
foreach (Square s in list)
{
if (s.getButton().Text == ""))
{
// existing code in the foreach loop goes here
}
}
I got a strange C# programming problem. There is a data retrieval in groups of random lengths of number groups. The numbers should be all unique, like:
group[1]{1,2,15};
group[2]{3,4,7,33,22,100};
group[3]{11,12,9};
// Now there is a routine that adds a number to a group.
// For the example, just imagine the active group looks like:
// group[active]=(10,5,0)
group[active].add(new_number);
// Now if 100 were to be added to the active group
// then the active group should be merged to group[2]
// (as that one already contained 100)
// And then as a result it would like
group[1]{1,2,15};
group[2]{3,4,7,33,22,100,10,5,0}; // 10 5 0 added to group[2]
group[3]{11,12,9};
// 100 wasn't added to group[2] since it was already in there.
If the number to be added is already used (not unique) in a previous group.
Then I should merge all numbers in the active group towards that previous group, so I don’t get double numbers.
So in the above example if number 100 was added to the active
group, then all numbers in the group[active] should be merged into group[2].
And then the group[active] should start clean fresh again without any items. And since 100 was already in group[2] it should not be added double.
I am not entirely sure on how to deal with this in a proper way.
As an important criteria here is that it has to work fast.
I will have around minimal 30 groups (upper-bound unknown might be 2000 or more), and their length on average contains five integer numbers, but it could be much longer or only one number.
I kind of feel that I am reinventing the wheel here.
I wonder what this problem is called (does it go by a name, some sorting, or grouping math problem)?, with a name I might find some articles related to such problems.
But maybe it’s indeed something new, then what would be recommended? Should I use list of lists or a dictionary of lists.. or something else? Somehow the checking if the number is already present should be done fast.
I'm thinking along this path now and am not sure if it’s the best.
Instead of a single number, I use a struct now. It wasn't written in the original question as I was afraid, explaining that would make it too complex.
struct data{int ID; int additionalNumber}
Dictionary <int,List<data>> group =new Dictionary<int, List<data>>();
I can step aside from using a struct in here. A lookup list could connect the other data to the proper index. So this makes it again more close to the original description.
On a side note, great answers are given.
So far I don’t know yet what would work best for me in my situation.
Note on the selected answer
Several answers were given here, but I went for the pure dictionary solution.
Just as a note for people in similar problem scenarios: I'd still recommend testing, and maybe the others work better for you. It’s just that in my case currently it worked best. The code was also quite short which I liked, and a dictionary adds also other handy options for my future coding on this.
I would go with Dictionary<int, HashSet<int>>, since you want to avoid duplicates and want a fast way to check if given number already exists:
Usage example:
var groups = new Dictionary<int, HashSet<int>>();
// populate the groups
groups[1] = new HashSet<int>(new[] { 1,2,15 });
groups[2] = new HashSet<int>(new[] { 3,4,7,33,22,100 });
int number = 5;
int groupId = 4;
bool numberExists = groups.Values.Any(x => x.Contains(number));
// if there is already a group that contains the number
// merge it with the current group and add the new number
if (numberExists)
{
var group = groups.First(kvp => kvp.Value.Contains(number));
groups[group.Key].UnionWith(groups[groupId]);
groups[groupId] = new HashSet<int>();
}
// otherwise just add the new number
else
{
groups[groupId].Add(number);
}
From what I gather you want to iteratively assign numbers to groups satisfying these conditions:
Each number can be contained in only one of the groups
Groups are sets (numbers can occur only once in given group)
If number n exists in group g and we try to add it to group g', all numbers from g' should be transferred to g instead (avoiding repetitions in g)
Although approaches utilizing Dictionary<int, HashSet<int>> are correct, here's another one (more mathematically based).
You could simply maintain a Dictionary<int, int>, in which the key would be the number, and the corresponding value would indicate the group, to which that number belongs (this stems from condition 1.). And here's the add routine:
//let's assume dict is a reference to the dictionary
//k is a number, and g is a group
void AddNumber(int k, int g)
{
//if k already has assigned a group, we assign all numbers from g
//to k's group (which should be O(n))
if(dict.ContainsKey(k) && dict[k] != g)
{
foreach(var keyValuePair in dict.Where(kvp => kvp.Value == g).ToList())
dict[keyValuePair.Key] = dict[k];
}
//otherwise simply assign number k to group g (which should be O(1))
else
{
dict[k] = g;
}
}
Notice that from a mathematical point of view what you want to model is a function from a set of numbers to a set of groups.
I have kept it as easy to follow as I can, trying not to impact the speed or deviate from the spec.
Create a class called Groups.cs and copy and paste this code into it:
using System;
using System.Collections.Generic;
namespace XXXNAMESPACEXXX
{
public static class Groups
{
public static List<List<int>> group { get; set; }
public static int active { get; set; }
public static void AddNumberToGroup(int numberToAdd, int groupToAddItTo)
{
try
{
if (group == null)
{
group = new List<List<int>>();
}
while (group.Count < groupToAddItTo)
{
group.Add(new List<int>());
}
int IndexOfListToRefresh = -1;
List<int> NumbersToMove = new List<int>();
foreach (List<int> Numbers in group)
{
if (Numbers.Contains(numberToAdd) && (group.IndexOf(Numbers) + 1) != groupToAddItTo)
{
active = group.IndexOf(Numbers) + 1;
IndexOfListToRefresh = group.IndexOf(Numbers);
foreach (int Number in Numbers)
{
NumbersToMove.Add(Number);
}
}
}
foreach (int Number in NumbersToMove)
{
if (!group[groupToAddItTo - 1].Contains(Number))
{
group[groupToAddItTo - 1].Add(Number);
}
}
if (!group[groupToAddItTo - 1].Contains(numberToAdd))
{
group[groupToAddItTo - 1].Add(numberToAdd);
}
if (IndexOfListToRefresh != -1)
{
group[IndexOfListToRefresh] = new List<int>();
}
}
catch//(Exception ex)
{
//Exception handling here
}
}
public static string GetString()
{
string MethodResult = "";
try
{
string Working = "";
bool FirstPass = true;
foreach (List<int> Numbers in group)
{
if (!FirstPass)
{
Working += "\r\n";
}
else
{
FirstPass = false;
}
Working += "group[" + (group.IndexOf(Numbers) + 1) + "]{";
bool InnerFirstPass = true;
foreach (int Number in Numbers)
{
if (!InnerFirstPass)
{
Working += ", ";
}
else
{
InnerFirstPass = false;
}
Working += Number.ToString();
}
Working += "};";
if ((active - 1) == group.IndexOf(Numbers))
{
Working += " //<active>";
}
}
MethodResult = Working;
}
catch//(Exception ex)
{
//Exception handling here
}
return MethodResult;
}
}
}
I don't know if foreach is more or less efficient than standard for loops, so I have made an alternative version that uses standard for loops:
using System;
using System.Collections.Generic;
namespace XXXNAMESPACEXXX
{
public static class Groups
{
public static List<List<int>> group { get; set; }
public static int active { get; set; }
public static void AddNumberToGroup(int numberToAdd, int groupToAddItTo)
{
try
{
if (group == null)
{
group = new List<List<int>>();
}
while (group.Count < groupToAddItTo)
{
group.Add(new List<int>());
}
int IndexOfListToRefresh = -1;
List<int> NumbersToMove = new List<int>();
for(int i = 0; i < group.Count; i++)
{
List<int> Numbers = group[i];
int IndexOfNumbers = group.IndexOf(Numbers) + 1;
if (Numbers.Contains(numberToAdd) && IndexOfNumbers != groupToAddItTo)
{
active = IndexOfNumbers;
IndexOfListToRefresh = IndexOfNumbers - 1;
for (int j = 0; j < Numbers.Count; j++)
{
int Number = NumbersToMove[j];
NumbersToMove.Add(Number);
}
}
}
for(int i = 0; i < NumbersToMove.Count; i++)
{
int Number = NumbersToMove[i];
if (!group[groupToAddItTo - 1].Contains(Number))
{
group[groupToAddItTo - 1].Add(Number);
}
}
if (!group[groupToAddItTo - 1].Contains(numberToAdd))
{
group[groupToAddItTo - 1].Add(numberToAdd);
}
if (IndexOfListToRefresh != -1)
{
group[IndexOfListToRefresh] = new List<int>();
}
}
catch//(Exception ex)
{
//Exception handling here
}
}
public static string GetString()
{
string MethodResult = "";
try
{
string Working = "";
bool FirstPass = true;
for(int i = 0; i < group.Count; i++)
{
List<int> Numbers = group[i];
if (!FirstPass)
{
Working += "\r\n";
}
else
{
FirstPass = false;
}
Working += "group[" + (group.IndexOf(Numbers) + 1) + "]{";
bool InnerFirstPass = true;
for(int j = 0; j < Numbers.Count; j++)
{
int Number = Numbers[j];
if (!InnerFirstPass)
{
Working += ", ";
}
else
{
InnerFirstPass = false;
}
Working += Number.ToString();
}
Working += "};";
if ((active - 1) == group.IndexOf(Numbers))
{
Working += " //<active>";
}
}
MethodResult = Working;
}
catch//(Exception ex)
{
//Exception handling here
}
return MethodResult;
}
}
}
Both implimentations contain the group variable and two methods, which are; AddNumberToGroup and GetString, where GetString is used to check the current status of the group variable.
Note: You'll need to replace XXXNAMESPACEXXX with the Namespace of your project. Hint: Take this from another class.
When adding an item to your List, do this:
int NumberToAdd = 10;
int GroupToAddItTo = 2;
AddNumberToGroup(NumberToAdd, GroupToAddItTo);
...or...
AddNumberToGroup(10, 2);
In the example above, I am adding the number 10 to group 2.
Test the speed with the following:
DateTime StartTime = DateTime.Now;
int NumberOfTimesToRepeatTest = 1000;
for (int i = 0; i < NumberOfTimesToRepeatTest; i++)
{
Groups.AddNumberToGroup(4, 1);
Groups.AddNumberToGroup(3, 1);
Groups.AddNumberToGroup(8, 2);
Groups.AddNumberToGroup(5, 2);
Groups.AddNumberToGroup(7, 3);
Groups.AddNumberToGroup(3, 3);
Groups.AddNumberToGroup(8, 4);
Groups.AddNumberToGroup(43, 4);
Groups.AddNumberToGroup(100, 5);
Groups.AddNumberToGroup(1, 5);
Groups.AddNumberToGroup(5, 6);
Groups.AddNumberToGroup(78, 6);
Groups.AddNumberToGroup(34, 7);
Groups.AddNumberToGroup(456, 7);
Groups.AddNumberToGroup(456, 8);
Groups.AddNumberToGroup(7, 8);
Groups.AddNumberToGroup(7, 9);
}
long MillisecondsTaken = DateTime.Now.Ticks - StartTime.Ticks;
Console.WriteLine(Groups.GetString());
Console.WriteLine("Process took: " + MillisecondsTaken);
I think this is what you need. Let me know if I misunderstood anything in the question.
As far as I can tell it's brilliant, it's fast and it's tested.
Enjoy!
...and one more thing:
For the little windows interface app, I just created a simple winforms app with three textboxes (one set to multiline) and a button.
Then, after adding the Groups class above, in the button-click event I wrote the following:
private void BtnAdd_Click(object sender, EventArgs e)
{
try
{
int Group = int.Parse(TxtGroup.Text);
int Number = int.Parse(TxtNumber.Text);
Groups.AddNumberToGroup(Number, Group);
TxtOutput.Text = Groups.GetString();
}
catch//(Exception ex)
{
//Exception handling here
}
}
I'm working on a hacker rank problem and I believe my solution is correct. However, most of my test cases are being timed out. Could some one suggest how to improve the efficiency of my code?
The important part of the code starts at the "Trie Class".
The exact question can be found here: https://www.hackerrank.com/challenges/contacts
using System;
using System.Collections.Generic;
using System.IO;
class Solution
{
static void Main(String[] args)
{
int N = Int32.Parse(Console.ReadLine());
string[,] argList = new string[N, 2];
for (int i = 0; i < N; i++)
{
string[] s = Console.ReadLine().Split();
argList[i, 0] = s[0];
argList[i, 1] = s[1];
}
Trie trie = new Trie();
for (int i = 0; i < N; i++)
{
switch (argList[i, 0])
{
case "add":
trie.add(argList[i, 1]);
break;
case "find":
Console.WriteLine(trie.find(argList[i, 1]));
break;
default:
break;
}
}
}
}
class Trie
{
Trie[] trieArray = new Trie[26];
private int findCount = 0;
private bool data = false;
private char name;
public void add(string s)
{
s = s.ToLower();
add(s, this);
}
private void add(string s, Trie t)
{
char first = Char.Parse(s.Substring(0, 1));
int index = first - 'a';
if(t.trieArray[index] == null)
{
t.trieArray[index] = new Trie();
t.trieArray[index].name = first;
}
if (s.Length > 1)
{
add(s.Substring(1), t.trieArray[index]);
}
else
{
t.trieArray[index].data = true;
}
}
public int find(string s)
{
int ans;
s = s.ToLower();
find(s, this);
ans = findCount;
findCount = 0;
return ans;
}
private void find(string s, Trie t)
{
if (t == null)
{
return;
}
if (s.Length > 0)
{
char first = Char.Parse(s.Substring(0, 1));
int index = first - 'a';
find(s.Substring(1), t.trieArray[index]);
}
else
{
for(int i = 0; i < 26; i++)
{
if (t.trieArray[i] != null)
{
find("", t.trieArray[i]);
}
}
if (t.data == true)
{
findCount++;
}
}
}
}
EDIT: I did some suggestions in the comments but realized that I can't replace s.Substring(1) with s[0]... because I actually need s[1..n]. AND s[0] returns a char so I'm going to need to do .ToString on it anyways.
Also, to add a little more information. The idea is that it needs to count ALL names after a prefix for example.
Input: "He"
Trie Contains:
"Hello"
"Help"
"Heart"
"Ha"
"No"
Output: 3
I could just post a solution here that gives you 40 points but i guess this wont be any fun.
Make use of Enumerator<char> instead of any string operations
Count while adding values
any charachter minus 'a' makes a good arrayindex (gives you values between 0 and 25)
I think, this link must be very helpfull
There, you can find the good implementation of a trie data structure, but it's a java implementation. I implemented trie on c# with that great article one year ago, and i tried to find solution to an another hackerrank task too ) It was successful.
In my task, i had to a simply trie (i mean my alphabet equals 2) and only one method for adding new nodes:
public class Trie
{
//for integer representation in binary system 2^32
public static readonly int MaxLengthOfBits = 32;
//alphabet trie size
public static readonly int N = 2;
class Node
{
public Node[] next = new Node[Trie.N];
}
private Node _root;
}
public void AddValue(bool[] binaryNumber)
{
_root = AddValue(_root, binaryNumber, 0);
}
private Node AddValue(Node node, bool[] val, int d)
{
if (node == null) node = new Node();
//if least sagnificient bit has been added
//need return
if (d == val.Length)
{
return node;
}
// get 0 or 1 index of next array(length 2)
int index = Convert.ToInt32(val[d]);
node.next[index] = AddValue(node.next[index], val, ++d);
return node;
}
i am making a Program of SCRATCH card code generator in c# Vs 2010..
Which Generates possible number of Combinations and unique number as well
means number is not repeated
for example:
5! = 120 combination or possible numbers
2! = 2 combination or possible numbers
we can give integer value and string value at same time and it generates its possible combinations
the program is successfully running..
You can set new value in MAIN METHOD string c = "abc";
for example: (You can change value here)
string c = "abc";
string c = "1232abc";
THE Whole code is here in Console c#:-
static void Main(string[] args)
{
Permute p = new Permute();
// here u can change value in string
string c = "abc";
char[] c2 = c.ToCharArray();
p.setper(c2);
Console.ReadKey();
}
class Permute
{
int count = 0 ;
private void swap (ref char a, ref char b)
{
char x;
if(a==b)return;
x = a;
a = b;
b = x;
}
public void setper(char[] list)
{
int x=list.Length-1;
go(list,0,x);
}
private void go (char[] list, int k, int m)
{
int i;
if (k == m)
{
Console.Write (list );
count++;
Console.WriteLine (" "+ count );
}
else
for (i = k; i <= m; i++)
{
swap (ref list[k],ref list[i]);
go (list, k+1, m);
swap (ref list[k],ref list[i]);
}
}
The Problem is we are not able to convert in WINDOWS FORM C#
when we convert it does not generate Unique numbers which was doing in CONSOLE Program
we have try to do it in WINDOWS FORM what is the PROBLEM we cannot detect it
The Code for Windows form c# is (which we have tried):
// this is our Button 1 we have changed name to BtGenerate
// we have used LISTBOX to show the generated values
// or u can say to show numbers in Listbox
private void BtGenerate_Click(object sender, EventArgs e)
{
string abc = textBox1.Text;
char[] c = abc.ToCharArray();
Permutation p = new Permutation();
string value = p.setper(c);
// here is our listbox
listBox1.Items.Add(value);
}
// we have used the PERMUTATION Class here
// which is generating numbers
// this class is changed compared to console Permutation class
class Permutation
{
public string Value;
private void swap(ref char a, ref char b)
{
if (a == b) return;
a ^= b;
b ^= a;
a ^= b;
}
public string setper(char[] list)
{
int x = list.Length - 1;
string ValueInString = go(list, 0, x);
return ValueInString;
}
int x = 0;
private string go(char[] list, int k, int m)
{
int i;
if (k == m)
{
if(x == 0)
{
x++;
for (int j = 0; j < list.Length; j++)
{
Value = Value + list[j].ToString();
}
//this code is used which gives gap like arrow to seperate number
//because we are not able to generate each number to new line
Value = Value + #"<--" + x + " ";
}
if (x > 0)
{
x++;
for (int j = 0; j < list.Length; j++)
{
Value = Value + list[j].ToString();
}
Value = Value + #"<--"+ x + " ";
}
}
else
for (i = k; i <= m; i++)
{
swap(ref list[k], ref list[i]);
go(list, k + 1, m);
swap(ref list[k], ref list[i]);
}
return Value;
}
Why it is not generating UNIQUE numbers as it is happening in CONSOLE PROGRAM???
What is the problem????
There's a number of issues here, none of which are the explicit problem you're having, but all of which make it that much harder to see. This looks much more like C++ code than C# code.
In well-written code:
You shouldn't ever need to pass by ref.
You shouldn't output from a class' functions, specifically so that you can reuse it between different types of things.
You should use foreach instead of for loops.
Variables and functions should have descriptive names to indicate what they are, unless it's trivially obvious from the context.
char[] should be string under most circumstances (this case may be a legit use)
For the actual permutation logic, see the answers to this question - the only change is that you'd be doing it on char instead of string. Alternatively, see here which is linked from there.
I am given a string of characters, in which every consequent pair of characters comprises an edge. What I mean by that is this is the string: ABBCAD. Edges of the string are:
A->B
B->C
A->D
Shortest path distance is A->D
The task at hand is to build up a Directed Acyclic Graph in memory from the string using the above rule and find the shortest path staring at the root node(in the example given it's A label) ending at terminal node.
NJKUUGHBNNJHYAPOYJHNRMNIKAIILFGJSNAICZQRNM
I gather one of the approaches that suites the task is to use the Depth First Search algo.
This is not homework...
This is a job for Djikstra's Algorithm. Once you build a representation of your graph it should be easy enough to produce the lowest cost traversal ... since in your case it seems that all paths have an equal cost (1).
You can look here on CodeProject for a reasonably decent implementation of Djikstra in C#.
could you present me with a pseudo code of your version of the graph representation for this case?
There are multiple ways to represent a graph in such a problem. If the number of vertices in your graph are likely to be small - it would be sufficient to use an adjacency matrix for the representation of edges. In which case, you could just use a .NET multidimensional array. The trick here is that you need to convert vertices labelled with characters to ordinal values. One approach would be to write a wrapper class that maps character codes to indices into the adjacency matrix:
class AdjacencyMatrix
{
// representation of the adjacency matrix (AM)
private readonly int[,] m_Matrix;
// mapping of character codes to indices in the AM
private readonly Dictionary<char,int> m_Mapping;
public AdjacencyMatrix( string edgeVector )
{
// using LINQ we can identify and order the distinct characters
char[] distinctChars = edgeVector.Distinct().OrderBy(x => x);
m_Mapping = distinctChars.Select((c,i)=>new { Vertex = c, Index = i })
.ToDictionary(x=>x.Vertex, x=>x.Index);
// build the adjacency cost matrix here...
// TODO: I leave this up to the reader to complete ... :-D
}
// retrieves an entry from within the adjacency matrix given two characters
public int this[char v1, char v2]
{
get { return m_Matrix[m_Mapping[v1], m_Mapping[v2]];
private set { m_Matrix[m_Mapping[v1], m_Mapping[v2]] = value; }
}
}
For this particular case, Dijkstra's could be greatly simplified. I imagine something like this would do the trick.
class Node {
public object Value;
// Connected nodes (directed)
public Node[] Connections;
// Path back to the start
public Node Route;
}
Node BreadthFirstRoute(Node[] theStarts, Node[] theEnds) {
Set<Node> visited = new Set<Node>();
Set<Node> frontier = new Set<Node>();
frontier.AddRange(theStarts);
Set<Node> ends = new Set<Node>();
ends.AddRange(theEnds);
// Visit nodes one frontier at a time - Breadth first.
while (frontier.Count > 0) {
// Move frontier into visiting, reset frontier.
Set<Node> visiting = frontier;
frontier = new Set<Node>();
// Prevent adding nodes being visited to frontier
visited.AddRange(visiting);
// Add all connected nodes to frontier.
foreach (Node node in visiting) {
foreach (Node other in node.Connections) {
if (!visited.Contains(other)) {
other.Route = other;
if (ends.Contains(other)) {
return other;
}
frontier.Add(other);
}
}
}
}
return null;
}
Just for the record. This is your graph example:
Where the shortest path from A to M is marked in blue.
It is a very short program in Mathematica:
a = StringSplit["NJKUUGHBNNJHYAPOYJHNRMNIKAIILFGJSNAICZQRNM", ""]
b = Table[a[[i]] -> a[[i + 1]], {i, Length#a - 1}]
vertexNumber[g_, vName_] := Position[ Vertices[g, All], vName][[1, 1]];
Needs["Combinatorica`"]
c = ToCombinatoricaGraph[b]
sp = ShortestPath[c, vertexNumber[c, "A"], vertexNumber[c, "M"]]
vlsp = GetVertexLabels[c, sp]
vlspt = Table[{vlsp[[i]], vlsp[[i + 1]]}, {i, Length#vlsp - 1}]
GraphPlot[b, VertexLabeling -> True, ImageSize -> 250,
DirectedEdges -> True, Method -> {"SpringEmbedding"},
EdgeRenderingFunction ->
(If[Cases[vlspt, {First[#2], Last[#2]}] == {},
{Red, Arrowheads[Medium], Arrow[#1, .1]},
{Blue, Arrowheads[Medium], Arrow[#1, .1]}] &)]
LBushkin's answer is correct. Eric Lippert has a series about implementing the A* algorithm in C#. A* is a more general case of Dijkstra's algorithm : if your cost estimation function always returns 0, it is exactly equivalent to Dijkstra.
Another option would be to use a graph library that has various shortest path algorithms implemented. One I have used in the past and found to be good is QuickGraph. The documentation is quite good. For example, here is a page in the documentation that explains how to use Dijkstra's algorithm.
Because your graph is acyclic the Viterbi algorithm can be used, visit the states in topological order and update the costs in preceding vertices (states).
The below code implements the search algorithm and data structure. I wasn't 100% sure of the definition of the valid based on the original question. But it should be straight forward to modify the code to construct other topologies and solve various dynamic programming task using a DAG.
Changing the outer for loop when computing the state potentials to while loop with a queue will allow for different shortestpath algorithms to used easily changed by changing the queue discipline. For example a binary heap based queue will give Dijkstra algorithm or a FIFO queue will Bellman-Ford algorithm.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DAGShortestPath
{
class Arc
{
public Arc(int nextstate, float cost)
{
Nextstate = nextstate;
Cost = cost;
}
public int Nextstate { get; set; }
public float Cost { get; set; }
};
class State
{
public bool Final { get; set; }
public List<Arc> Arcs { get; set; }
public void AddArc(int nextstate, float cost)
{
if (Arcs == null)
Arcs = new List<Arc>();
Arcs.Add(new Arc(nextstate, cost));
}
}
class Graph
{
List< State > _states = new List< State >();
int _start = -1;
public void AddArc(int state, int nextstate, float cost)
{
while (_states.Count <= state)
AddState();
while (_states.Count <= nextstate)
AddState();
_states[state].AddArc(nextstate, cost);
}
public List<Arc> Arcs(int state)
{
return _states[state].Arcs;
}
public int AddState()
{
_states.Add(new State());
return _states.Count - 1;
}
public bool IsFinal(int state)
{
return _states[state].Final;
}
public void SetFinal(int state)
{
_states[state].Final = true;
}
public void SetStart(int start)
{
_start = -1;
}
public int NumStates { get { return _states.Count; } }
public void Print()
{
for (int i = 0; i < _states.Count; i++)
{
var arcs = _states[i].Arcs;
for (int j = 0; j < arcs.Count; j++)
{
var arc = arcs[j];
Console.WriteLine("{0}\t{1}\t{2}", i, j, arc.Cost);
}
}
}
}
class Program
{
static List<int> ShortertPath(Graph graph)
{
float[] d = new float[graph.NumStates];
int[] tb = new int[graph.NumStates];
for (int i = 0; i < d.Length; i++)
{
d[i] = float.PositiveInfinity;
tb[i] = -1;
}
d[0] = 0.0f;
float bestscore = float.PositiveInfinity;
int beststate = -1;
for (int i = 0; i < graph.NumStates; i++)
{
if (graph.Arcs(i) != null)
{
foreach (var arc in graph.Arcs(i))
{
if (arc.Nextstate < i)
throw new Exception("Graph is not topologically sorted");
float e = d[i] + arc.Cost;
if (e < d[arc.Nextstate])
{
d[arc.Nextstate] = e;
tb[arc.Nextstate] = i;
if (graph.IsFinal(arc.Nextstate) && e < bestscore)
{
bestscore = e;
beststate = arc.Nextstate;
}
}
}
}
}
//Traceback and recover the best final sequence
if (bestscore == float.NegativeInfinity)
throw new Exception("No valid terminal state found");
Console.WriteLine("Best state {0} and score {1}", beststate, bestscore);
List<int> best = new List<int>();
while (beststate != -1)
{
best.Add(beststate);
beststate = tb[beststate];
}
return best;
}
static void Main(string[] args)
{
Graph g = new Graph();
String input = "ABBCAD";
for (int i = 0; i < input.Length - 1; i++)
for (int j = i + 1; j < input.Length; j++)
{
//Modify this of different constraints on-the arcs
//or graph topologies
//if (input[i] < input[j])
g.AddArc(i, j, 1.0f);
}
g.SetStart(0);
//Modify this to make all states final for example
//To compute longest sub-sequences and so on...
g.SetFinal(g.NumStates - 1);
var bestpath = ShortertPath(g);
//Print the best state sequence in reverse
foreach (var v in bestpath)
{
Console.WriteLine(v);
}
}
}
}