Why we use -1 within a for Loop c# - c#

I have code which checks if a word if a palindrome or not. Within the for loop there is a -1 value. Can someone explain to me why -1 is used after the name.Length in c#
public static void Main()
{
string name = "Apple";
string reverse = string.Empty;
for (int i = name.Length - 1; i >= 0; i--)
{
reverse +=name[i];
}
if (name == reverse)
{
Console.WriteLine($"{name} is palindrome");
}else
{
Console.WriteLine($"{name} is not palindrome");
}

That's because whoever wrote the code, wanted to write:
reverse += name[i];
String operator [] takes values from 0 upto (string's length-1). If you pass length or more, you will get an exception. So, code's author had to ensure that i==Length won't be ever passed there. So it starts from Length-1 and counts downwards.
Also, note that the other bound of i is 0 (>=, not >, so 0 is included), so the loop visits all values from 0 to length-1, so it visits all characters from the string. Job done.
However, it doesn't have to be written in that way. The only thing is to ensure that the string operator [] wont see values of of its range. Compare this loop, it's identical in its results:
for (int i = name.Length; i >= 1; i--)
{
reverse += name[i-1];
}
Note that I also changed 0 to 1.
Of course, it's also possible to write a loop with the same effects in a lot of other ways.

The first element in an array is at the index 0 (array[0]). Because the indexing starts at 0 instead of 1 it means that the final element in the array will be at index array.Length-1.
If you had the word and then your array would look like:
name[0] = 'a'
name[1] = 'n'
name[2] = 'd'
the name.Length would equal 3. As you can see, there isn't an element at index 3 in the array so you need to subtract 1 from the length of the array to access the last element.
The for loop in your example starts with the last element in the array (using i as the index). If you tried to set i to i = name.Length then you would get an index out of bounds error because there isn't an element at the position name.Length.

String operator [] takes values from 0. The first element in an string is at the index 0, so we need to adjust by subtracting one.
For Example:
string str = "test";
int length = str.length; //Length of the str is 4. (0 to 3)

Related

How can I check for integers in list and print the index of them?

so my problem is that I don't know how to go forward in the list and print the next same integer if there is one.
Here is what I have at the moment:
while (list.Contains(input1))
{
Console.WriteLine(input1 + " is at index " + list.IndexOf(input1))
}
I am trying to list all of the integers that are in the list and print the index of them. But not remove after finding one of the integers (this was at least my first idea.).
IndexOf has an overload with two parameters, which allows you to start searching at a later position in the list.
Since this is obviously a learning exercise, I won't spoil it by providing the full code, but rather suggest that you try to implement the following algorithm:
Find the index of input starting at position 0.
If not found (i.e., IndexOf returns -1): we're done. Otherwise:
Print and remember that index.
Start again at step 1, but this time, don't start searching at 0 but at the index you remembered + 1.
You can do the following:
go through the list/array using for statement
for(int i=0; i < list.length; i++) // loop though list
then inside the loop check the value of the current item using if statement:
if(list[i] == input1)
//do smothing
The list[0] represent the first item in the array, which means the index is 0.
so in the example above the i will be the current index so long that you in the loop.
I didn't write the full code for learning purpose in reference to #Heinzi answer.
Hope that could be helpful!
This is an implementation possibility. It is longer than it has to be, but it makes it clearer for beginners how one could tackle this problem.
Since you wanted to only show numbers that come up more than once here is an implementation method. If you want to show numbers that come up only once too just erase everything about lastindex
List<int> yourlist = new List<int> { 1,1,1,1,1,11,2,3,3,4,4,5 };
int input = 0;
input = Convert.ToInt32(Console.ReadLine());
var index = yourlist.IndexOf(input);
//this checks if your input is in the list
var lastindex = yourlist.LastIndexOf(input);
//this does the same but it searches for the last implementation of your input
if (index != -1 && lastindex != index)
//this if checks if your number comes up more than once. IndexOf returns -1 if there is no occurence of your input
{
Console.Write($"the index of {input} is {index}");
for (int i = index+1; i <= yourlist.Count; i++)
//this loop takes the position of the first occurence of your number and then counts up from there
{
var tempindex = yourlist.IndexOf(input, i);
if (tempindex != -1)
//this if lets everything except -1 through
{
Console.Write($" and {tempindex}");
}
}
}
else
{
Console.WriteLine("your number cannot be found twice in the list");
}

Domino recursion

I have a recursion assignment where I have to input into console the following data:
On the first line a natural number equal with the number of tiles I have to input on the following lines (in my example the first number is 6).
On the following lines the domino tiles in the following order:
1 2
1 3
3 4
2 3
3 5
4 5
On the last line another number representing the number of tiles that needs to be returned on each separate line (in my example the number is equal with 3).
With this data I have to display all possible combinations of pairs. For each separate line the number the second number from the first pair has to be equal with the first number of the following pair and so on. I had a hint for this assignment where I have to declare an intermediary list that is equal with the function (using recursion from the start) but when I'm trying to run the code it gives me a null exception for the intermediaryList.
In the first instance I read the data as a 2d array but settled with a simple string array where.
This is my code so far, could you help me with a suggestion, how to avoid the null exception?
(sorry if I missed something from the explanation, this is my second post here so far and thank you in advance). Also I have to mention that I'm allowed to use just "using System;" Not allowed to use Linq or anything else.
enter code here
static string[] ReadDominoTiles(int n)
{
string[] input = new string[n];
for (int i = 0; i < n; i++)
{
input[i] = Console.ReadLine();
}
return input;
}
static string[] DominoSolution(string[] dominoTiles, int numberOfPairs)
{
string[] finalList = new string[numberOfPairs];
if (numberOfPairs == 1)
{
return finalList;
}
string[] intermediaryList = DominoSolution(dominoTiles, numberOfPairs - 1);
for (int i = 0; i < intermediaryList.Length; i++)
{
for (int j = 0; j < dominoTiles.Length; j++)
{
// This is where I get the nullref exception, every value from intermediaryList is null
if (intermediaryList[i] != dominoTiles[j] && intermediaryList[j][1] == dominoTiles[j][0])
{
finalList[j] += intermediaryList[j] + " " + dominoTiles[j];
}
}
}
return finalList;
}
static void Main(string[] args)
{
int n = Convert.ToInt32(Console.ReadLine());
string[] dominoTiles = ReadDominoTiles(n);
int numberOfPairs = Convert.ToInt32(Console.ReadLine());
Console.WriteLine(DominoSolution(dominoTiles, numberOfPairs));
}
This is where I get the nullref exception, every value from intermediaryList is null
That's correct, you call the function recursively after doing exactly zero work, besides adding a recursion termination condition which returns an array of nulls. So the first time you come out of your recursion you have in intermediaryList a number of null elements, so when you pretend they're strings and try to get intermediaryList[j][1] you'll get a null reference exception.
As to the solution, it's not exactly clear what's with all the arrays you're allocating. Use a List<> with an actual type and do your work properly. Though I hate to break it to you but if I understand your assignment correctly the solution will use backtracking and combinatorics, which is much more code and much better structured than what you have here.

How should I properly compare my array index value against array length

Say I have an array that has 5 values int[] gear = new int[] {5,4,3,2,1}; and I also have a variable that I use to get the value I want int currentGear = 0; Now I would like to step through the array under a certain condition with this code:
if(rpm > shiftRPM && currentGear < gear.Length)
currentGear++;
Console.WriteLine( gear[cuurentGear] );
However, using that code I am able to go past the array length because gear.Length is 5, but array's are zero indexed(i.e. the max number I can have is 4).
So my solution is to just add 1 to currentGear in the if statement, but this for loops works as expected:
for(int i=0; i<gear.Length;i++;)
Console.Write(gear[i]);
And outputs: 5 4 3 2 1 with no errors.
Also, if I Console.Write(gear.Length); it outputs 5, so clearly my error is with my if statement allowing my index to pass gear.Length since 4 < 5 and 5 is out of range.
Is there a better way to increment my array index variable than doing this:
if(rpm > shiftRPM && (currentGear+1) < gear.Length)
currentGear++;
or is that the best way to handle this situation?
Your solution is basically the best way. The maximum value of an index is in fact Length-1, not Length, so when you only check that currentGear is less than Length, you are not really guarding against it getting too large.
why not initialize currentGear as:
var currentGear = -1;

How string quote, length total count and arrayname[int] work?

I'm making a program which reverses words to sdrow.
I understand that for it to work it needs to be written this way.
I'm more interested on WHY it has to be this way.
Here is my code:
Console.WriteLine("Enter a word : ");
string word = Console.ReadLine();
string rev = "";
int length;
for (length = word.Length - 1; length >= 0; length--)
{
rev = rev + word[length];
}
Console.WriteLine("The reversed word is : {0}", rev);
My questions are:
a) why you must use quotes to initialize your string
b) Why must you start your loop at one less than the total length of your string
c) How arrayname[int] works
I'm pretty new to C# and this site, as well. I hope my questions make sense and that I've asked them in the correct and proper way.
Thank you for your time!
This is how I've interpreted your question.
You want to know why you must use quotes to initialize your string
Why must you start your loop at one less than the total length of your string
How arrayname[int] works
I think that the best way to explain this to you is to go through your code, and explain what it does.
Console.WriteLine("Enter a word : ");
The first line of code prints Enter a word : into the console.
string word = Console.ReadLine();
This line "reads" the input from the console, and puts it into a string called word.
string rev = "";
This initiates a string called rev, setting it's value to "", or an empty string. The other way to initiate the string would be this:
string rev;
That would initiate a string called rev to the value of null. This does not work for your program because rev = rev + word[length]; sets rev to itself + word[length]. It throws an error if it is null.
The next line of your code is:
int length;
That sets an int (which in real life we call an integer, basically a number) to the value of null. That is okay, because it gets set later on without referencing itself.
The next line is a for loop:
for (length = word.Length - 1; length >= 0; length--)
This loop sets an internal variable called length to the current value of word.Length -1. The second item tells how long to run the loop. While the value of length is more than, or equal to 0, the loop will continue to run. The third item generally sets the rate of increase or decrease of your variable. In this case, it is length-- that decreases length by one each time the loop runs.
The next relevant line of code is his:
rev = rev + word[length];
This, as I said before sets rev as itself + the string word at the index of length, whatever number that is at the time.
At the first run through the for loop, rev is set to itself (an empty string), plus the word at the index of length - 1. If the word entered was come (for example), the index 0 would be c, the index 1 would be o, 2 would be m, and 3 = e.
The word length is 4, so that minus one is 3 (yay - back to Kindergarten), which is the last letter in the word.
The second time through the loop, length will be 2, so rev will be itself (e) plus index 2, which is m. This repeats until length hits -1, at which point the loop does not run, and you go on to the next line of code.
...Which is:
Console.WriteLine("The reversed word is : {0}", rev);
This prints a line to the console, saying The reversed word is : <insert value of rev here> The {0} is an internal var set by the stuff after the comma, which in this case would be rev.
The final output of the program, if you inserted come, would look something like this:
>Enter a word :
>come
>
>The reversed word is : emoc
a) you must to initialize or instantiate the variable in order to can work with it. In your case is better to use and StringBuilder, the string are inmutable objects, so each assignement means to recreate a new string.
b) The arrays in C# are zero index based so their indexes go from zero to length -1.
c) An string is an characters array.
Any case maybe you must to try the StringBuilder, it is pretty easy to use
I hope this helps
a) you need to initialize a variable if you want to use it in an assignment rev = rev + word[length];
b) you are using a for loop which means that you define a start number length = word.Length - 1, a stop criteria length >= 0 and a variable change length--
So lenght basically descends from 5 to 0 (makes 6 loops). The reason is that Arrays like 'string' a char[] are zerobased indexed.. means that first element is 0 last is array.Length - 1
c) So a string is basically a chain of char's.. with the []-Operator you can access a single index. The Return Type of words[index] is in this case a character.
I hope it helped
a) You need to first instantiate the string rev before you can assign it values in the loop. You could also say "string rev = String.Empty". You are trying to add word to rev and if you don't tell it first that rev is an empty string it doesn't know what it is adding word to.
b) The characters of the string have indexes to show which position they appear in the string. These indexes start at 0. So you're first character will have an index of 0. If the length of your string is 6 then the last character's index will be 5. So length - 1 will give you the value of the last character's index which is 5. A c# for loop uses the following parameters
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
where "int i = 0;" is the starting index; "i < 10" tells the loop when to stop looping; and "i++" tells it to increment i (the index) after each loop.
So in your code you are saying start at the last character of my string; perform this loop while there are still characters in the string; and decrease the index of the string after each loop so the next loop will look at the previous character in the string.
c) word[length] then in this scenario is saying add the character that has the position with index "length" to the rev string. This will basically reverse the word.
As usual you can do it in linq and avoid the (explicit) loops
using System;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Enter a word : ");
string word = Console.ReadLine();
Console.WriteLine("The reversed word is : {0}", new string (word.Reverse().ToArray()));
Console.ReadLine();
}
}
}
var reversedWords = string.Join(" ",
str.Split(' ')
.Select(x => new String(x.Reverse().ToArray())));
Take a look here :
Easy way to reverse each word in a sentence

Why does "abcd".StartsWith("") return true?

Title is the entire question. Can someone give me a reason why this happens?
Yes - because it does begin with the empty string. Indeed, the empty string logically occurs between every pair of characters.
Put it this way: what definition of "starts with" could you give that would preclude this? Here's a simple definition of "starts with" that doesn't:
"x starts with y if the first y.Length characters of x match those of y."
An alternative (equivalent) definition:
"x starts with y if x.Substring(0, y.Length).Equals(y)"
I will try to elaborate on what Jon Skeet said.
Let's say x, y and z are strings and + operator is in fact concatenation, then:
If we can split z to write z = x + y that means that z starts with x.
Because every string z can be split to z = "" + z it follows that every string starts with "".
So, because ("" + "abcd") == "abcd" it follows that "abcd" starts with ""
I'll start with a related fact that is easier to understand.
The empty set is a subset of every set.
Why? The definition of subset states that A is a subset of B if every element of A is an element of B. Conversely, A is not a subset of B if there is an element of A that is not an element of B.
Now fix a set B. I'll establish that the empty set is a subset of B. I'll do this by showing that it is not the case that the empty set is not a subset of B. If the empty set were not a subset of B then I could find an element of the empty set that is not in B. But the empty set does not have any elements and thus I can not find an element that is not in B. Therefore, it is not the case that the empty set is not a subset of B. Thus, the empty set must be a subset of B.
Any string starts with the empty string.
First, we must agree on our definition of starts with. Let s and t be strings We say that s starts with t if s.Length >= t.Length and the first t.Length characters of t match those of s. That is, s.Length >= t.Length and for every Int32 index such that 0 <= index < t.Length, s[index] == t[index] is true. Conversely, we would say that s does not start with t if the statement
s.Length < t.Length or s.Length >= t.Length and there is an Int32 index such that 0 <= index < t.Length and s[index] != t[index]
is true. In plain English, s is shorter than t, or, if not, there is a character in t not matching the character as the same position in s.
Now fix a string s. I'll establish that s starts with the empty string. I'll do this by showing that it is not the case that s does not start with the empty string. If s does not start with the empty string then s.Length < String.Empty.Length or s.Length >= String.Empty.Length and there is an Int32 index such that 0 <= index < String.Empty.Length. But s.Length >= 0 and String.Empty.Length is equal to zero so it is impossible for s.Length < String.Empty.Length to be true. Similarly, since ``String.Empty.Lengthis equal to zero, there is noInt32 indexsatisfying0 <= index < String.Empty.Length`. Therefore
s.Length < String.Empty.Length or s.Length >= String.Empty.Length and there is an Int32 index such that 0 <= index < String.Empty.Length
is false. Therefore, it is not the case that s does not start with the empty string. Thus, s must start with the empty string.
The following is an implementation of starts with coded as an extension to string.
public static bool DoStartsWith(this string s, string t) {
if (s.Length >= t.Length) {
for (int index = 0; index < t.Length; index++) {
if (s[index] != t[index]) {
return false;
}
}
return true;
}
return false;
}
The above two bolded facts are examples of vacuously true statements. They are true by virtue of the fact that the statements defining them (subset and starts with) are universal quantifications over empty universes. There are no elements in the empty set, so there can not be any elements of the empty set not in some other fixed set. There are no characters in the empty string, so there can not be a character as some position in the empty string not matching the character in the same position in some other fixed string.
This method compares the value parameter to the substring at the beginning of this string that is the same length as value, and returns a value that indicates whether they are equal. To be equal, value must be an empty string (Empty), a reference to this same instance, or match the beginning of this instance.
.NET String.StartsWith
true if the character sequence represented by the argument is a prefix of the character sequence represented by this string; false otherwise. Note also that true will be returned if the argument is an empty string or is equal to this String object as determined by the equals(Object) method.
Java String.startsWith
Let's just say "abcd".StartsWith("") returns false.
if so then what does the following expression eval to, true or false:
("abcd".Substring(0,0) == "")
it turns out that evals to true, so the string does start with the empty string ;-), or put in other words, the substring of "abcd" starting at position 0 and having 0 length equals the empty string "". Pretty logical imo.
In C# this is how the specification tells it to react;
To be equal, value must be an empty string (Empty), a reference to this same instance, or match the beginning of this instance.
The first N characters of the two strings are identical. N being the length of the second string, i.e. zero.
Why does “abcd”.StartsWith(“”) return true?
THE REAL ANSWER:
It has to be that way otherwise you'd have the case where
"".startsWith("") == false
"".equals("") == true
but yet
"a".startsWith("a") == true
"a".equals("a") == true
and then we'd have Y2K all over again because all the bank software that depends on equal strings starting with themselves will get our accounts mixed up and suddenly Bill Gates will have my wealth and I'd have his, and damn it! Fate just isn't that kind to me.
Just for the record, String.StartsWith() internally calls the method System.Globalization.CultureInfo.IsPrefix() which makes the following check explicitly:
if (prefix.Length == 0)
{
return true;
}
Because a string begins well with "nothing".
If you think of it in regular expressions terms, it makes sense.
Every string (not just "abcd", also "" and "sdf\nff") ,
returns true when evaluating the regular expression of 'starts with empty string'.

Categories