In enumerable type, index is useful to identify a member. In C# 3.0, some methods for enumerable provide index parameter such as Select and Where. But most of methods are still not provide index, such as GroupBy and OrderBy.
One of the easy way to inject index into enumerable is to use Closure. For example, if you want to order "ABCDEFG" alternately you may write.
int i = 0;
var e = "ABCDEFG".OrderBy(c => i++ % 2);
Console.WriteLine(e.ListMembers());
//A C E G B D F
To inject an index, you may declare a variable (i) and use this variable as an index in the delegate. You must also put incremental operator (++) to index variable to make index increase every iteration.
Anyway, using of Closure also has drawback. The index variable will not be cleared after enumeration. When you enumerate again index variable will be incorrect. For example:
int i = 0;
var e = "ABCDEFG".OrderBy(c => i++ % 2);
Console.WriteLine(e.ListMembers());
//A C E G B D F
Console.WriteLine(e.ListMembers());
//B D F A C E G
As you can see, the third command and the forth command are the same. But the result is not the same. Because, after run the third command, i value is equal to 7. Then when you call the forth command, the index will be started at index 7 and so on. Finally, the result will not be the same for the second time.
Anyway, this issue can be solved by make the class persistent.
int i = 0;
var e = "ABCDEFG".OrderBy(c => i++ % 2).ToArray();
Console.WriteLine(e.ListMembers());
//A C E G B D F
Console.WriteLine(e.ListMembers());
//A C E G B D F
Above example, we call ToArray after OrderBy method, and make e variable persistent. The result for e will be the same everytime.
Another solution for index injection is to create extension methods.
public static Dictionary<int, T> WithIndex<T>(this IEnumerable<T> source) {
return source.WithIndex(0.To(int.MaxValue), EqualityComparer<int>.Default);
}
public static Dictionary<T1, T2> WithIndex<T1, T2>(this IEnumerable<T2> source, IEnumerable<T1> index) {
return source.WithIndex(index, EqualityComparer<T1>.Default);
}
public static Dictionary<T1, T2> WithIndex<T1, T2>(this IEnumerable<T2> source, IEnumerable<T1> index, IEqualityComparer<T1> comparer) {
Dictionary<T1, T2> dict = new Dictionary<T1, T2>(comparer);
using (IEnumerator<T2> source_enum = source.GetEnumerator()) {
using (IEnumerator<T1> index_enum = index.GetEnumerator()) {
while (source_enum.MoveNext()) {
if (!index_enum.MoveNext())
throw new ArgumentException("index cannot has less length than source", "index");
dict.Add(index_enum.Current, source_enum.Current);
}
}
}
return dict;
}
You just call above method before enumeration. The result you get is a dictionary. Key is index, and Value is object. Then after enumeration, you may call Select method to remove index from the object. For example:
var e = from c in "ABCDEFG".WithIndex()
orderby c.Key % 2
select c.Value;
Console.WriteLine(e.ListMembers());
//A C E G B D F
Console.WriteLine(e.ListMembers());
//A C E G B D F
You can also pass any kind of index into WithIndex method. The index's length must be greater than or equal to source's length.
For example, you have source and position. And you want to sort source by position. In this case, you can assign position as an index of the source.
var e = from x in source.WithIndex(position)
orderby x.Key
select x.Value;
Index extraction is index from specific item in the enumerable. Here is the extension methods:
public static int IndexOf<T>(this IEnumerable<T> source, T item) {
return source.IndexOf(item, EqualityComparer<T>.Default);
}
public static int IndexOf<T>(this IEnumerable<T> source, T item, IEqualityComparer<T> comparer) {
IList<T> list = source as IList<T>;
if (list != null)
return list.IndexOf(item);
int i = 0;
foreach (T x in source) {
if (comparer.Equals(x, item))
return i;
}
return -1;
}
The example for IndexOf is from CodeGolf. The question is Reverse game. You will get list of numbers randomly. And you must tell how many numbers from the left to reverse. And target is to arrage the numbers.
int[] list = new[] { 8, 9, 4, 5, 1, 3, 6, 2, 7 };
Action<int> reverse = i => {
if (i > 1) {
Console.WriteLine("reverse: {0}", i);
list = list.Take(i).Reverse().Concat(list.Skip(i)).ToArray();
Console.WriteLine(list.ListMembers());
}
};
list.Length.DownTo(1).ForEach(x => {
if (x != list[x - 1]) {
reverse(list.IndexOf(x) + 1);
reverse(x);
}
});
//8 9 4 5 1 3 6 2 7
//reverse: 2
//9 8 4 5 1 3 6 2 7
//reverse: 9
//7 2 6 3 1 5 4 8 9
//reverse: 7
//4 5 1 3 6 2 7 8 9
//reverse: 5
//6 3 1 5 4 2 7 8 9
//reverse: 6
//2 4 5 1 3 6 7 8 9
//reverse: 3
//5 4 2 1 3 6 7 8 9
//reverse: 5
//3 1 2 4 5 6 7 8 9
//reverse: 3
//2 1 3 4 5 6 7 8 9
//reverse: 2
//1 2 3 4 5 6 7 8 9
Above example, you need IndexOf to identify position of the next number you want to reverse in the list. Then you reverse that number to the left, and then you reverse again to move the number to appropriate position.
Next, we will go to Roman Numerals.
วันพฤหัสบดีที่ 15 พฤษภาคม พ.ศ. 2551
Extension Methods for Enumerable Part II - Index injection and index extraction
เขียนโดย
Chaow
ที่
22:03
0
ความคิดเห็น
ป้ายกำกับ: codegolf, enumerable, extension
วันพฤหัสบดีที่ 24 เมษายน พ.ศ. 2551
Extension Methods for Math
Math class provided by core library of .NET is very good. But most methods are for double type. Today we will create math methods for integer types which include int, long, and BigInteger.
Start with GCD (Greatest Common Divisor), which I used once in Pythagorean article.
public static int Gcd(int a, int b) {
while (b != 0) {
int r = a % b;
a = b;
b = r;
}
return a;
}
public static long Gcd(long a, long b) {
while (b != 0L) {
long r = a % b;
a = b;
b = r;
}
return a;
}
And next one goes to LCM (Least Common Multiple).
public static int Lcm(int a, int b) {
return (b / Gcd(a, b)) * a;
}
public static long Lcm(long a, long b) {
return (b / Gcd(a, b)) * a;
}
Usage of these methods are easy, to find GCD and LCM of number 1 to 20.
Console.WriteLine(1.To(20).Aggregate(Math2.Gcd));
//1
Console.WriteLine(1.To(20).Aggregate(Math2.Lcm));
//232792560
Next is Integer Square Root. This method uses Newton's method to solve square root.
public static int Sqrt(this int num) {
if (num < 0)
throw new ArgumentOutOfRangeException("num", "num cannot be negative");
int x = num;
int y = (x + 1) / 2;
while (y < x) {
x = y;
y = (x + (num / x)) / 2;
}
return x;
}
public static long Sqrt(this long num) {
if (num < 0L)
throw new ArgumentOutOfRangeException("num", "num cannot be negative");
long x = num;
long y = (x + 1L) / 2L;
while (y < x) {
x = y;
y = (x + (num / x)) / 2L;
}
return x;
}
Usage is simple, to find square root of 2,000,000,000,000,000,000
Console.WriteLine(2000000000000000000.Sqrt());
//1414213562
Next is to find the Exponentiation
public static int Power(this int num, int pow) {
if (pow < 0)
throw new ArgumentOutOfRangeException("pow", "pow cannot be negative");
int result = 1;
while (pow != 0) {
if ((pow & 1) == 1) {
result *= num;
if (pow == 1)
return result;
}
num *= num;
pow >>= 1;
}
return result;
}
public static long Power(this long num, long pow) {
if (pow < 0L)
throw new ArgumentOutOfRangeException("pow", "pow cannot be negative");
long result = 1L;
while (pow != 0L) {
if ((pow & 1L) == 1L) {
result *= num;
if (pow == 1L)
return result;
}
num *= num;
pow >>= 1;
}
return result;
}
Usage is as simple as square root, to find 2nd power of 1,414,213,562.
Console.WriteLine(1414213562L.Power(2));
//1999999998944727844
When you use integer square root and power to a number, if result is not the same as that number, the number is not perfect square. In the example above, 2,000,000,000,000,000,000 is not perfect square.
Last one, Modular Exponentiation, is to perform power over a modulus.
public static int ModPow(this int num, int pow, int mod) {
if (pow < 0)
throw new ArgumentOutOfRangeException("pow", "pow cannot be negative");
int result = 1;
while (pow != 0) {
if ((pow & 1) == 1) {
result = (result * num) % mod;
if (pow == 1L)
return result;
}
num = (num * num) % mod;
pow >>= 1;
}
return result;
}
public static long ModPow(this long num, long pow, long mod) {
if (pow < 0L)
throw new ArgumentOutOfRangeException("pow", "pow cannot be negative");
long result = 1L;
while (pow != 0L) {
if ((pow & 1L) == 1L) {
result = (result * num) % mod;
if (pow == 1L)
return result;
}
num = (num * num) % mod;
pow >>= 1;
}
return result;
}
Example of modular exponentiation, to find last 5 digits of 10th power of 1,414,213,562.
Console.WriteLine(1414213562L.ModPow(10L, 100000L));
//60224
And below is the code for BigInteger
public static BigInteger Gcd(BigInteger a, BigInteger b) {
while (!b.IsZero()) {
BigInteger r = a % b;
a = b;
b = r;
}
return a;
}
public static BigInteger Lcm(BigInteger a, BigInteger b) {
return (b / Gcd(a, b)) * a;
}
static readonly BigInteger two = 2;
public static BigInteger Sqrt(this BigInteger num) {
if (num.IsNegative())
throw new ArgumentException("num cannot be negative", "num");
if (num.IsZero())
return BigInteger.Zero;
BigInteger x = num;
BigInteger y = (x + BigInteger.One) / two;
while (y < x) {
x = y;
y = (x + (num / x)) / two;
}
return x;
}
There is not Power and ModPow for BigInteger, because BigInteger already contains those methods.
Next article, is to find the ways to inject index into various enumerable methods.
เขียนโดย
Chaow
ที่
09:21
0
ความคิดเห็น
ป้ายกำกับ: biginteger, extension, math
วันเสาร์ที่ 5 เมษายน พ.ศ. 2551
Extension Methods for Delegate Types Part II - Passing anonymous type to generic function
How can you create function which its parameter or return type is anonymous type? You can't assign lambda expression to implicit local variable declaration.
//Compile error
var func = () => new { x = 1, y = 2 };
The c# compiler also does not accept type inference on instantiation, such as
//Compile error
var func = new Func(() => new { x = 1, y = 2 });
To create generic function, which accepts anonymous type, we must create method. Because for method, type inference is allowed.
Here is the code.
public static Func<TResult> CreateFunction<TResult>(Func<TResult> tResult) {
return tResult;
}
public static Func<T, TResult> CreateFunction<T, TResult>(T t, Func<T, TResult> tResult) {
return tResult;
}
public static Func<T1, T2, TResult> CreateFunction<T1, T2, TResult>(T1 t1, T2 t2, Func<T1, T2, TResult> tResult) {
return tResult;
}
public static Func<T1, T2, T3, TResult> CreateFunction<T1, T2, T3, TResult>(T1 t1, T2 t2, T3 t3, Func<T1, T2, T3, TResult> tResult) {
return tResult;
}
public static Func<T1, T2, T3, T4, TResult> CreateFunction<T1, T2, T3, T4, TResult>(T1 t1, T2 t2, T3 t3, T4 t4, Func<T1, T2, T3, T4, TResult> tResult) {
return tResult;
}
To create the method just pass lambda expression to the argument.
var func = Function2.CreateFunction(() => new { x = 1, y = 2 });
You can also create function which its arguments and return type are anonymous type
var func = Function2.CreateFunction(
new { Name = default(string), Age = default(int) },
default(decimal),
(person, salary) =>
new {
Name = person.Name,
Age = person.Age,
Salary = salary
});
var p = func(new { Name = "Lisa", Age = 20 }, 1000000);
//p = { Name = Lisa, Age = 20, Salary = 1000000 }
Just pass the empty class to specify type of arguments. Above code is to create function which accept an anonymous type (Name: string, Age: int) and a decimal, the function returns another anonymous type (Name: string, Age: int, Salary: decimal).
As a bonus here are some more extension methods.
public static Func<T2, T3, TResult> Partial<T1, T2, T3, TResult>(this Func<T1, T2, T3, TResult> func, T1 arg1) {
return (arg2, arg3) => func(arg1, arg2, arg3);
}
public static Func<T2, T3, T4, TResult> Partial<T1, T2, T3, T4, TResult>(this Func<T1, T2, T3, T4, TResult> func, T1 arg1) {
return (arg2, arg3, arg4) => func(arg1, arg2, arg3, arg4);
}
public static Func<T1, T2, T3, TResult> Memoize<T1, T2, T3, TResult>(this Func<T1, T2, T3, TResult> func) {
var dict = new Dictionary<T1, Func<T2, T3, TResult>>();
return (arg1, arg2, arg3) => {
Func<T2, T3, TResult> value;
if (!dict.TryGetValue(arg1, out value)) {
value = func.Partial(arg1).Memoize();
dict.Add(arg1, value);
}
return value(arg2, arg3);
};
}
public static Func<T1, T2, T3, T4, TResult> Memoize<T1, T2, T3, T4, TResult>(this Func<T1, T2, T3, T4, TResult> func) {
var dict = new Dictionary<T1, Func<T2, T3, T4, TResult>>();
return (arg1, arg2, arg3, arg4) => {
Func<T2, T3, T4, TResult> value;
if (!dict.TryGetValue(arg1, out value)) {
value = func.Partial(arg1).Memoize();
dict.Add(arg1, value);
}
return value(arg2, arg3, arg4);
};
}
public static Func<T1, T2, T3, TResult> When<T1, T2, T3, TResult>(this Func<T1, T2, T3, TResult> func, Func<T1, T2, T3, bool> predicate, Func<T1, T2, T3, TResult> alternative) {
return (arg1, arg2, arg3) => predicate(arg1, arg2, arg3) ? alternative(arg1, arg2, arg3) : func(arg1, arg2, arg3);
}
public static Func<T1, T2, T3, T4, TResult> When<T1, T2, T3, T4, TResult>(this Func<T1, T2, T3, T4, TResult> func, Func<T1, T2, T3, T4, bool> predicate, Func<T1, T2, T3, T4, TResult> alternative) {
return (arg1, arg2, arg3, arg4) => predicate(arg1, arg2, arg3, arg4) ? alternative(arg1, arg2, arg3, arg4) : func(arg1, arg2, arg3, arg4);
}
These are Parial, Memoize, and When functions, which are the same as previous post. You can find detail of functions in previous post. The only difference of these functions and functions in previous post is, these functions accept 3 and 4 arguments.
Next post, extension methods for math.
เขียนโดย
Chaow
ที่
16:31
0
ความคิดเห็น
วันศุกร์ที่ 25 มกราคม พ.ศ. 2551
Extension Methods for String
This post continues on extension methods, now for string. String is the most common type in all programming languages. It is a human-readable text for any kind of information. These are some more extension methods, which may make you to present your data easier.
public static string Join(this IEnumerable<string> source, string separator) {
string[] value = source as string[];
if (value != null)
return string.Join(separator, value);
return string.Join(separator, source.ToArray());
}
public static string Reverse(this string text) {
int len = text.Length;
char[] charArray = new char[len--];
for (int i = 0; len >= 0; i++, len--)
charArray[i] = text[len];
return new string(charArray);
}
public static string Repeat(this string source, int num) {
if (num <= 0)
return string.Empty;
StringBuilder sb = new StringBuilder(source.Length * num);
num.Times(x => sb.Append(source));
return sb.ToString();
}
Join method is the same as String.Join, but this is for enumerable of string. Below is example.
var result = new[] { "Hello", "World!" }.Join(", ");
//result = "Hello, World!"
Reverse method is to reverse the character order of a string. Below is example.
var result = "Hello, World!".Reverse();
// result = "!dlroW ,olleH"
Repeat method is to duplicate a string for specific number of times. Below is example.
var result = "Hello, World!".Repeat(3);
// result = "Hello, World!Hello, World!Hello, World!"
Some more useful methods used to transform enumerable of objects to a string, which I always use when debugging. Following is the code.
public static string ListMembers<T>(this IEnumerable<T> source, string format, string separator) {
return source.Select(s => string.Format(format, s)).Join(separator);
}
public static string ListMembers<T>(this IEnumerable<T> source) {
return source.Select(s => s.ToString()).Join(" ");
}
ListMembers method can be used as ToString method. It transforms every object to string and join them together. Below is example.
var result = new[] { 1, 2, 3, 4, 5 }.ListMembers();
//result = "1 2 3 4 5"
Next post, go to interesting topic about finding solutions by specifying constraints. It is called Constraint Programming.
เขียนโดย
Chaow
ที่
00:09
0
ความคิดเห็น
วันศุกร์ที่ 18 มกราคม พ.ศ. 2551
Extension Methods for Enumerable
Visual Studio 2008 provides many extension method for enumerable, extension method in this post is additional extension that I wrote while developing programs.
public static IEnumerable<T> Repeat<T>(this IEnumerable<T> source, int num) {
for (int x = 0; x < num; x++) {
using (IEnumerator<T> source_enum = source.GetEnumerator()) {
while (source_enum.MoveNext())
yield return source_enum.Current;
}
}
}
public static IEnumerable<T> AsEnumerable<T>(T item) {
yield return item;
}
Repeat method is to reiterate enumerable for specific amount of times. This method is unlike built-in Repeat method of VS 2008. The built-in Repeat method repeats a single item, but this Repeat method repeats an enumerable.
var result = new[] { 1, 2, 3 }.Repeat(3);
//result = {1, 2, 3, 1, 2, 3, 1, 2, 3}
Example above makes the repeat of array {1, 2, 3} for 3 times.
AsEnumerable method makes single item to an enumerable of single element. This method is unlike built-in AsEnumerable method of VS 2008. The built-in AsEnumerable method just cast an enumerable to IEnumerable interface. This AsEnumerable method is not casting, but wrap single item with enumerable.
var result = new[] { 1, 2, 3 }.Concat(Enumerable2.AsEnumerable(4));
//result = {1, 2, 3, 4}
Example above array of {1, 2, 3} is able to concatenate with enumerable of 4.
Some more functions:
public static bool All<T>(this IEnumerable<T> source, Func<T, int, bool> predicate) {
int i = 0;
foreach (T item in source) {
if (!predicate(item, i++))
return false;
}
return true;
}
public static bool Any<T>(this IEnumerable<T> source, Func<T, int, bool> predicate) {
int i = 0;
foreach (T item in source) {
if (predicate(item, i++))
return true;
}
return false;
}
Both All and Any methods are the same with built-in All/Any methods, but the different is these methods provide index used in predicate function.
var result = new[] { 0, 1, 2 }.All((x, i) => x == i);
//result = true
var result2 = new[] { 2, 1, 0 }.Any((x, i) => x == i);
//result2 = true
Example above, All method tests every element's value is equal to index, which is true. Any method tests any element's value is equal to index, it is true because number 1's value is equal to index.
Last 2 functions, these functions are not extension of enumerable, but they are related to enumerable.
public static IEnumerable<T> Enum<T>() {
return System.Enum.GetValues(typeof(T)).Cast<T>();
}
public static T[] Append<T>(this T[] source, T item) {
int len = source.Length;
T[] ret = new T[len + 1];
source.CopyTo(ret, 0);
ret[len] = item;
return ret;
}
Enum method creates enumerable from enum.
var result = Enumerable2.Enum<DayOfWeek>();
//result = {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday}
Example above, Enum method creates enumerable of DayOfWeek type. Values range from Sunday to Saturday.
Append method appends an item to an array.
var result = new[] { 1, 2, 3 }.Append(4);
//result = {1, 2, 3, 4}
Example above 4 is appended to array of {1, 2, 3} and results to new array of {1, 2, 3, 4}.
Next post is still be on more Extension Methods.
เขียนโดย
Chaow
ที่
16:11
0
ความคิดเห็น
ป้ายกำกับ: enumerable, extension
วันเสาร์ที่ 12 มกราคม พ.ศ. 2551
Extension Methods for Delegate Types
The great resource, that I highly recommend you to read is Wesdyer's blog. His blog contains much information about Functional Programming in C#. Articles you should read that relate to this post are Function Memoization and Partial Function Application.
Put this code onto your extension class (source: Wesdyer's blog).
public static Func<T, TResult> Memoize<T, TResult>(this Func<T, TResult> func) {
var dict = new Dictionary<T, TResult>();
return arg => {
TResult value;
if (!dict.TryGetValue(arg, out value)) {
value = func(arg);
dict.Add(arg, value);
}
return value;
};
}
public static Func<T2, TResult> Partial<T1, T2, TResult>(this Func<T1, T2, TResult> func, T1 arg1) {
return arg2 => func(arg1, arg2);
}
Function Memoization is technic to speed up repeating calculation by storing arguments and result.
Compare this simple fibonacci function
Func<int, int> fib = null;
fib = n => n > 1 ? fib(n - 1) + fib(n - 2) : n;
Console.WriteLine(fib(38));
//39088169
//2.35 seconds
with memoized fibonacci
Func<int, int> fib = null;
fib = n => n > 1 ? fib(n - 1) + fib(n - 2) : n;
fib = fib.Memoize();
Console.WriteLine(fib(38));
//39088169
//0.01 second
Memoized function performs much faster. Just add only 1 line of code.
Partial Function Application is to define an argument of a function and create another function with remaining argument.
Here is an example.
Func<int, int, int> gcd = null;
gcd = (x, y) => (y == 0) ? x : gcd(y, x % y);
Func<int, int> gcdBy20 = gcd.Partial(20);
var max = 1.To(15).Max(gcdBy20);
//max = 10
First, we declare Greatest Common Divisor (GCD) function. Then, we partial it and create new gcdBy20 function. This function takes only one argument and return greatest common divisor with 20. To use, we generate numbers 1 to 15, and find which value has maximum gcdBy20.
Now more extension methods by me.
public static Func<T1, T2, TResult> Memoize<T1, T2, TResult>(this Func<T1, T2, TResult> func) {
var dict = new Dictionary<T1, Func<T2, TResult>>();
return (arg1, arg2) => {
Func<T2, TResult> value;
if (!dict.TryGetValue(arg1, out value)) {
value = func.Partial(arg1).Memoize();
dict.Add(arg1, value);
}
return value(arg2);
};
}
public static Func<T, bool> And<T>(this Func<T, bool> predicate1, Func<T, bool> predicate2) {
return arg => predicate1(arg) && predicate2(arg);
}
public static Func<T, bool> Or<T>(this Func<T, bool> predicate1, Func<T, bool> predicate2) {
return arg => predicate1(arg) || predicate2(arg);
}
public static Func<T, TResult> When<T, TResult>(this Func<T, TResult> func, Func<T, bool> predicate, Func<T, TResult> alternative) {
return arg => predicate(arg) ? alternative(arg) : func(arg);
}
public static Func<T1, T2, TResult> When<T1, T2, TResult>(this Func<T1, T2, TResult> func, Func<T1, T2, bool> predicate, Func<T1, T2, TResult> alternative) {
return (arg1, arg2) => predicate(arg1, arg2) ? alternative(arg1, arg2) : func(arg1, arg2);
}
Memoize function memorizes the result of function with 2 arguments. The first memoize function is able to memorize only 1 argument. If you notice, you can see that this Memoize function uses both Partial and previous Memoize functionality to memorize.
And/Or functions are simple. They takes a predicate and produce another predicate with And/Or logic.
Func<int, bool> predicate = x => x % 2 == 0;
predicate = predicate.And(x => x % 3 == 0);
predicate = predicate.And(x => x % 4 == 0);
var value = 1.To(20).Where(predicate);
//value = {12}
Example above, we create predicate function which find whether x is divisible by 2 And 3 And 4. Then generate numbers 1 to 20, and filter which numbers pass the predicate.
"When" function provides conditional to evaluate alternative expression if condition is met.
Func<int, int> fact = null;
fact = x => fact(x - 1) * x;
fact = fact.When(x => x == 0, x => 1);
Console.WriteLine(fact(10));
//3628800
Factorial function equal to factorial of x - 1 multiply by x. But "When" function creates alternation instruction, when x equal to 0, result will equal to 1.
A little bit more extension methods
public static Func<T, bool> PredicateAll<T>(this IEnumerable<Func<T, bool>> source) {
using (var source_enum = source.GetEnumerator()) {
if (!source_enum.MoveNext())
return x => true;
Func<T, bool> result = source_enum.Current;
while (source_enum.MoveNext())
result = result.And(source_enum.Current);
return result;
}
}
public static Func<T, bool> PredicateAny<T>(this IEnumerable<Func<T, bool>> source) {
using (var source_enum = source.GetEnumerator()) {
if (!source_enum.MoveNext())
return x => false;
Func<T, bool> result = source_enum.Current;
while (source_enum.MoveNext())
result = result.Or(source_enum.Current);
return result;
}
}
PredicateAll transforms list of predicates to a predicate that will be true if all predicates are true. On the other hand, PredicateAny create predicate that will be false if all predicates false.
List<Func<int, bool>> predicateList = new List<Func<int, bool>>();
predicateList.Add(x => x % 2 == 0);
predicateList.Add(x => x % 3 == 0);
predicateList.Add(x => x % 4 == 0);
var predicateAll = predicateList.PredicateAll();
var predicateAny = predicateList.PredicateAny();
var result = 1.To(20).Where(predicateAll);
//result = {12}
var result2 = 1.To(20).Where(predicateAny);
//result2 = {2, 3, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20}
Example above, predicateAll returns true only numbers that is divisible by 2, and 3, and 4 which is 12. predicateAny returns true for any numbers that is divisible by 2, or 3, or 4 which are 2, 3, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20.
Next post continue on extension methods.
เขียนโดย
Chaow
ที่
16:23
0
ความคิดเห็น
วันพุธที่ 19 ธันวาคม พ.ศ. 2550
BigInteger, an integer with unbounded length
Usaully, when you think of number, Int32 almost covers all requirements. Its maximum value is 2,147,483,647. It almost never overflow. Int32 is not enough? That's very rare case. But you can using Int64 which its maximum value is 9,223,372,036,854,775,807 which considers an extreamly large number. Is it possible that an operation will make Int64 be overflown? It is possible. In mathematics and cryptography, large precision calculation is needed, and data length of an integer can be extended indefinitely.
Which type shall we use next to Int64? If your answer is Int128, the answer is wrong. Next class we gonna use has no length limitation. It is an integer with unbounded length. This type is called BigInteger.
BigInteger is not included in current C# package. But now you can find BigInteger in Silverlight package. Once you install Silverlight, BigInteger can be found in [drive]:\Program Files\Microsoft Silverlight\Microsoft.Scripting.dll under the namespace Microsoft.Scripting.Math.
Let's play around BigInteger (question from projecteuler.net) :)
Find the sum of digits in 100!
BigInteger bigInt = 1;
100.DownTo(2).ForEach(x => bigInt *= x); //Factorial 100!
Console.WriteLine(bigInt.ToString(10).Sum(c => (int)(c - '0'))); //Sum of Digit
//648
More question :)
What is the sum of the digits of the number 21000?
BigInteger bi = 1;
1000.Times(x => bi *= 2); //21000
Console.WriteLine(bi.ToString(10).Sum(c => (int)(c - '0'))); //Sum of Digit
//1366
Factorial of 100 and 2 power by 1000, Int64 is generally unable to handle above questions. But BigInteger can handle it easily and fast.
As a bonus, I had written some Extensions for BigInteger. First method is for getting sum of a list of BigInteger.
public static BigInteger Sum(this IEnumerable<BigInteger> source) {
BigInteger num = BigInteger.Zero;
foreach (BigInteger num2 in source)
num += num2;
return num;
}
public static BigInteger Sum<T>(this IEnumerable<T> source, Func<T,BigInteger> selector) {
return source.Select(selector).Sum();
}
Usage:
var list = new BigInteger[] { 1, 2, 3 };
Console.WriteLine(list.Sum());
//6
Next method is for parsing string into BigInteger:
public static BigInteger Parse(string s) {
using (System.IO.StringReader reader = new System.IO.StringReader(s)) {
char[] buffer = new char[10];
int startIndex = 0;
uint[] multiplier = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
int count = reader.ReadBlock(buffer, 0, 9);
BigInteger ret = int.Parse(new string(buffer, 0, count));
if (ret.IsNegative())
startIndex = 1;
while (count == 9) {
count = reader.ReadBlock(buffer, startIndex, 9);
ret *= multiplier[count];
ret += int.Parse(new string(buffer, 0, count + startIndex));
}
return ret;
}
}
public static bool TryParse(string s, out BigInteger result) {
try {
result = Parse(s);
return true;
} catch {
result = null;
return false;
}
}
Usage
BigInteger i = BigIntegerExtension.Parse("1234567890");
Console.WriteLine(i);
//1234567890
Next post, I will show you somethings bigger than BigInteger :)
เขียนโดย
Chaow
ที่
22:37
0
ความคิดเห็น
ป้ายกำกับ: biginteger, extension, projecteuler
วันอาทิตย์ที่ 16 ธันวาคม พ.ศ. 2550
How to use Extension Methods to extend C# language
Start my first blog with coding!
Usually, when we want to extend a type, we need to create a new derived type. But creating a new derived type, sometimes it is not suitable. Sometimes the extensions are so small, sometimes types are sealed and unable to be extended. Another solution is you can create new static methods. But those methods are not become parts of the type. New Visual Studio 2008 has a new feature enables you to add new methods without having to derive a type and able to create new methods that will become a part of the type. This new feature called "Extension Methods".
Interesting point is, we can use "Extension Methods" to enhance built-in types like int or IEnumerable. And that could change style of coding which totally different from C# 2.0. Do you know Ruby? Ruby is a programming language that is short and easy. Let's make C# to be as easy as Ruby.
Start with foreach. When you enumerate items in a list you use:
foreach (Object item in list)
But not in Ruby, in Ruby we just write:
list.each{|item| ...}
How easy! To make code like Ruby, put this source on your extension class.
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) {
foreach (T item in source)
action(item);
}
public static void ForEach<T>(this IEnumerable<T> source, Action<T, int> action) {
int i = 0;
foreach (T item in source)
action(item, i++);
}
After extension, you can write:
list.ForEach(item => ...);
list.ForEach((item,index)=> ...);
Here is the example:
string[] persons = new string[] {"Jack", "Lisa", "Ryan"};
persons.ForEach(person => Console.WriteLine("Hello {0}!", person));
//Hello Jack!
//Hello Lisa!
//Hello Ryan!
persons.ForEach((person, index) => Console.WriteLine("{0}. {1}", index + 1, person));
//1. Jack
//2. Lisa
//3. Ryan
Is that ok with you? If you like Ruby style go to next method. When we run number 0 to 2 (run 3 loop) we usaully write:
for (int i = 0; i <= 2; i++)
Ruby is much easily:
0..2
or
3.times{|x| ..}
Jealous? Put this source on your extension class:
public static IEnumerable<int> To(this int from, int to) {
for (int x = from; x <= to; x++)
yield return x;
}
public static IEnumerable<int> DownTo(this int from, int to) {
for (int x = from; x >= to; x--)
yield return x;
}
public static IEnumerable<int> StepTo(this int from, int to, int step) {
if (step > 0) {
for (int x = from; x <= to; x += step)
yield return x;
} else if (step < 0) {
for (int x = from; x >= to; x += step)
yield return x;
} else {
throw new ArgumentException("Step cannot be zero.", "step");
}
}
public static void Times(this int num, Action<int> action) {
for (int x = 0; x < num; x++)
action(x);
}
Now you can write:
string[] persons = new string[] { "Jack", "Lisa", "Ryan" };
0.To(2).ForEach(i => Console.WriteLine(persons[i]));
//Jack
//Lisa
//Ryan
2.DownTo(0).ForEach(i => Console.WriteLine(persons[i]));
//Ryan
//Lisa
//Jack
0.StepTo(2, 2).ForEach(i => Console.WriteLine(persons[i]));
//Ryan
//Jack
//(run 0 to 2 with step 2)
3.Times(i => Console.WriteLine(persons[i]));
//Jack
//Lisa
//Ryan
Try practical use, with question from projecteuler.net.
Add all the natural numbers below 1000 that are multiples of 3 or 5.
Console.WriteLine(1.To(999).Where(x => (x % 3 == 0) || (x % 5 == 0)).Sum());
//233168
Now we can completed question above with only one line of code. If you use C# 2.0, you will never write code like this. There are more several methods that you can extend C# from Ruby (or any other languages). Make your code shorter, your life will be easier.
เขียนโดย
Chaow
ที่
06:45
0
ความคิดเห็น
ป้ายกำกับ: enumerable, extension, projecteuler