Divisors of triangle numbers (Euler 12) - c#

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.

Related

How to use bulk insert condition for particular number of records inside for loop

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);
}

How do we count the number of occurrence from left to right and continue until we have consecutive numbers?

So the code that I wrote, is for the number of occurrence. Suppose in the sample part which is mentioned, if I give an input Array of {2,1,1,1,3}, it will give me the count of Number 2 occurrence as 1. Now, I'm struggling to write the code in a manner so that it gives me the count only if it's continuous from left to right. Suppose, if my array is {1,1,1,2,0}, only then it will give me the total occurrence of 1 as 3, but not if it's {1,0,1,2,1} or {0,0,1,1,1} or {1,1,2,2,1}
static void Evaluate_V5B(int[] window, int[] PayCombos,)
{
int[] Counters1 = new int[3];
for (int index0 = 0; index0 < 5; index0++)
{
Console.Write("{0} ", window[index0]);
int symbol = window[index0];
Counters1[symbol]++;
}
Console.WriteLine();
for (int indexJ = 0; indexJ < Counters1.Length; indexJ++)
{
Console.WriteLine("{0}", Counters1[indexJ]);
}
}
This will take the 1st element in the array and return continuous occurrences from left to right. If that element found anywhere else it will return 0 as count:
static void Evaluate(int[] array)
{
var count = 1;
var first = array[0];
for (int i = 1; i < array.Length; i++)
{
if(array[i] == first)
{
count++;
}
else{
for (int j = i + 1; j < array.Length; j++)
{
if(first == array[j]) {
count = 0;
break;
}
}
break;
}
}
Console.WriteLine($"Count of Number {first} occurrence is {count}");
}
This function will find the number of continuous occurrences of a specific number num in the array nums, if it is the first number.
static int ContinuousOccurrences(int[] nums, int num)
{
if (nums[0] == num)
{
int continuousOccurrences =
nums.TakeWhile(x => x == num).Count();
int totalOccurrences =
nums.Where(x => x == num).Count();
if(continuousOccurrences == totalOccurrences)
{
return continuousOccurrences;
}
else
{
return 0;
}
}
return 0;
}
If you want to know the number of continuous occurrences of the first number, call the function this way:
ContinuousOccurrences(nums, nums[0])

Solving with only loop

The number 124 has the property that it is the smallest number whose first three multiples contain the digit 2. Observe that
124*1 = 124, 124*2 = 248, 124*3 = 372 and that 124, 248 and 372 each contain the digit 2. It is possible to generalize this property to be the smallest number whose first n multiples each contain the digit 2. Write a function named smallest(n) that returns the smallest number whose first n multiples contain the digit 2. Hint: use modulo base 10 arithmetic to examine digits.
Its signature is
int smallest(int n)
Examples
If n is return because
4 624 because the first four multiples of 624 are 624, 1248, 1872, 2496 and they all contain the
digit 2. Furthermore 624 is the smallest number whose first four multiples contain the digit 2.
5 624 because the first five multiples of 624 are 624, 1248, 1872, 2496, 3120. Note that 624 is also
the smallest number whose first 4 multiples contain the digit 2.
6 642 because the first five multiples of 642 are 642, 1284, 1926, 2568, 3210, 3852
7 4062 because the first five multiples of 4062 are 4062, 8124, 12186, 16248, 20310, 24372, 28434.
Note that it is okay for one of the multiples to contain the digit 2 more than once (e.g., 24372).
I tried to solve this by this way
//Its a incomplete code
public static int smallest(int n)
{
int i = 1;
for (; ; )
{
int temp = 0;
int myNum = 0;
for (int j = 1; j <= n; j++)
{
myNum = i * j;
//check for condition
}
//if condition ture break
}
}
But I am stick to the problem is I cannot create hard coded n times variable.. Can you help me proceed that?
You may assume that such a number is computable on a 32 bit machine, i.e, you do not have to detect integer overflow in your answer.
using System;
using System.Collections.Generic;
namespace firstconsoleproject
{
class MainClass
{
public static void Main (string[] args)
{
int first=4;
int c=0;
int ax;
int ai;
Console.WriteLine ("please enter n");
ax = Convert.ToInt32( Console.ReadLine());
for (int i=11 ; ax>0 ;)
{ if (first==1)
{
c = ax+1;
i++;
}
c--;
ai=i*c;
for (int ten=10 ; ; )
{
if(ai%ten==2)
{
first=0;
break;
}else if (ai==0)
{
first=1;
break;
}
ai/=10;
}
if (c==0){Console.WriteLine("number is "+i);break;}
}Console.ReadKey ();
}
}
}
// Function smallest n
public int smallest(int a)
{
int temp = 0, holder = 0, k = 0;
if (a <= 0) return 0;
else
{
for (int i = 100; i < Int16.MaxValue; i++)
{
int count = 0;
k = 0;
int[] array = new int[a];
for (int j = 1; j < 9; j++)
{
holder = i * j;
temp = holder;
while (temp > 0)
{
int rem = temp % 10;
if (rem == 2)
{
count++;
if (k < a)
{
array[k] = j;
k++;
break;
}
}
temp /= 10;
}
if (count == a)
{
int countTemp = 0;
for (int h = 0; h < a; h++)
{
if (h + 1 < a)
{
if (array[h + 1] == array[h] + 1 && array[0] == 1 && array[h] > 0)
{
countTemp++;
if (countTemp == a - 1)
return i;
}
}
}
}
}
}
}
return 0;
}
public static int smallest(int n)
{
int i = 1;
for (; ; )
{
int contain = 0;
int temp = 0;
int myNum = 0;
for (int j = 1; j <= n; j++)
{
myNum = i * j;
temp = myNum;
while (true)
{
if (temp % 10 == 2)
{
contain++;
break;
}
temp = temp / 10;
if (temp <= 0)
break;
}
}
if (contain == n)
break;
i++;
}
return i;
}

"myList.Count" is less then the amount of elements inside the list

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.

List/Array member can't be addressed - Euler 14

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);
}

Categories

Resources