type Googol = {
number : float
power : float
result : float
}
let generatePowers (n:float) : list<Googol> =
let rec powerInner (n:float) (p:float) (acc : list<Googol>) =
match n with
| p when p <= 1.0 -> acc
| p when p > 1.0 -> powerInner n (p-1.0) ([{ number=n; power=p; result=n**p}]#acc)
let rec numberInner (n:float) (acc : list<Googol>) =
match n with
| n when n <=1.0 -> acc
| n when n >1.0 -> numberInner (n-1.0) ((powerInner n [])#acc)
numberInner n []
ProjectEuler.fsx(311,50): error FS0001: This expression was expected to have type
'Googol list'
but here has type
'Googol list -> Googol list'
I am trying to solve this problem -> https://projecteuler.net/problem=56 | but for this I need to generate powers below n < 100. When I try to concatenate [{ number=n; power=p; result=n**p}]#acc
these lists I get the error above. Explain please why error says 'Googol list -> Googol list' is in the function, does I plug a function as a parameter to the function or I plug the actual list when just after concatenation. Is # a function?
This looks like homework or practice, so first I'll give some hints to move on. Finally I'll show a version that seems to work, and then tell how I would approach the problem.
The task is to find the number a ** b, for a and b less than 100, that has the highest sum of its own digits.
The first problem is that float won't give us all the digits of a ** b, so that type is useless to solve the problem. To fix that, we turn to the BigInteger type, and the BigInteger.Pow function. Then we get a 1 followed by 200 zeroes if we run the following snippet, just like it says in the problem description.
let x: bigint = BigInteger.Pow (100I, 100)
let x: string = string x
printfn "s=%s" x
To get useful results, change the Googol type so that it uses bigint, except for power that should be an int.
Why are the functions powerInner and numberInner inside the function generatePowers? This doesn't seem to have a specific purpose, so I suggest moving them out to make this clearer.
The function powerInner do a match on n, but then goes on to name the results p, which shadows the p parameter so that it is unused. Ok, the intention here is probably to match on p rather than n, so just fix that, and then the shadowing of the p parameter is perfectly fine.
The tests first on <= 1 and then on > 1 causes incomplete matches. If the first line checks that the number is less or equal to one, then it must the greater than one in the next line. So just use n -> without the when to fix that. I also suspect you want to test <= 0 instead of 1.
This
[{ number=n; power=p; result=n**p}]#acc
can be just
{ number=n; power=p; result=n**p } :: acc
and here
(powerInner n [])
I suspect you just need a starting value for the power, which would be 99
(powerInner n 99 [])
SPOILER WARNING
After a bit of tinkering, this is what I ended up with, and it seems to print out a useful list of numbers. Note that in order to not run through all 99 by 99 results with printouts, I've used low starting numbers 3 and 5 for the countdowns here, so we get some simple printout we can study for analysis.
type Googol = { number: bigint; power: int; result: bigint }
let rec powerInner (n: bigint) (p: int) (acc: Googol list) =
match p with
| p when p <= 0 -> acc
| p ->
let newNumber = { number = n; power = p; result = n ** p }
printfn "newNumber=%0A" newNumber
powerInner n (p - 1) (newNumber :: acc)
let rec numberInner (n: bigint) (acc: Googol list) =
match n with
| n when n <= 0I -> acc
| n -> numberInner (n - 1I) ((powerInner n 5 []) # acc)
let generatePowers (n: bigint) : Googol list =
numberInner n []
let powers = generatePowers 3I
I'm not sure if this solution is correct. I'd do it differently anyway.
I would simply loop through a and b in two loops, one inside the other. For each a ** b I would convert the result to a string, and then sum the digits of the string. Then I'd simply use a mutable to hold on to whichever result is the highest. The same could be achieved in a more functional way with one of those fancy List functions.
You're missing a parameter here:
| n when n >1.0 -> numberInner (n-1.0) ((powerInner n [])#acc)
^^^^^^^^^^^^^^^
here
powerInner is defined with three parameters, but you're only passing two.
In F# it is not technically illegal to pass fewer parameters than defined. If you do that, the result will be a function that "expects" the remaining parameters. For example:
let f : int -> int -> string
let x = f 42
// Here, x : int -> string
let y = x 5
// Here, y : string
So in your case omitting the last parameter makes the resulting type Googol list -> Googol list, which then turns out to be incompatible with the type Googol list expected by operator #. Which is what the compiler is telling you in the error message.
Related
I'm working on a problem where they ask us to write a function to determine if a matrix is square (n by n, for any n >= 0) with OCaml
I have a type matrix already defined
type matrix = float list list
Also I previously have a function that works to determine the length of a list
let rec length (l : 'a list): int =
match l with
| [] -> 0
| _ :: xs' -> 1 + length xs'
Right now I'm thinking about writing a helper function which checks if the length of all rows are equal
let rec check_row_equal (m : matrix): bool =
match m with
| [] -> true
| h1 :: h2 :: t ->
if length h1 <> length h2 then false
else check_row_equal (h2 :: t)
But when I ran this function in utop, it says Match_failure ("//toplevel//", 2, 2). If I have this helper function running correctly, my thought for my next function would be
let rec is_square (m : matrix): bool =
let l = length m in
if check_row_equal m == false then false
else if (l != the length of one of the rows) then false
else true
I haven't figured out how to calculate the length of the row, maybe another helper function like
let row_length (m : matrix): int =
match m with
| [] -> 0
| h :: t -> length h
But again, I need help with the check_row_equal function, please help me to fix that, thank u!
let rec check_row_equal (m : matrix): bool =
match m with
| [] -> true
| h1 :: h2 :: t ->
if length h1 <> length h2 then false
else check_row_equal (h2 :: t)
You're getting a match error because you have a case for an empty list, and a list with two or more elements, but not a list with one element. Presumably if there is only one row, this should return true.
Incorporating this and simplifying the code a bit.
let rec check_row_equal (m : matrix): bool =
match m with
| [] | [_] -> true
| h1 :: (h2 :: _ as tl) ->
length h1 = length h2 && check_row_equal tl
You don't say what it means specifically to check whether a matrix is square. I'll assume you want to check the lengths of all the contained lists to make sure they're the same, and this should also be the same as the length of the outer list.
Here are a couple of comments:
Your length function works correctly in the abstract, but it doesn't work for the normal kind of OCaml list. In OCaml, the empty list (the final tail of every list) looks like [] and Cons (a, b) looks like a :: b. Maybe your code is supposed to work with a custom list type, but then it's confusing to name it list, like the normal OCaml list.
You already have a function length that visits every element of a list and calculates an answer. You need a function just like this except that each element of the list is another list, and you want to determine whether the lengths of these are all the same. Just as your length function gets a new result by adding 1 to the returned result, you can figure out an operation that tracks whether the lists have all been the same length so far and, if so, what that length was.
I hope this helps. I don't want to write code for you because this is an assignment.
. Write a function that takes an integer list and return sum of all elements of the list. If the list is empty then return None.
This is my code now:
let rec sum (xs: int list) =
match xs with
| [] -> None
| [x] -> Some x
| hd::tl -> let m = (hd + (sum tl)) in
Some m
;;
The problem is that I can't seem to find a way to add up the last element without getting an error.
This is my error.
Error: This expression has type int but an expression was expected of type 'a option.
Your recursive call to sum does indeed return an int option. You know this because you're the author of the function, and you coded it up to return that type :-) You can either write a helper function that returns an int, or you can extract the int from the return value of sum, something like this:
let tlsum =
match sum tl with
| None -> (* figure this part out *)
| Some n -> (* figure this part out *)
You can define the addition of two int option.
let sum l =
let (+) a b =
match (a,b) with
| (None,x) | (x,None) -> x
| (Some x,Some y) -> Some (x+y)
in
let convert a = Some a in
let opt_l=List.map convert l in
List.fold_left (+) None opt_l
Test
# sum [];;
- : int option = None
# sum [1;2];;
- : int option = Some 3
That looks like an assignment so I'll be vague:
The easiest way to do that is probably to first define a function of type int list -> int that returns the "normal" sum (with 0 for the empty case). That function will be recursive and 0 will correspond to the base case.
Then write another function of type int list -> int option that checks whether its argument is empty or not and does the right thing based on that.
Trying to write the recursion directly probably is not a good idea since there are two cases when you will need to handle []: when it's the only element in the list, and when it's at the end of a nonempty list.
I have the following problem: given a max(max) apacity, and given a list of values(listOfValues) i need to return a list with values from the listOfValues. The sum of the elements must be <= max and i need to prioritize the higher values.
Example: typing solvingProblem 103 [15, 20, 5, 45, 34] i must get: [45, 45, 5, 5]
To solve the problem i create the following code:
solvingProblem max [] = 0
solvingProblem max listOfValues | max == 0 = 0
| otherwise = createList max listOfValues []
createList max [] result = -1
createList max listOfValues result | smaller listOfValues > max = -1
| higher listOfValues > max = createList max (remove (higher listOfValues) listOfValues) result
| otherwise = createList (max - higher listOfValues) listOfValues (insert (higher listOfValues) result)
higher [a] = a
higher (a:b:x) | a > b = higher (a:x)
| otherwise = higher (b:x)
smaller [a] = a
smaller (a:b:x) | a < b = smaller (a:x)
| otherwise = smaller (b:x)
remove x [] = []
remove x (h:t) | x == h = remove x t
| otherwise = h : remove x t
insert x (h:t) = x : h : t
In the two lines where i'll returning "-1" should be the parameter "result", but if i change "-1" to "result" the code don't load on ghci.
Can someone help me?
Thank you and sorry for my bad english.
If I may begin with a bit of a side note, some of your functions already exist in Haskell (now that I come to think of it you might have written them for an exercise, but just in case it wouldn't be the case, let's discuss that): your higher is maximum, your smaller is minimum and your insert is just (:), beacause like you write it yourself insert x list = x:list. Note that your version will fail if you give it the empty list because the pattern matching is non-exhaustive. Also you could write remove in terms of filter: remove x list = filter (== x) list.
Now why doesn't your code load properly? ghci tells you:
• Non type-variable argument in the constraint: Num [a]
(Use FlexibleContexts to permit this)
• When checking the inferred type
solvingProblem :: forall a.
(Ord a, Num [a], Num a) =>
a -> [a] -> [a]
Which I agree is pretty cryptic, but what it's saying is that the return type of solvingProblem is a list of a and for some reason it is also an instance of the Num type class. The reason why it says it's an instance of Num is because one of the return value of solvingProblem is 0 which is a number, which is a bit odd because it is also a list. Changing the 0 with [] makes the code compile and work (if you change insert with (:) otherwise you get the non-exhaustive pattern matching I was talking about earlier).
λ> solvingProblem 103 [15,20, 5, 45, 34]
[5,5,45,45]
it :: (Ord t, Num t) => [t]
The problem is with the last guard clause in createList.
The type you intended for createList seems to be:
createList :: Int -> [Int] -> Int -> Int
but if you look at the last guard clause you have:
| otherwise = createList (max - ...) listOfValues (insert ...)
^^^^^^^^^^^ ^^^^^^^^^^^^ ^^^^^^^^^^^^
Int [Int] [Int]
Even though GHC is very good at inferring types, always adding
type signatures to your code is a good way of catching these kinds
of errors early.
I wrote a function that is giving me a syntax error, not exactly sure why. You can skip to the bottom of this and read the code and error, the rest of the stuff in here is just more information that might not be needed.
I have to make a multiply numbers function that multiplies two lists of numbers and returns the result as a list.
let bigMul l1 l2 =
let f a x = failwith "to be implemented" in
let base = failwith "to be implemented" in
let args = failwith "to be implemented" in
let (_, res) = List.fold_left f base args in
res
It multiplies by pretending representing big ints as lists so 1234x24 is [1;2;3;4] x[2;4] It uses several functions that I already wrote and tested. One is mulByDigit which multiplies each int in a list by an int and returns a list such as [2;3;4;5] 1 would return [2;3;4;5]. It also uses padZero which takes 2 lists of ints and makes them equal in length by adding zeroes to the shorter one and returns a tuple with both lists ex [1;2;3] and [1] would return a tuple with ([1;2;3],[0;0;1]). The last function bigAdd takes 2 lists and adds them and returns the result so like for [1;2;3] [1;2;3] it would give [2;4;6]. All of those functions have been tested and work correctly so Im not gonna provide the code for them.
I wrote a function which follows the logic of taking list l1, multiplying it by every digit of l2 with trailing zeroes depending on the digit and maintaining the sum. Ex if list 1 is [1;2;3;4] and l2 is [2;4] i take the second list and reverse it first of all to get [4;2] and then i multiply 1234 by 4 and get the result. I add this result to the current value in the accumulator which is nothing at first and increment the i to let me know to have a trailing zero for the next one. Then i take the 2 remaining and multiply it by 1234 and have a trailing zero so 24680. I add this to my old accumulator to get the final value and return the value when there are no more numbers left in l2. So 1234+24680=25914. Here is the function that I wrote. a is the accumulator in it, i is for keeping track of how many zeroes I need
let bigMul l1 l2 =
let f (i,a) x =
let sum = padZero ( (mulByDigit x l1)#(clone 0 i) ) a in
in let (first,second) = match sum with
| (y,z)->(y,z) in
( i+1, ( bigAdd first second ) ) in
let base = (0,[]) in
let args = List.rev ( l2 ) in
let (_, res) = List.fold_left f base args in
res
im getting a syntax error when i run it that says unbound value l2. Not sure why so any thoughts.
Here's what I see:
let sum = padZero ( (mulByDigit x l1)#(clone 0 i) ) a in
in let (first,second) = match sum with
There are two in keywords in a row there.
For what it's worth, this:
let (first,second) = match sum with
| (y,z)->(y,z)
in
Is equivalent to:
let (first, second) = sum in
Found it : I wrote in twice
let sum = padZero ( (mulByDigit x l1)#(clone 0 i) ) a in
in let (first,second) = match sum with
I am trying to achieve the following: Finding the element at a specific index.
So if I had a list of [5; 2; 3; 6] and ask for the element at index 2, it would return 3.
let counter = 0;;
let increase_counter c = c + 1;;
let rec get_val x n = match x with
[] -> -1
| (h::t) ->
if (counter = n) then
h
else
increase_counter counter ; get_val t n
;;
But this code is giving me a bug saying that -1 is not of type 'unit'?
As Jeffrey Scofield said, you should write let counter = ref 0 to make counter mutable. Now, you can use the built in incr function to increment it (equivalent to counter := !counter + 1), and you'll get its value with !counter.
There is also a problem in your algorithm : if the counter is equal to n, you return the head of the list... you mean : if the head of the list is equal to n, you return the counter.
Your program is then :
let counter = ref 0;;
let rec get_val x n = match x with
[] -> -1
| (h::t) ->
if (h = n) then
!counter
else
begin incr counter ; get_val t n end
;;
Note that I've added begin and end around the else block so it can be interpreted as a sequence of instructions.
Your program now works, but it is not the best way to solve this problem with ocaml.
You should write something like
let get_val x n =
let rec get_val_aux x n counter = match x with
| [] -> -1
| h :: _ when h = n -> counter
| _ :: t -> get_val_aux t n (succ counter)
in
get_val_aux x n 0
;;
Here, we add a parameter to the get_val_aux function which we increment at each call. This function is nested within the get_val function to hide this additional parameter which is initialized with 0 on the first call.
Instead of using an if statement, we use the when condition to know when the element has been found, and add a new case to match the last case (not found). Note the use of the _ wildcard to avoid an unused variable.
The succ function (for successor) only adds 1 to its parameter. It is equivalent to counter + 1.
There are many problems with this code. If you ignore your immediate problem for a moment, you are treating OCaml variables like the variables of an imperative language. However, OCaml variables are immutable. This function
let increase_counter c = c + 1
Doesn't change the value of any variable. It just returns a number 1 bigger than what you give it.
The only error I get from the toplevel when I enter your code is for this expression:
increase_counter counter ; get_val t n
The compiler is warning you that the expression before ; is supposed to be executed for its side effects. I.e., it should almost always have type unit. Since (as I say) your function increase_counter returns an int, the compiler is warning you about this.