Date Range Overlap with Nullable Dates - language-agnostic

I'm looking for an extended answer to the question asked here:
Determine Whether Two Date Ranges Overlap
where any of the dates in either date range can be null. I've come up with the following solution, but I'm not sure if it can be simplified further.
(StartA == NULL || StartA <= EndB) &&
(EndA == NULL || EndA >= StartB) &&
(StartB == NULL || StartB <= EndA) &&
(EndB == NULL || EndB >= StartA)
Assuming:
DateTime ranges of StartA to EndA and StartB to EndB
EDIT: Sorry I quickly threw the above logic together, which seems to fail when either range's start and end dates are NULL. See David's solution below for a better & well-explained approach.

This case can be handled by a slight generalization of Charles Bretana's excellent answer to that question.
Let CondA Mean DateRange A Completely After DateRange B (True if StartA > EndB)
Let CondB Mean DateRange A Completely Before DateRange B (True if EndA < StartB)
In this case, assuming you want a null date to represent "no starting/ending bound," the conditions are modified. For CondA, for instance, in order for DateRange A to be completely after DateRange B, DateRange A must have a defined starting time, DateRange B must have a defined ending time, and the starting time of A must be after the ending time of B:
CondA := (StartA != null) && (EndB != null) && (StartA > EndB)
CondB is the same with A and B switched:
CondB := (StartB != null) && (EndA != null) && (StartB > EndA)
Continuing,
Then Overlap exists if Neither A Nor B is true
Overlap := !(CondA || CondB)
and
Now deMorgan's law, I think it is, says that
Not (A Or B) <=> Not A And Not B
Overlap == !CondA && !CondB
== ![(StartA != null) && (EndB != null) && (StartA > EndB)] &&
![(StartB != null) && (EndA != null) && (StartB > EndA)]
== [(StartA == null) || (EndB == null) || (StartA <= EndB)] &&
[(StartB == null) || (EndA == null) || (StartB <= EndA)]
I think this is actually a bit more robust than the solution you developed, because if EndB == NULL but StartA is not null, your first condition will wind up comparing StartA <= NULL. In most languages I'm familiar with, that's an error condition.

Without considering nulls, answer is
(StartA <= EndB) and (EndA >= StartB)
(see this for detailed explanation)
considering nulls for start and end dates,
Using C Ternary operator syntax:
(StartA != null? StartA: EndB <= EndB != null? EndB: StartA) &&
(EndA != null? EndA: StartB >= StartB != null? StartB: EndA)
Or C# 4.x style null operators:
(StartA??EndB <= EndB??StartA) && (EndA??StartB >= StartB??EndA)
or in SQL:
(Coalesce(StartA, EndB) <= Coalesce(EndB, StartA))
And (Coalesce(EndA, StartB ) <= Coalesce(StartB , EndA))
Explanation:
consider the non-null answer:
(StartA <= EndB) and (EndA >= StartB)
Now, consider that StartA is null, indicating that date range A has existed since beginning of time (BOT). In that case, DateRangeB can never be before DateRangeA. So first condition, (StartA(BOT) <= EndB) will ALWAYS be true, no matter what EndB is. So change this expression so that instead of comparing null with EndB, when StartA is null, compare EndB with itself
No matter what EndB is, the expression EndB <= EndB will be true.
(We could create variables to represent BOT and EOT, but this is easier).
Do the same for other three input variables.

That is probably as 'simple' as you can get it, although I haven't actually proven it.
It probably isn't worth it to simplify further, since that block ends up being about 8 operations in the worst case (4 on average thanks to short-circuit evaluation).

All answers are based if the condition is true. I'would like to add some note here.
1- The DateTime variable type is a struct and you can not set it to null unless that you are using nullable type like "DateTime?"
2- To find the overlap range follow the following steps
DateTime? StartOverLap = null,EndOverLap = null;
if (StartA != null && StartB != null)
{
StartOverLap = StartA > StartB ? StartA : StartB;
}
else if (StartA == null && StartB != null)
{
StartOverLap = StartB;
}
else if (StartA != null && StartB == null)
{
StartOverLap = StartA;
}
if (EndA != null && EndB != null)
{
EndOverLap = EndA < EndB ? EndA : EndB;
}
else if (EndA == null && EndB != null)
{
EndOverLap = EndB;
}
else if (EndA != null && EndB == null)
{
EndOverLap = EndA;
}
if (StartOverLap != null && EndOverLap == null)
{
if (EndOverLap < StartOverLap)
{
StartOverLap = null;
EndOverLap = null;
}
}

Related

Php How To Echo Null from MySql

I have the following script that I use for part of my count in payment_status from Mysql. I have seen some examples of this online, but I can't seem to figure out how to make this work WITH a Null instance. Any insight would be appreciated.
Note: The way I have it now doesn't work when Null is in the database. I'm guessing because that isn't an inserted word?
Objective: To add $row['payment_status'] == "Null" to this with the rest of the script.
if($row['payment_status'] == "Completed" || $row['payment_status'] == "Free" || $row['payment_status'] == "Cancelled" || $row['payment_status'] == "Null")
if payment_status column has default value NULL, Then try below change
if($row['payment_status'] == "Completed" || $row['payment_status'] == "Free" || $row['payment_status'] == "Cancelled" || $row['payment_status'] == null)

Why does ocaml ignore one function and does all the rest?

So i have this code, which its supposed to give me an yes or no answer. It doesnt give me any errors yet it seems like it doesnt enter my rec func function, which makes it give the wrong answer. Would much apreciate the help
let n = read_int()
let () =
let valor = ref true in
let i = ref 1 in
let a = ref 0 in
let b = ref 0 in
let c = ref 0 in
let e = ref 1 in (* 1 = variavel 0 = conetor*)
let rec func() =
i:=!i+1;
let () = Printf.printf "i" in
let r = read_line() in
if r="(" then a:=!a+1;
if r=")" then b:=!b+1;
if (r=")" && !e=1) then valor:=false;
if (r="(" && !e=0) then valor:=false;
if !b > !a then valor:=false;
if ((r="&" || r="|" || r="->" || r="<->")&&(!c>0 || !e=1)) then valor:=false;
if (r="&" || r="|" || r="->" || r="<->") then e:=1;
if r="!" then c:=!c+1;
if (r<>"!" && r<>"(" && r<>")" && r<>"&" && r<>"|" && r<>"->" && r<>"<->" && !e=0) then valor:=false;
if (r<>"!" && r<>"(" && r<>")" && r<>"&" && r<>"|" && r<>"->" && r<>"<->") then e:=0;
if (r<>"!" && r<>"(" && r<>")" && r<>"&" && r<>"|" && r<>"->" && r<>"<->" && !c>0) then c:=0;
if !i = n-1 then () else func()
in
if !e=1 then valor:=false;
if !c>0 then valor:=false;
if !a <> !b then valor:=false;
let msg = if !valor then "YES" else "NO" in
Printf.printf "%s \n" msg
Just skimming your code I see a definition of a function named func but no calls to this function (other than from inside the function).
I'd say you need to actually call func. That should get you started.

Are there any languages where "A == B == C" works where A, B, and C are all non-boolean types?

Without thinking in C# I tried to compare three objects. It failed, and explained why [since (typeof("A == B") == bool) and (typeof(C) != bool) it was an invalid comparison]. Do any languages support short circuiting logic like this?
There are several languages that let you do multiple conditionals like this.
But the first I could think of was Python
Example:
a = 5
b = 5
c = 5
if(a == b == c):
print "yes"
else:
print "no"
Will print "yes" in the console.
It works with other types as well, like this:
a = ["A",1]
b = ["A",1]
c = ["A",1]
d = ["A",1]
if(a == b == c == d):
print "YES"
else:
print "NO"
Now the reason for C# (And other C like languages) doesn't support this is that they evaluate comparison expressions down to a true / false, so what your compiler sees when you do (5 == 5 == 5) is ((5 == 5) == 5) which yields: (true == 5) which invalid since you cannot compare a Boolean to an integer, you could actually write (a == b == c) if c is a Boolean, so (5 == 5 == true) would work.

Boolean negation

One of my exam questions reads:
! ( ! ( a != b) && ( b > 7 ) )
The choices:
a) (a != b) || (b < 7)
b) (a != b) || (b <= 7)
c) (a == b) || (b <= 7)
d) (a != b) && (b <= 7)
e) (a == b) && (b > 7)
Initially, I thought it would be D. This is incorrect, and I realize why. I don't understand how the logical negation operator reverses && and greater than/less than. I believe I have narrowed it down to the first two. Is there any instance > would change to <= ?
Is there any instance > would change to <= ?
Answer: every time you negate it.
Consider x > 1. The negation of this is clearly x <= 1. If you simply negate it as x < 1 then neither case covers the x == 1 case.
That being said, the given boolean ! ( ! ( a != b) && ( b > 7 ) ) can be decomposed as follows:
Given:
! ( !(a != b) && (b > 7))
Negate a != b:
! ((a == b) && (b > 7))
Distribute the !:
!(a == b) || !(b > 7)
Negate a==b:
(a != b) || !(b > 7)
Negate b>7:
(a != b) || (b <= 7)
The answer is, therefore, B.
The answer should be B. This is because the negation next to the (a != b) is evaluated first, then you distribute the outside negation to the entire proposition.
Using DeMorgan's Laws, the && will switch to ||. Similarly, != becomes ==, and > becomes <=.
!(!(a != b) && (b > 7))
!((a == b) && (b > 7))
(a != b) || (b <= 7)
! ( ! ( a != b) && ( b > 7 ) )
= ! ( (a = b) && (b > 7))
= (a != b) || (b <= 7)
answer is B.
to understand this :
! ( ! ( a != b) && ( b > 7 ) )
Lets break it into parts.
Part dummy: (a!=b)
Part X: !dummy
Part Y: (b>7)
Now !X = double negate of dummy => dummy => (a!=b)
!Y = !(b>7) => b should not be greater than 7 => b should be less than or equal to 7 => (b<=7)
Now problem left is how && becomes ||
So original question is: !( X && Y ) => should not be (X and Y) => it should be either negate of X or it should be negate of Y, because if instead of X it is ~X, the condition (X and Y) becomes false and hence !(X and Y) becomes true and hence original condition is achieved. Similarly for Y.
Firt apply the inner bracket Logical NOT (!):
!(!(a != b) && (b > 7)) becomes !((a == b) && (b > 7))
With De Morgan's Law we reverse the operators to their counterpart.
We change > to <= because the > operator does not include 7 itself or anything less, hence the <= is the only one that satisfies that condition.
Now the outer !:
When looking at truth tables (picture above), you'll notice that Logical AND (&&) and Logical OR (||) have opposite results when comparing 2 different boolean expressions (i.e. truth false, false true), hence when we apply the !, we reverse the && with ||. Finally we need to switch the == to != again.
All up, this produces
((a != b) || (b <= 7))

Why exactly the output of this expression return true

I have this expression:
!(1 && !(0 || 1))
The output returns 1 true. And that's ok. When I read the expression I came to the same conclusion before checking the output. But I would really appreciate if someone can explain to me why the returning value is true, that way, I will have a better understanding of boolean logic and how to implement better evaluators in my code.
Key observation here: ! is not, && is the "And" operator, and || is the "Inclusive Or" Operator.
What are you really asking when you say "why it's true?".
0 = false
1 = true
AND && table
0 0 -> 0
0 1 -> 0
1 0 -> 0
1 1 -> 1
OR || table
0 0 -> 0
0 1 -> 1
1 0 -> 1
1 1 -> 1
NOT ! table
0 -> 1
1 -> 0
With parentheses implying "do this first", the statement reduces using the tables above:
!(1 && !(0 || 1))
!(1 && !1)
!(1 && 0)
!0
1
But I don't know "why" it's true. Because that's what an AND operation is, what an OR operation is, and what a NOT operation is, and how reducing a statement works. With those definitions, it can't be another answer, so it's that answer. But you already know that, because you did it yourself and got the same answer ... so what does the question mean?
The innermost expression (0 || 1) is always true.
So !(0 || 1) is always false.
That leaves 1 && 0, which is always false.
So !(false) is always true.
Please forgive my freely intermixing 0/false and 1/true.
The human evaluator (:-).
Working through the expression, following order of operation:
!(1 && !(0 || 1))
= !(1 && !(1))
= !(1 && 0)
= !(0)
= 1
Step by step explanation:
1 = true
0 = false
Starting point: !(1 && !(0 || 1))
Lets start with the inner most expression: !(0 || 1)
Var1 || Var2 =
Var1 or Var2 =
If Var1 or Var2 is 1 or both are 1, the result is 1.
(0 || 1) = 0 or 1 -> the second variable is 1 so the expression is 1.
Insert the result (0 || 1) = 1 into Startingpoint: !(1 && !(1))
! = not (inverts the value of what is behinde)
!1 = 0
!0 = 1
!(0 || 1) = !(1) = 0
Insert the result !(1) = 0 into Startingpoint: !(1 && 0)
So we have !(1 && 0)
Var1 && Var2 = And =
the opossite of or =
If Var1 AND Var2 are both 1, the result is 1. Else it is 0 =
If Var1 or Var2 is 0, the result is zero
1 && 1 = 1
1 && 0 = 0
everything else: 0
So this is left: !(0)
Reminder: ! = not = inverts the expression behind it. So !0 = 1 (and !1 = 0)
This is 1. Or in your case: true
A good book for Beginner C programmers and people who want to learn about programming and logic in an easy, understandable way:
C for Dummies by Dan Godkins
!(1 && !(0 || 1))
Since, you have used parenthesis, evaluation takes place according to them.
First, evaluate innermost parenthesis.
0 || 1 => always true.
!(0 || 1) => !(true) => always false.
1 && !(0 || 1) => 1 && false => always false.
!(1 && !(0 || 1)) => !false => always true.