Bubblesorting Need answers [duplicate] - c#

This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 8 years ago.
I need some help with this code. I'm playing with this for a couple of hours and got nothing. So I'm asking for help from you guys.
The Array[b] was always returns out of bounds exception. I don't know why.
{
int[] Array = new int[6];
Array[0] = c;
Array[1] = d;
Array[2] = e;
Array[3] = f;
Array[4] = g;
int a = 0;
int b = 1;
int temp = 0;
for (int counter = 0; counter < Array.Length; counter++)
{
for (int counter2 = 0; counter2 < Array.Length; counter2++)
{
if (Array[a] > Array[b])
{
Console.WriteLine("{0} is Greater Than {1}, Swapping ({0},{1})", Array[a], Array[b]);
temp = Array[a];
Array[a] = Array[b];
Array[b] = temp;
Console.WriteLine("");
}
else
{
Console.WriteLine("{0} is Less Than {1}, Retain Value Position", Array[a], Array[b]);
Console.WriteLine("");
}
a += 1;
b += 1;
}
a = 0;
b = 0;
}
for (int counter = 0; counter < Array.Length; counter++)
{
Console.Write(Array[counter] + " ");
}
Console.WriteLine("Final Position");
return a;
}
Thanks, this is my code i hope any one of you can help me.

You are comparing one element to the next, so if you've arrived at the last element, there is no "next" element and you're out of bounds.
Change the inner loop to only go until Length - 1 to prevent this:
for (int counter = 0; counter < Array.Length; counter++)
{
for (int counter2 = 0; counter2 < Array.Length - 1; counter2++)
// ...
}

before incrementing b, check if you are in the last index of the array, because you start b at 1 instead of 0, so it will go out of bounds if you enter the block while looping over the last array index.

Related

C#: how to detect repeating values in an array and process them in such a way that each repeating value is only processed once?

I wrote this simple program:
class Program
{
static void Main(string[] args)
{
Console.Write("Number of elements in the array: ");
int numberOfElements = int.Parse(Console.ReadLine());
int[] array = new int[numberOfElements];
for(int i = 0; i < numberOfElements; i++)
{
Console.Write($"Element no {i+1}: ");
array[i] = int.Parse(Console.ReadLine());
}
for(int i = 0; i < array.Length; i++)
{
int count = 0;
for(int j = 0; j < array.Length; j++)
{
if(array[i] == array[j])
{
count++;
}
}
Console.WriteLine($"{array[i]} appears " + count + " times");
}
}
}
}
Is there any option to make the displayed values print only once?
For example, if there are three occurrences - the message displays three times. Is it possible to make it display once when there are more occurrences though?
You could use a GroupBy instead of the for loop
Groups the elements of a sequence.
var results = array
.GroupBy(x => x)
.Select(x => new {Value = x, Count = x.Count()});
foreach(var g in results)
Console.WriteLine($"{g.Value} appears {g.Count} times");
Or another way it to use a HashSet to keep track of what you have displayed. A HashSet is basically a collection that contains no duplicate elements. The Add methods returns true if it can add an element or false otherwise
HashSet<T>.Add(T) Method
returns true if the element is added to the HashSet object; false if the
element is already present.
var hashSet = new HashSet<int>();
for (int i = 0; i < array.Length; i++)
{
int count = 0;
for (int j = 0; j < array.Length; j++)
if (array[i] == array[j])
count++;
// Add to the hashset, if the add method returns true,
// it means the value was uniquely added, ergo you have not displayed yet
if (hashSet.Add(array[i]))
Console.WriteLine($"{array[i]} appears " + count + " times");
}
Full Demo Here
Or another approach is to use a Dictionary. The premise is to iterate over the array, try an add each item to the dictionary with TryAdd if it's already found increment the value
var dictionary = new Dictionary<int,int>();
foreach(var item in array)
if(!dictionary.TryAdd(item,1))
dictionary[item]++;
foreach(var item in dictionary)
Console.WriteLine($"{item.Key} appears {item.Value} times");
Full Demo Here
The first idea I had was the same of the comment from Jon Skeet, since the simplicity it implies.
The idea is to set null for the value we have already counted (matched).
From a developer point of view it is very simple and doesn't deviate too much from the OP's code.
Console.Write("Number of elements in the array: ");
int numberOfElements = int.Parse(Console.ReadLine());
int?[] array = new int?[numberOfElements];
for (int i = 0; i < numberOfElements; i++)
{
Console.Write($"Element no {i + 1}: ");
array[i] = int.Parse(Console.ReadLine());
}
for (int i = 0; i < array.Length; i++)
{
int count = 0;
int? current = array[i];
if (array[i] != null)
{
for (int j = 0; j < array.Length; j++)
{
if (current == array[j])
{
count++;
array[j] = null;
}
}
Console.WriteLine($"{current} appears " + count + " times");
}
}
int?[] defines a nullable value type. Therefore each item in the array can have either a null or int value - documentation here.
An approach using Dictionary with O(n) complexity.
Console.Write("Number of elements in the array: ");
int numberOfElements = int.Parse(Console.ReadLine());
var dictionary = new Dictionary<int, int>();
for (int i = 0; i < numberOfElements; i++)
{
Console.Write($"Element no {i + 1}: ");
var value = int.Parse(Console.ReadLine());
if (!dictionary.ContainsKey(value)) dictionary.Add(value, 0);
dictionary[value] = dictionary[value] + 1;
}
foreach (var item in dictionary)
{
Console.WriteLine($"{item.Key} appears {item.Value} times");
}
One simple way would be to swap your outer for loop with a foreach using a set to obtain distinct values.
So replace this:
for (int i = 0; i < array.Length; i++)
With this:
foreach (int i in new HashSet<int>(array))
And this:
if (array[i] == array[j])
With this:
if (i == array[j])
Other approach more suited for you would be too take only unique values from array, i.e.:
var unique = array.Distinct().ToArray();
for (int i = 0; i < unique.Length; i++)
{
int count = 0;
for (int j = 0; j < array.Length; j++)
{
if (array[i] == array[j])
{
count++;
}
}
Console.WriteLine($"{unique[i]} appears " + count + " times");
}
In the inner loop, try to check if there were already any occurrences of the current element until you exceed the outer index.
for(int i = 0; i < array.Length-1; i++)
{
int count = 1;
bool appeared = false;
for(int j = 0; j < array.Length; j++)
{
// until we are not at the same index as the outer loop
// check if we haven't already met the current element
if(j < i)
{
if (array[i] == array[j])
{
// set current value appearance to true
// to know if current element should be displayed
appeared = true;
// break the loop because there is no sense of continuing
// current look
break;
}
}
// if we are ahead of outer index
// check if there are occurences of the element
else if(j > i)
{
if (array[i] == array[j])
count++;
}
}
// don't print the current element if it has appeared before
if(!appeared)
Console.WriteLine($"{array[i]} appears {count} times");
}
I believe there should be a more optimal solution, as this one's time complexity is linear... You can think of some optimization. For example, you can store occurred elements in the array and check through the array at each iteration, so you don't need to start the inner loop from the beginning, but instead start it from the outer loop's position + 1 but it's also not the best solution.
P.S check out about string interpolation, because you don't need to concatenate strings when you use it.
You can also use Lookup here:
var sb = new StringBuilder();
foreach (var value in array.ToLookup(item => item))
{
sb.AppendLine($"{value.Key} appears " + value.Count() + " times");
}
Console.WriteLine(sb.ToString());

Re-prompt if input is less than or equal to 0 [duplicate]

This question already has answers here:
C# How to loop user input until the datatype of the input is correct?
(4 answers)
Closed 3 years ago.
I have a function which asks for input from the user which will be parsed to an int and that will be used to create a pyramid.
I know I have to use a loop of some kind and I have tried a do/while loop but I don't seem to understand it. I can't declare n above the Console.Write outside the do/while and if I have it below inside of the do/while, the while condition wont accept it because it's out of the scope. It would seem so simple to say, do(ask for input and assign to n) while(n <=0), but I can't do that.
I also had an idea I tried which was to run the function within itself as long as n was <=0 but that runs the function infinitely. Not sure if I'm on the right track but I feel lost right now.
static void Pyramid()
{
Console.Write("Choose a pyramid height: ");
int n = Int32.Parse(Console.ReadLine());
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n - 1 - i; j++)
{
Console.Write(" ");
}
for (int j = 0; j < i + 2; j++)
{
Console.Write("#");
}
Console.Write(" ");
for (int j = 0; j < i + 2; j++)
{
Console.Write("#");
}
Console.WriteLine();
}
}
It should works:
int n;
do
{
Console.Write("Choose a pyramid height: ");
n = Int32.Parse(Console.ReadLine());
if ( n <= 0) Console.WriteLine("Value must be greater than 0.");
}
while ( n <= 0 );
Just use an infinite while loop, and continue if the number is invalid:
static void Pyramid()
{
while(true)
{
Console.Write("Choose a pyramid height: ");
int n = Int32.Parse(Console.ReadLine());
if (n <= 0)
{
Console.Error.WriteLine("That's an invalid number");
continue;
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n - 1 - i; j++)
{
Console.Write(" ");
}
for (int j = 0; j < i + 2; j++)
{
Console.Write("#");
}
Console.Write(" ");
for (int j = 0; j < i + 2; j++)
{
Console.Write("#");
}
Console.WriteLine();
}
}
}
Let's extract method. We should implement 2 checks:
If input is an integer value at all (e.g. "bla-bla-bla" is not an integer)
If input is a valid integer (we don't accept -123)
Code:
public static int ReadInteger(string prompt,
Func<int, bool> validation = null,
string validationMessage = null) {
int result;
while (true) {
if (!string.IsNullOrEmpty(prompt))
Console.WriteLine(prompt);
string input = Console.ReadLine();
if (!int.TryParse(input, out result))
Console.WriteLine("Sorry, your input is not a valid integer value. Please, try again.");
else if (validation != null && !validation(result))
Console.WriteLine(string.IsNullOrEmpty(validationMessage)
? "Sorry the value is invalid. Please, try again"
: validationMessage);
else
return result;
}
}
then you can easily use it:
int n = ReadInteger(
"Choose a pyramid height:",
(value) => value > 0,
"Pyramid height must be positive. Please, try again.");
//TODO: your code here to draw the pyramid of height "n"
please, note, that you can easily restrict the upper bound as well (a pyramid of height 1000000000 will hang the computer):
int n = ReadInteger(
"Choose a pyramid height:",
(value) => value > 0 && value <= 100,
"Pyramid height must be in [1..100] range. Please, try again.");

c# Code : System.IndexOutOfRangeException: 'Index was outside the bounds of the array.' please see my code [duplicate]

This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 3 years ago.
These codes aren't running.When inside the nested loop I'm trying to assign integer value on totalMembers[j] array index , the compiler throws mentioned exeption.please help so that this program can run.
int totalHours = 0, memArraySize = 0;
int[] totalMembers = new int[memArraySize];
int[] memHours = new int[memArraySize];
for (int i = 0; i < 2; i++)
{
var stringNumbers = Console.ReadLine();
var numbers = stringNumbers.Split(' ');
int.TryParse(numbers[0], out totalHours);
int.TryParse(numbers[1], out memArraySize);
for (int j = 0; j < 2; j++)
{
totalMembers[j] = Convert.ToInt32(Console.ReadLine());
memHours[i] = memHours[i] + totalMembers[j];
}
}
int totalHours, memArraySize;
int[] totalMembers;
int[] memHours;
for (int i = 0; i < 2; i++)
{
var stringNumbers = Console.ReadLine();
var numbers = stringNumbers.Split(' ');
int.TryParse(numbers[0], out totalHours);
int.TryParse(numbers[1], out memArraySize);
totalMembers = new int[memArraySize];
memHours = new int[memArraySize];
for (int j = 0; j < 2; j++)
{
totalMembers[j] = Convert.ToInt32(Console.ReadLine());
memHours[i] = memHours[i] + totalMembers[j];
}
}
so that the arrays totalMembers and memHours can contain values.

What's the best, correct way way to optimize this code and find MIN and MAX value for each ROW/COLUMN [duplicate]

This question already has answers here:
Get minimum and maximum value using linq
(3 answers)
Closed 4 years ago.
I'm trying to make this code as efficient as possible, what is the best and most correct way to do this? Also, I need to find the MIN and MAX values for each column and row and display the values next to the specific row and column.
Code:
using System;
using System.Linq;
public class Program
{
public static void Main()
{
Random rand = new Random();
int ri, ki;
int i, j;
int max = 1;
int min = 0;
int rndnumber = rand.Next(64, 128);
int[,] array = new int[9, 4]; // Izveido array 9x4 (rin x kol)
for (i = 0; i < 9; i++) //
{
for (j = 0; j < 4; j++)
array[i, j] = rand.Next(1, 100 + 1);
}
for (i = 0; i < 9; i++) //
{
for (j = 0; j < 4; j++)
{
Console.Write("|\t{0}\t ", array[i, j]); // /t - tab
}
Console.WriteLine("\n"); // new line
}
for (i = 0; i < 9; i++) //
{
for (j = 0; j < 4; j++)
if (max < array[i, j]) // Aprekina max
{
max = array[i, j];
}
}
Console.WriteLine("Maksimalais sk tabula: {0}", max);
Console.WriteLine("Min sk tabula: {0}", min);
//rndnumber = rand.Next();
//Console.WriteLine("Hello World {0}", rndnumber);
Console.ReadKey();
/*
Izveidot ka zem katras rindas un kol ir min un max skaitlis
*/
}
}
If you make the multidimensional array into an IEnumerable, you can use Linq on it:
// Order and use Cast<int>() to get an ordered IEnumerable<int>,
var orderedAscending = from x in array.Cast<int>()
orderby x
select x;
// Use linq First() & Last() to get min and max.
var min = orderedAscending.First();
var max = orderedAscending.Last();

C# foreach loop take values from outer loop to inner loop

I have the below code.
int[] a = new int[] { 8, 9 };
for(int i=0;i<n;i++)
{
print i;
int z;
//during first iteration
z=8;
during second iteration
z=9;
}
Output should be something like this.
during first iteration i=0 and z=8
during second iteration i=1 and z=9
array a contains 2 elements. N and number of elements in array a will be always same. next my for loop will execute. during first iteration want z value should be 8(first element of array ) and second iteration my z value should be 9. I want to map 1st element of integer array to first iteration of for loop and so on.
try
for (int i = 0; i < a.Length; i++) // or i < n if you want
{
print i;
int z = a[i]; // this line will get value from a one by one, 0, 1, 2, 3 and so on...
}
Edit 1 -
After seeing the comments on the other answer, the array 'a' turns out is a dynamic array which have size n (which is 2)
the revised edition:
int n = 2;
int[] a = new int[n];
string input = null;
for (int i = 0; i < a.Length; i++) // or i < n if you want
{
print i;
input = Console.ReadLine();
try {
a[i] = int.Parse(input);
Console.WriteLine(string.Format(
"You have inputted {0} for the {1} element",
input, i
));
} catch { Console.WriteLine("Non integer input"); i -= 1; }
}
you can try this
int [] a = {8,9};
for(int i=0; i< a.Length; i++)
{
int z = a[i]; //for taking value from array at the specific ith position
Console.WriteLine("i: " + i + " z:" + z);
}
try this
List<int> a = new List<int>();
int n = 2; // you can change it according to your need
for (int i = 0; i < n; i++)
{
string str = Console.ReadLine(); // make sure you enter an integer and conver it
int z = int.Parse(str);
a.Add(z);
}
foreach (int k in a)
{
Console.WriteLine(k);
}

Categories