I am trying to figure out why this works, but when I can the numbers around it doesn't. What the code is suppose to do is have two stacks, the program is suppose to sort in ascending order, which it does, but if I change the:
first.Push(7)
to something like
first.Push(80)
it doesn't work.
Can someone explain this, please?
Here is what I have:
using System;
using System.Collections;
namespace Project03_03
{
class Program
{
static void Main(string[] args)
{
Stack first = new Stack();
first.Push(50);
first.Push(45);
first.Push(11);
first.Push(7);
Stack second = new Stack();
second.Push(67);
second.Push(65);
second.Push(32);
second.Push(12);
ProcessInOrder(first, second);
Console.WriteLine(
"Press any key to continue...");
Console.ReadKey();
}
static void ProcessInOrder(Stack first,
Stack second)
{
while (first.Count > 0 || second.Count > 0)
{
if (first.Count == 0)
{
Console.WriteLine(second.Pop());
continue;
}
if (second.Count == 0)
{
Console.WriteLine(first.Pop());
continue;
}
if ((int)first.Peek()
>= (int)second.Peek())
{
Console.WriteLine(
second.Pop());
}
else
{
Console.WriteLine(first.Pop());
}
}
}
}
}
what your code is doing is merging two already sorted stacks. So it pretty much just traverses the stack and sees which value is smaller and then displays that one. Thus is you have two already sorted stacks it can merge them into one larger stack that is also already sorted.
By changing your code so the last item pushed into the first stack is 80 vs 7 it breaks this state and thus your logic is flawed. A different approach to solve this code might be to first merge the two stacks then pop them and sort them at that time. Here is a some code to sort a stack (dont click it if you want to try and figure it out yourself first)
You can also write some unit tests to confirm these scenarios are fixed as you modify your code.
Lastly if you compare your new sorting code to one of the examples maybe you can measure the difference in performance between the two like this example did
Related
This question already has answers here:
Add new item in existing array in c#.net
(20 answers)
Closed 1 year ago.
I do not have anything other than the normal
using System;
namespace TryStuff
{
class Program
{
static void Main(string[] args)
{
}
}
}
And I know that having nothing at the start and still asking questions isnt highly looked on but STILL...
Im trying to create a code that asks you for an integer, and if you answer anything over 0, it ADDS the given number to an array, once you stop giving numbers (example type some "stop") it prints out ALL the numbers given to the array.
I DO NOT need the full code for something like this, just an answer to how do I append to an array without making it insanely complicated (things ive found on the google are like 20 lines of code but im pretty sure its not that hard).
Sorry for the long post and in short, how do I append to an array? If you can provide me a code, please implement it in the C# code or give me a "explanation" how to do it. Thank you very much!
You probably don't want to use an array, you want a different data structure that allows easy expansion, like List<T>. For List<T>, you simply call .Add, like:
using System;
using System.Collections.Generic;
namespace TryStuff
{
class Program
{
static void Main(string[] args)
{
var myList = new List<int>();
while(int.TryParse(Console.ReadLine(), out int x))
{
if (x > 0)
{
myList.Add(x);
}
}
Console.WriteLine("You entered: " + string.Join(",", myList));
}
}
}
This should keep allowing you to enter integer numbers and add them to the list if the number is greater than 0. It ignores all numbers 0 or less than 0. If you type anything that is not a number, it will stop and print out the list you entered.
Is there a built in way to limit the depth of a System.Collection.Generics.Stack? So that if you are at max capacity, pushing a new element would remove the bottom of the stack?
I know I can do it by converting to an array and rebuilding the stack, but I figured there's probably a method on it already.
EDIT: I wrote an extension method:
public static void Trim<T> (this Stack<T> stack, int trimCount)
{
if (stack.Count <= trimCount)
return;
stack = new
Stack<T>
(
stack
.ToArray()
.Take(trimCount)
);
}
So, it returns a new stack upon trimming, but isn't immutability the functional way =)
The reason for this is that I'm storing undo steps for an app in a stack, and I only want to store a finite amount of steps.
What you are looking for is called a dropout stack. AFAIK, the BCL does not contain one, although they are trivial to implement. Typically Undo and Redo functionality relies on such data structures.
They are basically an array, and when you push onto the stack the 'top' of the stack moves around the array. Eventually the top will wrap back to the beginning when the stack is full and replace the 'bottom' of the stack.
Google didn't provide much info on it. This is the best i could find:
(Warning PDF)
http://courses.cs.vt.edu/~cs2704/spring04/projects/DropOutStack.pdf
Here's some boiler plate code, to get you started. I'll let you fill in the rest (sanity checking, count, indexer, etc.)
class DropOutStack<T>
{
private T[] items;
private int top = 0;
public DropOutStack(int capacity)
{
items = new T[capacity];
}
public void Push(T item)
{
items[top] = item;
top = (top + 1) % items.Length;
}
public T Pop()
{
top = (items.Length + top - 1) % items.Length;
return items[top];
}
}
You're actually looking at something similar to circular list implementation. There's a LimitedQueue implementation done by PIEBALDconsult at CodeProject. It's similar to your requirement. You just need to wrap Stack instead of Queue as done by the author. Plus the author also implemented indexer, which is handy if you need to access anything else other than the top stack (to show undo list maybe).
EDIT: The author's implementation also raise an event when the last(first, depends on whether it's a queue or stack) is being removed, so that you can know when something is being thrown away.
I can't see a way. You can inherit from Stack<T>, but there doesn't appear to be anything useful to override.
The easy (if a bit tedious) way would be to wrap the Stack<T> in your own, say, LimitedStack<T>. Then implement the methods you want and pass through to an internal Stack<T>, while including your limiting logic in the Push method and wherever else you need it.
It's a pain to write all those pass-through members, especially if you're implementing all the same interfaces as Stack<T>...but on the other hand, you only have to do it once and then it's done.
I believe you're looking for a (possibly-modified) dequeue - the data structure that allows access from either end.
the solution provided By Greg Dean => dropout stack is very good, but I think the main question, is about removing the bottom of the stack when the stack overflowed
But the provided solution just replace the last item of the stack once the stack was filled, so you do not get a real history,
But to get a real history, you need to shift the list once the list reaches your specific capacity, but this is an expansive operation,
So I think the best solution for this is a linked list
This is my solution to the problem
public class HistoryStack<T>
{
private LinkedList<T> items = new LinkedList<T>();
public List<T> Items => items.ToList();
public int Capacity { get;}
public HistoryStack(int capacity)
{
Capacity = capacity;
}
public void Push(T item)
{
// full
if (items.Count == Capacity)
{
// we should remove first, because some times, if we exceeded the size of the internal array
// the system will allocate new array.
items.RemoveFirst();
items.AddLast(item);
}
else
{
items.AddLast(new LinkedListNode<T>(item));
}
}
public T Pop()
{
if (items.Count == 0)
{
return default;
}
var ls = items.Last;
items.RemoveLast();
return ls == null ? default : ls.Value;
}
}
Test it
var hs = new HistoryStack<int>(5);
hs.Push(1);
hs.Push(2);
hs.Push(3);
hs.Push(4);
hs.Push(5);
hs.Push(6);
hs.Push(7);
hs.Push(8);
var ls = hs.Items;
Console.WriteLine(String.Join(",", ls));
Console.WriteLine(hs.Pop());
Console.WriteLine(hs.Pop());
hs.Push(9);
Console.WriteLine(hs.Pop());
Console.WriteLine(hs.Pop());
Console.WriteLine(hs.Pop());
Console.WriteLine(hs.Pop());
Console.WriteLine(hs.Pop()); // empty
Console.WriteLine(hs.Pop()); // empty
The Result
4,5,6,7,8
8
7
9
6
5
4
0
0
How do I write a Do .. While loop in C#?
(Edit: I am a VB.NET programmer trying to make the move to C#, so I do have experience with .NET / VB syntax. Thanks!)
The general form is:
do
{
// Body
} while (condition);
Where condition is some expression of type bool.
Personally I rarely write do/while loops - for, foreach and straight while loops are much more common in my experience. The latter is:
while (condition)
{
// body
}
The difference between while and do...while is that in the first case the body will never be executed if the condition is false to start with - whereas in the latter case it's always executed once before the condition is ever evaluated.
Since you mentioned you were coming from VB.NET, I would strongly suggest checking out this link to show the comparisons. You can also use this wensite to convert VB to C# and vice versa - so you can play with your existing VB code and see what it looks like in C#, including loops and anything else under the son..
To answer the loop question, you simple want to do something like:
while(condition)
{
DoSomething();
}
You can also do - while like this:
do
{
Something();
}
while(condition);
Here's another code translator I've used with success, and another great C#->VB comparison website. Good Luck!
//remember, do loop will always execute at least once, a while loop may not execute at all
//because the condition is at the top
do
{
//statements to be repeated
} while (condition);
Quite surprising that no one has mentioned yet the classical example for the do..while construct. Do..while is the way to go when you want to run some code, check or verify something (normally depending on what happened during the execution of that code), and if you don't like the result, start over again. This is exactly what you need when you want some user input that fits some constraints:
bool CheckInput(string input) { ... }
...
string input;
...
do {
input=Console.ReadLine();
} while(!CheckInput(input));
That's quite a generic form: when the condition is simple enough, it's common to place it directly on the loop construct (inside the brackets after the "while" keyword), rather than having a method to compute it.
The key concepts in this usage are that you have to request the user input at least once (in the best case, the user will get it right at the first try); and that the condition doesn't really make much sense until the body has executed at least once. Each of these are good hints that do..while is the tool for the job, both of them together are almost a guarantee.
Here's a simple example that will print some numbers:
int i = 0;
do {
Console.WriteLine(++i);
} while (i < 10);
using System;
class MainClass
{
public static void Main()
{
int i = 0;
do
{
Console.WriteLine("Number is {0}", i);
i++;
} while (i < 100);
}
}
Another method would be
using System;
class MainClass
{
public static void Main()
{
int i = 0;
while(i <100)
{
Console.WriteLine("Number is {0}", i);
i++;
}
}
}
The answer by Jon Skeet is correct and great, though I would like to give an example for those unfamiliar with while and do-while in c#:
int i=0;
while(i<10)
{
Console.WriteLine("Number is {0}", i);
i++;
}
and:
int i=0;
do
{
Console.WriteLine("Number is {0}", i);
i++;
}while(i<10)
will both output:
Number is 0
Number is 1
Number is 2
Number is 3
Number is 4
Number is 5
Number is 6
Number is 7
Number is 8
Number is 9
as we would expect. However it is important to understand that the do-while loop always executes the body the first time regardless of the check. This means that if we change i's starting value to 100 we will see very different outputs.
int i=100;
while(i<10)
{
Console.WriteLine("Number is {0}", i);
i++;
}
and:
int i=100;
do
{
Console.WriteLine("Number is {0}", i);
i++;
}while(i<10)
Now the while loop actually generates no output:
however the do-while loop generates this:
Number is 100
despite being well over 10. This is because of the unique behavior of a do-while loop to always run once unlike a regular while loop.
Apart from the Anthony Pegram's answer, you can use also the while loop, which checks the condition BEFORE getting into the loop
while (someCriteria)
{
if (someCondition)
{
someCriteria = false;
// or you can use break;
}
if (ignoreJustThisIteration)
{
continue;
}
}
I am having trouble implementing a sort algo (merge) for singly list as defined below
My mergesort method always gives me null..I am not able to figure out what is wrong
Can you guys help me out?
Node class
public class Node
{
private int data;
private Node next;
}
Linked List class
public class SSL
{
private Node head;
}
My merge sort code
public static void MergeSort(SSL a)
{
SSL x = new SSL();
SSL y = new SSL();
if (a.Head == null || a.Head.Next == null) // base case if list has 0 or 1 element
return;
AlternateSplitting(a, x, y);
MergeSort(x);
MergeSort(y);
a = SortedMerge(x, y);
}
I implemented following helper methods to implement merge sort
AlternateSplitting: This method will split the list into 2 lists
public static void AlternateSplitting(SSL src, SSL odd, SSL even)
{
while (src.Head != null)
{
MoveNode(odd, src);
if (src.Head != null)
MoveNode(even, src);
}
} // end of AlternateSplitting
This method will merge the 2 list and return a new list
public static SSL SortedMerge(SSL a, SSL b)
{
SSL c = new SSL();
if (a.Head == null)
return b;
else
if (b.Head == null)
return a;
else
{
bool flagA = false;
bool flagB = false;
Node currentA = new Node();
Node currentB = new Node();
while (!flagA && !flagB)
{
currentA = a.Head;
currentB = b.Head;
if (currentA.Data < currentB.Data)
{
MoveNodeToEnd(a, c);
currentA = a.Head;
if (currentA== null)
flagA = true;
}
else
if (currentA.Data > currentB.Data)
{
MoveNodeToEnd(b, c);
currentB = b.Head;
if (currentB== null)
flagB = true;
}
} // end of while
if (flagA)
{
while (currentB != null)
{
MoveNodeToEnd(b, c);
currentB = b.Head;
}
}
else
if(flagB)
{
while (currentA != null)
{
MoveNodeToEnd(a, c);
currentA = a.Head;
}
}
return c;
} // end of outer else
} // end of function sorted merge
I am not able to figure out what is
wrong Can you guys help me out?
Find a bug and you fix it for a day. Teach how to find bugs and believe me, it takes a lifetime to fix the bugs. :-)
Your fundamental problem is not that the algorithm is wrong -- though, since it gives incorect results, it certainly is wrong. But that's not the fundamental problem. The fundamental problem is that you don't know how to figure out where a program goes wrong. Fix that problem first! Learn how to debug programs.
Being able to spot the defect in a program is an acquired skill like any other -- you've got to learn the basics and then practice for hundreds of hours. So learn the basics.
Start by becoming familiar with the basic functions of your debugger. Make sure that you can step through programs, set breakpoints, examine local variables, and so on.
Then write yourself some debugging tools. They can be slow -- you're only going to use them when debugging. You don't want your debugging tools in the production version of your code.
The first debugging tool I would write is a method that takes a particular Node and produces a comma-separated list of the integers that are in the list starting from that node. So you'd say DumpNode(currentB) and what would come back is, say "{10,20,50,30}". Obviously doing the same for SSL is trivial if you can do it for nodes.
I would also write tools that do things like count nodes in a list, tell you whether a given list is already sorted, and so on.
Now you have something you can type into the watch window to more easily observe the changes to your data structures as they flow by. (There are ways to make the debugger do this rendering automatically, but we're discussing the basics here, so let's keep it simple.)
That will help you understand the flow of data through the program more easily. And that might be enough to find the problem. But maybe not. The best bugs are the ones that identify themselves to you, by waving a big red flag that says "there's a bug over here". The tool that turns hard-to-find bugs into self-identifying bugs is the debug assertion.
When you're writing your algorithm, think "what must be true?" at various points. For example, before AlternateSplitting runs, suppose the list has 10 items. When it is done running, the two resulting lists had better have 5 items each. If they don't, if they have 10 items each or 0 items each or one has 3 and the other has 7, clearly you have a bug somewhere in there. So start writing debug-only code:
public static void AlternateSplitting(SSL src, SSL odd, SSL even)
{
#if DEBUG
int srcCount = CountList(src);
#endif
while (src.Head != null) { blah blah blah }
#if DEBUG
int oddCount = CountList(odd);
int evenCount = CountList(even);
Debug.Assert(CountList(src) == 0);
Debug.Assert(oddCount + evenCount == srcCount);
Debug.Assert(oddCount == evenCount || oddCount == evenCount + 1);
#endif
}
Now AlternateSplitting will do work for you in the debug build to detect bugs in itself. If your bug is because the split is not working out correctly, you'll know immediately when you run it.
Do the same thing to the list merging algorithm -- figure out every point where "I know that X must be true at this point", and then write a Debug.Assert(X) at that point. Then run your test cases. If you have a bug, then the program will tell you and the debugger will take you right to it.
Good luck!
I'm working on a portion of code that is essentially trying to reduce a list of strings down to a single string recursively.
I have an internal database built up of matching string arrays of varying length (say array lengths of 2-4).
An example input string array would be:
{"The", "dog", "ran", "away"}
And for further example, my database could be made up of string arrays in this manner:
(length 2) {{"The", "dog"},{"dog", "ran"}, {"ran", "away"}}
(length 3) {{"The", "dog", "ran"}.... and so on
So, what I am attempting to do is recursively reduce my input string array down to a single token. So ideally it would parse something like this:
1) {"The", "dog", "ran", "away"}
Say that (seq1) = {"The", "dog"} and (seq2) = {"ran", "away"}
2) { (seq1), "ran", "away"}
3) { (seq1), (seq2)}
In my sequence database I know that, for instance, seq3 = {(seq1), (seq2)}
4) { (seq3) }
So, when it is down to a single token, I'm happy and the function would end.
Here is an outline of my current program logic:
public void Tokenize(Arraylist<T> string_array, int current_size)
{
// retrieve all known sequences of length [current_size] (from global list array)
loc_sequences_by_length = sequences_by_length[current_size-min_size]; // sequences of length 2 are stored in position 0 and so on
// escape cases
if (string_array.Count == 1)
{
// finished successfully
return;
}
else if (string_array.Count < current_size)
{
// checking sequences of greater length than input string, bail
return;
}
else
{
// split input string into chunks of size [current_size] and compare to local database
// of known sequences
// (splitting code works fine)
foreach (comparison)
{
if (match_found)
{
// update input string and recall function to find other matches
string_array[found_array_position] = new_sequence;
string_array.Removerange[found_array_position+1, new_sequence.Length-1];
Tokenize(string_array, current_size)
}
}
}
// ran through unsuccessfully, increment length and try again for new sequence group
current_size++;
if (current_size > MAX_SIZE)
return;
else
Tokenize(string_array, current_size);
}
I thought it was straightforward enough, but have been getting some strange results.
Generally it appears to work, but upon further review of my output data I'm seeing some issues. Mainly, it appears to work up to a certain point...and at that point my 'curr_size' counter resets to the minimum value.
So it is called with a size of 2, then 3, then 4, then resets to 2.
My assumption was that it would run up to my predetermined max size, and then bail completely.
I tried to simplify my code as much as possible, so there are probably some simple syntax errors in transcribing. If there is any other detail that may help an eagle-eyed SO user, please let me know and I'll edit.
Thanks in advance
One bug is:
string_array[found_array_position] = new_sequence;
I don't know where this is defined, and as far as I can tell if it was defined, it is never changed.
In your if statement, when if match_found ever set to true?
Also, it appears you have an extra close brace here, but you may want the last block of code to be outside of the function:
}
}
}
It would help if you cleaned up the code, to make it easier to read. Once we get past the syntactic errors it will be easier to see what is going on, I think.
Not sure what all the issues are, but the first thing I'd do is have your "catch-all" exit block right at the beginning of your method.
public void Tokenize(Arraylist<T> string_array, int current_size)
{
if (current_size > MAX_SIZE)
return;
// Guts go here
Tokenize(string_array, ++current_size);
}
A couple things:
Your tokens are not clearly separated from your input string values. This makes it more difficult to handle, and to see what's going on.
It looks like you're writing pseudo-code:
loc_sequences_by_length is not used
found_array_position is not defined
Arraylist should be ArrayList.
etc.
Overall I agree with James' statement:
It would help if you cleaned up the
code, to make it easier to read.
-Doug