SML - prime factorization, building list error - list

I'm trying to write an SML function that will return a list of all the prime factors to a given number. This will end up being a helper function to another function later on.
Originally the bigNumber is the number that I need to find the prime factors for and I pass in 1 less than that number as the divisor. Here's an example on how I'd call it to find the prime factors for the number 100. getPrimeFactors 100 99;
I'm not too worried about if there are flaws with the algorithm right now, but if you spot any errors with it I'd be happy to listen.
My main problem is trying to pass the return values up the recursion chain as lists and then combining those lists as they meet up with other lists.
fun getPrimeFactors bigNumber divisor =
if divisor > 0 then
if (bigNumber mod divisor) = 0 then List.concat(getPrimeFactors (bigNumber div divisor) ((bigNumber div divisor) - 1), getPrimeFactors divisor (divisor - 1))
else [getPrimeFactors bigNumber (divisor - 1)]
else [bigNumber];
Running this gives me this error.
C:.....\run.x86-win32.exe: Fatal error -- Uncaught exception Error with 0
raised at ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
C:\.....\commonFactors.sml:3.39-3.160 Error: operator and operand don't agree [tycon mismatch]
operator domain: 'Z list list
operand: 'Y * 'Y
in expression:
List.concat
((getPrimeFactors (<exp> div <exp>)) (<exp> div <exp> - 1),
(getPrimeFactors divisor) (divisor - 1))
[Finished in 0.4s with exit code 1]
Any help would be greatly appreciated!

You're trying to call List.concat on a tuple. The type of List.concat is
fn : 'a list list -> 'a list
That is, it takes a list of lists, concatenates all of those together, and returns the result. That's your error.
If, instead of using List.concat, we use the # operator, we get a different error (which may look slightly different on your system):
File "test.sml", line 7, characters 14-53:
! else [getPrimeFactors bigNumber (divisor - 1)]
! ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
! Type clash: expression of type
! 'a list
! cannot have type
! 'a
! because of circularity
This error is because getPrimeFactors is supposed to return an int list, but here you're trying to stuff the result from getPrimeFactors into a list, thus getting int list list.

Just in case anyone was curious here's the corrected code with the right algorithm. Was able to fix the List.concat errors thanks to Tayacan.
fun getPrimeFactors big small =
if small > 1 then
if (big mod small) = 0 then List.concat[(getPrimeFactors (big div small) (big div small - 1)), (getPrimeFactors small (small - 1))]
else List.concat[(getPrimeFactors big (small - 1))]
else if big = 1 then nil
else [big];

Related

Unknown assertion failed in FStar

I'd like to understand what's wrong with this simple exercise.
let even n = (n % 2) = 0
let rec even_sqr (n:nat {even n}) : Lemma (even (n * n)) =
match n with
| 0 -> ()
| _ -> even_sqr (n - 2)
FStar returns '(Error) Unknown assertion failed'.
An "Unknown assertion failed" error means that Z3 did not give F* any reason for the proof failing. Usually, this is either evidence for the need for a more detailed proof, or that the statement is false. In this particular case, the statement is true, it is just that Z3 is not great at non-linear arithmetic (and this example combines both multiplication and modulo operators).
In such a case, some small amount of hand-holding helps. You can do this by adding some assertions that might help point it in the right direction.
In this particular case, I added a new assertion that expands n*n in terms of n-2, and the proof then goes through:
let rec even_sqr (n:nat {even n}) : Lemma (even (n * n)) =
match n with
| 0 -> ()
| _ ->
assert (n * n == (n - 2) * (n - 2) + 4 * n - 4); (* OBSERVE *)
even_sqr (n - 2)
Notice that I am not adding any complex proofs, but merely surfacing some properties that might be helpful for the solver to go along. Sometimes with non-linear proofs, however, this may not be enough, and you may require writing a few lemmas, at which point, a good resource is FStar.Math.Lemmas in the standard library.

Psum not accumulating (Polymorphic Higher order function) without forcing a type

New to OCaml and Functional Programming as a whole so I was having some problems with keeping the type ambiguous. I'm trying to make a function which takes in a symbol accum(which looks like (+) or (-.) or (*) etc.) and a function f. My current implementation is below and if let's say I passed in (** f (x) = 3x^2 + 5x + 6 **) but I always get '6' instead of '276' because in the else part I'm not summing adding the results of the previous rounds so I just get the final value of '6'.
I get type errors because of the + so when I throw floats in it breaks. How can I overcome this (let partial accept floats or ints but actually accumulate the answer)?
let rec powerSum(sign )(f):'a =
fun x ->
if x = 0 then
f (x)
else if x < 0 then
raise(Failure "Error arg isn't '+'")
else
powerSum sign f (x-1);
Hint: you should use accum at some point.

Trouble in Making an isPrime Function

This is a homework. OCaml seems to be made by a psychopath.
let prime : int -> bool
= fun n ->
if n > 2 then
let a = n - 1 in
let rec divisor n a =
if a > 1 && n mod a = 0 then false
else if a = 2 && n mod a <> 0 then true
else divisor n a-1 ;;
else if n = 2 then true
else if n = 1 then false
I am not good at coding and I know that my isPrime algorithm is wrong.
But I wonder where in my code is the mistake that produces the syntax error.
Also is there any way to define the isPrime function in a recursive form?
Example:
let rec prime n = ~
You'll get better responses from experts if you don't gratuitously insult their language :-) But I'm an easygoing guy, so I'll take a stab at your syntax error.
There are quite a few problems in this code. Here are 3 that I see right off:
The symbol ;; is used to tell the interpreter that you've entered a full expression that you want it to evaluate. It's definitely out of place in the middle of a function declaration.
Your second let doesn't have an associated in. Every let must have an in after it. The only exception is for defining values at the top level of a module (like your prime function).
The expression divisor n a-1 is parsed as (divisor n a) - 1. You want parentheses like this: divisor a (n - 1).

Sum of digits in an integer using SML

I'm trying to create a function that will sum the digits of an integer in SML but I'm getting the following error.
Error: operator and operand don't agree [overload conflict]
operator domain: real * real
operand: [* ty] * [* ty]
in expression:
n / (d * 10)
I've tried to typecast the variables to real but it didn't work. Also I don't understand why I'm getting this error. Is not possible to use operators such as * and / with int and real in SML?
The code is the following:
fun sumDigits (n) =
if n < 10 then n
else
let
val d = 10
in
n mod d + sumDigits(trunc(n/(d*10)))
end
Looks like you have a few things wrong. To start, you'll want to use "div" rather than "/" when dividing integers. / is for reals. Also, trunc is a function for reals. 3rd, you'll want your recursive logic to just be sumDigits(n div 10), not sumDigits(n div (d*10)). You can also clean up the code by removing the d variable.
fun sumDigits (n) =
if n < 10 then n
else
n mod 10 + sumDigits(n div 10)

F# tricky recursive algorithm

I have this code in VBA (looping through the array a() of type double):
bm = 0 'tot
b = 0 'prev
For i = 24 To 0 Step -1
BP = b 'prevprev = prev
b = bm 'prev = tot
bm = T * b - BP + a(i) 'tot = a(i) + T * prev - prevprev
Next
p = Exp(-xa * xa) * (bm - BP) / 4 '* (tot - prevprev)/4
I'm putting this in F#. Clearly I could use an array and mutable variables to recreate the VBA. And maybe this is an example of the right time to use mutable that I've seen hinted at. But why not try to do it the most idiomatic way?
I could write a little recursive function to replicate the loop. But it kind of feels like littering to hang out a little sub-loop that has no meaning on its own as a standalone, named function.
I want to do it with List functions. I have a couple ideas, but I'm not there yet. Anyone get this in a snap??
The two vague ideas I have are: 1. I could make two more lists by chopping off one (and two) elements and adding zero-value element(s). And combine those lists. 2. I'm wondering if a list function like map can take trailing terms in the list as arguments. 3. As a general question, I wonder if this might be a case where an experienced person would say that this problem screams for mutable values (and if so does that dampen my enthusiasm for getting on the functional boat).
To give more intuition for the code: The full function that this is excerpted from is a numerical approximation for the cumulative normal distribution. I haven't looked up the math behind this one. "xa" is the absolute value of the main function argument "x" which is the number of standard deviations from zero. Without working through the proof, I don't think there's much more to say than: it's just a formula. (Oh and maybe I should change the variable names--xa and bm etc are pretty wretched. I did put suggestions as comments.)
It's just standard recursion. You make your exit condition and your recur condition.
let rec calc i prevPrev prev total =
if i = 0 then // exit condition; do your final calc
exp(-xa * xa) * (total - prevPrev) / 4.
else // recur condition, call again
let newPrevPrev = prev
let newPrev = total
let newTotal = (T * newPrev - newPrevPrev + a i)
calc (i-1) newPrevPrev newPrev newTotal
calc 24 initPrevPrev initPrev initTotal
or shorter...
let rec calc i prevPrev prev total =
if i = 0 then
exp(-xa * xa) * (total - prevPrev) / 4.
else
calc (i-1) prev total (T * total - prev + a i)
Here's my try at pulling the loop out as a recursive function. I'm not thrilled about the housekeeping to have this stand alone, but I think the syntax is neat. Aside from an error in the last line, that is, where the asterisk in (c * a.Tail.Head) gets the red squiggly for float list not matching type float (but I thought .Head necessarily returned float not list):
let rec RecurseIt (a: float list) c =
match a with
| []-> 0.0
| head::[]-> a.Head
| head::tail::[]-> a.Head + (c * a.Tail) + (RecurseIt a.Tail c)
| head::tail-> a.Head + (c * a.Tail.Head) - a.Tail.Tail.Head + (RecurseIt a.Tail c)
Now I'll try list functions. It seems like I'm going to have to iterate by element rather than finding a one-fell-swoop slick approach.
Also I note in this recursive function that all my recursive calls are in tail position I think--except for the last one which will come one line earlier. I wonder if this creates a stack overflow risk (ie, prevents the compiler from treating the recursion as a loop (if that's the right description), or if I'm still safe because the algo will run as a loop plus just one level of recursion).
EDIT:
Here's how I tried to return a list instead of the sum of the list (so that I could use the 3rd to last element and also sum the elements), but I'm way off with this syntax and still hacking away at it:
let rec RecurseIt (a: float list) c =
match a with
| []-> []
| head::[]-> [a.Head]
| head::tail::[]-> [a.Head + (c * a.Tail)] :: (RecurseIt a.Tail c)
| head::tail-> [a.Head + (c * a.Tail.Head) - a.Tail.Tail.Head] :: (RecurseIt a.Tail c)
Here's my try at a list function. I think the problem felt more complicated than it was due to confusing myself. I just had some nonsense with List.iteri here. Hopefully this is closer to making sense. I hoped some List. function would be neat. Didn't manage. For loop not so idiomatic I think. :
for i in 0 .. a.Length - 1 do
b::
a.Item(i) +
if i > 0 then
T * b.Item(i-1) -
if i > 1 then
b.Item(i-2)
else
0
else
0