I am having a condition as follows
if (fedId == ftax)
{
index = 0;
string strEntryDets = string.Empty;
strEntryDets = EntryDetail().ToString();
sbBatchHeaderFile.AppendLine(strEntryDets);
}
When this statement is true i should increment the index value starting from zero can any one give me an idea
Set it to zero outside the if block.
Also, what's the point of setting strEntryDets to an emptry string if you're just going to set it again on the very next line? In fact, you can just avoid setting that variable altogether.
index = 0;
if (fedId == ftax)
{
index++;
sbBatchHeaderFile.AppendLine(EntryDetail().ToString());
}
If you need to use index (starting at zero) and THEN increment it, you can do this:
if (fedId == ftax)
{
foo(index++);
}
This will pass in 0 and then increment it to 1.
I don't know what is your iteration logic and when you are using all this stuff thats why I'm giving this suggestion.
Add this class to your application:
public class IndexHolder
{
private static int m_Index = -1;
public static int GetNext()
{
return m_Index++;
}
public static void Reset()
{
m_Index = -1;
}
}
In your code use as this :
index = IndexHolder.GetNext();
Related
Im trying to write a function complex_decode( string str) in c sharp that takes a non-simple repeated encoded string, and returns the original un-encoded string.
for example, "t11h12e14" would return "ttttttttttthhhhhhhhhhhheeeeeeeeeeeeee". I have been successful in decoding strings where the length is less than 10, but unable to work with length for than 10. I am not allowed to use regex, libraries or loops. Only recursions.
This is my code for simple decode which decodes when length less than 10.
public string decode(string str)
{
if (str.Length < 1)
return "";
if(str.Length==2)
return repeat_char(str[0], char_to_int(str[1]));
else
return repeat_char(str[0], char_to_int(str[1]))+decode(str.Substring(2));
}
public int char_to_int(char c)
{
return (int)(c-48);
}
public string repeat_char(char c, int n)
{
if (n < 1)
return "";
if (n == 1)
return ""+c;
else
return c + repeat_char(c, n - 1);
}
This works as intended, for example input "a5" returns "aaaaa", "t1h1e1" returns "the"
Any help is appreciated.
Here is another way of doing this, assuming the repeating string is always one character long and using only recursion (and a StringBuilder object):
private static string decode(string value)
{
var position = 0;
var result = decode_char(value, ref position);
return result;
}
private static string decode_char(string value, ref int position)
{
var next = value[position++];
var countBuilder = new StringBuilder();
get_number(value, ref position, countBuilder);
var result = new string(next, Convert.ToInt32(countBuilder.ToString()));
if (position < value.Length)
result += decode_char(value, ref position);
return result;
}
private static void get_number(string value, ref int position, StringBuilder countBuilder)
{
if (position < value.Length && char.IsNumber(value[position]))
{
countBuilder.Append(value[position++]);
get_number(value, ref position, countBuilder);
}
}
I've refactored your code a bit. I've removed 2 unnecessary methods that you don't actually need. So, the logic is simple and it works like this;
Example input: t3h2e4
Get the first digit. (Which is 2 and has index of 1)
Get the first letter comes after that index, which is our next letter. (Which is "h" and has index of 2)
Slice the string. Start from index 1 and end the slicing on index 2 to get repeat count. (Which is 3)
Repeat the first letter of string for repeat count times and combine it with the result you got from step 5.
Slice the starting from the next letter index we got in second step, to the very end of the string and pass this to recursive method.
public static string Decode(string input)
{
// If the string is empty or has only 1 character, return the string itself to not proceed.
if (input.Length <= 1)
{
return input;
}
// Convert string into character list.
var characters = new List<char>();
characters.AddRange(input);
var firstDigitIndex = characters.FindIndex(c => char.IsDigit(c)); // Get first digit
var nextLetterIndex = characters.FindIndex(firstDigitIndex, c => char.IsLetter(c)); // Get the next letter after that digit
if (nextLetterIndex == -1)
{
// This has only one reason. Let's say you are in the last recursion and you have c2
// There is no letter after the digit, so the index will -1, which means "not found"
// So, it will raise an exception, since we try to use the -1 in slicing part
// Instead, if it's not found, we set the next letter index to length of the string
// With doing that, you either get repeatCount correctly (since remaining part is only digits)
// or you will get empty string in the next recursion, which will stop the recursion.
nextLetterIndex = input.Length;
}
// Let's say first digit's index is 1 and the next letter's index is 2
// str[2..3] will start to slice the string from index 2 and will stop in index 3
// So, it will basically return us the repeat count.
var repeatCount = int.Parse(input[firstDigitIndex..nextLetterIndex]);
// string(character, repeatCount) constructor will repeat the "character" you passed to it for "repeatCount" times
return new string(input[0], repeatCount) + Decode(input[nextLetterIndex..]);
}
Examples;
Console.WriteLine(Decode("t1h1e1")); // the
Console.WriteLine(Decode("t2h3e4")); // tthhheeee
Console.WriteLine(Decode("t3h3e3")); // ttthhheee
Console.WriteLine(Decode("t2h10e2")); // tthhhhhhhhhhee
Console.WriteLine(Decode("t2h10e10")); // tthhhhhhhhhheeeeeeeeee
First you can simplify your repeat_char function, you have to have a clear stop condition:
public static string repeat_char(char c, int resultLength)
{
if(resultLength < 1) throw new ArgumentOutOfRangeException("resultLength");
if(resultLength == 1) return c.ToString();
return c + repeat_char(c, resultLength - 1);
}
See the use of the parameter as equivalent of a counter on a loop.
So you can have something similar on the main function, a parameter that tells when your substring is not an int anymore.
public static string decode(string str, int repeatNumberLength = 1)
{
if(repeatNumberLength < 1) throw new ArgumentOutOfRangeException("length");
//stop condition
if(string.IsNullOrWhiteSpace(str)) return str;
if(repeatNumberLength >= str.Length) repeatNumberLength = str.Length; //Some validation, just to be safe
//keep going until str[1...repeatNumberLength] is not an int
int charLength;
if(repeatNumberLength < str.Length && int.TryParse(str.Substring(1, repeatNumberLength), out charLength))
{
return decode(str, repeatNumberLength + 1);
}
repeatNumberLength--;
//Get the repeated Char.
charLength = int.Parse(str.Substring(1, repeatNumberLength));
var repeatedChar = repeat_char(str[0], charLength);
//decode the substring
var decodedSubstring = decode(str.Substring(repeatNumberLength + 1));
return repeatedChar + decodedSubstring;
}
I used a default parameter, but you can easily change it for a more traditonal style.
This also assumes that the original str is in a correct format.
An excellent exercise is to change the function so that you can have a word, instead of a char before the number. Then you could, for example, have "the3" as the parameter (resulting in "thethethe").
I took more of a Lisp-style head and tail approach (car and cdr if you speak Lisp) and created a State class to carry around the current state of the parsing.
First the State class:
internal class State
{
public State()
{
LastLetter = string.Empty;
CurrentCount = 0;
HasStarted = false;
CurrentValue = string.Empty;
}
public string LastLetter { get; private set; }
public int CurrentCount { get; private set; }
public bool HasStarted { get; private set; }
public string CurrentValue { get; private set; }
public override string ToString()
{
return $"LastLetter: {LastLetter}, CurrentCount: {CurrentCount}, HasStarted: {HasStarted}, CurrentValue: {CurrentValue}";
}
public void AddLetter(string letter)
{
CurrentCount = 0;
LastLetter = letter;
HasStarted = true;
}
public int AddDigit(string digit)
{
if (!HasStarted)
{
throw new InvalidOperationException($"The input must start with a letter, not a digit");
}
if (!int.TryParse(digit, out var num))
{
throw new InvalidOperationException($"Digit passed to {nameof(AddDigit)} ({digit}) is not a number");
}
CurrentCount = CurrentCount * 10 + num;
return CurrentCount;
}
public string GetValue()
{
if (string.IsNullOrEmpty(LastLetter))
{
return string.Empty;
}
CurrentValue = new string(LastLetter[0], CurrentCount);
return CurrentValue;
}
}
You'll notice it's got some stuff in there for debugging (example, the ToString override and the CurrentValue property)
Once you have that, the decoder is easy, it just recurses over the string it's given (along with (initially) a freshly constructed State instance):
private string Decode(string input, State state)
{
if (input.Length == 0)
{
_buffer.Append(state.GetValue());
return _buffer.ToString();
}
var head = input[0];
var tail = input.Substring(1);
var headString = head.ToString();
if (char.IsDigit(head))
{
state.AddDigit(headString);
}
else // it's a character
{
_buffer.Append(state.GetValue());
state.AddLetter(headString);
}
Decode(tail, state);
return _buffer.ToString();
}
I did this in a simple Windows Forms app, with a text box for input, a label for output and a button to crank her up:
const string NotAllowedPattern = #"[^a-zA-Z0-9]";
private static Regex NotAllowedRegex = new Regex(NotAllowedPattern);
private StringBuilder _buffer = new StringBuilder();
private void button1_Click(object sender, EventArgs e)
{
if (textBox1.Text.Length == 0 || NotAllowedRegex.IsMatch(textBox1.Text))
{
MessageBox.Show(this, "Only Letters and Digits Allowed", "Bad Input", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
label1.Text = string.Empty;
_buffer.Clear();
var result = Decode(textBox1.Text, new State());
label1.Text = result;
}
Yeah, there's a Regex there, but it's just to make sure that the input is valid; it's not involved in calculating the output.
I have probably been overthinking it but I am trying to take a list I have and go through the list one by one with a keypress.
For example, I have three strings in a list, and when the player presses L it goes from option 1, to 2. Then 2 to 3. Then 3 to 1. I also need to save this option to a separate string.
Thanks to anyone who can help
Edit:
So I have one script that checks if they key has been pressed
private void Update()
{
if (Input.GetKeyDown(KeyCode.L))
{
gs.ChangeLevel(levelTxt);
}
}
And then on a different script I have the function that will change the option. I know this isn't correct but hopefully you will be able to see what i am trying to do
public List<String> levels;
public string level;
public void ChangeLevel()
{
level = levels.Count[]++;
if(levels.Count > levels.Count)
{
levels.Count[0];
}
}
Edit #2
So I have almost got it with help from the comments. I just need it to increment now (if this is suppose to it will only stay on the first one)
```
public string IncrementLevel()
{
if (levels.Count == 0)
{
levelIndex = 0;
return "";
}
levelIndex = (levelIndex >= levels.Count - 1) ? 0 : levelIndex++;
return levels[levelIndex];
}
And
public void ChangeLevel(Text level)
{
level.text = levels[levelIndex].ToString();
Debug.Log("It is now set to " + levels[levelIndex]);
}
Edit #3
Hey again guys, so the code shared in the comments helped but now I need to take it and decrease it with a different button. Any help would be appreciated.
I am not sure if we are on the same wavelength, however, if you just want to iterate a list then you need a pointer. You can create a function to increment the pointer and pop the value all in one.
private List<string> levels = new List<string>();
private int levelIndex = -1;
public string IncrementLevel()
{
levelIndex = (levels.Count == 0) ? -1 : (levelIndex >= levels.Count - 1) ? 0 : levelIndex + 1;
return (levelIndex == -1) ? "" : levels[levelIndex];
}
public string DecrementLevel()
{
levelIndex = (levels.Count == 0) ? -1 (levelIndex <= 0) ? levels.Count - 1 levelIndex - 1;
return (levelIndex == -1) ? "" : levels[levelIndex];
}
and
private void Update()
{
if (Input.GetKeyDown(KeyCode.L))
{
gs.ChangeLevel(IncrementLevel());
}
}
Try this:
// not tested for compilation, I used 0 as the start
// since that's the index of the first item in a list
int index = 0;
if (Input.GetKey("L"))
{
index++;
if (index > 2)
{
index = 0;
}
// the item you want is yourList[index],
// do whatever you want with it, just make sure
// it's used after the if index > 2 statement;
}
this is the class
data members and getters and setters:
class Queue
{
int[] data; //array
int size; //size of array
int counter; //checker if array is fully or impty
int first; // first element of array
int last; // last element of arry
}
fixed size constructor
public Queue(int size) {
data = new int[this.size];
size = this.size;
counter = 0;
first = 0;
last = 0;
}
default constructor
public Queue() { //default constructor
data = new int[10];
size = 10;
counter = 0;
first = 0;
last = 0;
}
enqueing function "push"
public bool Enqueue(int num) {
bool result;
if (counter<size)
{
data[last] = num;
last++;
if(last == size)
last = 0;
counter++;
return result = true
}
else
{
return result = false;
}
return result;
}
dequeueing function "pop"
public int Dequeueing() {
int result=-1;
// I know that i should make this nullable function but (-1) good at this time
if (counter>0)
{
result = data[first];
first++;
if (first==size)
first = 0;
counter--;
}
return result;
}
on the main it is excute the enqueueing good but dequeueing its (first++)and (counter--) but it doesn't delete first input **
**why it doesn't delete (17)
static void Main(string[] args)
{
Queue q1 = new Queue();
q1.Enqueue(17);
q1.Enqueue(20);
q1.Enqueue(25);
q1.Enqueue(15);
q1.Enqueue(14);
q1.Enqueue(13);
q1.Dequeueing();
Console.ReadLine();
}
Your expectation that once you do first++; and counter--;, the data[first] will be deleted is misplaced. Frankly, if it will somehow cause data[first] to be deleted then rest of your code will not work. What that code does is to simply Dequeue. The Queue bounds are marked using first and last, with the help of counter, so only those things need to change and no array element deletion needs to happen
Let me help you understand your code a bit. Your Queue class is what is called a Circular Queue. In such an implementation, you have the benefit that the amount of storage allocated for the Queue is "fixed" and determined on construction. This also implies that when you Enqueue there will be no extra memory requested and when you Dequeue there will be no memory released.
If you wish to somehow identify an unoccupied slot in the array, you can use special values. For example, making int?[] data, you can store var item = data[front]; data[front] = null before Dequeueing. Or, you can use a routine like GetQueueData to return all the elements in the Queue as a separate IEnumerable
public IEnumerable<int> GetQueueData() {
for (int i = first, cnt = 0; cnt < counter; i = (i + 1) % size, ++cnt)
yield return data[i];
}
The array named data will remain in the same state as when you created it as you have not done anything to make this otherwise.
I have written a recursion (actually I found the recursion online) to get all possible permutations of a set of numbers but in some occasions, due to the large number of possible permutations, I would like to add an If statement to terminate the recursion before it goes through all permutations. I have tried entering a return statement but it doesn't seem to work.
I am a bit of a newbie in coding so apologies if the answer obvious to everyone, I just cannot get it.
class EntryPoint
{
static void Main()
{
//input an initial sequence of the trains to schedule
Console.Write("Input train permutation");
string inputLine = Console.ReadLine();
GenerateTrainOrder GTO = new GenerateTrainOrder();
GTO.InputSet = GTO.MakeCharArray(inputLine);
GTO.CalcPermutation(0);
}
}
class GenerateTrainOrder
{
private int elementLevel = -1; // elements examined iterates immediately after the CalcPermutation initiates so we must set it equal -1 to start from 0
private int[] permutationValue = new int[0];
public int[,] Paths = new int[ParametersClass.timetableNumber, ParametersClass.trainsToSchedule];
private char[] inputSet;
public char[] InputSet
{
get { return inputSet; }
set { inputSet = value; }
}
private int permutationCount = 0;
public int PermutationCount
{
get { return permutationCount; }
set { permutationCount = value; }
}
//transform the input from the console to an array for later use
public char[] MakeCharArray(string InputString)
{
char[] charString = InputString.ToCharArray();
Array.Resize(ref permutationValue, charString.Length);
return charString;
}
public void CalcPermutation(int k)
{
elementLevel++;
permutationValue.SetValue(elementLevel, k);
//if we have gone through all the elements which exist in the set, output the results
if (elementLevel == ParametersClass.trainsToSchedule)
{
OutputPermutation(permutationValue); // output TrainOrder by passing the array with the permutation
}
//if there are elements which have not been allocated a place yet
else
{
for (int i = 0; i < ParametersClass.trainsToSchedule; i++)
{
//iterate until we come upon a slot in the array which has not been allocated an elements yet
if (permutationValue[i] == 0)
{
CalcPermutation(i); //rerun the code to allocate an element to the empty slot. the location of the empty slot is given as a parameter (this is how k increments)
}
}
}
elementLevel--;
permutationValue.SetValue(0, k);
}
private void OutputPermutation(int[] value)
{
int slot = 0;
foreach (int i in value)
{
Paths[permutationCount, slot] = Convert.ToInt16(Convert.ToString(inputSet.GetValue(i-1)));
slot++;
}
PermutationCount++;
}
}
It is a bit tricky to stop a recursive calculation. The best method involves a global variable (or a private class variable if you have objects).
This variable says if the recursion should stop or not:
bool stopRecursion = false;
Now inside your calculation you update this variable after each step:
if(_my_condition_is_met) stopRecursion = true;
At the start of your recursively called method you check the state of this variable:
public void CalcPermutation(int k)
{
if(stopRecursion) return;
...
And you check this variable after each call to CalcPermutation:
for (int i = 0; i < ParametersClass.trainsToSchedule; i++)
{
//iterate until we come upon a slot in the array which has not been allocated an elements yet
if (permutationValue[i] == 0)
{
CalcPermutation(i);
if(stopRecursion) return;
....
With this method you unwind even deep call levels as soon as your stop condition is met.
Thanks for the replies everyone. I managed to make it work by doing the following:
Under the CalcPermutation(i) line, I wrote
if (permutationCount == ParametersClass.timetableNumber)
{
return;
}
I tried running it a few times with different inputs and it seems to work just fine.
for (int i = 0; i < ParametersClass.trainsToSchedule; i++)
{
//iterate until we come upon a slot in the array which has not been allocated an elements yet
if({your condition}){
break;
}
if (permutationValue[i] == 0)
{
CalcPermutation(i); //rerun the code to allocate an element to the empty slot. the location of the empty slot is given as a parameter (this is how k increments)
}
}
I am working with a datagrid view, this datagrid view allows the user to edit cells, I want to set it up so that when a user inserts a negative value, it will convert this value to 0, what would be the best way to code this, i have created the followin code below, it appears to check for negative values, however it does not change the value to zero
if (Convert.ToInt32(dgvDetails.CurrentRow.Cells[2].Value.ToString()) < -0)
{
intQtyInsp = 0;
}
else
{
intQtyInsp = Int32.Parse(row.Cells[2].Value.ToString());
That might be because dgvDetails.CurrentRow.Cells[2].Value.ToString() and row.Cells[2].Value.ToString() might not be the same cell you are checking..
This will do what you require
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
DataGridViewCell currentCell =
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
int cellValue = Convert.ToInt32(currentCell.Value);
if (cellValue < 0)
currentCell.Value = 0.ToString();
}
I hope this helps.
intQtyInsp =Int32.Parse(dgvDetails.CurrentRow.Cells[2].Value.ToString());
if(intQtyInsp < 0)
{
intQtyInsp = 0;
}
if(score < 0) { *score = 0; }
int valueFromCell = Convert.ToInt32(dgvDetails.CurrentRow.Cells[2].Value.ToString());
intQtyInsp = valueFromCell < 0
? 0
: valueFromCell ;
I suggest to use a extension method to ensure if the user inputs a int.
Extension method
public static class StringExtension
{
public static int TryConvertToInt32(this string value)
{
int result = 0;
if (Int32.TryParse(value, out result))
return result;
return result;
}
}
Usage
// call the extension method
int intQtyInsp = dgvDetails.CurrentRow.Cells[2].Value.ToString().TryConvertToInt32();
// And check for lower than zero values.
intQtyInsp = intQtyInsp >= 0 ? intQtyInsp : 0;