In SWI-Prolog, I can write that
:- use_module(library(clpfd)).
and(A,B):- A , B.
And I get:
?- and((X #= 4), (X #> 3)).
X = 4.
?- and((X #= 4), (X #< 3)).
false.
?- and((X #< 4), (X #> 3)).
false.
?- and((X #< 5), (X #> 3)).
X = 4.
?- and((X #< 5), (X #< 3)).
X in inf..2.
Is it possible to write that in Rust using std::cmp ?
For now, I'll settle for the answer true, false, without instantiating the X variable.
Thank you for any tip.
Related
I'm tackling a simple leap year exercise in Haskell, and I'd like to make my solution point-free. Starting from this:
isLeapYear :: Integer -> Bool
isLeapYear year = divisibleBy 400 year || divisibleBy 4 year && not (divisibleBy 100 year)
where
divisibleBy m y = (== 0) $ flip mod m y
I tried using liftA3, with a function doing (x || (y && z)) following this, but the tests do not finish and I don't know why.
So, then, I have 3 questions:
Do you have any pointers as to how could I achieve this?
In my first solution, what's preventing divisibleBy to be point-free? (Typechecker complains if I remove the arguments)
As I mentioned before, I tried something like liftA3 (\x y z -> x || (y && z)) (divisibleBy 400) (divisibleBy 4) (indivisibleBy 100), but the tests hang. Why does that happen? I'm not getting how liftA3 works.
Thanks a lot for your help.
In my first solution, what's preventing divisibleBy to be point-free? (Typechecker complains if I remove the arguments)
You might think that these are equivalent (I am writing flipmod as one function for simplicity's sake):
divisibleBy m y = (== 0) $ flipmod m y
divisibleBy' = (== 0) . flipmod
But in actuality, divisibleBy' is now an (invalid) function that takes an argument x and then compares flipmod x to zero:
((==0) . flipmod) 5
→ (==0) (flipmod 5)
→ flipmod 5 == 0
Comparing a function (flipmod 5) and a number is certainly no good.
You'd need to write something more sophisticated, namely:
divisibleBy = ((== 0) .) . flipmod
So that now, properly:
divisibleBy 5 6
→ (((== 0) .) (flipmod 5)) 6
→ ((== 0) . flipmod 5) 6
→ (== 0) (flipmod 5 6)
→ flipmod 5 6 == 0
This construction (f.).g can also be written as ((.).(.)) f g, and that operator is sometimes called dot. I don't think writing things like this is a very good idea, but it might answer your question.
The tests hang. Why does that happen?
I don't know. You'll probably need to provide an mcve here, because this works fine for me as a full program:
import Control.Applicative
isLeapYear :: Integer -> Bool
isLeapYear = liftA3 (\x y z -> x || (y && z))
(divisibleBy 400)
(divisibleBy 4)
(not . divisibleBy 100)
where
divisibleBy m y = (== 0) $ flip mod m y
main = print (filter isLeapYear [1850..1950])
Let S be the subset of the set of ordered pairs of integers defined recursively by
Basis step: (0, 0) ∈ S.
Recursive step: If (a,b) ∈ S,
then (a,b + 1) ∈ S, (a + 1, b + 1) ∈ S, and (a + 2, b + 1) ∈ S.
List the elements of S produced by the first four application
def subset(a,b):
base=[]
if base == []:
base.append((a,b))
return base
elif (a,b) in base:
base.append(subset(a,b+1))
base.append(subset(a+1,b+1))
base.append(subset(a+2,b+1))
return base
for number in range(0,5):
for number2 in range(0,5):
print(*subset(number,number2))
The output is
(0, 0)
(0, 1)
(0, 2)
(0, 3)
(0, 4)
(1, 0)
(1, 1)
(1, 2)
(1, 3)
(1, 4)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 0)
(3, 1)
(3, 2)
(3, 3)
(3, 4)
(4, 0)
(4, 1)
(4, 2)
(4, 3)
(4, 4)
But the correct answer is more than what I got.
(0, 1), (1, 1), and (2, 1) are all in S. If we apply the recursive step to these we add (0, 2), (1, 2), (2, 2), (3, 2), and (4, 2). The next round gives us (0, 3), (1, 3), (2, 3), (3, 3), (4, 3), (5, 3), and (6, 3). And a fourth set of applications adds (0,4), (1,4), (2,4), (3,4), (4,4), (5,4), (6,4), (7,4), and (8,4).
What did I do wrong with my code?
Is this what you want ? Based on the result you wanted :
def subset(a):
#Returns a list that contains all (i, a + 1) from i = 0 to i = (a + 1) * 2 + 1
return [(i, a + 1) for i in range((a + 1) * 2 + 1)]
setList = []
for i in range(4):
setList += subset(i) #Fill a list with subset result from i = 0 -> 3
print(setList)
If you want to use a recursive function, you can do that too :
def subset(a, b):
if a < b * 2:
#Returns a list that contains (a, b) and unzipped result of subset(a + 1, b)
#Otherwise it would add a list in the list
return [(a, b), *subset(a + 1, b)]
else:
return [(a, b)] #If deepest element of recursion, just return [(a, b)]
setList = []
for i in range(5):
setList += subset(0, i)
print(setList)
I am new to Haskell and I am working some exercises in the craft of functional programming.
Below is an example of how to specify finding the maximum of two numbers:
max :: Integer -> Integer -> Integer
max x y
| x >= y = x
| otherwise = y
max' :: Integer -> Integer -> Integer
max' x y =
if x >= y then x else y
prop_max1 :: Integer -> Integer -> Bool
prop_max1 x y =
x <= max x y && y <= max' x y
I want to use the prop_max1 function so I write:
prop_max1 (max 1 2) (max' 1 2)
which returns True.
But if I write
prop_max1((max 1 2) (max' 1 2))
this doesn't work and I get an error along the lines of couldn't match expected type. Why can I not write it this way?
If you're familiar with Python, Ruby, Java or C#, functions are generally invoked as this:
func(a, b)
While in Haskell, F#, and OCaml they're invoked like this:
func a b
This means one term followed by another in Haskell a-la a b is a function call a-la a(b) in Python.
What this basically boils down to is this:
prop_max1 (max 1 2) (max' 1 2) -- is the same as prop_max1(max(1, 2), max'(1, 2))
While
prop_max1 ((max 1 2) (max' 1 2)) -- is the same as prop_max1(max(1, 2)(max'(1, 2))))
Notice how prop_max1(max(1, 2), max'(1, 2)) and prop_max1(max(1, 2)(max'(1, 2)))) differ in terms of () placement.
Side note: A function call that looks like this: f(a)(b) is essentially the same as this:
g = f(a)
g(b)
But written as a single statement, meaning max(1, 2)(max'(1, 2)) is the same as
m1 = max(1, 2)
m1(max'(1, 2))
Same holds for Haskell, where (max 1 2) (max' 1 2) is the same as:
m1 = max 1 2
m1 (max' 1 2)
Anyway, it's probably easier to see if we remove the 1 and 2, making it prop_max1(max, max') vs prop_max1(max(max')).
In the first case max and max' are the first and second argument of prop_max1 respectively, while in the second case max' is max's returned function's argument.
That's why prop_max1 (max 1 2) (max' 1 2) works, and prop_max1 ((max 1 2) (max' 1 2)) doesn't.
prop_max1((max 1 2) (max' 1 2))
Is the same as:
prop_max1 ((max 1 2) (max' 1 2))
Which you might write, in a language like Python or Java which uses () as function invocation, as:
prop_max1(max(1, 2)(max'(1, 2)))
When you put the parens like that, you're saying that you want to invoke the return value of max 1 2 with the return value of max' 1 2. But max 1 2 doesn't return a function, so that doesn't typecheck.
Haskell uses the space character to mean function invocation, and parens are only used for grouping expressions. (Er, and for tuples.)
Why does 2(*i.)5 evaluate to 0 2 4 6 8 ?
It's clear that 2*i.5 does, but the () creates a hook and evaluating from right to left it seems we get
(*i.)5 == 0 5 10 15 20
and 2 won't act on that list -- so where am I going wrong ?
2 (* i.) 5, is a dyadic hook, which translates to 2 * (i. 5).
(* i.) 5, is a monadic hook, which translates to 5 * (i. 5).
The dyadic hook, x (u v) y is equivalent to x u (v y), which is the same as x u v y.
The monadic hook, (u v) y is equivalent to y u (v y), which is the same as y u v y.
http://www.jsoftware.com/jwiki/Vocabulary/hook
x (u v) y <--> x u (v y) for dyadic hooks.
A use might be to reshape y into the shape x as shown at
http://www.jsoftware.com/jwiki/Vocabulary/hook
[t=.i. 3 2
0 1
2 3
4 5
2 3 ($ ,) t
0 1 2
3 4 5
t = True
f = False
anzNachbarn :: [[Bool]] -> (Integer,Integer) -> Integer
anzNachbarn a (x,y)
| x < 0 || y < 0=-1
| otherwise ... here comes the comparison
This is an example matrix:
[[True,False,False],
[True,False,False],
[False,True,False]]
here i need an algorithm, where it calculates (for given x and y position in matrix) its neighbours (only "true" neighboors) and increase it by 1 for each true neighboor.
For example: anzNachbarn [[True,False,False],[True,False,False],[False,True,False]] (0,1)
returns 2 back.
:Edit
I still have a question how can I now implement each component of the result matrix, the number of named elements with True neighboring fields indicates the corresponding component of the argument matrix Applies to
[[True, False, False],
[True, False, False],
[False, True , False]]
the function func returns the results matrix [[1,2,0], [2,3,1], [2,1,1]]
with signature func :: [[Bool]] -> [[Integer]]
have you got any idea about this ?
You almost certainly want to use an array (from Data.Array) in this situation, since looking up an item in a list by its index is very slow.
Here's a quick implementation using Array:
countNeighbors :: Array (Int, Int) Bool -> (Int, Int) -> Int
countNeighbors board (x, y) = length
[ (x', y')
| x' <- [x - 1, x, x + 1]
, y' <- [y - 1, y, y + 1]
, x' /= x || y' /= y
, inRange (bounds board) (x', y')
, board ! (x', y')
]
This is a list comprehension with two generators and three guards. The generators simply give us the indices of the nine positions in a three-by-three square centered at (x, y) (you'll need a minor change if you don't want neighbors at the corners to be considered).
The first guard (x' /= y') ignores (x, y) itself. The second throws out positions that aren't within the bounds of the array. The final guard throws out positions that are in the array but have a False value.
So we now have a list of indices for the neighbors with True values. The length of this list is the desired count.
This is ugly, but seems to work...
anzNachbarn :: [[Bool]] -> (Int,Int) → Integer
anzNachbarn a (x,y)
| x < 0 || y < 0 = -1
| otherwise = sum [v x' y' | x' <- [max 0 (x-1)..x+1],
y' <- [max 0 (y-1)..y+1],
x ≠ x' || y ≠ y' ]
where v i j = if j >= length a
|| i >= length (a !! 0)
|| not (a !! j !! i)
then 0 else 1
[Edit]
In order to convert the whole array, you can write the equally ugly
conv a = [line y | y <- [0 .. (length a) - 1]]
where line y = [anzNachbarn a (x,y) | x <- [0 .. ((length (a !! 0) - 1)]]
Note that the performance of this is terrible.