So i was given this question below to answer and I initially created a for loop to do this which worked fine but i was told i could also do it in a while loop which is what i am trying now however i am not sure where I've gone wrong in my code below as i'm getting a indexoutofrange exception.
Question 4 -
Write a piece of software that compares two strings and outputs the number of characters in the same position.
E.g. “helloworld” and “worldhello” would output 2 as there are two l’s in the same positions
compare the strings below to calculate your answer.
String1 - "helloworld"
String2 - "worldhello"
My for loop code which works perfectly
string string1 = "helloworld";
string string2 = "worldhello";
int list = 0;
for (int i = 0; i < string1.Length; i++)
{
if (string1[i] == string2[i])
{
list = list + 1;
}
}
Console.WriteLine(list);
Now this is my while loop code which isn't working
string string1 = "helloworld";
string string2 = "worldhello";
int i = 0;
int total = 0;
while (i < string1.Length)
{
i++;
if (string1[i] == string2[i])
{
total = total + 1;
}
}
You are nearly there!
The third part of the for loop (i++) will run at the end of each iteration, so you should not put i++; as the first statement in the while loop version. You should put it as the last statement:
while (i < string1.Length)
{
if (string1[i] == string2[i])
{
total = total + 1;
}
i++;
}
In general, a for loop of the form:
for (x ; y ; z) { w; }
can be written as a while loop like this:
x;
while (y) {
w;
z;
}
Related
You're given an array of integers,in case if you see subsequence in which each following bigger than the previous on one(2 3 4 5) you have to rewrite this subsequence in the resulting array like this 2 - 5 and then the rest of the array. So in general what is expected when you have 1 2 3 5 8 10 11 12 13 14 15 the output should be something like 1-3 5 8 10-15.
I have my own idea but can't really implement it so all I managed to do is:
static void CompactArray(int[] arr)
{
int[] newArr = new int[arr.length];
int l = 0;
for (int i = 0,k=1; i <arr.length ; i+=k,k=1) {
if(arr[i+1]==arr[i]+1)
{
int j = i;
while (arr[j+1]==arr[j]+1)
{
j++;
k++;
}
if (k>1)
{
}
}
else if(k==1)
{
newArr[i] = arr[i];
}
}
In short here I walk through the array and checking if next element is sum of one and previous array element and if so I'm starting to walk as long as condition is true and after that i just rewriting elements under indices and then move to the next.
I expect that people will help me to develop my own solution by giving me suggestions instead of throwing their own based on the tools which language provides because I had that situation on the russian forum and it didn't help me, and also I hope that my explanation is clear because eng isn't my native language so sorry for possible mistakes.
If I understand the problem correctly, you just need to print the result on the screen, so I'd start with declaring the variable which will hold our result string.
var result = string.Empty
Not using other array to store the state will help us keep the code clean and much more readable.
Let's now focus on the main logic. We'd like to loop over the array.
for (int i = 0; i < array.Length; i++)
{
// Let's store the initial index of current iteration.
var beginningIndex = i;
// Jump to the next element, as long as:
// - it exists (i + 1 < array.Length)
// - and it is greater from current element by 1 (array[i] == array[i+1] - 1)
while (i + 1 < array.Length && array[i] == array[i+1] - 1)
{
i++;
}
// If the current element is the same as the one we started with, add it to the result string.
if (i == beginningIndex)
{
result += $"{array[i]} ";
}
// If it is different element, add the range from beginning element to the one we ended with.
else
{
result += $"{array[beginningIndex]}-{array[i]} ";
}
}
All that's left is printing the result:
Console.WriteLine(result)
Combining it all together would make the whole function look like:
static void CompactArray(int[] array)
{
var result = string.Empty;
for (int i = 0; i < array.Length; i++)
{
var beginningIndex = i;
while (i + 1 < array.Length && array[i] == array[i+1] - 1)
{
i++;
}
if (i == beginningIndex)
{
result += $"{array[i]} ";
}
else
{
result += $"{array[beginningIndex]}-{array[i]} ";
}
}
Console.WriteLine(result);
}
I'm trying to cycle through chars in a string.
string cycleMe = "Hi StackOverflow! Here is my string."
However, I want to skip over certain ranges of indexes. The ranges I want to skip over are stored in a List of objects, delims.
List<Delim> delims = delimCreator();
To retrieve each starting index and ending index for a range, I have to write a loop that accesses each "delim":
delims[0].getFirstIndex() //results in, say, index 2
delims[0].getLastIndex() //results in, say, index 4
delims[1].getFirstIndex() //results in, say, index 5
delims[1].getLastIndex() //results in, say, index 7
(there can be infinitely many "delim" objects in play)
If the above were my list, I'd want to print the string cycleMe, but skip all the chars between 2 and 4 (inclusive) and 5 and 7 (inclusive).
Expected output using the numbers above:
HiOverflow! Here is my string.
Here is the code I have written so far. It loops far more often than I'd expect (it loops ~x2 the number of characters in the string). Thanks in advance! =)
List<Delim> delims = delimAggregateInator(displayTextRaw);
for (int x = 0; x < cycleMe.Length;x++){
for (int i = 0; i < delims.Count; i++){
if (!(x >= delims[i].getFirstIndex() && x <= delims[i].getLastIndex())){
Debug.Log("test");
}
}
I assume that by skipping you meant you want to omit those characters from the original string. If that is the case, you can try Aggregate extension method like below.
string result = delims.Aggregate<Delim, string>(cycleMe, (str, d) => cycleMe = cycleMe.Remove(d.FirstIndex, (d.LastIndex - d.FirstIndex) + 1));
Make sure that the delim list is in the proper order.
Solution might be converting the string to char array, replacing the desired parts to spaces, and converting the output back to string.
Here is the modified version of your code:
string cycleMe = "Hi StackOverflow! Here is my string."
var charArray = cycleMe.ToCharArray(); // Converting to char array
List<Delim> delims = delimAggregateInator(displayTextRaw);
for (int x = 0; x < cycleMe.Length;x++){
for (int i = 0; i < delims.Count; i++){
// ORIGINAL: if (!(x >= delims[i].getFirstIndex() && x <= delims[i].getLastIndex())){
if (x >= delims[i].getFirstIndex() && x <= delims[i].getLastIndex()){
Debug.Log("test");
charArray[x] = ' '; // Replacing the item with space
}
}
string output = new string(charArray); // Converting back to string
P.S. This is probably not the most optimal solution but at least it should work.
You should use LINQ for that
struct Delim
{
public int First { get; set; }
public int Last { get; set; }
}
static void Main(string[] args)
{
string cycleMe = "Hi StackOverflow! Here is my string.";
var delimns = new List<Delim> { new Delim { First=2, Last=4}, new Delim { First = 5, Last = 7 } };
var cut = cycleMe.Where((c, i) =>
!delimns.Any(d => i >= d.First && i <= d.Last));
Console.WriteLine(new string(cut.ToArray());
}
That means I am basically only selecting letters, at positions which are not part of any cutting range.
Also: Fix your naming. A delimiter is a character, not a position (numeric)
So I have pow - a list containing numbers. I have to examine other numbers like this: Get all the digits and sum the numbers from pow having the same index as the certain digit.
So if I check number 4552 I need to get pow[4]+pow[5]+pow[5]+pow[2]. Because I'm a noob I try to convert the number to string, get the characters with loop and then convert back to int to get the index. So the code is as follows for getting the sums between 4550 and 4559:
for (int i = 4550; i < 4560; i++)
{
int sum = 0;
for (int j = 0; j < i.ToString().Length; j++)
{
sum += pows[Convert.ToInt32(i.ToString()[j])]; //here is the error - index was out of range
//do something with sum (like store it in another list)
}
}
So what is wrong with that?
EDIT: To avoid confusion... pow has 10 elements, from indexes 0-9.
SOLUTION: The issue with my code was that I got the character code not the digit itself, thanks Steve Lillis. Though the solution provided by Dmitry Bychenko is far more superior to my attempt. Thank you all.
What you're looking for is similar to a digital root:
Modulus (% in C#) is easier and faster than conversion to string:
public static int DigitalRootIndex(IList<int> list, int value) {
if (value < 0)
value = -value;
int result = 0;
// for value == 4552
// result == list[4] + list[5] + list[5] + list[2]
while (value > 0) {
int index = value % 10;
result += list[index];
value /= 10;
}
return result;
}
...
int test = DigitalRootIndex(pow, 4552);
This bit of code gets a single character such as '4' which is character code 59:
c = i.ToString()[j]
Then this bit of code turns that char into an integer. It doesn't parse it like you're expecting, so the result for '4' is 59, not 4:
Convert.ToInt32(c)
Do this instead:
int.Parse(c.ToString())
Something like this (quick and dirty try)?
int currentDigit;
int sum;
for (int i = 4550; i < 4560; i++)
{
sum = 0;
currentDigit = i;
while (currentDigit > 0)
{
if (pow.Count > (currentDigit % 10))
{
sum += pow[((currentDigit % 10))];
}
}
}
Note that lists have zero based index so when you do pow[1], you are actually accessing second element in the list. Is that what you want?
I have the following foreach loop in C#:
foreach(var item in mod)
{
int i;
i = i + 1;
if (i % 2 == 0)
{
string y = "even number";
}
}
How come I get the message that local variable is unassigned. I am trying to find the even number here.
To resolve the message you are getting, you simply need to initialize it:
int i = 0;
If your intention is to count every item, then you will also need to change the scope of i to outside of the foreach. Otherwise, as you originally posted, the variable i will have the same value for every iteration of the loop.
See this code snippet for both the initialization and scope change:
int i = 0;
foreach (var item in mod)
{
i = i + 1; // is the first item considered even or odd? that answer changes where this should go
if (i % 2 == 0) {
string y = "even number";
}
}
You need to initialise your i variable:
int i = 0;
You're currently trying + 1 to an unassigned variable.
You get the warning because you are not assigning i before using it in i = i + 1. You want to declare i outside of your foreach loop, so you it isn't bound to the scope of the loop. Then initialize with 0 and use the increment feature. Something like:
int i = 0;
foreach (var item in mod)
{
i++;
if (i % 2 == 0)
{
string y = "even number";
}
}
An alternative to what others have suggested here (although correct) would be to use a for loop, this would take care of i for you, e.g.
for (int i = 0; i < mod.length; i++)
{
if (i % 2 == 0)
{
string y = "even number";
}
}
Change this: int i;
to this: int i = 0;
Values types in C# like int do have default values, but you're still not allowed to use an unassigned value-type variable.
You need to assign an initial value for i before you can do i=i+1
You have to initialize i. Right now the compiler is reading this as i = garbage in memory. So you have garbage in memory = garbage in memory + 1. That i could be equal to a string, a number, or anything.
int i = 0;
In addition, you need to initialize that variable outside of the for...each loop, or it will keep resetting itself to 0.
int i = 0;
foreach(var item in mod){
i = i + 1;
if (i % 2 == 0) {
string y = "even number";
}
}
int i = 0;
foreach(var item in mod)
{
if (i % 2 == 0)
{
string y = "even number";
}
i = i + 1;
}
//what are you doing with y and how are you returning y if you need it..
are you expecting to break out at some point.. ? what if item has zero items..??
Im trying to get specific lines from a file and put them in a another string or maybe if we can put it in anothe textbox it wont be a prob :P
string[] msglines;
msglines = System.IO.File.ReadAllLines(#"C:\\Users\xA\Desktop\MESSAGES.txt");
for (int x = 0; x < msglines.Length; x++)
{
this.textBox5.Text = msglines[c];
c = c + 2;
}
I get a :
Index was outside the bounds of the array.
If you want to get every second line.
Change your loop to
//Odd Lines
for (int x = 0; x < msglines.Length; x = x + 2)
{
this.textBox5.Text += msglines[x];
}
//Even Lines
for (int x = 1; x < msglines.Length; x = x + 2)
{
this.textBox5.Text += msglines[x];
}
As was pointed out in the comments, you can shorten x = x + 2 to x += 2
And in the interest of LinqY Goodness...
//ODDS
msgLines
.Where((str, index) => index % 2 == 0)
.ToList()
.ForEach(str => textBox1.Text += String.Format("{0}\r\n", str));
//EVENS
msgLines
.Where((str, index) => index % 2 == 1)
.ToList()
.ForEach(str => textBox1.Text += String.Format("{0}\r\n", str));
your loop is controlled by x, but you're indexing by c [hence you need logic to prevent c getting greater than size of the array]
Because you are increasing the line index (c) by 2 each time; just use x:
this.textBox5.Text = msglines[x];
Of course, from a loop this will result in just the last line being shown. What line is it you actually want to show?
Edit re comment; in which case, simply:
StringBuilder sb = new StringBuilder();
for (int x = 1; x < msglines.Length; x+=2)
{
sb.AppendLine(msglines[x]);
}
this.textBox5.Text = sb.ToString();
In your for loop, you are using c. You need to use x. Could I suggest that you have a look at the reference for for.
Try this instead...
string[] msglines;
msglines = System.IO.File.ReadAllLines(#"C:\\Users\xA\Desktop\MESSAGES.txt");
for (int x = 0; x < msglines.Length; x++)
{
this.textBox5.Text = msglines[x];
}
Then you should use X as an index, with a step of 2, instead of 1.
Try this
string[] msglines;
msglines = System.IO.File.ReadAllLines(#"C:\Users\xA\Desktop\MESSAGES.txt");
for (int x = 0; x < msglines.Length; x++)
{
this.textBox5.Text = msglines[x++];
}
You say you want all odd-numbered lines in the TextBox, but your loop will only show the last line, as you overwrite the contents on each pass.
To show all odd-numbered lines, separated by line breaks:
string lineSep = "";
for (int x = 0; x < msglines.Length; x += 2)
{
this.textBox5.Text += lineSep + msglines[x];
lineSep = "\r\n";
}
For simplicity I'll use an example of taking every other character from a string, but the case of taking every other line from an array of strings is analogous.
Lets take "Hello" as an example for your msglines string
(source: javabat.com)
and let us say that your global variable c i initialized to 0 before you enter the for loop. Your msglines.Lenght will be 5. In the the fourth iteration through the loop (x == 3) you are going to try to access msglines[6], which is outside of the bounds of the array, hence the error.
You probably wanted something along the lines of
int x = 0;
while(x <= msglines.Lenght){
this.textBox5.Text += msglines[x];
x = x + 2;
}
or
for(x=0; x <= msglines.Lenght ; x+=2){
this.textBox5.Text += msglines[x];
}
To get the odd lines you would start with x initialized to 1.
As for which of the two fully equivalent versions above to use, I would suggest using the one that is more readable to you. In my experience that is always the better choice.
You have a double backslash in the ReadAllLines() call, causing it to fail opening the file.
Also, you are using c as an array index, it looks like you want x
The code i wrote is exactly how I want it to be.....
I actually want every odd line from my file to be sent to the textbox.and yeah P.S C initializes from 1
Besides the already mentioned indexing problems of c versus x, you are also overwriting textBox5.Text on every iteration, so you'll only ever see the last line. It seems somehow unlikely to be intended behaviour. You might want something like this instead:
this.textBox5.Text += msglines[x]; // note x instead of c
Or if you really want everything and the +2 was a typo in itself you could do this without any loop:
this.textBox5.Text = String.Join( "\n", msglines );
The following function will return an IEnumerable that gives the odd numbered lines in a file:
private IEnumerable<string> GetOddLines(string fileName)
{
string[] lines = File.ReadAllLines(fileName);
IEnumerator allLines = lines.GetEnumerator();
while (allLines.MoveNext())
{
yield return (string)allLines.Current;
if (!allLines.MoveNext())
{
break;
}
}
}
If you want the even numbered lines, just add a call to allLines.MoveNext() before the while loop.
You need to loop the array with Length -1. Array of 45 Length will only index to 44.