1

I am writing a scheduling program using an algorithm. At the last stage of the algorithm I need to look into the timetable (the timetable which was created) to see if the student is already assigned to a class at that time.

Therefore, we have:

Current Class Start Time: (2017, 02, 09, 10, 00, 00)
Current Class Finish Time: (2017, 02, 09, 11, 00, 00)

At this moment we will search into the timetable to see what other classes student A is assigned to:

For example, let's say on the same date they are already assigned to:

Class 'Z' Start Time: (2017, 02, 09, 09, 00, 00)
Class 'Z' Finish Time: (2017, 02, 09, 12, 00, 00)

Now I want to find the time range of Class 'Z' and compare it with the time range of Current Class.

DateTime startClassZ = new DateTime(2017, 02, 09, 09, 00, 00);
DateTime endClassZ = new DateTime(2017, 02, 09, 12, 00, 00);

DateTime StartCurrent = new DateTime(2017, 02, 09, 10, 00, 00);
DateTime StartCurrent = new DateTime(2017, 02, 09, 11, 00, 00);

if (They do not clash)
{
   Assign
}
if (Clash)
{
   Select Another Student
}

Could anyone please help me with my 'IF statements' and also how to solve this problem.

The way that I am thinking of it, there are three possibilities:

  1. If 'current class' (Start and end time) lands in between 'Class Z' (Clash 1)
  2. If the 'start time' of 'current class' lands in between 'Class Z' (Clash 2)
  3. If the 'end time' of 'current class' lands in between 'Class Z' (Clash 3)

Thank You

Manfred Radlwimmer
  • 13,257
  • 13
  • 53
  • 62
Tim Jones
  • 63
  • 1
  • 10
  • 1
    "the way that I am thinking of it, there are three possibilities" Have you tried implementing that and seeing what happens? What have you already tried? http://stackoverflow.com/help/how-to-ask –  Feb 10 '17 at 11:39
  • There are more than 3 possibilities since classes are not all the same length. So you have four variables : Start A, End A, Start B, End B. The combinations are : 1) A starts and ends before B starts 2) A starts before B and ends before B 3) A starts before B and ends after B 4) A starts after B and end before B ends 5) A starts after B and end after B 6) A starts after B ends – jdweng Feb 10 '17 at 11:44
  • No because I want to know if there would be a solution that I can have a variable with e.g. 09:00:00 to 12:00:00 then I can use if statements to see if start time finish time or a new variable (10:00:00 to 11:00:00) would land in between Variable of Class Z (09:00:00 to 12:00:00) – Tim Jones Feb 10 '17 at 11:45
  • @jdweng you are right there is a 4th possibility: if the current class duration is longer than Class Z – Tim Jones Feb 10 '17 at 11:50
  • Tim : I covered all 6 possible combinations in my answer. You cannot just look at the length of the class. Your if/else statements have to cover all 6 cases. – jdweng Feb 10 '17 at 11:55
  • @TimJones What is wrong with my answer? – ProgrammingLlama Feb 10 '17 at 11:56

3 Answers3

5

This is the simplest way to do it:

public static bool HasOverlap(DateTime start1, DateTime end1, DateTime start2, DateTime end2)
{
    return start1 < end2 && end1 > start2;
}

Or if the dates aren't necessarily in the correct start/end order:

public static bool HasOverlap(DateTime start1, DateTime end1, DateTime start2, DateTime end2)
{
    return Min(start1, end1) < Max(start2, end2) && Max(start1, end1) > Min(start2, end2);
}

public static DateTime Max(DateTime d1, DateTime d2)
{
    return d1 > d2 ? d1 : d2;
}

public static DateTime Min(DateTime d1, DateTime d2)
{
    return d2 > d1 ? d1: d2;
}

Note, if a class ends at 2 and the next starts at 2 there will be no overlap. Since you're talking about classes, I'm assuming this is how you want it.

Testing your example:

static void Main(string[] args)
{
    DateTime startClassZ = new DateTime(2017, 02, 09, 09, 00, 00);
    DateTime endClassZ = new DateTime(2017, 02, 09, 12, 00, 00);

    DateTime StartCurrent = new DateTime(2017, 02, 09, 10, 00, 00);
    DateTime EndCurrent = new DateTime(2017, 02, 09, 11, 00, 00);


    if(HasOverlap(startClassZ, endClassZ, StartCurrent, EndCurrent))
    {
        Console.WriteLine("clash");
    }
    else
    {
        Console.WriteLine("yay");
    }
    Console.Read();
}

I've added some quick tests for you:

public static void Test1()
{
    // Class A overlaps class B
    DateTime aStart = DateTime.Parse("2017-01-01T09:00:00");
    DateTime aEnd = DateTime.Parse("2017-01-01T10:00:00");

    DateTime bStart = DateTime.Parse("2017-01-01T09:30:00");
    DateTime bEnd = DateTime.Parse("2017-01-01T11:00:00");

    bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == true;
    Console.WriteLine($"1: {isCorrect}");
}

public static void Test2()
{
    // Class A "surrounds" class B
    DateTime aStart = DateTime.Parse("2017-01-01T09:00:00");
    DateTime aEnd = DateTime.Parse("2017-01-01T15:00:00");

    DateTime bStart = DateTime.Parse("2017-01-01T09:30:00");
    DateTime bEnd = DateTime.Parse("2017-01-01T11:00:00");

    bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == true;
    Console.WriteLine($"2: {isCorrect}");
}

public static void Test3()
{
    // Class B "surrounds" class A
    DateTime aStart = DateTime.Parse("2017-01-01T09:30:00");
    DateTime aEnd = DateTime.Parse("2017-01-01T11:00:00");

    DateTime bStart = DateTime.Parse("2017-01-01T09:00:00");
    DateTime bEnd = DateTime.Parse("2017-01-01T15:00:00");

    bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == true;
    Console.WriteLine($"3: {isCorrect}");
}

public static void Test4()
{
    // Class A is before Class B
    DateTime aStart = DateTime.Parse("2017-01-01T09:00:00");
    DateTime aEnd = DateTime.Parse("2017-01-01T11:00:00");

    DateTime bStart = DateTime.Parse("2017-01-01T11:00:00");
    DateTime bEnd = DateTime.Parse("2017-01-01T12:00:00");

    bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == false;
    Console.WriteLine($"4: {isCorrect}");
}

public static void Test5()
{
    // Class A is after Class B
    DateTime aStart = DateTime.Parse("2017-01-01T12:00:00");
    DateTime aEnd = DateTime.Parse("2017-01-01T14:00:00");

    DateTime bStart = DateTime.Parse("2017-01-01T11:00:00");
    DateTime bEnd = DateTime.Parse("2017-01-01T12:00:00");

    bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == false;
    Console.WriteLine($"5: {isCorrect}");
}

public static void Test6()
{
    // Class B overlaps class A
    DateTime bStart = DateTime.Parse("2017-01-01T09:00:00");
    DateTime bEnd = DateTime.Parse("2017-01-01T10:00:00");

    DateTime aStart = DateTime.Parse("2017-01-01T09:30:00");
    DateTime aEnd = DateTime.Parse("2017-01-01T11:00:00");

    bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == true;
    Console.WriteLine($"6: {isCorrect}");
}

static void Main()
{
    Test1();
    Test2();
    Test3();
    Test4();
    Test5();
    Test6();
    Console.Read();
}
ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86
  • But why do have 3 set of codes? I understand the first two set but what about the 3rd set? – Tim Jones Feb 10 '17 at 12:33
  • @TimJones What? The first one is the code you need, the other is your example, and the third is a set of logical test cases which should all return true to prove it works. Especially when other people answering seem to think it doesn't work, it seems wise to prove it does. – ProgrammingLlama Feb 10 '17 at 12:35
  • Any reason for the downvote, mysterious downvoter. Please provide a test case where the function doesn't work. – ProgrammingLlama Feb 10 '17 at 12:39
  • No!!! it is actually working. well done mate... there is only one problem (however user cannot enter start date before finish date) but if we have 15:00:00 to13:00:00 it will give wrong answer. therefore, it will allow student being assigned. by the way i did not give you a downvote – Tim Jones Feb 10 '17 at 13:19
  • @TimJones I've added another example with a couple of methods to choose the max/min date values so that the check doesn't care about the order of start/end. – ProgrammingLlama Feb 10 '17 at 13:31
  • john how can I have your email address? also, the new code you have provided is ok but still give out the same answer ( however it is ok as I am happy with the code you have provided). Thank you – Tim Jones Feb 10 '17 at 14:10
0

You are offering three possibilities:

A) Whole currentClass is in zClass

B) Start of currentClass is in zClass

C) End of currentClass is in zClass

I would like to point out that A) means the same as B) and C) combined, thus does not need a special attention. Moreover, if you will try and draw a simplest sketch in your mind (or on paper) of duration of classes, then the conditions will pop themselves out quite naturally as:

clash = (endOfCurrentClass > startOfZClass) || (startOfCurrentClass < endOfZClass)

What remains is to think about equivalence (e.g. endOfCurrentClass == startOfZClass) but this depends on other constraints (does class-times incorporate pauses in between classes? Are they in a same room? ...). However this is another problem.

Rao
  • 802
  • 8
  • 19
0

You need double check: classZ with current in this case

DateTime startClassZ = new DateTime(2017, 02, 09, 09, 00, 00);
DateTime endClassZ = new DateTime(2017, 02, 09, 12, 00, 00);

DateTime startCurrent = new DateTime(2017, 02, 10, 10, 00, 00);
DateTime endCurrent = new DateTime(2017, 02, 09, 11, 00, 00);

and current with classZ

DateTime startClassZ = new DateTime(2017, 02, 09, 09, 00, 00);
DateTime endClassZ = new DateTime(2017, 02, 09, 12, 00, 00);

DateTime startCurrent = new DateTime(2017, 02, 08, 10, 00, 00);
DateTime endCurrent = new DateTime(2017, 02, 09, 13, 00, 00);

Full code is here:

DateTime startClassZ = new DateTime(2017, 02, 09, 09, 00, 00);
DateTime endClassZ = new DateTime(2017, 02, 09, 12, 00, 00);

DateTime startCurrent = new DateTime(2017, 02, 08, 10, 00, 00);
DateTime endCurrent = new DateTime(2017, 02, 09, 13, 00, 00);


bool ClashCurrentStart = startClassZ < startCurrent && startCurrent < endClassZ;
bool ClashCurrentEnd = startClassZ < endCurrent && endCurrent < endClassZ;
//bool ClashCurrentBetween = ClashCurrentStart && ClashCurrentEnd;

bool ClashClassZStart = startCurrent < startClassZ && startClassZ < endCurrent;
bool ClashClassZEnd = startCurrent < endClassZ && endClassZ < endCurrent;
//bool ClashClassZBetween = ClashClassZStart && ClashClassZEnd;


bool Clash = ClashCurrentStart || ClashCurrentEnd || ClashClassZStart || ClashClassZEnd;

if (!Clash)
{
    //Assign
}
else // Clash
{
    //Select Another Student
}
Hossein Golshani
  • 1,847
  • 5
  • 16
  • 27