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?