Factorial using Task - c#

I am looking for a way to use task to compute factorial of a number. My purpose is to compare the result with factorial using a sequential loop. For example
16! task1 = 16*15*14*13*12*11 and task2 = 10*9*8*7*6 and task3 = 5*4*3*2*1
I have searched online but I cannot find a solution that matched my need. Thanks in anticipation.
static long factorialmethod(int number)
{
long factorial;
factorial = number;
if (number <= 1) { return 1; }
else
for (int i = number-1; i >= number; i--)
{
factorial *= i;
}
return factorial;
}
static void Main(string[] args)
{
int number;
Console.WriteLine("Please input your whole number");
number = int.Parse(Console.ReadLine());
Console.WriteLine("\nFactorial of the number is {0}",factorialmethod(number));
Console.ReadKey()
}

An easiest way to try parallel when computing factorial is PLinq (Parallel Linq):
using System.Linq;
...
static long factorialmethod(int number) {
if (number <= 1)
return 1; // strictly speaking, factorial on negative (-N)! = infinity
return Enumerable
.Range(1, number)
.AsParallel() // comment it out if you want sequential version
.Aggregate(1L, (s, a) => s * a);
}
Use Stopwatch to benchmark; comment out .AsParallel(): do you really want parallel implementation (let Task alone)?

You can use #DmitryBychenko answer if you want to go PLINQ way. But as an alternative, you can directly use the Parallel library too. If you are literally trying to solve your stated problem using Task library, I think PLINQ is a cleaner solution, but if you are using the posted question as a reduced version of some similar problem, where you need more control, then the below solution might help
static long Factorial(int number) {
if (number < 1)
return 1;
var results = new ConcurrentBag<long>();
Parallel.ForEach(Partitioner.Create(1, number + 1, 5 /*You can select your range size here. You can also derive it based on Environment.ProcessorCount, if you so wish */),
(range, loopState) => {
long product = 1;
for (int i = range.Item1; i < range.Item2; i++) {
product *= i;
}
results.Add(product);
});
long factorial = 1;
foreach (var item in results)
factorial *= item;
return factorial;
}

Related

C# Find every number divisible by 3, in a string of numbers

this is my first post here, I'm new to C# and I have some problems with my code.
class Program
{
static void Main(string[] args)
{
#region FindAllNumbersDivisibleBy3
Console.Write("Enter a string of numbers: ");
string Nums = Console.ReadLine();
List<long> arr = new List<long>();
for (int i = 0; i < Nums.Length; i++)
{
for(int j = Nums.Length - 1; j >= i; j--)
{
try
{
string substring = Nums.Substring(i, j);
if (Convert.ToInt64(substring) % 3 == 0)
{
arr.Add(Convert.ToInt64(substring));
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
Console.WriteLine("The following numbers are divisble by 3: ");
for (int i = 0; i < arr.Count; i++)
{
Console.WriteLine(arr[i]);
}
Console.ReadLine();
#endregion
}
}
The problem is the following: I'm given a series of numbers, probably too big and inefficient to be stored as an integer, so it's recommended to use a string, and you have to find every single number divisible by three. That could be the entire string, or some sub-strings, or just single digit numbers, etc. I get some conversion errors from the catch exception, as well as something else regarding some length parameter and I don't really understand what's the problem. It's also possible that the for loops' arguments have some errors too, but as far as I'm concerned the problems start in the try block.
Sorry if this is a very dumb question, I'm still in high school so I'm not very good at programming yet. Thank you for your help in advance.
This is still vulnerable to overflows, but it would take a very long string indeed to reach that point:
class Program
{
static void Main(string[] args)
{
Console.Write("Enter a string of numbers: ");
string Nums = Console.ReadLine();
Console.WriteLine("The following numbers are divisble by 3: ");
foreach(var result in DivisibleByThree(Nums))
{
Console.WriteLine(result);
}
Console.ReadKey(true);
}
public static IEnumerable<string> DivisibleByThree(string input)
{
for (int i = 0; i < input.Length; i++)
{
for(int j = input.Length; j > i; j--)
{
string segment = input.Substring(i, j-i);
if (SumOfDigits(segment) % 3 == 0)
{
yield return segment;
}
}
}
}
public static int SumOfDigits(string digits)
{
return digits.Where(c => char.IsDigit(c)).Select(c => c-'0').Sum();
}
}
See it work here:
https://dotnetfiddle.net/KacyAD
And since someone suggested recursion, I thought that'd be fun to try. I didn't quite get as far as I wanted (removing both loops and using recursion as the only repetition mechanism), but this does work:
public static IEnumerable<string> DivisibleByThree(string input)
{
if (input.Length > 1)
{
foreach(var item in DivisibleByThree(input.Substring(0, input.Length-1)))
{
yield return item;
}
}
while(input.Length > 0)
{
if ( SumOfDigits(input) % 3 == 0) yield return input;
input = input.Substring(1);
}
}
But that's the boring recursion. From a pure performance standpoint, it still spends a lot of time summing the same sequences of digits. There's a probably a way to use recursion to preserve prior work on each recursive call, and in that way make this run significantly faster.
That is, rather than start with a big string and check progressively smaller segments, start with the small string and with each check add the sum for the just the additional digit:
public static IEnumerable<string> DivisibleByThree(string input)
{
for(int i = input.Length - 1; i>=0; i--)
{
foreach(var item in DivisibleByThreeR(input.Substring(i, input.Length - i), 0, 0, 0)) yield return item;
}
}
public static IEnumerable<string> DivisibleByThreeR(string input, int startPos, int nextPos, int sum)
{
sum += input[nextPos] - '0';
if (sum % 3 == 0) yield return input.Substring(startPos, nextPos - startPos + 1);
if (++nextPos < input.Length)
{
foreach (var item in DivisibleByThreeR(input, startPos, nextPos, sum)) yield return item;
}
}
I'm not sure this is really any faster. I didn't benchmark or test at all beyond getting the right result. In fact, I suspect the iterators will eat up any improvements over the pure-loop version.
There's also probably a way to move the loop in the outer method also into the recursive function thereby optimize even further. But it was a nice exercise.
Here's my final fiddle if anyone else wants to play:
https://dotnetfiddle.net/dGFWNx
Here's a solution close to your code that uses BigInteger (you need .NET5+). This shall eliminate the risk of running into OverflowException. Please note that there can be duplicates in the output (you didn't say if you want to see them).
using System.Numerics;
class Program
{
static void Main(string[] args)
{
#region FindAllNumbersDivisibleBy3
Console.Write("Enter a string of numbers: ");
string Nums = Console.ReadLine();
List<BigInteger> results = new();
for (int i = 0; i < Nums.Length; i++)
{
for (int j = Nums.Length; j >= i; j--)
{
try
{
string substring = Nums.Substring(i, j - i);
if (BigInteger.TryParse(substring, out var bi) && BigInteger.ModPow(bi, 1, 3).IsZero)
{
results.Add(bi);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
Console.WriteLine("The following numbers are divisible by 3:");
for (int i = 0; i < results.Count; i++)
{
Console.WriteLine(results[i]);
}
Console.ReadLine();
#endregion
}
}
Something that will work even with numbers other than 3 and 9 would be to implement long division and only keep track of the carry remainder (added a Linq version since it seemed like an appropriate problem for it):
static bool IsDivisibleBy(string input, long divBy = 3)
{
long remainder = 0;
foreach (char c in input)
{
var num = Convert.ToInt64(c);
remainder = ((remainder * 10) + num) % divBy;
}
return remainder == 0;
}
static bool IsDivisibleByLinq(string input, long divBy = 3)
{
return input.Select(c => Convert.ToInt64(c))
.Aggregate(0L, (remainder, num) =>
((remainder * 10) + num) % divBy) == 0;
}

Display of digits from 1 to 100 in c# such that each line ends with a modulus of 10

I am a beginner learning c#, I have this code
static void Main(string[] args)
{
int a = 0;
while (a < 100)
{
a = a + 1;
if ((a % 10) == 0)
{
Console.WriteLine(a);
}
else
{
Console.Write(a);
Console.Write(",");
}
}
}
Is there a more efficient way of writing this code? I feel there might be a better way of doing this in c#. This is my very first code. I will appreciate a response. Thanks
the short version would look like this:
int stepSize = 10;
for (int i = 1; i < 100; i+=stepSize )
{
Console.WriteLine(String.Join(",", Enumerable.Range(i, stepSize)));
}
Explanation:
You walk in steps of 10 through your for-loop. at each step the
Enumerable.Range method creates an array which holds numbers enumerated from a start value (i) until the count value (10).
The String.Join method takes each element of this array and combines them into a string separated by a ,
Since it looks like homework:
You should research how to useString.Format. This way you could arrange elements in one line at certain positions.
For iterations with a counter variable a for-loop is preferable, because it is exactly made for it with a clearly readable head signature.
You actually wrote a very readable code, which in my opinion is efficient. A shortening of codelines does not make it necessarily more efficient or faster or more readable. Sometimes the only advantage is that it looks a little more elegant ;) that's all
EDIT:
You can even get it down to one line:
Console.WriteLine(Enumerable.Range(0, 10).Select(x => String.Join(",", Enumerable.Range(x * 10 + 1, 10))));
it is short, but it is horrible to read and understand :)
First step would be using a foor loop instead.
for(int i = 0; i <= 100; i++)
{
if ((i % 10) == 0)
{
Console.WriteLine(i);
}
else
{
Console.Write(i);
Console.Write(",");
}
}
You could replace
Console.Write(i);
Console.Write(",");
with
Console.Write(string.Format("{0},", i));
or even better with
Console.Write($"{i},");
Just yet another approach
for (var i = 1; i <= 100; i++)
{
Console.Write(i);
Console.Write(i % 10 == 0 ? Environment.NewLine : ",");
}

Weird behavior of multithread random numbers generator

Please check below code, this code try to compute birthday conflict possibility. To my surprise, if i execute those code with sequence, the result is expected around 0.44; but if try on PLinq, the result is 0.99.
Anyone can explain the result?
public static void BirthdayConflict(int num = 5, int people = 300) {
int N = 100000;
int act = 0;
Random r = new Random();
Action<int> action = (a) => {
List<int> p = new List<int>();
for (int i = 0; i < people; i++)
{
p.Add(r.Next(364) + 1);
}
p.Sort();
bool b = false;
for (int i = 0; i < 300; i++)
{
if (i + num -1 >= people) break;
if (p[i] == p[i + num -1])
b = true;
}
if (b)
Interlocked.Increment(ref act);
// act++;
};
// Result is around 0.99 - which is not OK
// Parallel.For( 0, N, action);
//Result is around 0.44 - which is OK
for (int i = 0; i < N; i++)
{
action(0);
}
Console.WriteLine(act / 100000.0);
Console.ReadLine();
}
You're using a shared (between threads) instance System.Random. It's not thread-safe then you're getting wrong results (well actually it just doesn't work and it'll return 0). From MSDN:
If your app calls Random methods from multiple threads, you must use a synchronization object to ensure that only one thread can access the random number generator at a time. If you don't ensure that the Random object is accessed in a thread-safe way, calls to methods that return random numbers return 0.
Simple (but not so efficient for parallel execution) solution is to use a lock:
lock (r)
{
for (int i = 0; i < people; i++)
{
p.Add(r.Next(364) + 1);
}
}
To improve performance (but you should measure) you may use multiple instances of System.Random, be careful to initialize each one with a different seed.
I find a useful explanation why random does not work under multi-thread, although it was original for Java, still can be benefitical.

C#, finding the largest prime factor of a number

I am new at programming and I am practicing my C# programming skills. My application is meant to find the largest prime factor of a number entered by the user. But my application is not returning the right answer and I dont really know where the problem is. Can you please help me?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Calcular máximo factor primo de n. De 60 es 5.");
Console.Write("Escriba un numero: ");
long num = Convert.ToInt64(Console.ReadLine());
long mfp = maxfactor(num);
Console.WriteLine("El maximo factor primo es: " + num);
Console.Read();
}
static private long maxfactor (long n)
{
long m=1 ;
bool en= false;
for (long k = n / 2; !en && k > 1; k--)
{
if (n % k == 0 && primo(k))
{
m = k;
en = true;
}
}
return m;
}
static private bool primo(long x)
{
bool sp = true;
for (long i = 2; i <= x / 2; i++)
{
if (x % i == 0)
sp = false;
}
return sp;
}
}
}
It will be much faster to remove the small factors until the residue is prime.
static private long maxfactor (long n)
{
long k = 2;
while (k * k <= n)
{
if (n % k == 0)
{
n /= k;
}
else
{
++k;
}
}
return n;
}
For example, if n = 784, this does 9 modulo operations instead of several hundred. Counting down even with the sqrt limit still would do 21 modulo ops just in maxfactor, and another dozen in primo.
New more optimized version here
Console.WriteLine("El maximo factor primo es: " + mfp);
instead of
Console.WriteLine("El maximo factor primo es: " + num);
you have condition (!en) that makes it iterate only until first prime factor. Also you can reduce bounds from n/2 to sqrt(n)+1
Catalin DICU already answered your question, but you've got some non-idiomatic constructs in your code that you should probably look at refactoring. For example, in your maxfactor method, you don't need the "en" condition, just return the value as soon as you've found it:
static private long maxfactor (long n)
{
for (long k = n / 2; k > 1; k--)
{
if (n % k == 0 && primo(k))
{
return k;
}
}
// no factors found
return 1;
}
Similarly for your primo method, you can just return false as soon as you find a factor.
here's a f# version for this:
let lpf n =
let rec loop n = function
|k when k*k >= n -> n
|k when n % k = 0I -> loop (n/k) k
|k -> loop n (k+1I)
loop n 2I
This runs for less than three seconds.
public static void Main()
{
int prime=1;
long n=600851475143;
for (long i=2;i<=n;i++)
{
while (n%i==0)
n=n/i;
prime++;
}
Console.WriteLine(prime);
Console.WriteLine("Hello World!");
Console.ReadKey();
}

Finding Fibonacci sequence in C#. [Project Euler Exercise]

I'm having some trouble with this problem in Project Euler.
Here's what the question asks:
Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
Find the sum of all the even-valued terms in the sequence which do not exceed four million.
My code so far: EDITED WITH NEW CODE THAT STILL DOESN'T WORK.
static void Main(string[] args)
{
int a = 1;
int b = 2;
int Container = 0;
int Sum = 0;
while (b < 4000000)
{
if (a % 2 == 0)
{
Container += a;
}
Sum = a + b;
a = b;
b = Sum;
}
Container += b;
Console.WriteLine(Container.ToString());
Console.ReadLine();
}
One of the fun feature in C# is the "yield" keyword, which is very useful for this kind of thing:
IEnumerable<int> Fibonacci()
{
int n1 = 0;
int n2 = 1;
yield return 1;
while (true)
{
int n = n1 + n2;
n1 = n2;
n2 = n;
yield return n;
}
}
long result=0;
foreach (int i in Fibonacci().TakeWhile(i => i<4000000).Where(i => i % 2 == 0))
{
result+=i;
}
Console.WriteLine(result);
The "traditional" recursive Fibonacci implementation is problematic here because it throws away all the work done along the way to the last requested term. You would have to call such a function over and over in a loop, which would duplicate a lot of work, or you could start with that implementation and add an argument to the recursive function to build up the desired sum result as the final fibonacci term is calculated. I like this much better, because it's still a general purpose fibonacci sequence at the core, rather than one you had to re-write or specialize.
Another approach is to use events (delegates) in a traditional implementation to call a separate method as each term is completed, but as I still like the iterator method better I'll leave the delegate option as an exercise for the reader.
Your problem is not that your code contains a bug; your problem is that your code contains a bug and you don't know how to find it. Solve the second problem first, and then you won't need to ask us when you have a bug, you'll be able to find it yourself.
Learning how to find bugs is hard and takes a lot of practice. Here's how I would approach this problem.
I'd start by simplifying the problem down to something I could do myself. Instead of "what's the sum of the even fib numbers that do not exceed four million?" I'd ask "what's the sum of the even fib numbers that do not exceed 40?" That's easy to work out by hand -- 2 + 8 + 34 = 44.
Now run your program in a debugger, stepping through each line, and see where things go wrong. Does your program actually add up 2, 8 and 34? And if so, does it get the correct result?
int sum = 2;
for(int f1 = 1, f2 = 2, f3 = 0; !((f3 = (f1 + f2)) > 4000000); f1 = f2, f2 = f3)
sum += f3 * (~f3 & 1);
I think the question is written to say that you would add all the even numbers together while the numbers in the sequence don't exceed four million, meaning you would add 3,999,992.
You're checking both a and b on every iteration. So that means you're double counting almost everything.
Edit:
Ok, I see your update. This is pretty basic debugging, and you should really learn to try it yourself. Think about what the values of a and b are when your loop condition stops being true.
Joel, I wrote a very some similiar code; I'm posting it anyways:
static IEnumerable<int> Fibonacci(int maximum)
{
int auxiliar = 0;
int previous = 0;
int current = 1;
while (current < maximum)
{
auxiliar = previous;
previous = current;
current = auxiliar + current;
yield return current;
}
}
Console.WriteLine(Fibonacci(4000000).Where(number => number % 2 == 0).Sum());
The trickier way:
//1: Allow declaring of recursive functions
private delegate Func<T, R> FuncRec<T, R>(FuncRec<T, R> f);
static Func<T, R> RecFunction<T, R>(Func<Func<T, R>, Func<T, R>> f)
{
FuncRec<T, R> funcRec = r => t => f(r(r))(t);
return funcRec(funcRec);
}
//Define the factorial function
public static readonly Func<ulong, ulong> Fibonacci
= RecFunction<UInt64, UInt64>(fib => n =>
(n == 1 || n == 0)
? n
: fib(n - 1) + fib(n - 2));
//Make a "continous" version
static IEnumerable<ulong> ContinousFibonacci()
{
ulong count = 0;
while(true)
{
ulong n = Fibonacci(count);
count++;
yield return n;
}
}
//Linq result
static void Main(string[] args)
{
ulong result = ContinousFibonacci()
.TakeWhile(r => r < 4000000)
.Where(IsEven)
.Aggregate<ulong, ulong>(0,(current, s) => (s + current));
Console.WriteLine(result);
Console.ReadLine();
}
///The Functional-Style method of allowing one to create recursive functions such as above was made by Bart De Smet. See http://bartdesmet.net/blogs/bart/archive/2009/11/08/jumping-the-trampoline-in-c-stack-friendly-recursion.aspx
Here's a nice way to find Fibonnaci numbers.
IEnumerable<BigInteger> Fibs()
{
for(BigInteger a = 0,b = 1;;b = a + (a = b))
yield return b;
}
// count(user input) of Fibonacci numbers
int[] array = new int[20];
array[0] = 0;
array[1] = 1;
Console.WriteLine(array[0] + "\n" + array[1]);
for (int i = 2; i < 20; i++)
{
array[i] = array[i - 1] + array[i - 2];
Console.WriteLine(array[i]);
}

Categories

Resources