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

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.

Related

OCaml : recursive function dealing with parity between list elements and an int

This function should take two arguments a list and an int. if an element of the list and the number “a” parity is equal then they’d have to be summed, else the two numbers should be subtracted.
The calculation should be done in this order :
At the beginning, the residual value r is the value of a,
Each element e of lst (taken in the order given by the list) affects the residual value: if e and r are of the same parity (both odd or both even) then the new r’ is equal to the sum of r + e, if not then it should be equal to the subtraction of r - e,
The last r is the result expected.
To put this into an example:
par [4;7;3;6] 5
should return -1, it would work as follows :
5 and 4 have a different parity so we subtract -> 5 - 4 = 1
1 and 7 are both odd, so we add them together -> 1 + 7 = 8
8 and 3 have a different parity -> 8 - 3 = 5
Finally, 5 and 6 have different parity -> 5 - 6 = -1
I have thought of something like this below :
let rec par lst a =
match lst with
| [] -> 0
| h::t -> if (h mod 2 == 0 && a mod 2 == 0) || (h mod 2 == 1 && a mod 2 == 1) then a + h
| h::t -> if (h mod 2 == 0 && a mod 2 == 1) || (h mod 2 == 1 && a mod 2 == 0) then a - h :: par t a ;;
EDIT1 : Here is the error I get from the compiler :
Line 4, characters 83-88: Error: This expression has type int but an
expression was expected of type unit because it is in the result of a
conditional with no else branch
The idea is to build this function using no more than the following predefined functions List.hd, List.tl et List.length.
What is disturbing in my proposition above and how to remediate it? Anyone can help me resolve this, please?
EDIT 2:
I was able to do what is needed with if...then... else syntax (not the best I know for OCaml) but I personally have more difficulties sometimes understanding the pattern matching. Anyhow here's what I got :
let rec par lst a = (* Sorry it might hurt some sensible eyes *)
if List.length lst = 0 then a
else
let r = if (List.hd lst + a) mod 2 == 0 then (a + (List.hd lst))
else (a - (List.hd lst)) in
par (List.tl lst) r ;;
val par : int list -> int -> int = <fun>
Suggestions and help to put it into a pattern-matching syntax are welcomed.
Your code doesn't compile. Did you try compiling it? Did you read the errors and warnings produced by the compiler? Could you please add them to your question?
A few comments about your code:
| h::t -> if ... then ... should be | h::t when ... -> ...;
(h mod 2 == 0 && a mod 2 == 0) || (h mod 2 == 1 && a mod 2 == 1) can be simplified to (h - a) mod 2 == 0;
The compiler likes to know that the matching was exhaustive; in particular, you don't need to repeat the test in the third line of the matching (the third line will only be read if the test was false in the second line);
You are missing the recursive call in the second line of the matching;
In the third line of the matching, you are returning a list rather than a number (the compiler should have explicitly told you about that type mismatch!! did you not read the compiler error message?);
In the first line of the matching, in case the list is empty, you return 0. Are you sure that 0 is the value you want to return, when you've reached the end of the list? What about the residual value that you have calculated?
Once you have fixed this version of your code as a recursive function, I recommend trying to write a code solving the same problem using List.fold_left, rather than List.hd and List.tl as you are suggesting.
When I first wrote my answer, I included a fixed version of your code, but I think I'd be doing you a disservice by handing out the solution rather than letting you figure it out.

Simplify "all or nothing" boolean expression

Can a "all or nothing" boolean expression be simplified? Suppose I have three values, A, B, C, and want to determine if all three are true, or all three are false. Like a XOR gate, but with N values.
Can this statement be simplified?
(A && B && C) || !(A || B || C)
All true or all false basically means that all should be the same. So if the equality comparison is acceptable you can do this:
A == B && B == C

The type signature for `isprime' lacks an accompanying binding

I have this code:
esprimo :: Int->Bool
esPrimo x = if length (div x x) == 2 then True else False
But I pulled the error is above
In addition to what sibi said, I think what you are trying to do is this:
isPrime :: Int -> Bool
isPrime x = if length [d | d <- [1..x], x `mod` d == 0] == 2 then True else False
this is basically the direct translation of the mathematical concept of beeing prime into Haskell.
As you don't need the if as it checks the same == already returns a bit more readable might be:
isPrime :: Int -> Bool
isPrime x = length divisors == 2
where divisors = [d | d <- [1..x], x `isMultipleOf` d]
isMultipleOf m n = m `mod` n == 0
Please note that this is of course not the most performant prime-test.
The exact reason for your error is because of the different cases you have used in the type signature and the type definition:
esprimo :: Int -> Bool -- p should be capital here to work.
esPrimo x = if length (div x x) == 2 then True else False
Haskell is case sensitive, so esprimo and esPrimo are different. That being said there is other type error in your code: the type of div is div :: Integral a => a -> a -> a, so it returns a and you are applying length function on it. But length function only accepts list i.e [a] and not a which will produce you type error.

Haskell--Defining function with Guards

I am fairly new to Haskell and am working on an assignment simulating checkers currently. I am having a bit of difficulty determining the proper method of conditionally checking an expression and updating the values of a tuple. I have a function called getPos that will return the Char at a specific location on the board to determine its state.
onemove :: (Int,[Char],[[Char]],(Int,Int)) -> (Int,[Char],[[Char]])
onemove (a,b,c,(d,e))
| e <= 0 =(a-30,b,c)
| e > 50 =(a-30,b,c)
| (((posTo == 'r') || (posTo == 'i')) &&((posFrom == 'w')||(posFrom == 'k'))) == 'true' =(a-20,b,c)
| (((posTo == 'w')||(posTo == 'k')) && ((posFrom == 'r') || (posFrom == 'i')))== 'true' =(a-20,b,c)
| otherwise = (1000,b,c)
where posFrom = getPos (d, c)
posTo = getPos (e,c)
Is it correct to use a function to define a variable within my where clause? I receive the following error on my last line:
parse error on input `='
Your immediate problem is mostly just caused by indentation. Guards need to be indented w.r.t the definition they're associated with.
onemove :: (Int,[Char],[[Char]],(Int,Int)) -> (Int,[Char],[[Char]])
onemove (a,b,c,(d,e))
| e <= 0 =(a-30,b,c)
| e > 50 =(a-30,b,c)
| (((posTo == 'r') || (posTo == 'i')) &&((posFrom == 'w')||(posFrom == 'k'))) =(a-20,b,c)
| (((posTo == 'w')||(posTo == 'k')) && ((posFrom == 'r') || (posFrom == 'i'))) =(a-20,b,c)
| otherwise = (1000,b,c)
where posFrom = getPos (d, c)
posTo = getPos (e,c)
Notice I also removed the == 'true' in your original code. That was wrong for three separate reasons.
Single quotes denote a Char. Double quotes for String.
You can't compare a Boolean value to a String just because that String
happens to say "true". You would have to say == True.
There's no reason to ever write bool == True, because that's
exactly the same as just writing bool.
Also, a, b, c, and (d,e) should probably all be separate arguments, not a single tuple. You lose all the advantages of currying that way.

Reducing a boolean expression

I am having an expression, suppose,
a = 1 && (b = 1 || b != 0 ) && (c >= 35 || d != 5) && (c >= 38 || d = 6)
I expect it to be reduced to,
a = 1 && b != 0 && (c >= 38 || d = 6)
Does anyone have any suggestions? Pointers to any algorithm?
Nota Bene: Karnaugh Map or Quine-McCluskey are not an option here, I believe. As these methods don't handle grey cases. I mean, expression can only be reduced as far as things are like, A or A' or nothing, or say black or white or absense-of-colour. But here I'm having grey shades, as you folks can see.
Solution: I have written the program for this in Clojure. I used map of a map containing a function as value. That came pretty handy, just a few rules for a few combinations and you are good. Thanks for your helpful answers.
I think you should be able to achieve what you want by using Constraint Handling Rules. You would need to write rules that simplify the OR- and AND-expressions.
The main difficulty would be the constraint entailment check that tells you which parts you can drop. E.g., (c >= 35 || d != 5) && (c >= 38 || d = 6) simplifies to (c >= 38 || d = 6) because the former is entailed by the latter, i.e., the latter is more specific. For the OR-expressions, you would need to choose the more general part, though.
Google found a paper on an extension of CHR with entailment check for user-defined constraints. I don't know enough CHR to be able to tell you whether you would need such an extension.
I believe these kinds of things are done regularly in constraint logic programming. Unfortunatly I'm not experienced enough in it to give more accurate details, but that should be a good starting point.
The general principle is simple: an unbound variable can have any value; as you test it against inequalities, it's set of possible values are restricted by one or more intervals. When/if those intervals converge to a single point, that variable is bound to that value. If, OTOH, any of those inequalities are deemed unsolvable for every value in the intervals, a [programming] logic failure occurs.
See also this, for an example of how this is done in practice using swi-prolog. Hopefully you will find links or references to the underlying algorithms, so you can reproduce them in your platform of choice (maybe even finding ready-made libraries).
Update: I tried to reproduce your example using swi-prolog and clpfd, but didn't get the results I expected, only close ones. Here's my code:
?- [library(clpfd)].
simplify(A,B,C,D) :-
A #= 1 ,
(B #= 1 ; B #\= 0 ) ,
(C #>= 35 ; D #\= 5) ,
(C #>= 38 ; D #= 6).
And my results, on backtracking (line breaks inserted for readability):
10 ?- simplify(A,B,C,D).
A = 1,
B = 1,
C in 38..sup ;
A = 1,
B = 1,
D = 6,
C in 35..sup ;
A = 1,
B = 1,
C in 38..sup,
D in inf..4\/6..sup ;
A = 1,
B = 1,
D = 6 ;
A = 1,
B in inf.. -1\/1..sup,
C in 38..sup ;
A = 1,
D = 6,
B in inf.. -1\/1..sup,
C in 35..sup ;
A = 1,
B in inf.. -1\/1..sup,
C in 38..sup,
D in inf..4\/6..sup ;
A = 1,
D = 6,
B in inf.. -1\/1..sup.
11 ?-
So, the program yielded 8 results, among those the 2 you were interested on (5th and 8th):
A = 1,
B in inf.. -1\/1..sup,
C in 38..sup ;
A = 1,
D = 6,
B in inf.. -1\/1..sup.
The other were redundant, and maybe could be eliminated using simple, automatable logic rules:
1st or 5th ==> 5th [B == 1 or B != 0 --> B != 0]
2nd or 4th ==> 4th [C >= 35 or True --> True ]
3rd or 1st ==> 1st ==> 5th [D != 5 or True --> True ]
4th or 8th ==> 8th [B == 1 or B != 0 --> B != 0]
6th or 8th ==> 8th [C >= 35 or True --> True ]
7th or 3rd ==> 3rd ==> 5th [B == 1 or B != 0 --> B != 0]
I know it's a long way behind being a general solution, but as I said, hopefully it's a start...
P.S. I used "regular" AND and OR (, and ;) because clpfd's ones (#/\ and #\/) gave a very weird result that I couldn't understand myself... maybe someone more experienced can cast some light on it...