I have the below code. I create a list (tried with array as well) with one million and one members. All of them has the value 0 by default. It should work like a multidimensional array, but it's not necessary as the first 'column' has to be numbers from 1-1.000.000. To make life easier I made 1.000.001 members to avoid using the 0th place.
At a certain point I have to use a member of this list addressed by a variable: list[n], and to avoid issues this only happens if n < 1.000.000. As there are members from 0-1.000.000 I think it's OK, but still my program crashes after a while with error code ArgumentOutOfRangeException.
What am I missing here?
int highestCount = 0;
int highestNum = 0;
List<int> list = new List<int>();
for(int j = 0; j <= 1000001; j++)
{
list.Add(0);
}
for (int i = 2; i < 1000000; i++)
{
int count = 0;
int number = i;
do
{
if (i % 2 == 0)
{
number = number / 2;
if (number < 1000000)
{
if (list[number] != 0)
{
count += list[number];
break;
}
else
{
count++;
}
}
else { count++; };
}
else
{
number = (number * 3) + 1;
if (number < 1000000)
{
if (list[number] != 0) //program dies here
{
count += list[number];
break;
}
else
{
count++;
}
}
else { count++; };
}
} while (number > 1);
list[i] = count;
if (count > highestCount)
{
highestCount = count;
highestNum = i;
}
}
MessageBox.Show(highestNum.ToString());
I think it's just a problem with your logic.
When i == 3 (on the second run), it will go into the do-while block.
Since i % 2 != 0 at that point, it will hit the else.
The number is multiplied by 3 and you add 1.
It is less than 1000000, but....
if(list[number] != 0)
never evaluates to true and you are stuck in an infinite do-while loop and it never breaks out because A) number will always be greater than 1 (satisfying the while condition); and B) you set every element of the array to zero in the code above this loop (thus never satisfying the above if condition):
for(int j = 0; j <= 1000001; j++)
{
list.Add(0);
}
Related
So I have a method which returns an array of the factors of a number
Tools.cs
public static long[] GetFactors(long number)
{
long range = number / 2;
long potentialFactors = 2;
long[] factors = new long[range + 1];
factors[0] = 1;
factors[range] = number;
for (long i = 1; i < range; i++)
{
if (number % potentialFactors == 0)
{
factors[i] = potentialFactors;
potentialFactors++;
} else
{
potentialFactors++;
}
}
Console.WriteLine($"here are the factors for the number {number}:\n"+string.Join("\n", factors));
return factors;
}
program.cs
static void Main(string[] args)
{
Tools.GetFactors(24);
Console.ReadLine();
}
But when I run my code, this appears:
here are the factors for the number 24:
1
2
3
4
0
6
0
8
0
0
0
12
24
How can I stop 0 from appearing, should I rewrite the "for" loop, or is there a way to remove 0 from the array?
You are allocating a fixed size array and setting the element to non-zero only when it is a factor.
You should instead use a var factors = new List<long>(); and call factors.Add(potentialFactor); to only store those numbers which are valid factors.
This code is using List instead of Array and also there are some other changes.
public static List<long> GetFactors(long number)
{
long range = number / 2;
List<long> factors = new List<long>() { 1 };
for (long i = 2; i <= range; i++)
{
if (number % i == 0)
{
factors.Add(i);
}
}
factors.Add(number);
Console.WriteLine($"here are the factors for the number {number}:\n" + string.Join("\n", factors));
return factors;
}
I agree a list is better when you dont know before hand how many factors you will gote. But if you really want to use an Array. You can loop throught this array, find the 0's one by one and them swith Left the numbers. Like so :
// Extension Method of array
public static void RemoveAllZeros(this long[] array) // O(N^2)
{
for (int i = 0; i < array.Length; i++)
{
if (array[i] == 0)
{
// Grab the index override value and continue swift left
for (int j = i; j < array.Length - 1; j++)
{
array[j] = array[j + 1];
}
}
}
}
OR using a bit of LINQ and List :p :
// Extension Method of array
public static void RemoveAllZeros(this long[] numbers)
{
int zeroPst = numbers.ToList().IndexOf(0);
if (zeroPst == -1)
return;
for (int i = zeroPst; i < numbers.Length - 1; i++)
{
numbers[i] = numbers[i + 1];
}
numbers.RemoveAllZeros(); //Recursion, carefull
}
I want to use the bulk insert concept in C# once count reach 20.if we have 40 numbers no issue. but if we get 39 records got a problem, based on if the condition. how we able to avoid this problem. here below I added a simple program for reference.
var numbers = 39 // not static numbers
int count = 0;
for(int i=0; i<=numbers; i++)
{
count++;
if (count == 20)
{
//Logic
count = 0;
}
}
You can determine whether to batch insert the rest files by comparing the counter with the remaining number of files.
int num = 49;
int count = 0;
for(int i = 1; i <= num; i++)
{
count++;
var n = i / 20;
if(i % 20 == 0 ||count == (num - 20 * ( i / 20)))
{
//Logic
count = 0;
}
}
No need of count variable, you can use modulo operator inside for loop
Like
for(int i = 0; i <= numbers; i++)
{
//i != 0 to avoid bulk process at first
if(i != 0 && i % 20 == 0)
{
//Your bulk operation
}
}
I recommend you to use Console.WriteLine() to print value of i and counter in each iteration so that you will understand bug in your code.
var numbers = 39 // not static numbers
int count = 0;
for(int i=0; i<=numbers; i++)
{
count++;
//Print values to understand flow of program
Console.WriteLine($"For i = {i}, value of count is {count}");
if (count == 20)
{
Console.WriteLine("Time to reset count variable");
//Logic
count = 0;
}
}
You can use Linq .Skip() and .Take(), to do batches
var batchSize = 20;
var batchCount = files.Count() / batchSize;
for (int i = 0; i < batchCount; i++)
{
var bulkFiles = files.Skip(i * batchSize).Take(batchSize);
}
I have a task to write a program that takes some numbers and step as input. Then it must make a sequence of binary representation of those numbers and destroy bits at positions 1, 1*step, 2*step, 3*step... Here is the code:
using System;
using System.Collections.Generic;
class BitKiller
{
static void Main()
{
int
amountNumbers = int.Parse(Console.ReadLine()),
step = int.Parse(Console.ReadLine()),
counter = 0,
number = 0
;
int[]
numBin= new int[8],
numbers = new int[amountNumbers]
;
var sequence = new List<int>();
for(int i = 0; i < amountNumbers; i++)
{
numbers[i] = int.Parse(Console.ReadLine());
numBin = ToBin(numbers[i]);
sequence.InsertRange(counter * 8, numBin);
foreach(int b in sequence)
{
Console.Write(b);
}
Console.WriteLine("");
counter++;
}
if(step == 1)
{
Console.WriteLine(0);
return;
}
for(int i = sequence.Count; i >= 0; i--)
{
if(i % step == 1)
{
sequence.RemoveAt(i);
}
}
Console.WriteLine("List count = {0}", sequence.Count);
if(sequence.Count % 8 != 0)
{
int padding = 8 - (sequence.Count % 8);
for(int i = 0; i < padding; i++)
{
sequence.Add(0);
}
}
foreach(int b in sequence)
{
Console.Write(b);
}
Console.WriteLine("");
for(int i = 7, power = 0, y = 0; y < sequence.Count; i--, y++, power++)
{
number = number + (sequence[i]) * ToPower(2, power);
if(i == 0)
{
Console.WriteLine("Result = {0}", number);
sequence.RemoveRange(0, 8);
foreach(int b in sequence)
{
Console.Write(b);
}
Console.WriteLine("");
number = 0;
i = 7;
y = 0;
power = 0;
}
}
}
static int[] ToBin(int number)
{
var binSequence = new int[8];
for(int i = 7; i >= 0; number /= 2, i--)
{
if(number % 2 == 0 || (number == 0 && i >= 0))
{
binSequence[i] = 0;
}
else
{
binSequence[i] = 1;
}
}
return binSequence;
}
static int ToPower(int number, int power)
{
int numberReturn = number;
if(power == 0)
{
return 1;
}
if(number == 1)
{
return number;
}
for(int i = 0; i < power - 1; i++)
{
numberReturn = numberReturn * number;
}
return numberReturn;
}
}
Now, there are a couple of extra print lines so you can see the binary numbers coming up as you input numbers. In short my program converts the numbers to lists containing only '1' and '0' and then removes values from this list according to my formula. My main question is why is:
sequence.Count
returning 22, when there are obviously 24 '1's inside the list. Test it with the following input: 3,19,255,255,255. The Result will be: 255, 254, 252, while the correct output would be 255, 255, 252.
It is happening, because of this code:
if(sequence.Count % 8 != 0)
{
int padding = 8 - (sequence.Count % 8);
for(int i = 0; i < padding; i++)
{
sequence.Add(0);
}
}
Because the sequence.Count is 22 ( why? ) the condition is true and the following for loop is replacing my last two '1's with 2 zeros. Which is causing the wrong output. So back to the point. Why is sequence.Count equal to 22, when there are 24 '1's in the list.
Sorry, if it is a bit long and confusing, but I posted the whole code, because I have no idea what and how could be interfering to cause this issue.
You are removing two items from the list in this code:
for(int i = sequence.Count; i >= 0; i--)
{
if(i % step == 1)
{
sequence.RemoveAt(i);
}
}
With the example input you gave, sequence.RemoveAt is being called when i == 20 and when i == 1. There were 24 items, then you removed 2 of them.
Duly noted: A whole day into programming affects my basic calculus. The list count and if conditions are both performing properly. After another hour of testing I realized that the problem was that I need to set both 'y' and 'i' to - 1 value, because they are incrementing instantly by 1 when they hit the for loop. Thanks for the tips.
Its been bugging me for hours because it is always returning 0 at numbers[i] and I cant figure out the problem. code worked for a different program but I had to change it so it could have a custom array size and that's when everything went wrong.
any help would be great.
Thanks in advance.
int[] numbers = new int[Convert.ToInt16(TxtArray.Text)];
int j = 0;
for (j = numbers.Length; j >= 0; j--)
{
int i = 0;
for (i = 0; i <= j - 1; i++)
{
string NumbersInput = Microsoft.VisualBasic.Interaction.InputBox("Enter Numbers to be sorted",
"Numbers Input", "", -1, -1);
numbers[i] = Convert.ToInt16(NumbersInput);
//returns 0 in if statement
if (numbers[i] < numbers[i + 1])
{
int intTemp = 0;
intTemp = numbers[i];
numbers[i] = numbers[i + 1];
numbers[i + 1] = intTemp;
}
}
}
for (int i = 0; i < numbers.Length; i++)
{
LstNumbers.Items.Add(numbers[i]);
}
private void button1_Click(object sender, EventArgs e)
{
int sizeOfArrayInt = Convert.ToInt32(arraySize.Text);
int[] array = new int[sizeOfArrayInt];
string numbers = arrayValues.Text;
string[] numbersSplit = numbers.Split(',');
int count = 0;
foreach (string character in numbersSplit)
{
int value;
bool parse = Int32.TryParse(character, out value);
if (value != null)
{
array[count] = value;
}
count++;
}
array = this.SortArray(array);
foreach (int item in array)
{
this.listBox.Items.Add(item);
}
}
private int[] SortArray(int[] arrayToSort)
{
//int[] sortedArray = new int[arrayToSort.Length];
int count = arrayToSort.Length;
for (int j = count; j >= 0; j--)
{
int i = 0;
for (i = 0; i <= j - 2; i++)
{
if (arrayToSort[i] < arrayToSort[i + 1])
{
int intTemp = 0;
intTemp = arrayToSort[i];
arrayToSort[i] = arrayToSort[i + 1];
arrayToSort[i + 1] = intTemp;
}
}
}
return arrayToSort;
}
strong text
This I got to work as a Windows Form and the output displays in the list box as each array item or individual i iteration over the array. Of course there is no error checking. Hope that helps.
Setting aside the strangeness of how you are working with text boxes, your problem with throwing an exception would happen even without them because it lies here, in your inner loop:
for (i = 0; i <= j - 1; i++)
Suppose that numbers.Length == 2. This means that j == 2. So on the first time through the outer loop, you hit the inner loop with these conditions. The first time through, i == 0. You get to the if statement:
if (numbers[i] < numbers[i + 1])
numbers[0] exists, and numbers[1] exists, so this iteration goes through fine and i is incremented.
Now i == 1. Now the loop checks its boundary condition. i <= j - 1 == true, so the loop continues. Now when you hit that if statement, it tries to access numbers[i + 1], i.e., numbers[2], which does not exist, throwing an IndexOutOfRangeException.
Edit: Came back and realized that I left out the solution (to the exception, anyway). For the bubble sort to work, your inner loop's boundary condition should be i <= j - 2, because j's initial value is == numbers.Length, which is not zero-based, while array indexes are.
Second Edit: Note that just using a List won't actually solve this problem. You have to use the right boundary condition. Trying to access list[list.Count()] will throw an ArgumentOutOfRangeException. Just because a List will dynamically resize doesn't mean that it will somehow let you access items that don't exist. You should always take time to check your boundary conditions, no matter what data structure you use.
I have found a couple of topics related to this very problem, I just want to know why my code returns incorrect data.
So we have to find the first triangle number having more than 500 divisors. Details can be found here: http://projecteuler.net/problem=12
And here is my code:
Int64 triangularnum = 1;
for (Int64 num = 2; num > 0; num++)
{
if(has501Divisors(triangularnum))
{
MessageBox.Show(triangularnum.ToString());
break;
}
triangularnum += num;
}
private bool has501Divisors(Int64 candidate)
{
bool has501 = false;
int count = 0;
for (int i = 1; i < Math.Sqrt(candidate); i++)
{
if (candidate % i == 0) count += 1;
if (count > 501)
{
return true;
}
}
return has501;
}
This gives me number 842161320 which is apparently incorrect.
You should increment your count number by 2 not 1.
Also your
if (count > 501)
part is incorrect because your boundary should 500 not 501. Change it to count > 500 instead of.
static void Main(string[] args)
{
Console.WriteLine(Find());
}
public static int Find()
{
int number = 0;
for (int i = 1; ; i++)
{
number += i; // number is triangle number i
if (CountDivisorsOfNumber(number) > 500)
return number;
}
}
private static int CountDivisorsOfNumber(int number)
{
int count = 0;
int end = (int)Math.Sqrt(number);
for (int i = 1; i < end; i++)
{
if (number % i == 0)
count += 2;
}
if (end * end == number) // Perfect square
count++;
return count;
}
This prints 76576500 and looks like a right solution.
The problem is you are limiting your loop to the square root, which is smart, however that means you need to increment your count by two, not by 1 to account for both divisors.
Change your incrementation to this:
if (candidate % i == 0) count += 2;
Additionally, your count check checks for greater than 501 divisors, not 500.
Quick look but your check isn't ok:
if (count > 501)
This will stop at count 502, not 501.
for (int i = 1; i < Math.Sqrt(candidate); i++)
9 is divisible by 3, so you should use <= here. Also, you're divising by 1, you should start at i = 2.