Skip to content

Instantly share code, notes, and snippets.

@boop5
Last active October 25, 2018 03:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save boop5/8069ddb0cafc906bfed4d9f239e0de14 to your computer and use it in GitHub Desktop.
Save boop5/8069ddb0cafc906bfed4d9f239e0de14 to your computer and use it in GitHub Desktop.
/// <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