Using a nested for loop and getting unexpected repetitions in c# - c#

I've the following code in c# visual basic 2010:
for (int i = 7; i > 0; i--)
{
Char star = '*';
string numbers = "765432" ;
//Console.WriteLine(star);
for (int a = 0; a < i; a++)
{
Console.Write(star);
}
for (int b = 0; b < i; b++)
{
numbers.TrimEnd(numbers[numbers.Length - 1]);
Console.Write(numbers);
}
Console.WriteLine();
}
Console.ReadLine();
I was expecting the outcome:
*765432
repeated on the screen 7 times, instead I get:
*****765432765432765432765432765432
****765432765432765432765432
***765432765432765432
**765432765432
*765432
(I can't display the full outcome because it doesn't come back properly on screen but it's basically the variables star and numbers displayed 7 times on line 1, 6 times on line 2 etc. until once in line 7)
My understanding is that the a and b variables declared in the for loops should dictate how many times the for loop is entered into, why are the star and numbers variables also being written 7 times then 6 times to match the number of times the loop is entered into? Especially when they are initialised as * and 765432?

This is the problem (I suspect, anyway - it's certainly a problem):
numbers.TrimEnd(numbers[numbers.Length - 1]);
Strings are immutable in .NET. TrimEnd doesn't change the existing string - it returns a reference to a new one. As highlighted in the documentation:
This method does not modify the value of the current instance. Instead, it returns a new string in which all trailing characters found in trimChars are removed from the current string.
You'd also be better off using Substring for simplicity to "remove" the last character:
numbers = numbers.Substring(0, numbers.Length - 1);
Or indeed Remove:
numbers = numbers.Remove(numbers.Length - 1);
... although this will actually fail on the 7th iteration as the string will be empty at this point. It's not really what you were trying to achieve, but I think you need to take a step back from it and think carefully about each step in the process.

TrimEnd returns a new string, it doesn't modify the original string. You have to assign it back to number. Strings are immutable.
number = numbers.TrimEnd(numbers[numbers.Length - 1]);
Check for string length before indexing its element. In your for loop you can add the condition like:
for (int b = 0; b < i && numbers.Length > 0; b++)

No. The 'a' for loop runs, outputting that many stars, and the 'b' for loop runs next, outputting that many strings. If you just want '*765432' to repeat 7 times, you need to change
for (int a = 0; a < i; a++)
{
Console.Write(star);
}
for (int b = 0; b < i; b++)
{
numbers.TrimEnd(numbers[numbers.Length - 1]);
Console.Write(numbers);
}
To
for (int a = 0; a < 7; a++)
{
Console.Write(star);
Console.Write(numbers);
}
And take out the parent loop; that's what is giving you the incrementingly shorter lines.

This produce the output you are expecting:
for (int i = 0; i < 7; i++)
{
Char star = '*';
string numbers = "765432" ;
Console.WriteLine(star);
Console.Write(numbers);
Console.WriteLine();
}
I was expecting the outcome: *765432 repeated on the screen 7 times

You never need to use TrimEnd() and multiple for loop in this situation.
public static void Main()
{
for (int i = 7; i > 0;i--)
{
char star = '*';
string numbers = "765432";
Console.WriteLine(star + numbers);
}
Console.ReadLine();
}
output:
*765432
*765432
*765432
*765432
*765432
*765432
*765432

Related

Printing even numbers with commas except the last in C# not working

I have been trying to fix this issue for some days now but can't find the error. It seems as simple as an if statement for the code to print commas for all but the last number. It worked for me putting random numbers but when i put the specific numbers (24,7,35,2,27,7,89)it prints the comma at the end.
Print even numbers with commas
This is my code, but i tried multiple other ways.
using System.Collections.Generic;
using System.Text;
using System.Transactions;
namespace ArrayExercises
{
class TaskFour
{
public static void FindEvenNumbers()
{
int[] input = new int[7];
int count = 1;
string comma = ",";
Console.WriteLine("[== Please Enter 7 numbers ==]");
Console.WriteLine();
for (int i = 0; i < input.Length; i++)
{
Console.WriteLine($"Enter number {count}:");
input[i] = int.Parse(Console.ReadLine());
count++;
}
Console.WriteLine("The even numbers in this array are: ");
for (int i = 0; i < input.Length; i++)
{
if (input[i] % 2 == 0)
{
if (i < input.Length)
{
Console.Write(input[i] + comma);
}
else
{
Console.Write(input[i]);
}
}
}
}
}
}
Thanks in advance :)
You can use below code without introducing any extra space using for loop.
for (int i = 0; i < input.Length; i++)
{
if (input[i] % 2 == 0)
{
if (i != 0) Console.Write(comma);
Console.Write(input[i]);
}
}
Or use the inbuilt string.Join function.
Console.WriteLine(string.Join(',', input.Where(i => i % 2 == 0)));
This answer assumes that the above is homework/tutorial, there are more efficient means that what I am posting here
The problem is this segment:
if (i < input.Length)
{
Console.Write(input[i] + comma);
}
The problem is that you are always outputting a comma, regardless of what is to follow. I think that the easiest approach would be to add the comma before hand, meaning, while you are going through the second loop, if you have already printed a number before, you pre-pend a comma and print the number you have, if you did not print any numbers before (that is, you are about to print the first number) then you do not prepend the comma.
i will always be less than the length the input due to the loop's condition.
Instead of implementing this yourself, you could let string.join do the heavy lifting for you:
string result = string.Join(comma, input.Where(i => i % 2 == 0));
Console.WriteLine(result);
Your else condition will never execute. If you are rookie in C# then I would suggest get all even numbers first and store it in the list. Iterate over again to print with comma and just skip the last comma.
//Your existing source code
List<int> evenNumber = new List<int>();
for (int i = 0; i < input.Length; i++)
{
if (input[i] % 2 == 0)
{
evenNumber.Add(input[i]);
}
}
for(int i = 0; i < evenNumber.Length; i++)
{
//Print just number if it is last, otherwise print number with comma
if(i == evenNumber.Length - 1)
Console.Write(evenNumber[i]);
else
Console.Write(evenNumber[i]+comma);
}
If you know string.Join() then use linq to get list of even numbers and print list of even numbers with ',' as a delimiter
var evenNumbers = input.Where(x => x % 2 ==0); //Filter all even numbers
Console.WriteLine(string.Join(",", evenNumbers); //Print using string.Join
Yet another version:
string result = "";
for (int i = 0; i < input.Length; i++)
{
if (input[i] % 2 == 0)
{
result += $",{input[i]}";
}
}
Console.WriteLine( result.Length > 0 ? result.Substring(1).ToString() : "");

Printing square with non repetitive character

I want to print a rectangle like this :
&#*#
#*#&
*#&#
#&#*
But problem is that i can't find the algorithm to print this.
I only know how to print a simple rectangle/square
public static void Main(string[] args)
{
Console.Out.Write("Saisir la taille : ");
int taille = int.Parse(Console.In.ReadLine());
int i;
int j;
for(i = 0; i < taille; i++){
for(j = 0; j < taille; j++){
Console.Write("*");
}
Console.WriteLine("");
}
}
Thank you !
First things first unless you need your iterators outside of your loop, just declare them in the for declaration
public static void Main(string[] args)
{
Console.Out.Write("Saisir la taille : ");
int taille = int.Parse(Console.In.ReadLine());
for(int i = 0; i < taille; i++){
for(int j = 0; j < taille; j++){
Console.Write("*");
}
Console.WriteLine("");
}
}
Second you'll need a list of the characters you want to use, given your example
char[] chars = { '&', `#`, `*`, '#' };
and we'll need a way to know which character we want to use at any given time, say an iterator we can call characterIndex for simplicity. We will increment it each iteration. If incrementing it puts it out of the range of our character array, if characterIndex == 4, we set it back to zero.
int characterIndex;
To get the scrolling effect you have, before each line we must select a characterIndex that is offset by the row
characterIndex = i % chars.Length;
Tying it all together
public static void Main(string[] args)
{
char[] chars = { '&', `#`, `*`, '#' };
int characterIndex;
Console.Out.Write("Saisir la taille : ");
int taille = int.Parse(Console.In.ReadLine());
for(int i = 0; i < taille; i++){
characterIndex = i % chars.Length;
for(int j = 0; j < taille; j++){
Console.Write(chars[characterIndex]);
characterIndex++;
if(characterIndex == chars.Length)
characterIndex = 0;
}
Console.WriteLine("");
}
}
Getting the permutations by nesting for loops will only work if you know exactly how many elements there will be. Basically you need to write a for-loop for every element after the 1st.
The proper way to deal with this is Recursion. While there are cases where Recursion and nested for-loops are interchangeable. And in cases where they are, for loops have a potential speed advantage. While normally the speed rant applies to such differences, with the sheer amount of data both Recursion and Loops might have to deal with, it often maters - so best to prefer loops where possible.
Permutations is AFAIK not a case where loops and recursion are interchangeable. Recurions seems to be mandatory. Some problem as simply inherently recursive. As the recursion version is fairly well known, I will not post any example code.
You should defiitely use Recursion. With your example code I basically asume you are:
In a learning environment
You just learned recursion
A input variant recurions can effortless solve (like a 6 or 20 size input), is the next assignment

Storing numbers between two numbers in an array

as you can read from the title I'm trying to store all the numbers between two numbers in an array.
For example store the numbers between 21 and 43 (22,23,24,25,26,27,28,29...) in an array.
This is the code, I don't know why but it prints only the higher number minus one.
class Program
{
static void Main(string[] args)
{
int higher = 43;
int lower = 21;
int[] numbers = new int[22]; //the numbers between 21 and 43 are 22
for (int i = lower; i < higher;i++)
{
for (int a = 0; a < 22; a++)
{
numbers[a] = i;
}
}
for (int c = 0; c < 22; c++)
{
Console.WriteLine(numbers[c]);
}
Console.ReadLine();
}
}
This is the code, I don't know why but it prints only the higher number minus one.
This question will attract answers giving you a half dozen solutions you can cut and paste to do your assignment.
I note you did not ask a question in your question -- next time, please format your question in the form of a question. The right question to ask here is how do I learn how to spot mistakes in code I've written? because that is the vital skill you lack. Answers that give you the code will not answer that question.
I already gave you a link to a recent answer where I explain that in detail, so study that.
In particular, in your case you have to read the program you wrote as though you had not written it. As though you were coming fresh to the program that someone else wrote and trying to figure out what it does.
The first thing I would do is look at the inner loop and say to myself "what does this do, in words?"
for (int a = 0; a < 22; a++)
{
numbers[a] = i;
}
That is "put the value i in every slot of the array. Now look at the outer loop:
for (int i = lower; i < higher;i++)
{
put the value i in every slot of the array
}
Now the technique to use here is to logically "unroll" the loop. A loop just does something multiple times so write that out. It starts with lower, it goes to higher-1, so that loop does this:
put the value lower in every slot of the array
put the value lower+1 in every slot of the array
…
put the value higher-1 in every slot of the array
What does the third loop do?
print every item in the array
And now you know why it prints the highest number minus one multiple times. Because that's what the program does. We just reasoned it out.
Incidentally the answers posted so far are correct, but some are not the best.
You have a technique that you understand for "do something to every member of an array, and that is:
loop an indexer from 0 to the array size minus one
do something to the array slot at the indexer
But the solutions the other answers are proposing are the opposite:
loop an indexer from the lower to the higher value
compute an index
do something to the array slot at that index
It's important to understand that both are correct, but my feeling is that for the beginner you should stick with the pattern you know. How would we
loop an indexer from 0 to the array size minus one
do something to the array slot at the indexer
for your problem? Let's start with giving you a much better technique for looping the indexer:
for (int i = 0; i < numbers.Length; ++i)
That's a better technique because when you change the size of the array, you don't have to change the loop! And also you are guaranteed that every slot in the array is covered. Design your loops so that they are robust to changes and have good invariants.
Now you have to work out what the right loop body is:
{
int number = i + lower;
numbers[i] = number;
}
Now you know that your loop invariant is "when the loop is done, the array is full of consecutive numbers starting at lower".
For everytime you loop through i, you put that number in every slot of the array. The inner loop is what is causing your issue. A better solution would be:
int higher = 43;
int lower = 21;
int[] numbers = new int[21];
int index = 0;
for (int i = lower + 1; i < higher; i++) // if you want to store everything
// between 21 and 43, you need to
// start with 22, thus lower + 1
{
numbers[index] = i;
index++;
}
for (int c = 0; c < 21; c++)
{
Console.WriteLine(numbers[c]);
}
Console.ReadLine();
Replace a with a direct translation of i
for (int i = lower; i < higher;i++)
{
numbers[i-lower] = i;
}
Use below
int higher = 43;
int lower = 21;
int[] numbers = new int[22]; //the numbers between 21 and 43 are 22
for (int i = lower+1; i < higher; i++)
{
numbers[i-lower] = i;
}
for (int c = 1; c < 21; c++)
{
Console.WriteLine(numbers[c]);
}
Console.ReadLine();
I think higher & lower are variables so following will give you output
for any higher and lower numbers
class Program
{
static void Main(string[] args)
{
int higher = 43;
int lower = 21;
int numDiff = higher - lower - 1;
int[] numbers = new int[numDiff]; //the numbers between 21 and 43 are 22
for(int i = 0; i<numbers.Length; i++)
{
numbers[i] = numDiff + i + 1;
}
for(int b = 0; b<numbers.Length; b++)
{
Console.WriteLine(numbers[b]);
}
Console.ReadLine();
}
}

Im trying scramble randomaly strings but some of the strings dosen't get scrambled at all what could it be?

This is the code:
private static StringBuilder MakeRandomwords(string theWord)
{
var jumbleSb = new StringBuilder();
jumbleSb.Append(theWord);
int lengthSb = jumbleSb.Length;
for (int i = 0; i < lengthSb; ++i)
{
int index1 = (RandomGen.Next() % lengthSb);
int index2 = (RandomGen.Next() % lengthSb);
Char temp = jumbleSb[index1];
jumbleSb[index1] = jumbleSb[index2];
jumbleSb[index2] = temp;
}
return jumbleSb;
}
And this is the List that im using to build the scrambled words:
private void GetText()
{
_lengthaboveone = new List<string>();
for (int i = 0; i < _words.Count; i++)
{
string word = _words[i];
if (word.Length < 4) continue;
string first = word.Substring(0, 1);
string last = word.Substring(word.Length - 1, 1);
string middle = word.Substring(1, word.Length - 2);
_lengthaboveone.Add(middle);
_words[i] = first + MakeRandomwords(middle) + last;
}
_scrambledWords = _words;
}
In the end the List _scrambledWords contain over 1000 strings in each index a string of a word most of them scrambled but some of them are left the same as they were in the original.
The question is if there is something wrong with my MakeRandomwords ?
Could be it did scrambled the word and it was scrambled to how it was before ? So maybe i need to add something to the code that will keep scramble the word untill the word is scrambled by compraing it ot the original untill the word is scrambled ?
Take a look at the Fisher–Yates shuffle algorithm and implement the following pseudo code to achieve a good distribution of elements:
To shuffle an array a of n elements (indices 0..n-1):
for i from n − 1 downto 1 do
j ← random integer with 0 ≤ j ≤ i
exchange a[j] and a[i]
To elaborate on Tim Schmelter's comment asking about RandomGen.Next(), in case you've been wondering: If you instantiate a new Random instance every time you're entering the for loop, the generated pseudo-random numbers will by nature be quite repetitive. This is due to the way that the Random class is implemented in the .NET framework. By reusing a shared instance like you do, one can avoid that issue.
This is not the problem here, though. In your algorithm, you're picking two random array elements and swapping them. It's highly likely that there are some array elements that never get selected this way. Thus, there's a good chance that some elements won't have changed their position in the array when you're done, which is why it doesn't look shuffled well.
Instead of randomly swapping two locations, swap every location to a random location... it will look more random because each element will have moved. With your current design there is a good chance some items won't ever move.
for (int i = 0; i < lengthSb; ++i)
{
int index1 = i;
int index2 = (RandomGen.Next() % lengthSb);
Char temp = jumbleSb[index1];
jumbleSb[index1] = jumbleSb[index2];
jumbleSb[index2] = temp;
}

Code showing wrong output

I have developed a program in c# which is doing "Insertion Sort", the code takes in a max value for the elements and the values of the elements and then one by one shows the steps of sorted values.
Code:
static void insertionSort(int[] ar)
{
for (int i = 1; i < ar.Length; i++)
{
int temp = ar[i];
int j = i - 1;
while (j >= 0 && ar[j] > temp)
{
ar[j + 1] = ar[j];
foreach (int val in ar)
Console.Write(val + " ");
Console.WriteLine();
j--;
}
}
}
static void Main(String[] args)
{
int ar_size;
ar_size = Convert.ToInt32(Console.ReadLine());
int[] ar = new int[ar_size];
for (int i = 0; i < ar_size; i++)
{
ar[i] = Convert.ToInt32(Console.Read());
}
insertionSort(ar);
Console.ReadKey();
}
The Sample Input That I Give:
5
2 4 6 8 3
The Output That Comes:
Can anyone explain me why is this happening!
Any help would be greatly appreciated! :)
Apart from the problems with your sort itself, the reason for the strange numbers in your result is that you use Console.Read very wrong. It returns the ASCII value of the character entered by the user. Furthermore, it will return the ASCII values for all entered characters, not only for the numbers.
So, the first call to Console.Read() will return 50 (ASCII value of '2').
The second call will return 32 (ASCII value of a space).
The third call will return 52 (ASCII value of '4').
etc.
To fix this, initialize ar like this:
var numbers = Console.ReadLine().Split(' ');
for (int i = 0; i < ar_size; i++)
ar[i] = Convert.ToInt32(numbers[i]);
Please note that this code lacks error handling. It will throw an exception in the followin circumstances:
The user entered anything besides spaces and numbers
The user entered less numbers than he specified in the first line

Categories

Resources