how do I compare 3 numbers in sml? - comparison

I am trying to come up with an function that takes 3 numbers as input and returns the largest number among them. My code is as following:
fun max3(a,b,c)=
if a >= b andalso a >= c then a
else if b >= a andalso b >= c then b
else if c >= a andalso c >= b then c;
However, I get the following errors:
Error: syntax error: inserting LET
Error: syntax error: replacing SEMICOLON with EQUALOP
Error: syntax error found at EOF
Did I do something wrong?

Every time you have an if, you need a then and an else. You can see how this becomes a problem by changing how you indent things.
fun max3(a,b,c)=
if a >= b andalso a >= c
then a
else if b >= a andalso b >= c
then b
else if c >= a andalso c >= b
then c
(* notice how there is no else here? *)
;
However, you can simplify the logic a lot:
fun max3(a,b,c)=
if a >= b andalso a >= c then
(* a is the largest of a, b and c *)
a
else
(* a is not the largest, so either b or c is the largest *)
if b >= c then
(* b is the largest of the two *)
b
else
(* c is the largest of the two *)
c

I would reduce this problem to an already solved one:
fun max3 (a, b, c) = max2 (a, max2 (b, c))
where
fun max2 (a, b) = if a > b then a else b
or simply
val max2 = Int.max

Related

How to parse? top down parsing not possible?

We have to parse this two words:
"abccdef"
"cabddc"
but with:
S->aBC
B->b|dc
C->aD
D-ac
?? How is it possible to parse this words with that? Is that a misstake in the task?
As posted in my comment above, if in doubt, code it.
Of course, you can see that the characters e and f are not part of the parser rules and as such, it is kind of obvious.
Unless, of course, I misunderstood your D production rule. This is one reason, why you should always explain a bit more about your problem. The D-ac might be a local convention for something, the majority of people here cannot interpret. I considered it a typo, meaning the same as D->ac.
Here is how it looks in Common Lisp:
(defun parser (s &optional (n (length s)) (i 0) (state :s))
(when i
(if (= i n)
i
(let ((c (char s i)))
(ecase state
(:s
(when (char-equal c #\a)
(parser s n (parser s n (+ i 1) :b) :c)))
(:b
(when (and (or (char-equal c #\b) (char-equal c #\d))
(< (+ i 1) n)
(char-equal (char s (+ i 1)) #\c))
(+ i 2)))
(:c
(when (char-equal c #\a)
(parser s n (+ i 1) :d)))
(:d
(when (and (char-equal c #\a)
(< (+ i 1) n)
(char-equal (char s (+ i 1)) #\c))
(+ i 2))))))))
I use the symbols :s, :b, :c and :d as state information (which production rule is the current state of the program).
Translated to pleb, which might be a language you have seen before, it looks like this (I only had pleb 3.9 and so there is no switch case syntax in that language, since someone added it later in version 3.10. My version also has no enum built into the language, so I just misused a class for that.):
class State:
S = 1
B = 2
C = 3
D = 4
def parser(s,i=0,state=State.S):
n=len(s)
if i == n:
return i
else:
c = s[i]
if state == State.S:
if c == 'a':
return parser(s,
parser(s,i+1,State.B),
State.C)
elif state == State.B:
if (c == 'b' or c == 'd') and (i+1)<n and s[i+1]== 'c':
return i+2
elif state == State.C:
if c == 'a':
return parser(s,i+1,State.D)
elif state == State.D:
if c == 'a' and (i+1)<n and s[i+1] == 'c':
return i+2
else:
raise ValueError("Unknown parser state!")
Running either of the above, with your given strings, they return NIL or nothing, respectively and if you run it with an input, which conforms to the grammar, e.g. "abcaac" or "adcaac", you get the length of the input as return value.

Pure pattern matching

I am building a function that counts of many times a character appears in a string after the nth position.
countCh ("aaabbbccc", 3, 'b')
val it: int = 2
In C, I would use an accumulator with a while loop. But I am trying to learn the F# functional face, where this approach is discouraged.
So I used guards to test few conditions and build the function:
let rec countCh (s:string, n:int, ch:char) =
match s, n, ch with
| (s, n, ch) when n > s.Length -> 0 //p1
| (s, n, ch) when n < 0 -> 0 //p2
| (s, n, ch) when s.[n] <> ch -> countCh(s, n + 1, ch) //p3
| (s, n, ch) when s.[n] = ch -> 1 + countCh(s, n + 1, ch) //p4
The coexistence of patterns 3 and 4 is problematic (impossible, I am afraid). Even if it compiles, I have not been able to make it work. How can this task functionally be handled?
First, the coexistence of these branches is not problematic. They don't conflict with each other. Why do you think that it's problematic? Is it because you get an "Incomplete pattern match" compiler warning? That warning does not tell you that the branches conflict, it tells you that the compiler can't prove that the four branches cover all possibilities. Or do you think that for some other reason? If you want your questions to be answered accurately, you'll have to ask them more clearly.
Second, you're abusing the pattern matching. Look: there are no patterns! The patterns in every branch are exactly the same, and trivial. Only guards are different. This looks very counterintuitively within a match, but would be plainly expressed with if..elif:
let rec countCh (s:string) n ch =
if n >= s.Length || n < 0 then 0
elif s.[n] = ch then 1 + countCh s (n + 1) ch
else countCh s (n + 1) ch
NOTE 1: see how I made the parameters curried? Always use curried form, unless there is a very strong reason to use tupled. Curried parameters are much more convenient to use on the caller side.
NOTE 2: your condition n > s.Length was incorrect: string indices go from 0 to s.Length-1, so the bail condition should be n >= s.Length. It is corrected in my code.
Finally, since this is an exercise, I must point out that the recursion is not tail recursion. Look at the second branch (in my code): it calls the function recursively and then adds one to the result. Since you have to do something with the result of the recursive call, the recursion can't be "tail". This means you risk stack overflow on very long inputs.
To make this into tail recursion, you need to turn the function "inside out", so to say. Instead of returning the result from every call, you need to pass it into every call (aka "accumulator"), and only return from the terminal case:
let rec countCh (s:string) n ch countSoFar =
if n >= s.Length || n < 0 then countSoFar
elif s.[n] = ch then countCh s (n+1) ch (countSoFar+1)
else countCh s (n+1) ch countSoFar
// Usage:
countCh "aaaabbbccc" 5 'b' 0
This way, every recursive call is the "last" call (i.e. the function doesn't do anything with the result, but passes it straight out to its own caller). This is called "tail recursion" and can be compiled to work in constant stack space (as opposed to linear).
I agree with the other answers, but I'd like to help you with your original question. You need to indent the function, and you have an off by one bug:
let rec countCh (s:string, n:int, ch:char) =
match s, n, ch with
| s, n, _ when n >= s.Length-1 -> 0 //p1
| s, _, _ when n < 0 -> 0 //p2
| s, n, ch when s.[n+1] <> ch -> countCh(s, n+2, ch) //p3
| s, n, ch when s.[n+1] = ch -> 1 + countCh(s, n+2, ch) //p4
I'd suggest to not write it yourself, but ask the library functions for help:
let countCh (s: string, n, c) =
s.Substring(n+1).ToCharArray()
|> Seq.filter ((=) c)
|> Seq.length
Or use Seq.skip, along with the fact that you can drop the conversion to character array:
let countCh (s: string, n, c) =
s
|> Seq.skip (n + 1)
|> Seq.filter ((=) c)
|> Seq.length

(Pretty) Print large objects in Common Lisp

The problem generally appears if I have a class containing, for example, a couple of slots that would be filled with vectors. If I want to make the object of this class more-or-less transparent, I implement print-object for it. And here I am faced with the problem:
If I print everything in one line, REPL's heuristics are not good enough to determine how to arrange printable parts in multiple lines, causing everything to be shifted to the right (see example below).
If I decide to split the output into multiple lines manually, I have a problem of how to indent everything properly, such that if this object is a part of another object, indentation is preserved (see example below for more clarity).
Here is the code. Consider two classes:
(defclass foo ()
((slot1 :initarg :slot1)
(slot2 :initarg :slot2)))
(defclass bar ()
((foo-slot :initarg :foo)))
And I have the following instances:
(defparameter *foo*
(make-instance 'foo
:slot1 '(a b c d e f g h i j k l m n o p q r s t u v)
:slot2 #(1 2 3 4 5 6 7 8)))
(defparameter *bar*
(make-instance 'bar
:foo *foo*))
What I want to see, is something like this:
> *bar*
#<BAR
foo-slot = #<FOO
slot1 = (A B C D E F G H I J K L M N O P Q R S T U V)
slot2 = #(1 2 3 4 5 6 7 8)>>
Case 1: Printing everything in one line
Definitions of print-object for these classes can be something like these:
(defmethod print-object ((obj foo) out)
(with-slots (slot1 slot2) obj
(print-unreadable-object (obj out :type t)
(format out "slot1 = ~A slot2 = ~A" slot1 slot2))))
(defmethod print-object ((obj bar) out)
(with-slots (foo-slot) obj
(print-unreadable-object (obj out :type t)
(format out "foo-slot = ~A" foo-slot))))
However, their printable representation is less than ideal:
> *foo*
#<FOO slot1 = (A B C D E F G H I J K L M N O P Q R S T U V) slot2 = #(1 2 3 4 5
6 7 8)>
> *bar*
#<BAR foo-slot = #<FOO slot1 = (A B C D E F G H I J K L M N O P Q R S T U V) slot2 = #(1
2
3
4
5
6
7
8)>>
Case 2: Attempt to multiple line printing
Using multiple line printing, I don't know how to control indentation:
(defmethod print-object ((obj foo) out)
(with-slots (slot1 slot2) obj
(print-unreadable-object (obj out :type t)
(format out "~%~Tslot1 = ~A~%~Tslot2 = ~A" slot1 slot2))))
(defmethod print-object ((obj bar) out)
(with-slots (foo-slot) obj
(print-unreadable-object (obj out :type t)
(format out "~%~Tfoo-slot = ~A" foo-slot))))
Thus, *foo* prints OK, but *bar* isn't:
> *foo*
#<FOO
slot1 = (A B C D E F G H I J K L M N O P Q R S T U V)
slot2 = #(1 2 3 4 5 6 7 8)>
*bar*
#<BAR
foo-slot = #<FOO
slot1 = (A B C D E F G H I J K L M N O P Q R S T U V)
slot2 = #(1 2 3 4 5 6 7 8)>>
In the past I tried to play around with print-indent, but without a success (I couldn't see any effect from it, maybe wasn't using it correctly, SBCL 1.2.14).
Is there a (preferably simple) way to solve this?
Try something like this (might require more polishing):
(defmethod print-object ((obj foo) out)
(with-slots (slot1 slot2) obj
(print-unreadable-object (obj out :type t)
(format out "~<~:_slot1 = ~A ~:_slot2 = ~A~:>" (list slot1 slot2)))))
(defmethod print-object ((obj bar) out)
(with-slots (foo-slot) obj
(print-unreadable-object (obj out :type t)
(format out "~<~:_foo-slot = ~A~:>" (list foo-slot)))))
It uses ~< and ~:>, which are format operations for logical blocks. Then it uses ~:_, which is a conditional newline. You should read the relevant hyperspec section.

why this code returns Unsat?

Given c == a + 4 and t == c + b, if b == -4, then t == a. I am trying to do the opposite, meaning given the above 2 equations and t == a, I try to find value of b.
This is pretty similar to the related question, but this time I only switch a and b, and I am really confused that the code returns different result.
Following the code posted at above link, I have below code (similar, only a and b swiched):
#!/usr/bin/python
from z3 import *
a, b, c, t = BitVecs('a b c t', 32)
g = True
g = And(g, c == (a + 4))
g = And(g, t == (c + b))
s = Solver()
s.add(ForAll([t, a, c], Implies(t == a, g)))
if s.check() == sat:
print s.model()[b]
else:
print 'Unsat'
However, on Ubuntu, running the above code returns unexpected result Unsat, but not value -4 (or 0xfffffffc)
Any idea why this is wrong?
Thanks so much.
Z3 is actually returning unknown. The method check returns: sat, unsat or unknown.
Here is a custom tactic that shows that the formula is indeed unsat.
#!/usr/bin/python
from z3 import *
a, b, c, t = BitVecs('a b c t', 32)
g = True
g = And(g, c == (a + 4))
g = And(g, t == (c + b))
s = Goal()
s.add(ForAll([t, a, c], Implies(t == a, g)))
T = Then("simplify", "der", "distribute-forall")
# print the simplified formula. Note that it is unsat
print T(s)
# Create a solver using the tactic above and qe
s = Then("simplify", "der", "distribute-forall", "qe", "smt").solver()
s.add(ForAll([t, a, c], Implies(t == a, g)))
print s.check()
Update
The formula is of the form
forall t, a, c: t == a ==> c == (a + 4) and t == (c + b).
This formula is logically equivalent to:
forall a, c: c == (a + 4) and a == (c + b).
which is logically equivalent to
(forall a, c: c == (a + 4)) and (forall a, c: a == (c + b)).
Both subformulas are logically equivalent to false.
This is why the formula is unsatisfiable.
The comment you wrote suggests that you believe you created the slightly different formula
forall t, a, c: t == a ==> c == (a + 4) ==> t == (c + b).
This formula is sat. To create this formula we have to replace
g = True
g = And(g, c == (a + 4))
g = And(g, t == (c + b))
with
g = Implies(c == (a + 4), t == (c + b))
The updated example is available here.

F# fails with "Error 4 This expression was expected to have type int but here has type int -> int"

Here is the code that I am trying to get to work last line is where it is failing:
let rec gcd a b =
if b= 0 then
a
else
gcd b (a % b);;
let n = 8051
let mutable d = 0
let mutable c = 1
let mutable xi = 2
let mutable yi = 2
let f x = (pown x 2) + (c % n);;
while c < 100 do
while d = 1 do
xi <- (f xi)
yi <- (f(f(yi)))
printfn "%d%d" xi yi
d <- gcd(abs (xi - yi) n)
---------------------The Following Code works; Except for integer overflow on N---------
module Factorization
let rec gcd a b =
if b= 0 then
a
else
gcd b (a % b);;
let n = 600851475143N
let mutable d, c, xi, yi = 1, 1, 2, 2
let f x = (pown x 2) + (c % n);;
let maxN m =int(ceil(sqrt(float m)))
//if (n > maxN(xi)) && (n > maxN(yi)) then
while c < 100 do
d <- 1
while d = 1 do
if (maxN(n) > xi) && (maxN(n) > yi) then
xi <- f xi
yi <- f(f(yi))
d <- gcd (abs (xi - yi)) n
//fail
if d = n then d<-1
if d <> 1 then printfn "A prime factor of %d x = %d, y = %d, d = %d" n xi yi d
else
xi <- 2
yi <- 2
c <- c + 1;;
In addition to what #Rangoric pointed out, the outer brackets have to go as well otherwise currying won't work:
d <- gcd (abs(xi-yi)) n
Yikes, here are a few unsolicited tips (#BrokenGlass answered the question itself correctly).
First, you can assign all those mutables in one line:
let mutable d, c, xi, yi = 0, 1, 2, 2
Second, go easy on the parentheses:
xi <- f xi
yi <- f (f yi)
And of course, try to get rid of the mutables and while loops. But I'll leave that to you since I'm sure you are aware seeing that you implemented gcd using recursion.
Try:
d <- gcd (abs(xi-yi)) n
It is pointing out that abs is a int->int and not an int by itself. Wrapping it in parentheses causes the abs to be executed before gcd looks at it. This causes gcd to see the result of abs instead of abs itself.

Resources