Skip to content

Instantly share code, notes, and snippets.

@rglos
Created October 16, 2017 19:03
Show Gist options
  • Save rglos/93148edc503e0c736af94bfbf867a27b to your computer and use it in GitHub Desktop.
Save rglos/93148edc503e0c736af94bfbf867a27b to your computer and use it in GitHub Desktop.
Interview Assignment
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace PopularBikes
{
class Program
{
static void Main(string[] args)
{
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
// #1 - get the json as a string
var getJsonStopwatch = System.Diagnostics.Stopwatch.StartNew();
Console.WriteLine("Getting JSON...");
string surveyJson = null;
using (var webClient = new WebClient())
{
surveyJson = webClient.DownloadString("https://trekhiringassignments.blob.core.windows.net/interview/bikes.json");
}
if (surveyJson == null || string.IsNullOrEmpty(surveyJson))
{
Console.WriteLine("JSON null or empty"); // we could do other checks before going to step 2 if needing (i.e. is the JSON valid, in the manner we expect, etc)
return;
}
getJsonStopwatch.Stop();
Console.WriteLine($"Getting JSON - complete, Elapsed: {getJsonStopwatch.Elapsed}");
// #2 - deserialize the json into a nice object we can use to group, count and sort with LINQ
Console.WriteLine();
Console.WriteLine("Deserializing JSON");
List<SurveyResponse> surveyResponses = JsonConvert.DeserializeObject<List<SurveyResponse>>(surveyJson);
Console.WriteLine($"Found {surveyResponses.Count:n0} survery responses...");
// #3 - group, count, sort with LINQ
// We need a comparer to compare the string of bikes, I'm leaving my sample and testing code for references on why I created a SurveyResponseComparer
//
//var list1 = new List<string> { "A", "B" };
//var list2 = new List<string> { "A", "B" };
//var test = list1.OrderBy(x => x).SequenceEqual(list2.OrderBy(x => x));
//
//var list3 = new List<string> { "B", "A" };
//var test2 = list1.OrderBy(x => x).SequenceEqual(list3.OrderBy(x => x));
//
//var groupQuery = surveyResponses.GroupBy(x => x.Bikes.ToArray());
//var groupQuery = surveyResponses.GroupBy(x => x).Select(group => new { Group = group.Key, Count = group.Count() });
//var groupQuery = surveyResponses.GroupBy(x => x.Bikes, new SurveyResponseComparer());
//
var groupQuery = surveyResponses.GroupBy(x => x.Bikes, new SurveyResponseComparer()).Select(group => new { Group = group.Key, Count = group.Count() });
var sortedQuery = groupQuery.OrderByDescending(x => x.Count);
// #4 - only take the top 20
var topTwentyQuery = sortedQuery.Take(20);
// #5 - show the results
Console.WriteLine();
Console.WriteLine("Top 20 most popular responses:");
var number = 0;
foreach (var item in topTwentyQuery)
{
number += 1;
Console.WriteLine($"Number {number} with {item.Count:n0} responses: {string.Join(", ", item.Group)}");
}
stopwatch.Stop();
Console.WriteLine();
Console.WriteLine($"Main - complete, Elapsed: {stopwatch.Elapsed}");
}
}
class SurveyResponse
{
public List<string> Bikes { get; set; }
}
class SurveyResponseComparer : IEqualityComparer<List<string>>
{
public bool Equals(List<string> x, List<string> y)
{
// We don't care about order (i.e. {Bike1, Bike2} should equal {Bike2, Bike1}) so we can use SequenceEqual since it cares about order, so let's order the lists before we compare
var xOrdered = x.OrderBy(s => s);
var yOrdered = y.OrderBy(s => s);
return xOrdered.SequenceEqual(yOrdered);
}
public int GetHashCode(List<string> obj)
{
var ordered = obj.OrderBy(s => s);
return string.Join(",", ordered).GetHashCode();
}
}
}
@rglos
Copy link
Author

rglos commented Oct 16, 2017

This would produce the following output as of 2017.10.16:

Getting JSON...
Getting JSON - complete, Elapsed: 00:00:01.4046568

Deserializing JSON
Found 12,760 survery responses...

Top 20 most popular responses:
Number 1 with 4,633 responses: Trek Fuel EX 9.8
Number 2 with 1,015 responses: A%monda SLR 9
Number 3 with 958 responses: Boone 7
Number 4 with 763 responses: Madone 9.5
Number 5 with 732 responses: Speed Concept 9.9
Number 6 with 623 responses: Farley 9.9
Number 7 with 268 responses: ZEKTOR i3
Number 8 with 204 responses: Trek Fuel EX 9.8, Boone 7
Number 9 with 181 responses: Madone 9.5, Trek Fuel EX 9.8
Number 10 with 165 responses: Session 9.9 DH
Number 11 with 159 responses: CrossRip 3
Number 12 with 156 responses: A%monda SLR 9, Trek Fuel EX 9.8
Number 13 with 133 responses: Speed Concept 9.9, Trek Fuel EX 9.8
Number 14 with 123 responses: Trek Fuel EX 9.8, Farley 9.9
Number 15 with 117 responses: FX S 4 Women's
Number 16 with 101 responses: Electra Loft 7D
Number 17 with 95 responses: Fuel EX 9
Number 18 with 79 responses: Verve 3
Number 19 with 67 responses: Superfly 20, Trek Fuel EX 9.8
Number 20 with 60 responses: Trek Fuel EX 9.8, CrossRip 3

Main - complete, Elapsed: 00:00:01.5718514

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment