Recursive dealing of cards from deck? - c#

A standard 52 card deck may be represented using integer values: {0,1,..,50,51}. A standard poker hand contains 5 values from this set, without repetition.
To represent all 52C5 unique hands from a deck, the following loop may be used:
for (int card1 = 0; card1 < 48; card1++)
{
for (int card2 = card1 + 1; card2 < 49; card2++)
{
for (int card3 = card2 + 1; card3 < 50; card3++)
{
for (int card4 = card3 + 1; card4 < 51; card4++)
{
for (int card5 = card4 + 1; card5 < 52; card5++)
{
var handAbcde = new List<int> { card1, card2, card3, card4, card5 };
// do something with the hand...
}
}
}
}
}
I would like to know how to make this a recursive function. I attempted but I could not preserve the ordering of the cards from lowest to highest, as it would for the for loops above.
Example of desired output: (observe sequential ordering from lowest to highest without repetition)
0 1 2 3 4
0 1 2 3 5
0 1 2 3 6
.
.
.
47 48 49 50 49
47 48 49 50 50
47 48 49 50 51

Here's a helpful extension method, which does what you want using recursion:
public static IEnumerable<IEnumerable<T>> GetPermutations<T>(this IEnumerable<T> items, int count)
{
int i = 0;
foreach (var item in items)
{
if (count == 1) yield return new T[] { item };
else foreach (var result in items.Skip(i + 1).GetPermutations(count - 1))
yield return new T[] { item }.Concat(result);
++i;
}
}
And here's a sample use, to generate all possible combinations of five cards from a 52-card deck:
foreach (var hand in Enumerable.Range(0, 52).GetPermutations(5))
{
foreach (var card in hand)
Console.Write(card + " ");
Console.WriteLine();
}

Related

c# array in prime numbers - Where is my mistake?

//I want to fill an array with the first 15 prime numbers. the loop will only increase as you find the prime number and add it to the array.
int[] primes = new int[15];
int j = 0;
int i = 2;
while (j < 15)
{
if (IsPrime(i))
{
primes[j] = i;
j++;
}
i++;
}
for (int a = 0; a < primes.Length; a++)
{
Console.Write(primes[a] + " ");
}
}
//method
static bool IsPrime(int number)
{
for (int i = 2; i < number; i++)
{
if (number % i == 0)
{
return true;
}
}
return false;
}
Problem is that your IsPrime function is actually doing the exact oposite of what you want to achieve. Look at that function again and think about where the mistake is (hint: it is a minor problem, I feel like you just overlooked something and that the logic in your mind was correct).
After you get the result you want, I also recommend you to think about IsPrime function again and try to optimize it a little bit (hint: do you really need to test all the numbers, one by one?) and also to your while loop (hint: do you really need to iterate i by 1?).
Also welcome to Stackoverflow!
You have to fix the IsPrime function as follows:
static bool IsPrime(int number)
{
int i;
for (i = 2; i <= number - 1; i++)
{
if (number % i == 0)
{
return false;
}
}
if (i == number)
{
return true;
}
return false;
}
Output
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

C# implementation of Levenshtein algorithm for substring matching

I'm playing with Levenshtein distance for getting a C# implementation which allows not only to tell whether two strings are similar, but also find a similar string (the needle) in a larger string (the haystack).
To this end, I tried to follow the advice at the bottom of this excellent post, but I'm getting some issues.
To start with, I adopted this implementation, changing it to fit my additional requirements. I also added some diagnostic dump support to let me understand the algorithm better, inspired by this other post.
My implementation returns an object with score and (when requested) index and length, and also a reference to the calculated matrix used for diagnostic purposes:
public class LevenshteinMatch
{
public int Score { get; }
public int Index { get; }
public int Length { get; }
public int[,] Matrix { get; set; }
public LevenshteinMatch(int score, int index = 0, int length = 0)
{
Score = score;
Index = index;
Length = length;
}
public override string ToString()
{
return $"{Score} #{Index}x{Length}";
}
}
Here is my implementation: the Distance method works "normally" if sub is false; otherwise, it finds a similar substring. DumpMatrix is just a diagnostic helper method.
public static class Levenshtein
{
public static string DumpMatrix(int[,] d, string a, string b)
{
if (d == null) throw new ArgumentNullException(nameof(d));
if (a == null) throw new ArgumentNullException(nameof(a));
if (b == null) throw new ArgumentNullException(nameof(b));
// # k i t t e n
// 00 01 02 03 04 05 06
// # 00 .. .. .. .. .. .. ..
// s 01 .. .. .. .. .. .. ..
// ...etc (sitting)
StringBuilder sb = new StringBuilder();
int n = a.Length;
int m = b.Length;
// b-legend
sb.Append(" # ");
for (int j = 0; j < m; j++) sb.Append(b[j]).Append(" ");
sb.AppendLine();
sb.Append(" 00 ");
for (int j = 1; j < m; j++) sb.AppendFormat("{0:00}", j).Append(' ');
sb.AppendFormat("{0:00} ", m).AppendLine();
// matrix
for (int i = 0; i <= n; i++)
{
// a-legend
if (i == 0)
{
sb.Append("# 00 ");
}
else
{
sb.Append(a[i - 1])
.Append(' ')
.AppendFormat("{0:00}", i)
.Append(' ');
}
// row of values
for (int j = 0; j <= m; j++)
sb.AppendFormat("{0,2} ", d[i, j]);
sb.AppendLine();
}
return sb.ToString();
}
private static LevenshteinMatch BuildMatch(string a, string b, int[,] d)
{
int n = a.Length;
int m = b.Length;
// take the min rightmost score instead of the bottom-right corner
int min = 0, rightMinIndex = -1;
for (int j = m; j > -1; j--)
{
if (rightMinIndex == -1 || d[n, j] < min)
{
min = d[n, j];
rightMinIndex = j;
}
}
// corner case: perfect match, just collect m chars from score=0
if (min == 0)
{
return new LevenshteinMatch(min,
rightMinIndex - n,
n);
}
// collect all the lowest scores on the bottom row leftwards,
// up to the length of the needle
int count = n, leftMinIndex = rightMinIndex;
while (leftMinIndex > -1)
{
if (d[n, leftMinIndex] == min && --count == 0) break;
leftMinIndex--;
}
return new LevenshteinMatch(min,
leftMinIndex - 1,
rightMinIndex + 1 - leftMinIndex);
}
public static LevenshteinMatch Distance(string a, string b,
bool sub = false, bool withMatrix = false)
{
if (a is null) throw new ArgumentNullException(nameof(a));
if (b == null) throw new ArgumentNullException(nameof(b));
int n = a.Length;
int m = b.Length;
int[,] d = new int[n + 1, m + 1];
if (n == 0) return new LevenshteinMatch(m);
if (m == 0) return new LevenshteinMatch(n);
for (int i = 0; i <= n; i++) d[i, 0] = i;
// if matching substring, leave the top row to 0
if (!sub)
{
for (int j = 0; j <= m; j++) d[0, j] = j;
}
for (int j = 1; j <= m; j++)
{
for (int i = 1; i <= n; i++)
{
if (a[i - 1] == b[j - 1])
{
d[i, j] = d[i - 1, j - 1]; // no operation
}
else
{
d[i, j] = Math.Min(Math.Min(
d[i - 1, j] + 1, // a deletion
d[i, j - 1] + 1), // an insertion
d[i - 1, j - 1] + 1 // a substitution
);
}
}
}
LevenshteinMatch match = sub
? BuildMatch(a, b, d)
: new LevenshteinMatch(d[n, m]);
if (withMatrix) match.Matrix = d;
return match;
}
}
To be more complete, here is the demo console program using it. This just prompts the user for the matching mode (substring or not) and the two strings, then calls the Distance method, dumps the resulting matrix, and shows the substring if required.
internal static class Program
{
private static string ReadLine(string defaultLine)
{
string s = Console.ReadLine();
return string.IsNullOrEmpty(s) ? defaultLine ?? s : s;
}
private static void Main()
{
Console.WriteLine("Fuzzy Levenshtein Matcher");
string a = "sitting", b = "kitten";
bool sub = false;
LevenshteinMatch match;
while (true)
{
Console.Write("sub [y/n]? ");
string yn = Console.ReadLine();
if (!string.IsNullOrEmpty(yn)) sub = yn == "y" || yn == "Y";
Console.Write(sub? $"needle ({a}): " : $"A ({a}): ");
a = ReadLine(a);
Console.Write(sub? $"haystack ({b}): " : $"B ({b}): ");
b = ReadLine(b);
match = Levenshtein.Distance(a, b, sub, true);
Console.WriteLine($"{a} - {b}: {match}");
Console.WriteLine(Levenshtein.DumpMatrix(match.Matrix, a, b));
if (sub) Console.WriteLine(b.Substring(match.Index, match.Length));
}
}
}
Now, for substring matches this works in a case like "aba" in "c abba c". Here is the matrix:
aba - c abba c: 1 #3x3
# c a b b a c
00 01 02 03 04 05 06 07 08
# 00 0 0 0 0 0 0 0 0 0
a 01 1 1 1 0 1 1 0 1 1
b 02 2 2 2 1 0 1 1 1 2
a 03 3 3 3 2 1 1 1 2 2
Yet, in other cases, e.g. "abas" in "ego sum abbas Cucaniensis", I fail to collect the min scores from the bottom row:
abas - ego sum abbas Cucaniensis: 1 #-2x15
# e g o s u m a b b a s C u c a n i e n s i s
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
# 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
a 01 1 1 1 1 1 1 1 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 1 1 1 1
b 02 2 2 2 2 2 2 2 2 2 1 0 1 1 1 2 2 2 2 1 1 2 2 2 2 2 2
a 03 3 3 3 3 3 3 3 3 3 2 1 1 1 2 2 3 3 3 2 2 2 3 3 3 3 3
s 04 4 4 4 4 4 3 4 4 4 3 2 2 2 1 2 3 4 4 3 3 3 3 4 3 4 3
Here there is just a single score=1 in the bottom row. In the case of a perfect match (score=0) my code just takes the left N-characters (where N is the length of the needle) from the rightmost lowest score; but here I have scores greater than 0. Probably I've just misinterpreted the hints in the above post, as I'm new to the interals of this algorithm. Could anyone suggest the correct way of finding the needle's index and length in the haystack?
You start at the best score in the bottom row: the 1 at (13,4)
Then you find look at the predecessor states and transitions that could have got you there:
(12,4) - not possible, because it has a higher difference
(13,3) - not possible, because it has a higher difference
(12,3) - same difference and the characters match, so this works
From (12,3) you follow the same procedure to get to (11,2) and then (10,1)
At (10,1) the letters don't match, so you couldn't have come from (9,0). You could use either (10,0) for the similar string "bas", or you could use (9,1) then (8,0) for the similar string "abbas", both with distance 1.

Cumulative sum of array items

I have an sorted array having values like below: I need to calculate total as below:
Scenario 1 - Array values 12,15,17
12+15 = 27
27+17 = 44
44+27 = 71
Total = 71
Scenario 2 Array values 12,15,17,19
12+15 = 27
27+17 = 44
44+19 = 63
27+44+63 = 134
Total = 134
Scenario 3 Array values 12,15,17,19,23
12+15 = 27
27+17 = 44
44+19 = 63
63+23 = 86
27+44+63+86 = 220
Total = 220
Scenario 4 till N Array values 12,15,17,19,23.....N
I have to bring the above logic to C# code
I have written as below :
int[] myNumbers = new int[] { 100,250,1000};
Array.Sort(myNumbers);
int sum = 0;
int temp = 0;
foreach (int y in myNumbers)
{
sum = sum + y;
}
for(int i=0;i<myNumbers.Length-1;i++)
{
temp = temp + myNumbers[i];
}
sum = sum + temp;
Console.Write(sum);
The above code works fine for array values 100,250,1000
But it fails for any other array values
Need help!
Option 1
So if you want to get exact results as in your examples, you can use this method.
It will return you an array of partial sums, that you can later sum up to get the result:
private static long[] CumulativeSums(long[] values)
{
if (values == null || values.Length <= 1) return new long[0];
var results = new long[values.Length];
results[0] = values[0] + values[1];
for (var i = 1; i < values.Length - 1; i++)
{
results[i] = results[i - 1] + values[i + 1];
}
return results;
}
And the use it as this:
var numbers = new long[] { 12, 15, 17, 19 };
var sumOfCumulativeSums = CumulativeSums(numbers).Sum();
And sumOfCumulativeSums will be 134.
Option 2
But the actual correct representation of cumulative sum is: a, a+b, a+b+c, .... So if you want the correct representation of method that returns you proper cumulative sums, you can use this method instead:
public static long[] CumulativeSums(long[] values)
{
if (values == null || values.Length == 0) return new long[0];
var results = new long[values.Length];
results[0] = values[0];
for (var i = 1; i < values.Length; i++)
{
results[i] = results[i - 1] + values[i];
}
return results;
}
Edit
Hope this helps you to solve your problem in either of ways, and if you have any questions or edits about the code, please ask.
You can also obtain the sum without any intermediary array allocation:
static int Cumulate( int[] numbers )
{
if ( numbers == null || numbers.Length < 2 )
return 0;
Array.Sort( numbers );
var prevsum = numbers[0] + numbers[1];
var sum = prevsum;
for ( int i = 2 ; i < numbers.Length ; i++ )
{
prevsum += numbers[i];
sum += prevsum;
}
return sum;
}

Project Euler #23 in C#

Project Euler challenge 23 states this:
A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.
A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n.
As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24. By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit.
Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.
So I've been trying to get this working, however I keep getting back an incorrect result, I'm not sure where this is going wrong in the code though I have:
static void Main(string[] args)
{
List<int> abundantNums = Enumerable.Range(12, 1000000).Where(i => isAbundant(i)).ToList();
abundantNums = abundantNums.Distinct().ToList();
var boolArr = new bool[28124];
for (int i = 0; i < abundantNums.Count; ++i)
{
for (int j = i; j < abundantNums.Count; ++j)
{
var sum = abundantNums[i] + abundantNums[j];
if (sum < 28124) boolArr[sum] = true;
else break;
}
}
var total = 0;
for (int i = 0; i < boolArr.Length; i++)
{
if (boolArr[i] == false)
{
total += i;
}
}
Console.WriteLine(total);
Console.ReadKey();
}
static bool isAbundant(int num)
{
if (getFactors(num).Sum() > num)
{
return true;
}
else
{
return false;
}
}
And then to find the factors of a number I have:
static List<int> getFactors(int num)
{
List<int> factors = new List<int>();
Stopwatch watch = Stopwatch.StartNew();
for (int i=1; i < Math.Sqrt(num) + 1; i++)
{
if (num % i == 0)
{
factors.Add(i);
if (num / i != i)
{
factors.Add(num / i);
}
}
}
watch.Stop();
factors.Remove(num);
return factors;
}
Now I've been at this for a day or two and as far as I can tell this should be doing the trick, anyone wiser than I able to point out my failings?
The problem is your getFactors loop. Change:
for (int i=1; i < Math.Sqrt(num) + 1; i++)
to
for (int i=1; i <= Math.Sqrt(num); i++)
And it should work. I'll let you try and understand why :-)

array numbers which sum is dividing on 4

I want to print numbers on label from 1-to 100
The number's sum must be dividing on 4.
Example:
print 35. because 3+5 = 8 .
8 dividing on 4.
This is code
from loop printing numbers. but how choose those numbers?
print those numbers from 1 to 100 ;
for (int i = 1; i < 100; i++)
{
//select numbers wich sum is dividing on 4
label3.Text += Convert.ToString(i) + " | ";
}
Stolen from Greg Hewgill answer's, you can use his algorithm and use remainder operator (%) like;
int sum, temp;
for (int i = 1; i < 100; i++)
{
sum = 0;
temp = i;
while (temp != 0)
{
sum += temp % 10;
temp /= 10;
}
if (sum % 4 == 0)
{
Console.WriteLine(i);
}
}
Result will be;
4
8
13
17
22
26
31
35
39
40
44
48
53
57
62
66
71
75
79
80
84
88
93
97
Here a demonstration.
You should use a nested loop for that , and use the % operator (% means the rest of division):
for (int i = 1; i < 100; i++)
{
for (int j = i; j < 100; j++)
{
//select numbers wich sum is dividing on 4
if( (i+j)%4 == 0)
{
label3.Text += Convert.ToString(i) + Convert.ToString(j) " | ";
}
}
}

Categories

Resources