I have a some OCaml code that finds all combinations of change given a change amount. I have most of the code working, however I am not able to figure out how this recursive function will actually return the possible change combinations.
let change_combos presidents =
let rec change amount coinlist = match amount with
|0 -> [[]] (*exits when nothing*)
|_ when (amount < 0) -> [] (*exits when less than 0*)
|_ -> match coinlist with
|[] -> [] (*Returns empty list, exits program*)
(*h::f -> something, using [25;10;5;1] aka all change combinations...*)
(*using recursion, going through all combinations and joining lists returned together*)
let print_the_coin_matrix_for_all_our_joy enter_the_matrix =
print_endline (join "\n" (List.map array_to_string enter_the_matrix));;
Thanks for the help, let me know if I need to clarify something :)
It is a bit confusing what you're looking for. I believe that you want to generate a list of all the combinations of a list? You should think about the recursion and how to generate the individual elements. Start with the input type, and how you'd generate successive elements by reducing the problem space.
let rec generate lst = match lst with
| [] -> []
| h::t -> [h] :: (List.map (fun x -> h::x) (generate t)) # (generate t)
If the list is [] there are no combinations. If we have an element we generate all combinations without that element and base our construction on that assumption. The components fall into place at this point. Concatenate the list of combinations of t with the combinations of t and h cons'd onto each and a singleton of h.
Related
I have to implement a function that takes two lists of tuples let foo l1 l2 and has to append them and apply a recursive function let rec bar x l to one element of each tuple in the list.
The number of recursive calls depends on l, so I'd like to use the intermediate results of the pipe as l in order to reduce the calls instead of saving the initial list and pass that one.
My current solution is as follows and I'd like to optimise it with some sort of dynamic programming solution
let foo l1 l2 =
l = l1 # l2
l |> List.map (fun (x, y) -> x, bar y l)
Return the SUM of numeric elements in a nested list using LISP. If there are no numeric elements return an empty list/NIL
Examples:
(6 3 -2 5 (4 2 -3) 4) should return 19
(1 2 3 (-4 5) a b c) should return 7
Asking other people to do your homework for you is almost never a good way of learning anything.
But here's an answer, which is written in a Lisp (Racket) and which does show how you ought to go about solving this problem, and also (I think) demonstrates some nice ways of thinking about problems like this ... but which you almost certainly can't cut and paste.
Note that this does not quite agree with the requirements given: which is supposed to return a non-numeric value for a list with no numbers in it. That breaks a recursive algorithm like this, since the empty list is a list with no numbers in it. So this does something more sensible. Making this answer implement the requirements is left as an exercise to the student.
(define (sum-nested-list l)
(let sum-nested-list-loop ([thing l]
[running-total 0])
(match thing
['()
;; We're done if we've run out of list
running-total]
[(list* (? number? x) r)
;; A list whose first element is a number: add it to the running total
;; and carry on on the rest of the list
(sum-nested-list-loop r (+ running-total x))]
[(list* (? list? x) r)
;; A list whose first element is a nested list: recurse into the
;; nested list
(sum-nested-list-loop r (sum-nested-list-loop x running-total))]
[(list* _ r)
;; A list whose first element is not a number or a nested list:
;; carry on on the rest of the list
(sum-nested-list-loop r running-total)]
[_
;; Not a list at all: explode
(error 'sum-numeric-list "what?")])))
(defun flat-sum (tree)
(let ((count 0))
(tree-equal tree tree :test (lambda (left right)
(if (numberp left)
(incf count left) t)))
count))
1> (flat-sum '(1 2 3 (-4 5) a b c))
7
Write a function to split a list into two lists. The length of the first part is specified by the caller.
I am new to Elm so I am not sure if my reasoning is correct. I think that I need to transform the input list in an array so I am able to slice it by the provided input number. I am struggling a bit with the syntax as well. Here is my code so far:
listSplit: List a -> Int -> List(List a)
listSplit inputList nr =
let myArray = Array.fromList inputList
in Array.slice 0 nr myArray
So I am thinking to return a list containing 2 lists(first one of the specified length), but I am stuck in the syntax. How can I fix this?
Alternative implementation:
split : Int -> List a -> (List a, List a)
split i xs =
(List.take i xs, List.drop i xs)
I'll venture a simple recursive definition, since a big part of learning functional programming is understanding recursion (which foldl is just an abstraction of):
split : Int -> List a -> (List a, List a)
split splitPoint inputList =
splitHelper splitPoint inputList []
{- We use a typical trick here, where we define a helper function
that requires some additional arguments. -}
splitHelper : Int -> List a -> List a -> (List a, List a)
splitHelper splitPoint inputList leftSplitList =
case inputList of
[] ->
-- This is a base case, we end here if we ran out of elements
(List.reverse leftSplitList, [])
head :: tail ->
if splitPoint > 0 then
-- This is the recursive case
-- Note the typical trick here: we are shuffling elements
-- from the input list and putting them onto the
-- leftSplitList.
-- This will reverse the list, so we need to reverse it back
-- in the base cases
splitHelper (splitPoint - 1) tail (head :: leftSplitList)
else
-- here we got to the split point,
-- so the rest of the list is the output
(List.reverse leftSplitList, inputList)
Use List.foldl
split : Int -> List a -> (List a, List a)
split i xs =
let
f : a -> (List a, List a) -> (List a, List a)
f x (p, q) =
if List.length p >= i then
(p, q++[x])
else
(p++[x], q)
in
List.foldl f ([], []) xs
When list p reaches the desired length, append element x to the second list q.
Append element x to list p otherwise.
Normally in Elm, you use List for a sequence of values. Array is used specifically for fast indexing access.
When dealing with lists in functional programming, try to think in terms of map, filter, and fold. They should be all you need.
To return a pair of something (e.g. two lists), use tuple. Elm supports tuples of up to three elements.
Additionally, there is a function splitAt in the List.Extra package that does exactly the same thing, although it is better to roll your own for the purpose of learning.
I want to solve the following problem in Haskell:
Let n be a natural number and let A = [d_1 , ..., d_r] be a set of positive numbers.
I want to find all the positive solutions of the following equation:
n = Sum d_i^2 x_i.
For example if n= 12 and the set A= [1,2,3]. I would like to solve the following equation over the natural numbers:
x+4y+9z=12.
It's enough to use the following code:
[(x,y,z) | x<-[0..12], y<-[0..12], z<-[0..12], x+4*y+9*z==12]
My problem is if n is not fixed and also the set A are not fixed. I don't know how to "produce" a certain amount of variables indexed by the set A.
Instead of a list-comprehension you can use a recursive call with do-notation for the list-monad.
It's a bit more tricky as you have to handle the edge-cases correctly and I allowed myself to optimize a bit:
solve :: Integer -> [Integer] -> [[Integer]]
solve 0 ds = [replicate (length ds) 0]
solve _ [] = []
solve n (d:ds) = do
let maxN = floor $ fromIntegral n / fromIntegral (d^2)
x <- [0..maxN]
xs <- solve (n - x * d^2) ds
return (x:xs)
it works like this:
It's keeping track of the remaining sum in the first argument
when there this sum is 0 where are obviously done and only have to return 0's (first case) - it will return a list of 0s with the same length as the ds
if the remaining sum is not 0 but there are no d's left we are in trouble as there are no solutions (second case) - note that no solutions is just the empty list
in every other case we have a non-zero n (remaining sum) and some ds left (third case):
now look for the maximum number that you can pick for x (maxN) remember that x * d^2 should be <= n so the upper limit is n / d^2 but we are only interested in integers (so it's floor)
try all from x from 0 to maxN
look for all solutions of the remaining sum when using this x with the remaining ds and pick one of those xs
combine x with xs to give a solution to the current subproblem
The list-monad's bind will handle the rest for you ;)
examples
λ> solve 12 [1,2,3]
[[0,3,0],[3,0,1],[4,2,0],[8,1,0],[12,0,0]]
λ> solve 37 [2,3,4,6]
[[3,1,1,0],[7,1,0,0]]
remark
this will fail when dealing with negative numbers - if you need those you gonna have to introduce some more cases - I'm sure you figure them out (it's really more math than Haskell at this point)
Some hints:
Ultimately you want to write a function with this signature:
solutions :: Int -> [Int] -> [ [Int] ]
Examples:
solutions 4 [1,2] == [ [4,0], [0,1] ]
-- two solutions: 4 = 4*1^2 + 0*2^2, 4 = 0*1^2 + 1*2^2
solutions 22 [2,3] == [ [1,2] ]
-- just one solution: 22 = 1*2^2 + 2*3^2
solutions 10 [2,3] == [ ]
-- no solutions
Step 2. Define solutions recursively based on the structure of the list:
solutions x [a] = ...
-- This will either be [] or a single element list
solutions x (a:as) = ...
-- Hint: you will use `solutions ... as` here
In working through Exercise 2 here, I offered this solution to the compiler and got an Infinite Type error.
flatten : Tree a -> List a
flatten tree =
case tree of
Empty -> []
Node v left right ->
[v] :: flatten left :: flatten right
This doesn't seem too different from my solution to the first exercise:
sum : Tree Int -> Int
sum tree =
case tree of
Empty -> 0
Node v left right ->
v + sum left + sum right
I wondered if perhaps the issue had to do with order of operations, so I added parens to ensure flatten gets evaluated before ::, but this doesn't seem to make a difference:
flatten : Tree a -> List a
flatten tree =
case tree of
Empty -> []
Node v left right ->
[v] :: (flatten left) :: (flatten right)
So now I'm just stumped.
:: is the cons operator, which means it will prepend a single element onto a list. Its type signature is a -> List a -> List a. That means this isn't valid code since the first argument, [v] is a list:
[v] :: flatten left :: flatten right -- invalid!
If you want to concatenate two lists, you use the concatenation operator: ++. You could just replace :: with ++ in your example to get it to compile:
[v] ++ flatten left ++ flatten right
Another way to represent that line is to concatenate the two lists, then prepend the list with v using the cons operator.
v :: flatten left ++ flatten right
-- The following is the same as above, but with parentheses showing precedence
v :: (flatten left ++ flatten right)
There are more efficient ways to do this, of course, but it highlights the difference between cons and concatenation.
The reason your sum example works is because it is returning an int instead of a list of ints. The type you are returning in sum is the same as the value in the tree, so you end up with an aggregate, not another list.