static void Main()
{
var array = new[] {1, 2, 3, 4, 5};
Array.Sort(array, (x, y) => x % 2 == y % 2 ? 0 : x % 2 == 1 ? -1 : 1);
array.ToList().ForEach(Console.WriteLine);
}
The output result is 3,5,1,2,4.
According to my understanding, in the sort delegate: Odd numbers equal odd numbers; Even number equal even numbers; Odd numbers are before even numbers. Why the output is not 1,3,5,2,4? Thanks.
From MSDN:
Array.Sort uses the QuickSort algorithm. This implementation performs an unstable sort; that is, if two elements are equal, their order might not be preserved. In contrast, a stable sort preserves the order of elements that are equal.
You are just comparing even and odd in your comparer function. Like the others said, quicksort is non-stable. Why not add an additional check for value in addition to even/odd when the values are both either even or odd.
// if x odd and y even return -1
// else if x even and y odd return 1
// else return x.CompareTo(y)
Array.Sort(array, (x, y) => x % 2 == y % 2 ? x.CompareTo(y) : x % 2 > y % 2 ? -1 : 1);
Related
i've write this piece of code to check if a number is prime or not, but it doesen't work, I mean that the output is:
1 isn't a prime number
2 is a prime number
3 isn't a prime number
4 is a prime number etc.
please can you tell me what are my mistakes,
thanks
p.s. i've writenumber =1 because i can't divide a number for 0.
for( int number =1;number <101 && number >0;number++)
{
int reimander = (number / 1) & (number / number);
Console.WriteLine(number +(reimander == 0 ? " is a prime number" : " isn't a prime number"));
}
As mentioned Daisy Shipton, your checkings are not sufficient to determine if your number is prime.
In order for a number to be prime, it has to be only divisible by one or itself.
That mean you should check the division by every single numbers between 3 and the number which you are checking the fact of behing prime.
In reality, you don't need to check every numbers between 3 and your number but only the ones between 3 and the square of your number.
In fact, if a whole number k is composite (non prime), it can be written as the product of two whole numbers p and q : k = p*q
Howevern those two numbers p and q can't be simultaneously greater than the square (s) of k, because in this case, their product whould be greater than k.
if p > s and q > s, then p x q > s x s, that to say p x q > k.
The code should looks like something like that (not tested) :
public static bool IsPrime(int number)
{
/****** easy check before going to long calculations *******/
if (number < 2) return false; // A prime number is always greater than 1
if (number == 2) return true; // 2 is prime
if (number % 2 == 0) return false; // Even numbers except 2 are not prime
/****** if your number is Odd and not equals to 2,
you have to check every numbers between 3
and the square of your number *******/
var boundary = (int)Math.Floor(Math.Sqrt(number)); // square of your number
// increment i by 2 because you already checked that your number is Odd
// and therefore not divisible by an Even number
for (int i = 3; i <= boundary; i += 2)
{
if (number % i == 0) return false; // the number can be devided by an other => COMPOSITE number
}
return true; // number at least equals to 3, divisible only by one or itself => PRIME number
}
Now you could do a basic loop for each numbers you want to test and call this function of them. Their is a lot of methods to calculate a series of prime numbers but their are also much more complicated to understand.
for (int number = 1; number < 101 && number > 0; number++)
{
Console.WriteLine(number + " is " + (IsPrime(number) ? "prime" : "not prime"));
}
There are two sorts of problem here: the is-prime algorithm and the C# syntax.
To understand the algorithm for whether a number is prime, search math sites online. For example, here.
Once you know how the math works, you can convert it into code. Based on the code you already have, you should learn the difference between & and && and how to get a remainder.
I have a function which calculates the factorial and combinations as follows.
int faktorial(int n)
{
if( (n == 0)||(n == 1))
{
return (1);
}
else
{
return (n * faktorial(n-1));
}
}
int Kombinasi(int x, int y)
{
int n = faktorial(x);
int k = (faktorial(x - y)) * (faktorial(y));
int hasil = n / k;
return (hasil);
}
But there is a problem that in calculating the factorial.
Suppose I want to count combination with x = 1000 and y = 4. The function of the combination of the existing call factorial function. but the factorial function is not able to count them. How to solve this problem ?. Sorry my english is very bad. thanks.
BigInteger works and is pretty fast at 1000!.
BigInteger faktorial(BigInteger n)
{
if ((n == 0) || (n == 1))
{
return (1);
}
else
{
return (n * faktorial(n - 1));
}
}
BigInteger Kombinasi(BigInteger x, BigInteger y)
{
BigInteger n = faktorial(x);
BigInteger k = (faktorial(x - y)) * (faktorial(y));
BigInteger hasil = n / k;
return (hasil);
}
Answer:
402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Note, however, that it appears to overflow the stack above around 8889!.
First, to answer your question - you can handle bigger values (up to 2^64 - 1) if you use
ulong c;
Second, a little help - that won't help you with the exercise. Even unsigned long won't be able to handle such large values. However, note that instead, to get (n choose k), you can simply calculate (n * (n - 1) * .... * (n - k + 1)) / k!, Which deals with much smaller values.
Since it looks like what you really want to do is compute a binomial coefficient, an alternative to using BigInteger is to take advantage of some of the numerical properties of factorials. So rather than computing factorials directly (which can be large), you can instead do this:
long Kombinasi(long x, long y)
{
if( y == 0 ) return 1;
return ( x * Kombinasi( x - 1, y - 1 ) ) / y;
}
You could also use this algorithm in combination with BigInteger if you need even larger values:
BigInteger Binomial( BigInteger n, BigInteger k )
{
if( k <= 0 ) return 1;
return ( n * Binomial( n - 1, k - 1 ) ) / k;
}
This will be much more efficient than computing the factorials and dividing since it takes advantage of the fact that most of the factorial terms cancel out. It will also perform fewer multiplications, especially if k is small.
As suggested by other members We can use BitInteger for big numbers.
I dont know whether it is useful or not, but I want to explain one point here.
So lets say We have a signed int which has big value(int.Max) and If you try to add some positive integer value (10), It wont give you System.OverflowException. It simply give you negative value. So If you want to raise exception in such cases. You can use checked keyword. if the expression produces a value that is outside the range of the destination type. If the expression contains one or more non-constant values, the compiler does not detect the overflow. Overflow checking can be enabled by use of the checked keyword. So when you try something like I mentioned above, It will throw exception and you can handle it accordingly.
checked in C#
I'm currently learning about PLINQ (Parallel Language Integrated Query) on Visual Studio 2012's C#.
In the one lesson Where(i => i % 2 == 0) was given to me, but I've no idea what it means and the book i'm studying from didn't give any explanation.
Does anyone know what this means?
First hope you know % which is "The % operator computes the remainder after dividing its first operand by its second". Read more about % Operator
if you have a list of numbers
var list = new List<Int32>() {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
var result = list.Where(i => i%2 == 0);
So the result will have 2,4,6,8 and 10.
Same thing can be written as
var ans = new List<Int32>();
foreach (var an in list)
{
if (an%2 == 0)
ans.Add(an);
}
The query is selecting only even numbers, where division by 2 has no remainder.
The % operator computes the remainder after dividing its first
operand by its second. All numeric types have predefined remainder
operators.
http://msdn.microsoft.com/en-us/library/0w4e0fzs.aspx
lambda expressions are a bit weird at 1st however when you experiment a bit in VS (and its intellisense) you'll get used to it in no time. as soon as you type in "i=>" you declare a range variable of your type of object which implements IEnumerable(<T>) interface. In this case i is one element of your list (or other IEnumerable>> list, dictionary....) to investigate this case you search for even numbers...
Let's say this is the case:
List<int> source = new List<int>() { 1, 2, 3, 4 };
var evenNumbers = source.Where(i => i % 2 == 0);
Where is filtering source and returning only it's even numbers.
Where is a Linq extension method that works on any object implementing the IEnumerable interface (likeList).
i => i % 2 == 0 is a lambda expression. In this case it means that for each item i in source, Where will apply the expression i % 2 == 0.
Where selects the items in source for which the lambda expression is true. In this case, the expression is true when i is an even number.
This is because of the modulo operator %, which returns the remainder of the integer division between two numbers a and b: a % b. If a = 4 and b = 3, then a % b values 1, because it is what remains when dividing 4 by 3. If % returns 0, then it means that a is divided by b. If b is 2, then it means that a is even.
Where(i => i % 2 == 0)
it means i goes to where i % 2 == 0 that is if
you are doing it for a list of integer it will return all even numbers from list
I have the following collection:
-3, -2, -1, 0, 1, 2, 3
How can I in a single order by statement sort them in the following form:
The negative numbers are sorted first by their (absolute value) then the positive numbers.
-1, -2, -3, 0, 1, 2, 3
Combination sorting, first by the sign, then by the absolute value:
list.OrderBy(x => Math.Sign(x)).ThenBy(x => Math.Abs(x));
or:
from x in list
orderby Math.Sign(x), Math.Abs(x)
select x;
This is conceptually similar to the SQL statement:
SELECT x
FROM list
ORDER BY SIGN(x), ABS(x)
In LINQ-to-Objects, the sort is performed only once, not twice.
WARNING: Math.Abs(x) will fail if x == int.MinValue. If this marginal case is important, then you have to handle it separately.
var numbers = new[] { -3, -2, -1, 0, 1, 2, 3 };
var customSorted = numbers.OrderBy(n => n < 0 ? int.MinValue - n : n);
The idea here is to compare non-negative numbers by the value they have. And compare negative numbers with the value int.MinValue - n which is -2147483648 - n and because n is negative, the higher negative number we, the lower negative result the outcome will be.
It doesn't work when the list itself contains the number int.MinValue because this evaluates to 0 which would be equal to 0 itself. As Richard propose it could be made with longĀ“s if you need the full range but the performance will be slightly impaired by this.
Try something like (VB.Net example)
Orderby(Function(x) iif(x<0, Math.Abs(x), x*1000))
...if the values are <1000
You could express it in LINQ, but if I were reading the code two years later, I'd prefer to see something like:
list.OrderBy(i=>i, new NegativeThenPositiveByAscendingAbsoluteValueComparer());
You will need to implement IComparer.
i have the following problem and I cannot figure out where it comes from. I would appreciate help very much.
The code:
List<Point> lst = new List<Point>();
lst.Add(new Point(0, -2));
lst.Add(new Point(-1, -2));
lst.Sort(delegate (Point x,Point y)
{
if (x.X == 0)
return -1;
else if (y.X == 0)
return 1;
else
{
double retVal1 = x.Y * 1.0 / -x.X;
double retVal2 = y.Y * 1.0 / -y.X;
int retVal = -Math.Sign(retVal1 - retVal2);
return retVal;
}
});
If executed, I recieve an ArgumentException saying that IComparer doesn't not return 0(null). However, it actually cannot return anything else but -1, 0 and 1, or?
Thank you very much for your help!
Ah, btw i'm using .NET 3.5
Actually the error message says: IComparer (or the IComparable methods it relies upon) did not return zero when Array.Sort called x. CompareTo(x). x: '' x's type: 'Point' The IComparer: 'System.Array+FunctorComparer`1[System.Drawing.Point]'.
You must return 0 if the objects are identical:
lst.Sort(delegate(Point x, Point y) {
if (x.X == y.X && x.Y == y.Y) { // you are missing this
return 0;
}
if (x.X == 0)
return -1;
else if (y.X == 0)
return 1;
else {
double retVal1 = x.Y * 1.0 / -x.X;
double retVal2 = y.Y * 1.0 / -y.X;
int retVal = -Math.Sign(retVal1 - retVal2);
return retVal;
}
});
You haven't completely read the Exception-Message. It most likely says that it does not return 0 for the same instance of the object.
Your code is wrong, if the same instance of Point or an identical value is passed in, it needs to return 0. Otherwise he would never know when he's done with sorting and would end up in an endless loop...and we all know that this is an absolute negative performance hit.
As said, a comparer must return 0 for the the same value as identity entails equality (something is always equal to itself) and equality entails equivalence (you may order two different things equivalently, but you must order two equal things equivalently).
There is a further problem, in that your check for .X being 0 could result in the same items returning inconsistent ordering if they both have .X equal to 0. It's an important rule that a comparison method must always be consistent in that:
If x < y then y > x.
If x < y and y < z then x < z.
Your algorithm breaks the first rule as thus:
Say point a is {0, 3} and point b is {0, 2}
Calling with (a, b) then returns -1 meaning a < b, but calling with (b, a) returns -1 meaning b < a.
Replace the whole thing with:
lst.Sort(delegate (Point x,Point y)
{
return (x.Y * 1.0 / -x.X).CompareTo(y.Y * 1.0 / -y.X);
});
(Note that this implicitly returns 0 for equal points - we could add an explicit check if this was a heavier calculation as an optimisation, but it isn't necessary.
Also, is Point here System.Drawing.Point? If so then this code is now fine, but if it's something else then it's worth noting that the code is fine if Point is a struct, but should contain a null check if Point is a class.