Inspired by this r/dailyprogrammer post, the task is too calculate which records to use in order to serve the most records without any of the records having overlapping time spans.
I accomplish this goal by sorting the list of records by their total days spanned, then by iterating over each element and adding it to a new list as long as that record does not overlap with any records already within the “optimized” list.
The source,
internal class Program { private static void Main(string[] args) { var rentalRecords = RentalRecordLoader.Load("rentals.txt"); var result = RentalRecordOptimizer.CalculateMostEfficientRecords(rentalRecords); Console.WriteLine($ "Total Records: {result.Count}"); result.ForEach(r => Console.WriteLine($ "{r.StartDay} : {r.EndDay}")); } } public class RentalRecord { public int StartDay { get; set; } public int EndDay { get; set; } public RentalRecord(int startDay, int endDay) { StartDay = startDay; EndDay = endDay; } public int TotalDays() { return EndDay - StartDay; } public bool Overlapping(RentalRecord rentalRecord) { return StartDay <= rentalRecord.EndDay && rentalRecord.StartDay <= EndDay; } } public abstract class RentalRecordLoader { public static List<RentalRecord> Load(string path) { int recordCount; int[] startDays; int[] endDays; using (var reader = new StreamReader(path)) { recordCount = int.Parse(reader.ReadLine()); startDays = ConvertStringToIntArray(reader.ReadLine()); endDays = ConvertStringToIntArray(reader.ReadLine()); } var rentalList = new List<RentalRecord>(); for (var i = 0; i < recordCount; i++) { rentalList.Add(new RentalRecord(startDays[i], endDays[i])); } return rentalList; } // Load() helper method private static int[] ConvertStringToIntArray( string value, string delimeter = " ") { return value.Trim().Split(delimeter) .Select(x => int.Parse(x)) .ToArray(); } } public abstract class RentalRecordOptimizer { public static List<RentalRecord> CalculateMostEfficientRecords( List<RentalRecord> rentals) { var efficientRentals = new List<RentalRecord>(); foreach (var rental in rentals.OrderBy(x => x.TotalDays())) { // Cant have any overlapping days. // The car cant be in two places at once. if (efficientRentals.Any(x => x.Overlapping(rental))) { continue; } efficientRentals.Add(rental); } return efficientRentals; } }
The input used (stored in rentals.txt)
10 1 2 5 12 13 40 30 22 70 19 23 10 10 29 25 66 35 33 100 65
And the output:
Total Records: 5 5 : 10 30 : 35 13 : 25 40 : 66 70 : 100
Optimizations and better code design is obviously welcome, but I also had a specific question as well.
- What would be the best way to handle incorrectly formatted data in
rentals.txt? Just catch the exception in the Load function?