Find all possible multiplications numbers to a specified sum. C# - c#

I need help with finding all possible unordered representations for a given natural number n(breakdowns) of n as a product of natural numbers (not necessarily different).
An integer n is entered from the keyboard.
Example: input: 50 output: 25 * 2 , 10 * 5 , 5 * 5 * 2
Hint: The algorithm by which you can perform the decomposition is analogous to the one that is
described in problem 3. Instead of devNum (n-k, cnt + 1) we will recursively call devNum (n / k, cnt + 1), when
this is not for every k, but only for those for which n% k == 0. The condition for continuing
the break (loop for) will be k & gt; 1, not k ≥ 1, i.e. the bottom of the recursion will be k == 1, not
k == 0 (the latter is easily explained: 0 and 1 are precisely the identities of the operations of addition and
multiplication).

This program I wrote may be close to what you're looking for. It would be helpful if you provided more information to the problem and any answers to prior questions (like question #3) and/or examples or clues provided by the homework on how the program is modeled. I can see there are strict constraints on how to write it, and not all of those exact boundaries are followed here. However, recursion is used on the same function with the same parameters, with similar arguments passed under certain conditionals. A list of lists is used to store the different sets of factors/divisors.
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
Console.WriteLine("Enter a positive integer: ");
int n;
while (!int.TryParse(Console.ReadLine(), out n))
{
Console.WriteLine("Please enter a whole number.");
}
List<List<int>> factors = FindFactors(n);
PrintFactors(factors);
}
public static List<List<int>> FindFactors(int n)
{
var res = new List<List<int>>();
if (n > 0) {
for (var i = n - 1; i >= 1; i--)
{
var temp = devNum(n, i);
foreach (var list in temp)
{
list.Reverse();
if (list.Count > 2 && list[list.Count - 1] == 1)
{
list.RemoveAt(list.Count - 1);
}
res.Add(list);
}
}
}
return res;
}
private static List<List<int>> devNum(int n, int k)
{
var beginWithFirst = new List<List<int>>();
if (n % k != 0 || (n > 1 && k == 1))
{
return beginWithFirst;
}
if (k == 1)
{
var end = new List<int>();
end.Add(k);
beginWithFirst.Add(end);
return beginWithFirst;
}
for (var i = n / k; i >= 1; i--)
{
var temp = devNum(n / k, i);
foreach (var list in temp.Where(list => list.Count > 0 && list[list.Count - 1] <= k))
{
list.Add(k);
beginWithFirst.Add(list);
}
}
return beginWithFirst;
}
public static void PrintFactors(List<List<int>> factors) {
int counter = 0;
foreach (List<int> lst in factors) {
counter++;
int[] arr = lst.ToArray();
if (counter != factors.Count) {
Console.Write("{0}", string.Join(" * ", arr) + ", ");
}
else {
Console.Write("{0}", string.Join(" * ", arr));
}
}
}
}
DotNet Fiddle

Related

Print out the successful development of prime numbers from small to large

Given any natural number N> 1 (previously assigned). Print out the successful development of prime numbers from small to large.
Example:
9 --> 3 * 3
12 --> 2 * 2 * 3
My idea is find all GCD and add to list int, and write a function isPrimeNumber(int n), browse List< int > and check if isPrimeNumber().
But I can't solve problem print out the successful development of prime numbers from small to large
Here is what I tried
static void Main(string[] args)
{
Console.WriteLine("Enter n: ");
int n = Convert.ToInt32(Console.ReadLine());
List<int> arr = new List<int>();
for (int i = 1; i <= n; i++)
{
if (n % i == 0)
{
arr.Add(i);
}
}
/* I need Print out the successful development of prime numbers from small to large here */
}
static bool isPrimeNumber(int n)
{
if (n < 2)
{
return false;
}
for (int i = 2; i <= Math.Sqrt(n); i++)
{
if (n % i == 0)
{
return false;
}
}
return true;
}
As you posted your working solution for that, let me share a different implementation for that that is still simple to understand, but more efficient, because it only tests primes until it reaches the square root of n. After that, there will not be any other divisor, except the number n itself, if n is prime.
static IList<int> Factors(int num) {
var result = new List<int>();
// avoid scenarios like num=0, that would cause infinite loop
if (num <= 1) {
return result;
}
// testing with 2 outside the main loop, otherwise we would skip factor 3
// (2 * 2 > 3)
while (num % 2 == 0) {
result.Add(2);
num /= 2;
}
// only test primes until sqrt(num)
int i = 3;
while (i * i <= num) {
if (num % i == 0) {
result.Add(i);
num /= i;
} else {
i++;
}
}
// if not 1 here, num is prime
if (num > 1) {
result.Add(num);
}
return result;
}
I solved it
Here is code
static void lesson6()
{
Console.WriteLine("Enter n: ");
int n = Convert.ToInt32(Console.ReadLine());
int a = n;
List<int> arr = new List<int>();
for (int i = 2; i <= n; i++)
{
while (n % i == 0)
{
arr.Add(i);
n /= i;
}
}
Console.Write($"{a} = ");
int lastIndex = arr.Count - 1;
for (int i = 0; i < arr.Count; i++)
{
if (i == lastIndex)
{
Console.Write(arr[i]);
}
else
{
Console.Write(arr[i] + "*");
}
}
}
As pointed by derpirscher in the comment, there are several sources online with different approaches for integer factorization.
I recommend you to look for Trial Division algorithm, as it is the easier to understand, and is similar to your approach.
Based on the code you shared, there are some thing you should consider:
for (int i = 1; i <= n; i++)
{
if (n % i == 0)
{
arr.Add(i);
}
}
After finding that a prime is a divisor and appending to the list, you are going to the next number. However, a prime can figure many times in the factorization of a number. E.g: 12 -> { 2, 2, 3 }.
You need divide n by the prime and continue testing the until it is not a divisor anymore, then you can go test the next prime.
This way, your n is shrinking down each time you find a prime divisor, until it eventually become 1. Then you know you found all prime divisors.

Why is the while condition neglected to n-1 value in this loop?

I have written a simple loop to get a factorial.However, the code seem to be neglecting the condition(n>=1) and i end u with zero as the n!.
The code works when i use (n >= 2) as opposed to (n >= 1).
class Program
{
static void Main(string[] args)
{
int n;
n = int.Parse(Console.ReadLine());
decimal factorial = 1;
Console.Write(" {0} * ", n);
do
{
n--;
factorial *= n;
Console.Write(" * " + n);
} while (n != 1);
Console.WriteLine("=" + factorial);
}
}
If i put n = 10, i expect to get 10*9*8*7*6*5*4*3*2*1 = 3628800
instead, i get, 10*9*8*7*6*5*4*3*2*1*0 = 0
Your looping logic was a little off, so I fixed it for you:
int n = int.Parse(Console.ReadLine()); // Maybe use int.TryParse here
decimal factorial = n;
Console.Write(n);
while (n > 1)
{
n--;
factorial *= n;
Console.Write($" * {n}");
}
Console.WriteLine($" = {factorial}");
I'm also going to leave my preferred way of calculating Factorials (using Recursion) here:
public decimal CalculateFactorial(int number)
{
if (number == 1)
return 1;
else
return number * CalculateFactorial(number - 1);
}

Sum of Numbers as Distinct Primes

//List Style
using System;
using System.Collections.Generic;
using System.Linq;
public class pr{
static public void Main (){
int n, i, j, k, l, sum,flag = 0;
//int sum = i+j;
//int k = (n-i);
//int l = (n-j);
//System.Console.WriteLine ("Enter a number");
//n = Convert.ToInt32 (Console.ReadLine());
//List <int> primes = new List <int>(); //list to handle the numbers
//HashSet <int> myPrimes = new HashSet <int> (primes);
System.Console.WriteLine ("Enter a number");
n = Convert.ToInt32 (Console.ReadLine());
//myPrimes.Add(n);
//myPrimes.Add(i);
//myPrimes.Add(j);
// var count = string.Join(", ", primes);
//System.Console.WriteLine("The value of n is {0}",myPrimes);
for(i=3; i<n/2; i++){
for(j=3; j<n/2; j++){
if(checkPrime(i) == 1){
if(checkPrime(j) == 1){
if (checkPrime(n-i) == 1){
if (checkPrime(n-j) == 1){
//if(i == j){
//sum = i+j;
System.Console.WriteLine("{0}={1}+{2}\n",n,i,n-i);
//}
}
}
}
}
if (flag == 0 && (n-i) <= 0 && (n-j) <= 0){ //check to avoid dupes
if (n <= 0 && i <= 0 && j <= 0){
Console.Write("{0}\n",n);
}
}
}
}
}
public static int checkPrime(int n){
int i, j, flag = 1;
for (i = 2; i<=(Math.Sqrt(n)); i++){
for (j = 2; j<=(Math.Sqrt(n)); j++){
if (n%i == 0 && n%j == 0 ){ //even number check
i++;
j++;
flag = 0;
}
}
}
return flag;
}
}
So I have been experimenting with this for a while now. I cant seem to print all possible solutions. For example for 24 I am able to print 7+17 but not 2+5+17. There are also some answers being repeated and this might have to do with the fact that I dont have duplicate checks. I tried to push the integers in a list and then use a hashset to only have distinct integers but I got stuck and tried to brute force it. All the numbers to be printed are supposed to be distinct prime integers. I dont understand how to print all distinct numbers and is there an elegant way to print out all the possible.
Thanks for the help!
Don't know if it's elegant enough for you, but I've just mashed a dirty way to make it work:
static void Main()
{
Console.WriteLine("Enter a number");
var numberToSum = Convert.ToInt32(Console.ReadLine());
var primesInRange = GetPrimesUpTo(numberToSum);
var foundSolutions = primesInRange.SubSetsOf().Where(prime => prime.Sum() == numberToSum);
foreach (var solution in foundSolutions.ToList())
{
var formatOperation = solution
.Select(x => x.ToString())
.Aggregate((a, n) => a + " + " + n) + " = " + numberToSum;
Console.WriteLine(formatOperation);
}
Console.ReadLine();
}
public static IEnumerable<int> GetPrimesUpTo(int end)
{
var primes = new HashSet<int>();
for (var i = 2; i <= end; i++)
{
var ok = true;
foreach (var prime in primes)
{
if (prime * prime > i)
break;
if (i % prime == 0)
{
ok = false;
break;
}
}
if (ok)
primes.Add(i);
}
return primes;
}
public static IEnumerable<IEnumerable<T>> SubSetsOf<T>(this IEnumerable<T> source)
{
if (!source.Any())
return Enumerable.Repeat(Enumerable.Empty<T>(), 1);
var element = source.Take(1);
var haveNots = SubSetsOf(source.Skip(1));
var haves = haveNots.Select(set => element.Concat(set));
return haves.Concat(haveNots);
}
I've found your solution quite dirty so I divided the problem to be more understandable. GetPrimesUpTo returns all prime number from 2 to the number you've provided in the input, SubSetsOf returns combination of numbers that summed up equals the input number you've provided and finally the foreach in Main produces formatted output that is easy on the eye. Hope it helps!
Providing that you have collection of primes and IsPrime method
private static int[] primes = new[] {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 };
private static bool IsPrime(int value) {
return primes.Contains(value);
}
You can implement recoursive solution
private List<List<int>> ToListOfPrimes(int value, List<int> parts = null) {
if (null == parts)
parts = new List<int>();
List<List<int>> result = new List<List<int>>();
if (value == 0) {
result.Add(parts.ToList());
return result;
}
int minPrime = parts.Count <= 0 ? 0 : parts[parts.Count - 1];
if (value <= minPrime)
return result;
// not that efficient: binary search will be a better choice here
for (int i = 0; i < primes.Length; ++i) {
int p = primes[i];
if (p <= minPrime)
continue;
else if (p > value)
break;
var list = parts.ToList();
list.Add(p);
var outcome = ToListOfPrimes(value - p, list);
foreach (var solution in outcome)
result.Add(solution);
}
return result;
}
Test
var result = ToListOfPrimes(28);
string report = String.Join(Environment.NewLine, result
.Select(line => String.Join(", ", line)));
Console.Write(report);
Outcome (28)
2, 3, 5, 7, 11
2, 3, 23
2, 7, 19
3, 5, 7, 13
5, 23
11, 17
For 24
2, 3, 19
2, 5, 17
5, 19
7, 17
11, 13
If you really want to implement it in other languages just throw your solution to rubbish bin. You should be more explicit about what is happening during execution. Nested for loops with multiple if statements are not explicit at all. What's even worse in the sample - you'll need to add new for loop every time you want more numbers in the sum. I do believe it's hard to understand it for a novice, but I find recursion the only way to go here.
See for yourself:
it's hard to say why output of your program is wrong, because of the logic
Variables should be named meaningfully so you know what they store instead of blind guessing.
Your checkPrime method returns int even though you return 0 or 1 so it should really return bool type
Use debugger and a piece of paper to understand how recursion works either in my previous answer or the one provided by Dmitry Bychenko

Finding an integer sum in an array of 1 000 000

Given a large list of integers (more than 1 000 000 values) find how many ways there are of selecting two of them that add up to 0.... Is the question
What I have done is create a positive random integer list:
Random pos = new Random();
int POSNO = pos.Next(1, 1000000);
lstPOS.Items.Add(POSNO);
lblPLus.Text = lstPOS.Items.Count.ToString();
POSCount++;
And created a negative list:
Random neg = new Random();
int NEGNO = neg.Next(100000, 1000000);
lstNEG.Items.Add("-" + NEGNO);
lblNegative.Text = lstNEG.Items.Count.ToString();
NegCount++;
To do the sum checking I am using:
foreach (var item in lstPOS.Items)
{
int POSItem = Convert.ToInt32(item.ToString());
foreach (var negItem in lstNEG.Items)
{
int NEGItem = Convert.ToInt32(negItem.ToString());
int Total = POSItem - NEGItem;
if (Total == 0)
{
lstADD.Items.Add(POSItem + "-" + NEGItem + "=" + Total);
lblAddition.Text = lstADD.Items.Count.ToString();
}
}
}
I know this is not the fastest route. I have considered using an array. Do you have any suggestions?
Let's see; your array is something like this:
int[] data = new int[] {
6, -2, 3, 2, 0, 0, 5, 7, 0, -2
};
you can add up to zero in two different ways:
a + (-a) // positive + negative
0 + 0 // any two zeros
in the sample above there're five pairs:
-2 + 2 (two pairs): [1] + [3] and [3] + [9]
0 + 0 (three pairs): [4] + [5], [4] + [8] and [5] + [8]
So you have to track positive/negative pairs and zeros. The implementation
Dictionary<int, int> positives = new Dictionary<int, int>();
Dictionary<int, int> negatives = new Dictionary<int, int>();
int zeros = 0;
foreach(var item in data) {
int v;
if (item < 0)
if (negatives.TryGetValue(item, out v))
negatives[item] = negatives[item] + 1;
else
negatives[item] = 1;
else if (item > 0)
if (positives.TryGetValue(item, out v))
positives[item] = positives[item] + 1;
else
positives[item] = 1;
else
zeros += 1;
}
// zeros: binomal coefficent: (2, zeros)
int result = zeros * (zeros - 1) / 2;
// positive/negative pairs
foreach (var p in positives) {
int n;
if (negatives.TryGetValue(-p.Key, out n))
result += n * p.Value;
}
// Test (5)
Console.Write(result);
Note, that there's no sorting, and dictionaries (i.e. hash tables) are used for positives and negatives so the execution time will be linear, O(n); the dark side of the implementation is that two additional structures (i.e. additional memory) required. In your case (millions integers only - Megabytes) you have that memory.
Edit: terser, but less readable Linq solution:
var dict = data
.GroupBy(item => item)
.ToDictionary(chunk => chunk.Key, chunk => chunk.Count());
int result = dict.ContainsKey(0) ? dict[0] * (dict[0] - 1) / 2 : 0;
result += dict
.Sum(pair => pair.Key > 0 && dict.ContainsKey(-pair.Key) ? pair.Value * dict[-pair.Key] : 0);
Fastest way without sorting!.
First of all you know that the sum of two integers are only 0 when they have equal absolute value but one is negative and the other is positive. So you dont need to sort. what you need is to Intersect positive list with negative list (by comparing absolute value). the result is numbers that ended up 0 sum.
Intersect has time complexity of O(n+m) where n is size of first list and m is size of second one.
private static void Main(string[] args)
{
Random random = new Random();
int[] positive = Enumerable.Range(0, 1000000).Select(n => random.Next(1, 1000000)).ToArray();
int[] negative = Enumerable.Range(0, 1000000).Select(n => random.Next(-1000000, -1)).ToArray();
var zeroSum = positive.Intersect(negative, new AbsoluteEqual());
foreach (var i in zeroSum)
{
Console.WriteLine("{0} - {1} = 0", i, i);
}
}
You also need to use this IEqualityComparer.
public class AbsoluteEqual : IEqualityComparer<int>
{
public bool Equals(int x, int y)
{
return (x < 0 ? -x : x) == (y < 0 ? -y : y);
}
public int GetHashCode(int obj)
{
return obj < 0 ? (-obj).GetHashCode() : obj.GetHashCode();
}
}
You tried to avoid check two numbers that are close (1, 2 are close, 3, 4 are close), but you didn't avoid check like (-100000, 1), (-1, 100000). Time complexity is O(n^2).
To avoid that you need to sort them first, then search from two direction.
var random = new Random();
var input = Enumerable.Range(1, 100).Select(_ => random.Next(200) - 100).ToArray();
Array.Sort(input); // This causes most computation. Time Complexity is O(n*log(n));
var expectedSum = 0;
var i = 0;
var j = input.Length - 1;
while (i < j) // This has liner time complexity O(n);
{
var result = input[i] + input[j];
if(expectedSum == result)
{
var anchori = i;
while (i < input.Length && input[i] == input[anchori] )
{
i++;
}
var anchorj = j;
while (j >= 0 && input[j] == input[anchorj])
{
j--;
}
// Exclude (self, self) combination
Func<int, int, int> combination = (n, k) =>
{
var mink = k * 2 < n ? k : n - k;
return mink == 0 ? 1
: Enumerable.Range(0, mink).Aggregate(1, (x, y) => x * (n - y))
/ Enumerable.Range(1, mink).Aggregate((x, y) => x * y);
};
var c = i < j ? (i - anchori) * (anchorj - j) : combination(i - anchori, 2);
for (int _ = 0; _ < c; _++)
{
// C# 6.0 String.Format
Console.WriteLine($"{input[anchori]}, {input[anchorj]}");
}
}
else if(result < expectedSum) {
i++;
}
else if(result > expectedSum) {
j--;
}
}
Here is another solution using (huh) LINQ. Hope the code is self explanatory
First some data
var random = new Random();
var data = new int[1000000];
for (int i = 0; i < data.Length; i++) data[i] = random.Next(-100000, 100000);
And now the solution
var result = data
.Where(value => value != int.MinValue)
.GroupBy(value => Math.Abs(value), (key, values) =>
{
if (key == 0)
{
var zeroCount = values.Count();
return zeroCount * (zeroCount - 1) / 2;
}
else
{
int positiveCount = 0, negativeCount = 0;
foreach (var value in values)
if (value > 0) positiveCount++; else negativeCount++;
return positiveCount * negativeCount;
}
})
.Sum();
Theoretically the above should have O(N) time and O(M) space complexity, where M is the count of the unique absolute values in the list.

Fast prime numbers between range

I am trying to develop one program for develop very fast prime numbers. Prime numbers are to be generated in range (Range <= 10000) and the result should be printed in under 6 seconds. This is the program i have made so far. It runs just fine on my machine 1.73 core 2 duo and produces result in under 3 seconds. But when i submit it to online program submission validator it gives time limit exceeded. I have even removed try catch block etc as i thought removing try catch may save few resources and buy me few milliseconds, but no matter whatever i do i always get time limit exceeded. This is my code :-
using System;
using System.Collections.Generic;
using System.Linq;
namespace PrimeNumberGenerator
{
class Program
{
static void Main(string[] args)
{
int T = Convert.ToInt32(Console.ReadLine());
List<string> listInput = new List<string>();
for (int i = 0; i < T; i++)
listInput.Add(Console.ReadLine());
for (int i = 0; i < T; i++)
{
string[] str = listInput[i].Split(' ');
int M = Convert.ToInt32(str[0]);
int N = Convert.ToInt32(str[1]);
if ((N - M) <= 100000 && M >= 1 && M <= 1000000000 && N >= 1 && N <= 1000000000)
{
int[] list = Enumerable.Range(M, (N - M + 1)).ToArray();
int k = 2;
while (true)
{
if ((k * k) > N)
break;
for(int j = 0 ; j < list.Count() ;j++)
{
if (list[j] != k && (list[j] % k) == 0 && list[j] != 1 && list[j] != -1)
list[j] = -1;
}
k++;
}
foreach (int item in list)
{
if (item != -1)
Console.WriteLine(item);
}
}
else
Console.WriteLine("Limit exceeded");
}
}
}
}
You have to give input like this :-
1
2 30
1 is no of test case and 2 and 30 mean that all primes between 2 and 30 should be produced.
You can give it 1 if you are only testing it once. I will be very grateful if you can optimise this program
Thanks in advance :)
EDIT :-
This is the original implmentation that i thought but obviously has overhead of list :-
using System;
using System.Collections.Generic;
using System.Linq;
namespace PrimeNumberGenerator
{
class Program
{
static void Main(string[] args)
{
try
{
int T = Convert.ToInt32(Console.ReadLine());
List<string> listInput = new List<string>();
for (int i = 0; i < T; i++)
listInput.Add(Console.ReadLine());
for (int i = 0; i < T; i++)
{
string[] str = listInput[i].Split(' ');
int M = Convert.ToInt32(str[0]);
int N = Convert.ToInt32(str[1]);
List<int> list = null;
if ((N - M) <= 100000 && M >= 1 && M <= 1000000000 && N >= 1 && N <= 1000000000)
{
list = Enumerable.Range(M, (N - M + 1)).ToList();
int k = 2;
while (true)
{
if ((k * k) > N)
break;
List<int> tempList = new List<int>();
foreach (int item in list)
if (item != k && (item % k) == 0 && item != 1)
tempList.Add(item);
list = list.Except(tempList).ToList();
k++;
}
//list.Remove(1);
foreach (int item in list)
Console.WriteLine(item);
Console.WriteLine();
}
else
Console.WriteLine("Limit exceeded");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadKey();
}
}
}
All I can say is that looks like a lot of loops within loops you've got going on. Probably the main issue is just your general algorithm.
To test if a number is prime, it's sufficient to check whether it's evenly divisible by any number between 2 and its sqrt (rounded down).
But if you're checking many primes, you ought to leverage the fact that as you check higher and higher numbers you can start with only primes (I would store these in a simple List<int>). For example, say you've reached the number 27. You only need to check whether it's divisible by 2, 3, or 5 (the prime numbers you've already found less than sqrt(25) which is 5), not 4 (since 4 is divisible by 2—if it's divisible by 4, then it's divisible by 2), and not anything above that (if it's evenly divisible by anything above 5, the quotient will be below 5, and you would have already checked it).
Those are some general concepts that ought to help you optimize what looks upon first glance like a pretty inefficient algorithm.
There are three solutions to performance problems: benchmarks, benchmarks, benchmarks.
Use a profiler to benchmark your code. For C# I personally prefer ANTS Performance Profiler but there are also other options available.
I suggest you to update (or post another) your question with specific bottlenecks.
Your program is expected to output the numbers in 6 seconds(time-critical), so you should make full use of the memory in the 6 seconds to save time. For example, you can use multi-threading or parallel programming to generate numbers faster(more CPU/memory usages). Currently you are working in a regular way, which can't show off C#'s advantages(your code can be converted directly into C/Java/others with few changes). You need to do it in the C# way, otherwise why do you choose C#? Here is an example(non-tested, but I think it should be correct) which is much more in C# way.
int min = 2;
int max = 10000;
Enumerable.Range(min, max - min + 1)
.AsParallel()
.ForAll(g =>
{
bool prime = true;
for (int i = 2; i <= Math.Sqrt(g); i++)
{
if (g % i == 0)
{
prime = false;
break;
}
}
if (prime) Console.WriteLine(g);
});
EDIT: I just tested the code, primes less than 10000 are printed out in 0 seconds, measured by StopWatch.

Categories

Resources