I'm having a problem with getting this code (from Rosetta Code) to work as part of a greater Windows Form Project:
It's a plain old insertion sort. Where it's going wrong is the bit involving the second for loop (The numbers generate just fine), in the sorting part of it. To me within a couple of iterations of the loop then j will be into negative figures and whilst other languages such as Javascript and Pascal don't seem to mind this...C# isn't happy.
private void button3_Click(object sender, EventArgs e)
{
int i, j, k;
int[] a = new int[12];
Random randomObject = new Random();
ClearOutputs(); // this is an event which just clears the
text
from the text boxes.
//Generate some random numbers
for (i = 0; i < a.Length; i++)
{
a[i] = randomObject.Next(1, 1000);
textBox1.AppendText(a[i].ToString() + "\n");
}
for (i = 1; i <= a.Length; i++)
{
k = a[i];
//*******************
for (j = i; j > 0 & k < a[j - 1]; j--)
{
a[j] = a[j - 1];
a[j] = k;
}
}
// ***************
//Display them...it never executes this part.
for (i = 0; i < a.Length; i++)
{
textBox2.AppendText(a[i].ToString() + "\n");
}
}
The longer term fix would be for me to understand the coding of the algorithm...and then fix it for myself, but if anyone could point me in the right direction...I've tried setting the 'for' loop at a higher initial value and yet still got the same "System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'" Any help would be greatly appreciated.
Following the provided Rosetta Code algorithm, you should change the second "for" block to:
for (i = 1; i < a.Length; i++)
{
k = a[i];
for (j = i - 1; j >= 0 && a[j] > k; j--)
{
a[j + 1] = a[j];
}
a[j + 1] = k;
}
Related
I'm new at programming in general and learning C# right now.
I just wrote a little programm where I have to step through an int[] in a specific pattern. The pattern is as follows:
Start at the last entry of the array (int i)
form the sum of i and (if avaible) the three entrys above (e.g. i += i-1 ... i += i-3)
Change i to i -= 4 (if avaible)
Repeat from step 2 until i = 0;
Therefore i wrote the following loop:
for (int i = intArray.Length - 1; i >= 0; i -= 4)
{
for (int a = 1; a <= 3; a++)
{
if (i - a >= 0)
{
intArray[i] += intArray[i - a];
intArray[i - a] = 0;
}
}
}
Now my new assignment is to change my code to only use 1 loop with the help of modulo-operations. I do understand what modulo does, but i can't figure out how to use it to get rid of the second loop.
Maybe somebody explain it to me? Thank you very much in advance.
While iterating over the array, the idea would be to use the modulo 4 operation to calculate the next index to which you will add the current value.
This should work with any array lengths:
for (int i = 0; i < intArray.Length; i++){
// we check how far away we are from next index which stores the sum
var offset = (intArray.Length - 1 - i) % 4;
if (offset == 0) continue;
intArray[i+offset] += intArray[i];
intArray[i] = 0;
}
iterating the array reversely makes it a bit more complicated, but what you wanted to get rid of inner loop with modulo is probably this:
var intArray = Enumerable.Range(1, 15).ToArray();
for (int i = 1; i < intArray.Length - 1; i ++)
{
intArray[i - (i % 4)] += intArray[i];
intArray[i] = 0;
}
So I'm just trying to understand how bubblesort (it may help me with other algorithms when I see this kind of stuff as well) works with the nested for loop.
I noticed that most people will do the loops like so:
public static void BubbleSort(int[] arr, int arr_size)
{
int i, j, temp;
bool swapped;
for (i = 0; i < arr_size - 1; i++)
{
swapped = false;
for (j = 0; j < arr_size - i -1; j++)
{
if (arr[j] > arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = true;
}
}
if (swapped == false)
{
break;
}
}
}
I have done it like this (only slightly different; note the nested loop size check:
public static void BubbleSort(int[] arr, int arr_size)
{
int i, j, temp;
bool swapped;
for (i = 0; i < arr_size - 1; i++)
{
swapped = false;
for (j = 0; j < arr_size - 1; j++)
{
if (arr[j] > arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = true;
}
}
if (swapped == false)
{
break;
}
}
}
And it seems to work with every check I've done so far.
I guess to sum it up, I am wondering why the first loop would be the size - 1 (I know this is because of the whitespace at the end) and the nested loop will be the size - i - 1 (at least I have seen this a lot). Thanks for any feedback !
The effect of the inner loop:
for (j = 0; j < arr_size - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = true;
}
}
is finding the maximum element in the array and placing it to the last position. Hence, for i == 0 (the index from the outer loop), it moves it to the last array position. For i == 1, the array's overall maximum element is already at the last array position, and hence it does not need to be processed again. For i == 2 etc. the situation is the same. In other words, the array is being sorted from 'backward' by 'bubbling' (hence the algorithm's name) the maximum elements up each iteration.
There is a nice step-by-step example on Wikipedia.
In your second example, by omitting the - i in the for loop clause, you are just unnecessarily checking array elements that are already in place from previous (outer loop) iterations and hence cannot change anymore.
I have a quick question: I know that the complexity of both snippets is same. Yet, I want to know which one is comparatively better and why? This is the selection sort code:
This is what I wrote:
for (int i = 0; i < n - 1; i++)
{
for (int j = i + 1; j <= n - 1; j++)
{
if (a[j] < a[i])
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
This is what my friend wrote:
for (int i = 0; i < n - 1; i++)
{
int iMin = i;
for (int j = i + 1; j <= n - 1; j++)
{
if (a[j] < a[i])
{
iMin = j;
}
int temp = a[i];
a[i] = a[iMin];
a[iMin] = temp;
}
}
Your code is slightly faster because you make swaps only when a[j] < a[i], whereas your friend's code is always making a swap. So, in most cases, your code will make less swaps.
The complexity of both codes are indeed the same, but your "constants" are smaller, so your code is faster.
I'm writing a program to find the largest palindromic number made from product of 3-digit numbers. Firstly,i Create a method which has ability to check if it is a palindromic number. Here is my code :
static int check(string input_number)
{
for (int i = 0; i < input_number.Length/2; i++)
if (input_number[i] != input_number[input_number.Length - i])
return 0;
return 1;
}
After that, it's my main code:
static void Main(string[] args)
{
int k = 0;
for (int i = 0; i < 999; i++)
for (int j = 0; j < 999; j++)
{
k = i * j;
if (check(k.ToString()) == 1)
Console.Write(k + " ");
}
}
But when it has a problem that the length of input_number is zero. So my code doesn't run right way. What can I do to solve the length of input_number?
You have a few bugs in your code:
1. 3-digit-numbers range from `100` to `999`, not from `0` to `998` as your loops currently do.
So your Main method should look like this:
static void Main(string[] args)
{
int k = 0;
for (int i = 100; i <= 999; i++)
for (int j = 100; j <= 999; j++)
{
k = i * j;
if (check(k.ToString()) == 1)
Console.Write(k + " ");
}
}
Now all pairs of three digit numbers are checked. But to improve performance you can let j start at i, because you already checked e.g. 213 * 416 and don't need to check 416 * 213 anymore:
for (int i = 100; i <= 999; i++)
for (int j = i; j <= 999; j++) // start at i
And since you want to find the largest, you may want to start at the other end:
for (int i = 999; i >= 100; i--)
for (int j = 999; j >= 100; j--)
But that still does not guarantee that the first result will be the largest. You need to collect the result and sort them. Here is my LINQ suggestion for your Main:
var results = from i in Enumerable.Range(100, 900)
from j in Enumerable.Range(i, 1000-i)
let k = i * j
where (check(k.ToString() == 1)
orderby k descending
select new {i, j, k};
var highestResult = results.FirstOrDefault();
if (highestResult == null)
Console.WriteLine("There are no palindromes!");
else
Console.WriteLine($"The highest palindrome is {highestResult.i} * {highestResult.j} = {highestResult.k}");
2. Your palindrome-check is broken
You compare the character at index i to input_number[input_number.Length - i], which will throw an IndexOutOfRangeException for i = 0. Strings are zero-based index, so index of the last character is Length-1. So change the line to
if (input_number[i] != input_number[input_number.Length - i - 1])
Finally, I suggest to make the check method of return type bool instead of int:
static bool check(string input_number)
{
for (int i = 0; i < input_number.Length/2; i++)
if (input_number[i] != input_number[input_number.Length - i - 1])
return false;
return true;
}
This seems more natural to me.
You can use method below. Because you are trying to find the largest number you start from 999 and head backwards, do multiplication and check if its palindrome.
private void FindProduct()
{
var numbers = new List<int>();
for (int i = 999; i > 99; i--)
{
for (int j = 999; j > 99; j--)
{
var product = i * j;
var productString = product.ToString();
var reversed = product.Reverse();
if (product == reversed)
{
numbers.Add(product);
}
}
}
Console.WriteLine(numbers.Max());
}
I have written a console application
Int64 sum = 0;
int T = Convert.ToInt32(Console.ReadLine());
Int64[] input = new Int64[T];
for (int i = 0; i < T; i++)
{
input[i] = Convert.ToInt32(Console.ReadLine());
}
for (int i = 0; i < T; i++)
{
int[,] Matrix = new int[input[i], input[i]];
sum = 0;
for (int j = 0; j < input[i]; j++)
{
for (int k = 0; k < input[i]; k++)
{
Matrix[j, k] = Math.Abs(j - k);
sum += Matrix[j, k];
}
}
Console.WriteLine(sum);
}
When I gave input as
2
1
999999
It gave Out of memory exception. Can you please help.
Look at what you are allocating:
input[] is allocated as 2 elements (16 bytes) - no worries
But then you enter values: 1 and 999999 and in the first iteration of the loop attempt to allocate
Matrix[1,1] = 4 bytes - again no worries,
but the second time round you try to allocate
Matrix[999999, 999999]
which is 4 * 10e12 bytes and certainly beyond the capacity of your computer even with swap space on the disk.
I suspect that this is not what you really want to allocate (you'd never be able to fill or manipulate that many elements anyway...)
If you are merely trying to do the calculations as per your original code, there is not need to allocate or use the array, as you only ever store one value and immediately use that value and then never again.
Int64 sum = 0;
int T = Convert.ToInt32(Console.ReadLine());
Int64[] input = new Int64[T];
for (int i = 0; i < T; i++)
input[i] = Convert.ToInt32(Console.ReadLine());
for (int i = 0; i < T; i++)
{
// int[,] Matrix = new int[input[i], input[i]];
sum = 0;
for (int j = 0; j < input[i]; j++)
for (int k = 0; k < input[i]; k++)
{
//Matrix[j, k] = Math.Abs(j - k);
//sum += Matrix[j, k];
sum += Math.Abs(j - k);
}
Console.WriteLine(sum);
}
But now beware - a trillion sums is going to take forever to calculate - it won't bomb out, but you might like to take a vacation, get married and have kids before you can expect a result.
Of course instead of doing the full squared set of calculations, you can calculate the sum thus:
for (int i = 0; i < T; i++)
{
sum = 0;
for (int j = 1, term = 0; j < input[i]; j++)
{
term += j;
sum += term * 2;
}
Console.WriteLine(sum);
}
So now the calculation is O(n) instead of O(n^2)
And if you need to know what the value in Matrix[x,y] would have been, you can calculate it by the simple expression Math.Abs(x - y) thus there is no need to store that value.