Solving Project Euler #1 - c#

The problem in project Euler says:
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
When I test it with the numbers < 10, it calculates 23, but when I try it with 1000, it gives the wrong answer. Please help :)
Code:
using System;
using System.Diagnostics;
using System.Collections.Generic;
namespace Test
{
class MainClass
{
public static void Main (string[] args)
{
//Initialisation
Console.WriteLine ("==============================");
Console.WriteLine ("Project Euler - Problem 1 - Multiples of 3 and 5 - Test");
Console.WriteLine ("Initialising");
Stopwatch stopwatch = new Stopwatch ();
stopwatch.Start ();
Console.WriteLine ("==============================");
HashSet<int> list = new HashSet<int> (); //Creates a list
int sum = 0;
//Add every multiple of 3 to the list
for (int x = 3; x < 10; x = x + 3) {
list.Add (x);
}
//Add every multiple of 5 to the list
for (int y = 5; y < 10; y = y + 5) {
list.Add (y);
}
//Remove every duplicate from the list
for (int z = 15; z <= 1000; z = z +15) {
list.Remove (z);
}
foreach (int x in list) {
sum = sum + x;
}
//Termination
Console.BackgroundColor = ConsoleColor.DarkRed;
Console.WriteLine ("==============================");
stopwatch.Stop ();
Console.WriteLine ("Time elapsed: {0}", stopwatch.Elapsed);
Console.WriteLine ("==============================");
Console.WriteLine ("Sum: " + sum);
Console.WriteLine ("==============================");
Console.WriteLine ("Terminating");
Console.WriteLine ("==============================");
}
}
}

You are using HashSet.
HashSet is an unordered collection containing unique elements
It doesn't store duplicate entries. You don't need to remove it.
Just remove your 3rd for loop.

Instead of having multiple for loops you could also have one and use the modulus operator. This will void the duplicates you are adding.
for(int i = 0; i < 1000; ++i)
{
if(i % 3 == 0 || i % 5 == 0)
{
// Add to list
}
}

You don't need to remove multiples of 15:
const int N = 1000;
//Add every multiple of 3 to the list
for (int x = 3; x < N; x += 3) {
list.Add(x);
}
//Add every multiple of 5 to the list
for (int y = 5; y < N; y += 5) {
list.Add(y);
}
int sum = list.Sum();

Related

Method to guess possible combination

For practice I want to write a program that will guess random positions of x and y. For example the first point would be
int x = 0;
int y = 0;
x += rand.Next(0, 4);
y += rand.Next(0, 4);
Then from that random point I will add the another random value to x and y to have a second point. However I want to go back to find those points randomly.
To make the points:
int x = 0;
int y = 0;
List<Point> points = new List<Point>();
for (int i = 0; i < numberOfPointsWanted; i++)
{
x += rand.Next(0, 4);
y += rand.Next(0, 4);
points.Add(new Point(x, y));
}
Now I wish to guess those random points almost as if I did not have them stored in a list. Because each new point relies on its predecessor I assume some sort of recursion would be necessary. Almost like a brute force guessing application that will find those points. I am having trouble completing the method that would be able to guess every possible point given a number of desired points.
This is what I have thus far to find the rounds:
class Program
{
static int nRounds = 2;
static Point[] points = new Point[nRounds];
static Point[] test = { new Point(1, 2), new Point(4, 1) };
static bool CheckArray()
{
for (int i = 0; i < points.Length; i++)
if (points[i] != test[i]) { return false; }
return true;
}
static void PrintArray()
{
for (int i = 0; i < points.Length; i++)
Console.Write("[" + tCount + "]\t" + points[i].X + " : " + points[i].Y + "\t");
Console.Write("\n");
}
static int tCount = 0;
static int rCount = 0;
static void GetRounds(int inX, int inY)
{
for (int x = inX; x < 5; x++)
{
for (int y = inY; y < 5; y++)
{
if (rCount < nRounds)
{
tCount++;
points[rCount] = new Point(x, y);
rCount++;
GetRounds(x, y);
if (CheckArray())
{
PrintArray();
return;
}
PrintArray();
}
}
}
rCount--;
}
static void Main(string[] args)
{
GetRounds(0, 0);
Console.ReadKey();
}
}
}
I am trying to randomly generate points as shown above and then guess them based on a hashed value representing all of those points together.
This is what im expecting to see:
If only guessing two points
Point one :: Point two x and y respectively
x y :: x y
0 0 :: 0 1
0 0 :: 0 2
0 0 :: 0 3
0 0 :: 1 0
0 0 :: 1 1
0 0 :: 1 2
0 0 :: 1 3
0 0 :: 2 0
0 0 :: 2 1
0 0 :: 2 2
0 0 :: 2 3
0 0 :: 3 0
0 0 :: 3 1
0 0 :: 3 2
0 0 :: 3 3
0 1 :: 0 0
0 1 :: 0 1
0 1 :: 0 2
And so on until all possibilities of point one and point two are guessed
I'm not sure if this is exactly what you're looking for, but one way to get all those combinations is to use nested for loops:
for (int ax = 0; ax < 4; ax++)
{
for (int ay = 0; ay < 4; ay++)
{
var pointA = new Point(ax, ay);
for (int bx = 0; bx < 4; bx++)
{
for (int by = 0; by < 4; by++)
{
var pointB = new Point(bx, by);
Console.WriteLine($"{pointA.X} {pointA.Y} :: {pointB.X} {pointB.Y}");
}
}
}
}
Output
You were asking about a solution that would allow a variable number of points to be passed in. This is fairly simple to do - you just keep a List<List<Point>> of the results, and on each iteration you generate a list of possible point values (16 possible values when min is 0 and max is 3), and then generate a new list for every item in the existing results for each Point in the new set.
The problem is the size of the result set. Since a single point has 16 possible combinations of X and Y if we have a min value of 0 and a max value of 3, then for each additional point, we raise 16 to that power. So for 10 points, there are over a billion combinations.
private static List<List<Point>> GetAllCombinations(int min, int max, int count)
{
var results = new List<List<Point>>();
for (int i = 0; i < count; i++)
{
var thisSet = new List<Point>();
for (int x = min; x <= max; x++)
{
for (int y = min; y <= max; y++)
{
thisSet.Add(new Point(x, y));
}
}
// If this is our first time through, we just add each point
// as a single-item list to our results
if (results.Count == 0)
{
foreach (var item in thisSet)
{
results.Add(new List<Point> {item});
}
}
// On subsequent iterations, for each list in our results, and
// for each item in this set, we create a new list for each item,
// adding to it a copy of the existing result list. We clear
// the results in the beginning (after making a copy) and then
// add each new list to it in the inner loop.
else
{
// Make a copy of our existing results and clear the original list
var tempResults = results.ToList();
results.Clear();
foreach (var existingItem in tempResults)
{
foreach (var newPoint in thisSet)
{
// Now we populate our results again with a new set of
// lists for each existingItem and each newPoint
var newItem = existingItem.ToList();
newItem.Add(newPoint);
results.Add(newItem);
}
}
}
}
return results;
}
Example usage:
private static void Main()
{
var results = GetAllCombinations(0, 3, 5);
foreach (var result in results)
{
Console.WriteLine(string.Join(" :: ", result.Select(p => $"{p.X} {p.Y}")));
}
Console.WriteLine("With a min value of 0 and max value of 3, " +
$"5 points generated {results.Count} results.");
GetKeyFromUser("Done! Press any key to exit...");
}
Output

Find the 10001st prime

I took a look at the following question from project euler:
By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
What is the 10 001st prime number?
I tried to take the square root of the number and than find all the prime numbers below the square root of the number and then divide the number by all the square roots and see if there is 0 left each time. If the number is not divisible by all the primes under its square root its a prime number. I did this to lower the itterations the programm has to make. Here is what I have now, I am not sure why it isn't working. Anybody knows what i did wrong?
List<int> primeNumbers = new List<int>();
bool prime = true;
bool MainPrime = true;
int check = 1;
for (long i = 3; i < long.MaxValue; i++)
{
if ((i % 2) != 0)
{
int root = Convert.ToInt32(Math.Sqrt(i));
for (int j = 1; j < root; j++)
{
for (int k = 2; k < j; k++)
{
if ((j% k) == 0)
{
prime = false;
}
}
if (prime)
{
primeNumbers.Add(j);
}
prime = true;
}
}
foreach (var item in primeNumbers)
{
if ((i%item) == 0)
{
MainPrime = false;
}
}
primeNumbers.Clear();
if (MainPrime)
{
check++;
}
if (check == 10001)
{
Console.WriteLine(i);
break;
}
}
Console.ReadKey();
Several points:
When finding possible prime divisors, you need to check all numbers up to the square root included, so your condition j < root is incorrect.
You don't have to recalculate the primes again for every number. Keep the list as you go and add new primes to it.
As soon as you find a divisor, you can break out of the foreach loop.
Improved code:
List<long> primeNumbers = new List<long>() { 2 };
for (long i = 3; i < long.MaxValue; i += 2)
{
if(!primeNumbers.Any(p => (i % p) == 0))
{
primeNumbers.Add(i);
if (primeNumbers.Count == 10001)
{
Console.WriteLine(i);
break;
}
}
}
Gives 104743 as the 10001st prime.
What we can do is we can use SieveOfEratosthenes to make an bool array in which all the prime numbers value are set to be true than after that;
1.As we found any prime number increment the count with 1;
2.And as count get equal to 10001 we print its value and break through the loop.
Have a Look at code in C++ (I recommend you to learn SieveOfEratosthenes first)
#include <bits/stdc++.h>
using namespace std;
void SieveOfEratosthenes(long long unsigned n)
{
bool prime[n];
memset(prime, true, sizeof(prime)); //This is SieveOfEratosthenes
for (long long p = 2; p * p <= n; p++)
{
if (prime[p] == true)
{
for (long long i = p * p; i <= n; i += p)
prime[i] = false;
}
}
long long count=0; //initializing count as 0;
for (long long p = 2; p <= n; p++) //running the loop form 2 to n
{
if (prime[p]) //we have bool array in which all prime number set to true using sieve
count++; //increment the count because we found a prime number
if(count==10001) // and as count reaches to 10001 we found our number
{
cout<<p;break;} // print the answer and also break form the loop
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
long long unsigned n=999999;
SieveOfEratosthenes(n); //pass the value of n in sieve function
return 0;
}
Try this one out using python
sp=2
cnt = 1
while cnt <= 10001:
primeflag = 0
for j in range(2,sp):
if(sp%j == 0):
primeflag = 1
break;
if(primeflag == 1):
pass
else:
print(cnt ,sp)
cnt = cnt +1
sp =sp+1
#which Gives
#10001 104743

Project Euler #23 in C#

Project Euler challenge 23 states this:
A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.
A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n.
As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24. By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit.
Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.
So I've been trying to get this working, however I keep getting back an incorrect result, I'm not sure where this is going wrong in the code though I have:
static void Main(string[] args)
{
List<int> abundantNums = Enumerable.Range(12, 1000000).Where(i => isAbundant(i)).ToList();
abundantNums = abundantNums.Distinct().ToList();
var boolArr = new bool[28124];
for (int i = 0; i < abundantNums.Count; ++i)
{
for (int j = i; j < abundantNums.Count; ++j)
{
var sum = abundantNums[i] + abundantNums[j];
if (sum < 28124) boolArr[sum] = true;
else break;
}
}
var total = 0;
for (int i = 0; i < boolArr.Length; i++)
{
if (boolArr[i] == false)
{
total += i;
}
}
Console.WriteLine(total);
Console.ReadKey();
}
static bool isAbundant(int num)
{
if (getFactors(num).Sum() > num)
{
return true;
}
else
{
return false;
}
}
And then to find the factors of a number I have:
static List<int> getFactors(int num)
{
List<int> factors = new List<int>();
Stopwatch watch = Stopwatch.StartNew();
for (int i=1; i < Math.Sqrt(num) + 1; i++)
{
if (num % i == 0)
{
factors.Add(i);
if (num / i != i)
{
factors.Add(num / i);
}
}
}
watch.Stop();
factors.Remove(num);
return factors;
}
Now I've been at this for a day or two and as far as I can tell this should be doing the trick, anyone wiser than I able to point out my failings?
The problem is your getFactors loop. Change:
for (int i=1; i < Math.Sqrt(num) + 1; i++)
to
for (int i=1; i <= Math.Sqrt(num); i++)
And it should work. I'll let you try and understand why :-)

Find Min-Max values of array without using Linq?

I've been working on this assignment for my programming class for a little bit and though I had it solved. A little info for anyone interested: My task is to find the score of the competitor from an array of scores (eg, int[] scores = 4, 5, 6 , 7, 8, 9). BUT I must not include the highest and lowest values when adding the rest of the scores together (eg, score would = 5+6+7+8 (no including 4 and 9)).
My solution when we were allowed to use linq was as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Scoring {
class Program {
static void Main(string[] args) {
int[] scores = { 4, 7, 9, 3, 8, 6 };
remove_duplicates(scores);
console_text(scores);
ExitProgram();
}
static void remove_duplicates(int[] scores) { //removes duplicat values from array
var pScores = scores.Distinct().ToArray();
}
static int result(int[] pScores) { //calculates results by removing max and min scores, then adding the remaining.
return pScores.Sum() - pScores.Max() - pScores.Min();
}
static void console_text(int[] pScores) { //renders the text in the consol window
int final_score = result(pScores);
Console.Write("Competitor your scores were " );
foreach (int i in pScores) {
Console.Write(" " + i);
}
Console.WriteLine("\r\n" + " and your score was " + final_score);
}
static void ExitProgram() {
Console.Write("\n\nPress any key to exit program: ");
Console.ReadKey();
}//end ExitProgram
}
}
So I thought I was done, but now I have recieved and email stating:
"cannot use any system.array methods nor can you use any functionality of Linq or any other library class you may discover"
This has me a bit lost and confused, any help at all would be appreciated.
Thanks
Here is one option. The only thing that is not very clear is weather if there are two equal values which are also min values or max values they should be removed both or only one max value and one min. I remove just one min and one max value:
int[] arr = new int[] { 2, 2, 3, 4, 5, 6, 6 };
int Lowest = arr[0];
int Highest = arr[0];
int sum = 0;
for (int i = 0; i < arr.Length; i++)
{
if (Lowest > arr[i])
{
Lowest = arr[i];
}
if (Highest < arr[i])
{
Highest = arr[i];
}
sum += arr[i];
}
sum -= (Lowest + Highest);
Console.WriteLine("The sum withot the highest and lowest score is : {0}", sum);
and if you and to remove all duplicated min and max scores add this before summing the final score:
int[] arrOfHighest = new int[arr.Length];
int[] arrOfLowest = new int[arr.Length];
int minCounter = 0;
int maxCounter = 0;
for (int i = 0; i < arr.Length; i++)
{
if (Lowest == arr[i])
{
arrOfLowest[minCounter] = arr[i];
minCounter++;
}
if (Highest == arr[i])
{
arrOfHighest[maxCounter] = arr[i];
maxCounter++;
}
}
int sumLoewst = 0;
for (int i = 0; i < arrOfLowest.Length; i++)
{
sumLoewst += arrOfLowest[i];
}
int sumHighest = 0;
for (int i = 0; i < arrOfHighest.Length; i++)
{
sumHighest += arrOfHighest[i];
}
sum -= (sumLoewst + sumHighest);
So the final touch based on the additional information. Since you want the min and max value to be added only once each inthe code above - sum -= (sumLoewst + sumHighest); right after this add:
sum -= (sumLoewst + sumHighest);
sum += (Highest + Lowest);
This way you will have all other values summed, no matter how times they appear in the array. And only one MAX and one MIN value added to the sum.

Function to multiply array elements

im doing a calculator, this is the code:
If i go to the Multiplication function and i enter for example i want to multiple 2*2*2
this code it's outputting 4 8 4
I dont understand why, well i know that 2*2 = 4 * 2 = 8 but why the last 4?
and how can i only get the result without getting the complete series?, when i try to do the Console WriteLine outside the for loops it throws an error. it doesn't let me.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void LetsSum(int [] myArray)
{
int sum = myArray.Sum();
Console.WriteLine(sum);
}
static void letsMult(int [] myArray)
{
for (int a = 0; a < myArray.Length; a++ )
{
for (int b = a+1; b < myArray.Length; b++ )
{
int multip = myArray[a] *= myArray[b];
Console.WriteLine(multip);
}
}
}
static void Main(string[] args)
{
//First Variable total of numbers from users input
int TotalNumb = 0;
//String to receive users input
string TotalN = string.Empty;
//Specifying size of array
Console.WriteLine("Please specify how many numbers do you want to do the math");
TotalN = Console.ReadLine();
//Converte because readline it's a string
TotalNumb = Convert.ToInt32(TotalN);
//Name of ARRAY and passing the value selected by the user
int[] myArray = new int[TotalNumb];
//counter for the loop
int i = 0;
for (i = 0; i < TotalNumb; i++ )
{
Console.WriteLine("Enter your number");
myArray[i] = Convert.ToInt32(Console.ReadLine());
}
Console.WriteLine("Please enter SUM, LESS, MULT, DIV");
string ToDo = Console.ReadLine();
if (ToDo == "SUM")
{
Program.LetsSum(myArray);
}
if (ToDo == "MULT")
{
Program.letsMult(myArray);
}
Console.Read();
}
}
}
Very simple... alter your code like as bellow...
static void letsMult(int [] myArray)
{
int output=1;
for (int a = 0; a < myArray.Length; a++ )
{
output=output*myArray[a];
Console.WriteLine(output);
}
}
The error message is because you're declaring int multip in the innermost scope of the for loop. The int goes out of scope after that, and is not usable. If you want multip to be accessible outside of the for loop, declare it outside of the for loop:
static void letsMult(int [] myArray)
{
int multip = 1;
for (int a = 0; a < myArray.Length; a++ )
{
for (int b = a+1; b < myArray.Length; b++ )
{
multip = myArray[a] *= myArray[b];
}
}
Console.WriteLine(multip);
}
Note, it's declared above the for loop, but used in the loop, and outputted outside the loop, but still in its scope (which in my case is "the entire function").
You still have a logical issue. Are you sure you need a nested loop? How would you describe to a person how to multiply a list of numbers to get the total product?
You have 3 Elements in your Array
[2, 2, 2]
Then you multiply 0 and 1 and output the result:
[4, 2, 2] OUTPUT: 4
Then you multiply 0 and 2 and output the result:
[8, 2, 2] OUTPUT: 8
The n you multiply 1 and 2 and output the result:
[8, 4, 2] OUTPUT: 8
Perhaps you want to remove the outer loop, in this case your Output would be
4, 8
You can do this with LINQ's Aggregate():
for sum :
int[] arr1 = new int[] { 2, 2, 2 };
int result = arr1.Aggregate((a, b) => b + a);
//or
int result = arr1.Sum();
for multiplication :
int[] arr1 = new int[] { 2, 2, 2 };
int result = arr1.Aggregate((a, b) => b * a);
I guess you want to display each multiplacation result.If so you can do the following:
int multip = myArray[0];
for (int a = 1; a < myArray.Length; a++ )
{
Console.Write("{0} * {1} = ",multip, myArray[a]);
multip *= myArray[a];
Console.WriteLine(multip);
}
use
int multip=1;
for (int a = 0; a < myArray.Length; a++ )
{
multip *= myArray[a];
Console.WriteLine(multip);
}
}

Categories

Resources