Last active
October 25, 2018 03:59
-
-
Save boop5/8069ddb0cafc906bfed4d9f239e0de14 to your computer and use it in GitHub Desktop.
My solution for https://markheath.net/post/linq-challenge-3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// These are short programming challenges, can be solved with a single LINQ expression. Of course, that might not | |
/// always make for the most readable code, so feel free to solve these with or without the help of LINQ, and of course | |
/// solutions in other languages are welcome. If you're using LINQ, then the MoreLINQ library often has extension | |
/// methods that simplify the task. | |
/// </summary> | |
/// <remarks>https://markheath.net/post/linq-challenge-3</remarks> | |
/// <remarks>https://github.com/morelinq/MoreLINQ</remarks> | |
public class LinqChallenge3 | |
{ | |
/// <summary> | |
/// The following string contains number of sales made per day in a month:<p /> | |
/// "1,2,1,1,0,3,1,0,0,2,4,1,0,0,0,0,2,1,0,3,1,0,0,0,6,1,3,0,0,0"<p /> | |
/// How long is the longest sequence of days without a sale? (in this example it's 4) | |
/// </summary> | |
public void Problem1() | |
{ | |
const string salesPerDay = "1,2,1,1,0,3,1,0,0,2,4,1,0,0,0,0,2,1,0,3,1,0,0,0,6,1,3,0,0,0"; | |
var result = salesPerDay.Split(',') | |
.Select((s, index) => salesPerDay.Replace(",", "") | |
.Substring(index) | |
.TakeWhile(e => e == s[0])) | |
.OrderByDescending(e => e.Count()) | |
.First() | |
.Count(); | |
Trace.WriteLine($"The longest sequence of days without sales is {result}."); | |
} | |
/// <summary> | |
/// In poker a hand is a "full house" if it contains three cards of one value and two of another value. The following | |
/// string defines five poker hands, separated by a semicolon:<p /> | |
/// "4♣ 5♦ 6♦ 7♠ 10♥;10♣ Q♥ 10♠ Q♠ 10♦;6♣ 6♥ 6♠ A♠ 6♦;2♣ 3♥ 3♠ 2♠ 2♦;2♣ 3♣ 4♣ 5♠ 6♠".<p /> | |
/// Write a LINQ expression that returns a sequence containing only the "full house" hands. | |
/// </summary> | |
public void Problem2() | |
{ | |
const string hands = "4♣ 5♦ 6♦ 7♠ 10♥;10♣ Q♥ 10♠ Q♠ 10♦;6♣ 6♥ 6♠ A♠ 6♦;2♣ 3♥ 3♠ 2♠ 2♦;2♣ 3♣ 4♣ 5♠ 6♠"; | |
hands.Split(';') | |
.Where(hand => hand.Split(' ') | |
.Select(card => card.Trim()) | |
.Select(card => Regex.Replace(card, "[^a-zA-Z0-9 -]", "")) | |
.GroupBy(g => g) | |
.Select(g => new {g.Key, Len = g.Count()}) | |
.Any(x => x.Len == 3 || x.Len == 2)) | |
.ToList() | |
.ForEach(hand => Trace.WriteLine(hand)); | |
} | |
/// <summary> | |
/// What day of the week is Christmas day (25th December) on for the next 10 years (starting with 2018)? The | |
/// answer should be a string (or sequence of strings) starting: Tuesday,Wednesday,Friday,... | |
/// </summary> | |
public void Problem3() | |
{ | |
Enumerable.Range(2018, 10) | |
.Select(i => new DateTime(i, 12, 25)) | |
.ToList() | |
.ForEach(d => Trace.WriteLine(d.DayOfWeek)); | |
} | |
/// <summary> | |
/// From the following dictionary of words,<p /> | |
/// "parts,traps,arts,rats,starts,tarts,rat,art,tar,tars,stars,stray"<p /> | |
/// return all words that are an anagram of star (no leftover letters allowed). | |
/// </summary> | |
public void Problem4() | |
{ | |
const string searched = "star"; | |
const string words = "parts,traps,arts,rats,starts,tarts,rat,art,tar,tars,stars,stray"; | |
words.Split(',') | |
.Select(s => s.ToCharArray()) | |
.Where(a => a.Length == searched.Length) | |
.Select(a => a.Where(c => searched.ToCharArray().Contains(c))) | |
.ToList() | |
.ForEach(x => Trace.WriteLine($"\"{new string(x.ToArray())}\" is an anagram of \"{searched}\"")); | |
; | |
} | |
/// <summary> | |
/// From the following list of names<p /> | |
/// "Santi Cazorla, Per Mertesacker, Alan Smith, Thierry Henry, Alex Song, Paul Merson, Alexis Sánchez, Robert Pires, | |
/// Dennis Bergkamp, Sol Campbell"<p /> | |
/// find any groups of people who share the same initials as each other. | |
/// </summary> | |
public void Problem5() | |
{ | |
const string names = "Santi Cazorla, Per Mertesacker, Alan Smith, Thierry Henry, Alex Song, Paul Merson, Alexis Sánchez, Robert Pires, Dennis Bergkamp, Sol Campbell"; | |
names.Split(',') | |
.Select(s => s.Trim()) | |
.Select(s => s.Split(' ')) | |
.GroupBy(a => $"{a[0][0]}{a[1][0]}") | |
.OrderBy(g => g.Count()) | |
.ToList() | |
.ForEach(g => Trace.WriteLine($"{g.Key} - {g.Count()}")); | |
} | |
/// <summary> | |
/// A video is two hours long exactly, and we want to make some edits, cutting out the following time ranges (expressed | |
/// in H:MM:SS): <p /> | |
/// "0:00:00-0:00:05;0:55:12-1:05:02;1:37:47-1:37:51".<p /> | |
/// (You can assume that the input ranges are in order and contain no overlapping portions)<p /> | |
/// We would like to turn this into a sequence of time-ranges to keep. So in this example, the output should be:<p /> | |
/// "0:00:05-0:55:12;1:05:02-1:37:47;1:37:51-2:00:00" | |
/// </summary> | |
public void Problem6() | |
{ | |
const string ranges = "0:00:00-0:00:05;0:55:12-1:05:02;1:37:47-1:37:51"; | |
var result = ranges.Split('-') | |
.Skip(1) | |
.Select(s => | |
{ | |
if (s.Contains(';')) | |
{ | |
var splitted = s.Split(';'); | |
var start = splitted[0].ToString(); | |
var end = splitted[1].ToString(); | |
return $"{start}-{end}"; | |
} | |
return $"{s}-2:00:00"; | |
}) | |
.Aggregate((c, n) => $"{c};{n}"); | |
Trace.WriteLine(result); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment