Project Euler - 1: Finding multiples of 3 and 5 [duplicate] - c#

This question already has answers here:
Add all natural numbers that are multiples of 3 and 5 : What is the bug in the following code
(5 answers)
Project Euler: Problem 1 (Possible refactorings and run time optimizations)
(13 answers)
Closed 9 years ago.
Project Euler - Problem 1: Find the sum of all the multiples of 3 or 5 below 1000.
Looking through the questions here about the same problem I assume the way I tried to solve is is quite bad. What is the best way to solve this?
And my other question: The sum value doesn't match the answer. I think the problem is that when I use foreach to write out the list value its starts from 705 instead of 3, but I have no idea why. I would appreciate if someone could explain it to me.
This is the code that I'm using now:
List<int> numbers = new List<int>();
for (int i = 3; i < 1000; i += 3)
{
numbers.Add(i);
}
for (int j = 5; j < 1000; j += 5)
{
numbers.Add(j);
}
numbers.ForEach(Console.WriteLine);
int sum1 = numbers.Sum();
Console.WriteLine(sum1);
Console.ReadLine();

This is because numbers allows duplicates. Note that you are going to have some duplicates, there - for example, numbers 15, 30, 45, and so on, will be added twice.
Replace
List<int> numbers = new List<int>();
with
ISet<int> numbers = new HashSet<int>();
and it's going to work because a HashSet won't allow duplicate values.

This is the first problem on Project Euler.
Personally, I used a one liner :
Enumerable.Range(0, 1000).Where(n => n % 3 == 0 || n % 5 == 0).Sum()
But you can also use the long way for more readability :
int sum = 0;
for (int i = 0; i < 1000; i++)
{
if ((i % 3 == 0) || (i % 5 == 0))
{
sum = sum + i;
}
}
If you don't know how the modulo (%) operator works, I suggest you read it here
If you need more details about the problem itself, just create an account on Project Euler, enter the answer, and read the Problem Overview.

You're not accounting for numbers that are both multiples of 3 and 5
If I were you, I'd have something like the following
for(int i=1; i<1000; i++)
{
if(i is a multiple of 15)
//account for 15
else if(i is a multiple of 3)
//account for 3
else if(i is a multiple of 5)
//account for 5
}

The reason your output starts with 705 is because your list of numbers is quite long (532 numbers to be exact). Your Console window can only contain a couple of lines before it starts scrolling.
So you do start with the number 3, it's just not visible.

As others have pointed out, the issue is that your code counts multiples of 15 twice. Of course, this task is pretty easy using Linq's Range and Where methods:
var numbers = Enumerable.Range(0, 1000)
.Where(n => n % 3 == 0 || n % 5 == 0);
foreach(var n in numbers)
{
Console.WriteLine(n);
}
var sum = numbers.Sum();
Console.WriteLine(sum);
Console.ReadLine();

You have duplicate values in the list. Thats why total sum is invalid. You better change the Data Structure to HashSet which not allow duplicates.
If you can't do that or you have to proceed with this way, try below
call numbers = numbers.Distinct().ToList(); before numbers.ForEach(Console.WriteLine);
I think the problem is that when I use foreach to write out the list
value its starts from 705 instead of 3, but I have no idea why.
Problem is duplicate values, foreach will print correctly but you may not able to scroll console to beginning of printing.
try Console.WriteLine(string.Join(",", numbers));

You could also solve it with Linq. Use Enumerable.Range to get all numbers between 0 and 999 (inclusive). Then use Where to filter those out which are divisible by 3 or divisible by 5. Finally use Sum.

Related

How to find subset of numbers in array that equals to 10? [duplicate]

This question already has answers here:
Find if pair of elements with given sum exists in large integer array
(6 answers)
Closed 8 years ago.
I want to find the sum of all subsets of adjacent numbers.
So if the set is 6 1 2 2 5
I want to find (the sum of)
6 1 2 2 5
6 1 2 2
1 2 2 5
6 1 2
1 2 2
2 2 5
6 1
1 2
2 2
2 5
So I want to find not anly subsets of 2 numbers,but more(example input: 6 1 2 2 5 -> 6+2+2=10 or 1+2+2+5=10) and print them.
using System;
class Subset
{
static void Main()
{
string[] num = Console.ReadLine().Split(' ');
int[] number = new int[num.Length];
for (int a = 0; a < 5; a++)
{
number[a] = Convert.ToInt32(num[a]);
}
int sum;
bool found = false;
for (int i = 0; i < 5; i++)
{
sum = 0;
for (int j = i; j < 5; j++)
{
sum = sum + number[j];
if (sum == 10)
{
found = true;
for (int k = i; k < j; k++)
{
Console.Write("{0} + ", number[k]);
}
Console.Write(number[j]);
Console.Write(" = 10\n");
}
}
}
if (found == false)
{
Console.WriteLine("no zero subset\n\n");
}
}
}
This is very similar to the subset sum problem. The only way to really find a combination that adds up to ten (or even all combinations), you will have to test all combinations. I am not sure if you want combinations of any size, or only two numbers. The examples you give only involve examples where two numbers add up to ten, which can be easily done by checking for all pairs.
for (int i = 1; i < numbers.Length; i++)
for (int j = 0, j < i; j++)
if (numbers[i] + numbers[j] == 10)
{
Console.WriteLine("{0} + {1} = 10", numbers[i], numbers[j];
return;
}
Console.WriteLine("no subset that sums up to 10");
If however you want to find any subset of numbers that add up to ten, you have to consider all subsets of the set you are given. The best way to do this is using dynamic programming. You loop through the array of numbers and for each number you make the decision to either include the element in the subset or not. Let's look at the following method:
bool SubsetSum(int[] numbers, int startIndex, int sum)
{
if (startIndex == numbers.Length - 1) // base case, only one element to consider
return numbers[startIndex] == sum || sum = 0;
return SubsetSum(numbers, startIndex + 1, sum) // don't take the current element
|| SubsetSum(numbers, startIndex + 1, sum - numbers[startIndex]; // take the current element
}
This method first checks if we arrived at the last element. In that case, we have two easy cases to consider: the sum we want to reach is 0, so we don't take the element, or the sum we want to reach is equal to the last element, in which case we do take it. Otherwise, there is no valid solution.
In all the other cases, we just branch into two paths, either taking or not taking the element into the subset.
This algorithm will run in exponential time in the amount of numbers as input. You can speed this up by using memorisation. You can create a huge table and save for every pair of startIndex and sum the outcome value. That way you are sure you will never evaluate the same thing twice. (Look up dynamic programming to learn more about this)
The method I described above only returns if a subset exists. To actually find the subset, you will also have to pass back the indices of the elements you have added to the subset. I won't work that out, as it makes the thing a lot more complicated. If you use a table in the dynamic programming approach, you are also able to use some backtracking techniques to find the right indices in linear time.

2d array,adding it values in a weird pattern

i started learning C# and programming a few months ago and have some problems. The idea here is we create a 2 dimensional array (the number of rows / columns are added by the user), the numbers need to be between 1 and 10.
Then when the array is created the number sequence ( 3-5-7-9-11 etc) is started in the first and finishes in the last column. The rest of the numbers in the columns are added via keyboard by the user starting with the first row (ignoring column 1 and the last column cause we have that added).
The questions are :
What will be the best way to check if the numbers of rows/columns are between 1 and 10? (I was thinking of IF-else but isn't there a better way ?)
How will i make it so that the number sequence 3-5-7 etc is started in the first and finishes in the last column?
Yeah i feel lost.
Where i am at the moment :
Console.WriteLine("Add row value of 1-10");
string s1
s1 = Console.ReadLine();
int k = int.Parse(s1);
Console.WriteLine("Add column value of 1-10");
string s2;
s2 = Console.ReadLine();
int p = int.Parse(s2);
int[,] M = new int[k, p];
Example : we added k(row) & p(coulmn) value of 4.So the array should look like :
3 x x 11
5 x x 13
7 x x 15
9 x x 17
Then the X's should be added again manually without overwriting the existing numbers .The value of the numbers doesnt matter.
So... If I get it right you want to ask user the "length and width" of dynamical 2d array?
To check if entered number is between 1 and 10 there's only 1 method:
int [,] M;
if (k >= 1 && k <= 10 && p >= 1 && p <= 10)
{
M = new int[k,p];
}
And better is to do int.TryParse() for case if user enters characters there instead of numbers, or else you can easily get an Exception.
Filling with numbers:
int num = 3;
for (int i = 0; i < k; ++i)
{
M[i,0] = num;
num+=2;
}
for (int i = 0; i < k; ++i)
{
M[i,p] = num;
num+=2;
}
This adds numbers in 1st and last column in each row. After that to fill other cells manually you check every cell thet it is not in firs or last column.
I hope I understood you correctly. Provided code may be simplified, but provided in such way for better understanding.
if(k>0 && k<11 && p>0 && p<11)
{
int i;
int M[,] = new int[k,p];
for (i=0;i<k;i++)
{
M[i,0]=i*2+3;
M[i,p-1]=(i+k)*2+3;
}
}

How to sort first M elements in N length array?

I have some tasks about sorting arrays in C#. I've been trying everything I could think of - no luck.
The task is to sort an array of integers by known sorting algorithms (insertion, selection, bubble, quick). Thing is, I have to sort ONLY the smallest M elements.
Example: I have an array of 7 elements 2 9 8 3 4 15 11 and I need to sort the smallest 3 elements so that my array becomes 2 3 4 9 8 15 11.
Please help, I can't seem to find anything neither here in SO, nor anywhere through Google. I don't ask to do all the algorithms for me, I just need one of those just to get hold on how's that possible.
E: Thank you for your thoughts. I've reviewed all of your recommendations and have accomplished to make an insertion sort like that:
static int[] insertSort(int[] arr, out int swaps, out int checks) {
int step = 0;
swaps = 0;
checks = 0;
for (int i = 0; i < arr.Length; i++) {
int min = arr[i], minind = i;
for (int j = i + 1; j < arr.Length; j++) {
checks++;
if (arr[j] < min) {
min = arr[j];
minind = j;
}
}
int temp = arr[minind];
if (step < M) {
for (int j = minind; j > i; j--) {
swaps++;
arr[j] = arr[j - 1];
}
arr[i] = temp;
swaps++;
step++;
}
}
return arr;
}
Swaps and checks - requirement for my application.
P.S. I've seen many times that SO doesn't like to do homework for someone. That's why I haven't asked for code, I've just asked for thoughts on how to accomplish that.
Thanks again for those who have helped me out here.
Since there is no efficiency limitations:
Set i to 0.
Look for the minimum among the not sorted elements.
Insert it into the position i, shift the array.
Increment i.
Repeat M times.
Complexity is O(N * M).
Without seeing your implementation, this is hard to answer. There are many ways to do this, and most are straight-forward.
Here are a few ideas though:
Create a "temporary" array that only holds the numbers to sort, sort it, then replace in original array (probably a sub-optimal solution)
Use a for loop that iterates the number of times you need (3 or whatever). This is probably the best solution
Post your code here on SO and some naive person will probably give you a solution so you don't have to do your schoolwork yourself. (This is a lazy and unbecoming solution)
I think here is what you are looking for, this is an example sorting of array ascending based on specific indixes.
int startIndex=2;
int endIndex=5;
int[] elements=new int[7];
elements[0]=2;
elements[1]=9;
elements[2]=8;
elements[3]=3;
elements[4]=4;
elements[5]=15;
elements[6]=11;
for (int a=startIndex-1;a<endIndex;a++){
for(int b=startIndex-1;b<endIndex;b++){
if (elements[a]<elements[b]){
int temp =elements[a];
elements[a]=elements[b];
elements[b]=temp;
}
}
}
for (int c=0;c<elements.Length;c++){
Console.Write(elements[c]+",");
}
Just change the "<" to ">" if you want to sort it desc.
You'd want to take a look at what sorting algorithm you're required to use. Say for example we're using one that uses a for loop. Most cases you'd see something like this
for(int i = 0; i < arrayName.length(); i++)
{}
In your case, just change the parameters of the for loop
for(int i = 0; i < M; i++)
{}
Where M is less than arrayName.length(); and is the number of positions from the beginning you would like to sort.
The rest of the array, untouched, should remain the same.
Couple things. Most sorting algorithms use array.length as the maximum range.
Could you just use m there instead? ie
for (int i = 0; i < m; i++)
Also, you could use a temporary array of the first m characters, sort it, then reassign.
int[] temp;
for (int i = 0; i < m; i++)
{
temp[i] = realArray[i];
}
//sort, then
for (int i = 0; i < m; i++)
{
realArray[i] = temp[i];
}
I would sort the full array and put it into the an other one.
Truncate the new array to only keep the smallest x elements.
Get the largest number from that array (in your example, 4).
Loop through the initial array and append all numbers that are higher.
Input: 2 9 8 3 4 15 11
Sort all: 2 3 4 8 9 11 15
Truncate: 2 3 4
Get highest value from this array (4)
Loop through original array and append
Is 2 higher than 4? no
Is 9 higher than 4? yes, append (we now have: 2 3 4 9)
Is 8 higher than 4? yes, append (we now have: 2 3 4 9 8)
Is 3 higher than 4? no
Is 4 higher than 4? no
Is 15 higher than 4? yes, append (we now have: 2 3 4 9 8 15)
Is 11 higher than 4? yes, append (we now have: 2 3 4 9 8 11)
*This is not the most efficient way and might cause problems if you have duplicate numbers
Any prescriptions on using LINQ?
int a[] = new int[] {2, 9, 8, 3, 4, 15, 11};
const int M = 5;
a = a.Take(M).OrderBy(e => e).ToArray(); // EDIT: Added .ToArray()

C#: the most efficient way to convert int[] into a string

I do know that this kind of questions have already been answered many times. Although I've found lots of possible answers, they still don't solve my problem, which is to implement the fastest possible way to convert an integer array into a single string. I have for example:
int[] Result = new int[] { 1753387599, 1353678530, 987001 }
I want it reversed, so I believe it's best to precede the further code with
Array.Reverse(Result);
Although I don’t iterate from the end, it’s equivalent to reversing, because I call elements from the end. So I have already done this. Just to let you know - if you can think of any other solution than mine, I suggest using this Array.Reverse, because the solution must be reversed.
I always care only about the last 9 digits of a number - so like modulo 1 000 000 000. Here is what I'd like to get:
987001|353678530|753387599
Separators just to have it clear now. I wrote my own function that is about 50% faster than using .ToString().
tempint - current element of the int array,
StrArray - a string array. It's not worth using StringBuilder or summing
strings, so at the end I simply join the elements of the AnswerArr to get the result.
IntBase - an array containing 1000 elements, numbers in strings from "000" to "999", indexed 0 to 999.
for (i = 0; i < limit; i++)
{
//Some code here
j = 3 * (limit - i);
//Done always
StrArray[j - 1] = IntBase[tempint % 1000];
if (tempint > 999999)
{
//Done in 99/100 cases
StrArray[j - 2] = IntBase[tempint % 1000000 / 1000];
StrArray[j - 3] = IntBase[tempint % 1000000000 / 1000000];
}
else
{
if (tempint > 999)
{
//Done just once
StrArray[j - 2] = IntBase[tempint % 1000 / 1000];
}
}
}
//Some code here
return string.Join(null, StrArray);
There ale lots of calculations before this part and they're are done very fast. While everything goes in 714 ms, without summing integers, it's just 337 ms.
Thanks in advance for any help.
Best regards,
Randolph
Faster? Most efficent? I am not sure, you should try it. But a simple way to convert
int[] Result = new int[] { 1753387599, 1353678530, 987001 };
var newstr = String.Join("|", Result.Reverse().Select(i => i % 1000000000));
I would suggest L.B's answer for most cases. But if you're running for the top efficiency, here are my suggestions:
You can iterate the array from the end, so there's no need to call Reverse of any kind
IntBase[tempint % 1000000 / 1000] is the same as IntBase[tempint % 1000] because division has higher priority than modulus
I bet the whole IntBase intermediate step is slowing you down tremendously
My suggestion would be something like this - much like L.B's code, but imperative and slightly optimized.
var sb = new StringBuilder();
var ints; // Your int[]
// Initial step because of the delimiters.
sb.Append((ints[ints.Length - 1] % 1000000000).ToString());
// Starting with 2nd last element all the way to the first one.
for(var i = ints.Length - 2; i >= 0; i--)
{
sb.Append("|");
sb.Append((ints[i] % 1000000000).ToString());
}
var result = sb.ToString();

Algorithm - java, c# or delphi - search a number in array which exists more than arraySize / 2. In one pass without additional memory

I need to do an algorithm that search a specific int in array of int.
That number must appear >= than arraySize/2 times.
example: [] = 4 4 3 5 5 5 5 5 5 6
arraysize: 10
number 5 exists 6x -> so this is the result of algorithm
but I need to do this without additionam memory, and in time O(n) -> in one pass.
Is this even possible? Any suggestions how to start it?
It is indeed possible; the task is known as "Dominant Element," and used for interviews and as a homework. Read the article below for a proper analysis; the solution itself is simple but not easy: proving that it indeed does what it promises is not quite trivial (unless of course you know the answer).
http://www.cse.iitk.ac.in/users/sbaswana/Courses/ESO211/problem.pdf
element x;
int count ← 0;
For(i = 0 to n − 1)
{
if(count == 0) { x ← A[i]; count ++; }
else if (A[i] == x) count ++;
else count −−
}
Check if x is dominant element by scanning array A.
Note though that the time is O(n), but as far as I'm aware, it is not possible to do it in one pass unless you know for sure there is a dominant element.
As of additional memory, you will need memory for i, the counter; x, the element to check and return; and count, the size of the imaginary working set. That's O(1) and is usually considered OK for such problems.
Moore describes the solution to this problem on his web site (with an example here).
Edit: Here is some Java code demonstrating the algorithm as described:
public class Majority
{
public static void main(String[] args)
{
int[]a = new int[]{4, 4, 3, 5, 5, 5, 5, 5, 5, 6};
int count = 0;
int candidateIndex = 0;
for (int i = 0; i < a.length; i++)
{
if (count == 0)
{
candidateIndex = i;
count++;
}
else
{
if (a[i] == a[candidateIndex])
count++;
else
count--;
}
}
System.out.println("Majority element: " + a[candidateIndex]);
}
}
After you get your candidateIndex, you can iterate though the array again to verify that it indeed occurs more than N / 2 times.

Categories

Resources