Doing a small project but after hours of work i still cant work out how to divide every element in a list by a variable
diver xs = map divhs j
where divhs = div hs
hs = tupleTest1 xs
j = jot xs
wont work and neither does
map (/ j) hs
anyone help at all would be most welcome
yours truly
haskell scrub
where divhs = div hs
hs = tupleTest1 xs
j = jot xs
This is not a correct indentation. The first nonspace character of each line (after where) is what matters. Since each line starts as more indented than the previous, the whole where block is parsed as if it were on a single line.
where divhs = div hs hs = tupleTest1 xs j = jot xs
Hence, errors arise, especially since hs and j are being parsed as additional arguments, and there are too many = signs on that line.
Your suggestion with map should work.
See below my example in ghci:
Prelude> let mylist = 1:2:3:4:5:[]
Prelude> mylist
[1,2,3,4,5]
Prelude> let diver xs d = map (/ d) xs
Prelude> diver mylist 2
[0.5,1.0,1.5,2.0,2.5]
Prelude>
or with your short version
Prelude> map (/ 2) mylist
[0.5,1.0,1.5,2.0,2.5]
Based on your comments and your error message
couldn't match expected type '[[int]]' with actual type int - * In the second argument of map' , namely j' - In the expression: map divhs j
the problem is that the input variable j is not an int as you're expecting, but instead a list of lists of int.
The problem thus probably lies in your function jot because you set j with where j = jot xs.
You say that jot returns you a number. I would recommend
trying whether diver works if you manually input arguments
making sure jot does not actually return something like [[1337]]. If it actually returns a list of lists, like the error message suggests, yet you think it is only one number, then it might be the case that it is just a single int wrapped into a list of lists.
If the second bullet point is the case, you could unpack it as a quick fix (but it would be preferable to fix your code of jot) :
Prelude> :{
Prelude| let myunpack (x:xs) = unpackagain x
Prelude| where
Prelude| unpackagain (y:ys) = y
Prelude| :}
Prelude> myunpack [[123]]
123
Related
I tried with something like this but it doesn't work how I wanted it to do. I'm new kinda new to Haskell, and I don't really know how to do it, and what's wrong.
insert a (x:xs) = insert2 a (x:xs) []
where insert2 el (x:xs) hd =
if (x:xs) == []
then []
else if ( a>=x && a < head(xs))
then hd ++ [x] ++ [a] ++ xs
else insert2 a xs hd++[x]
main = do
let list =[1 ,2 ,3 ,4 ,5 ,6]
let out = insert 2 list
print out
The output I get is [2,2,3,4,5,6,1]
First a couple of cosmetics:
Ensure indentation is right. When copy/pasting into StackOverflow, it's generally best to use ctrl+k to get it in code-block style.
There's no point matching (x:xs) only to pass the entire thing into your local function.
Omit unnecessary parentheses and use standardised spacing.
With that, your code becomes
insert a allxs = insert2 a allxs []
where insert2 el (x:xs) hd =
if x:xs == []
then []
else if a >= x && a < head xs
then hd ++ [x] ++ [a] ++ xs
else insert2 a xs hd ++ [x]
main = do
let list = [1, 2, 3, 4, 5, 6]
let out = insert 2 list
print out
Algorithmically speaking, there's no point in using an “accumulator argument” here. It's easier and actually more efficient to directly recurse on the input, and simply pass on the remaining tail after done with the insertion. Also remember to have a base case:
insert a [] = [a]
insert a (x:xs) = ...
You also don't need to use head. You've already pattern-matched the head element with the x:xs pattern. If you did need another list element, you should match that right there too, like
insert a (x:x':xs) = ...
...but you don't in fact need that, x is enough to determine what to do. Namely,
insert a (x:xs)
| a<=x = -- if the list was ordered, this implies that now _all_
-- its elements must be greater or equal a. Do you
-- need any recursion anymore?
| otherwise = -- ok, `x` was smaller, so you need to insert after it.
-- Recursion is needed here.
Here are some hints. It's a lot simpler than you're making it. You definitely don't need a helper function.
insert a [] = ??
insert a (x : xs)
| a <= x = ???
| otherwise = ???
Two things:
Prepending to a list is more efficient than appending to one.
Haskell lets you write separate definitions to avoid having to write single, nested conditional expressions.
There are two kinds of list you can insert into: empty and non-empty. Each can be handled by a separate definition, which the compiler will use to define a single function.
insert a [] = [a]
insert a (x:xs) = ...
The first case is easy: inserting into an empty list produces a singleton list. The second case is tricker: what you do depends on whether a is smaller than x or not. You can use a conditional expression
insert a (x:xs) = if a < x then a : insert x xs else x : insert a xs
thought you may see guards used instead:
insert a (x:xs) | a < x = a : insert x xs
| otherwise = x : insert a xs
In both cases, we know (because the list argument is already sorted) that insert x xs == x : xs, so we can write that directly to "short-circuit" the recursion:
insert a (x:xs) = if a < x then a : x : xs else x : insert a xs
don't complicate! , make simple ...
insertme a list = takeWhile (<a) list ++ [a] ++ dropWhile (<a) list
I found this question from CS 217.
Divide a list into one or more sublists so that each sublist contains integers in nondecreasing (sorted) order.
[3,5,1,8,9,2,1,0] returns [[3,5],[1,8,9],[2],[1],[0]]
[1,2,3,4,5,6] returns [[1,2,3,4,5,6]]
[5,4,3,2,1] returns [[5],[4],[3],[2],[1]]
below code works:
val Q1 = [ 3, 5, 1, 8, 9, 2, 1, 0 ]
val A1 = foldl (
fn (x, a) =>
if x > hd (hd a) then (x::hd a)::tl a
else [x]::a
) [ [ hd Q1 ] ] (tl Q1)
val A1 = map rev (rev A1)
or like this: use 2 temporary list to collect.
fun split l = let
fun split' tmp subset =
fn [] => []
| [x] => (x::tmp)::subset
| (a::(c as b::_)) =>
if a < b then split' (a::tmp) subset c
else split' [] ((a::tmp)::subset) c
in (rev o map rev) (split' [] [] l) end
So many solutions for this question,
But I still want to know how to code it as a pattern match function?
maybe something like below:
(Not sure if it is possible?)
fun split [] = [[]]
| split [x] = [[x]]
| split [a, b] = if a < b then (* here *) else (* here *)
| split (a::b) = if a < hd b then (* here *) else (* here *)
This question really stuck me.
Under the assumption that this is homework, I hesitate to give a complete answer, but here are a few hints:
1) In the empty basis case I think that you want to return [[]] rather than []. Your specification doesn't address this, but since the empty list is the longest list of nondecreasing integers which can be pulled from the front of the empty list, the return value should be the list consisting of the empty list. This is somewhat similar to the fact that the powerset (set of all subsets) of the empty set is the set containing the empty set rather than the empty set itself. It shouldn't really matter how you define this particular case, since the real basis case is ...
2) In the [x] case you really need to return [[x]] rather than [x] since the type of the function that you are trying to write is int list -> int list list
3) In the remaining case you can write the pattern like
| split (x::y::zs) = (* fill this in *)
then test if x <= y to decide what to do. Since both x <= y and x > y will involve split (y::zs) you could compute this once, giving this a name in a let binding and have the if in the scope of that binding, though that is mostly a matter of taste.
Note how the pattern works in this last case. Explicit use of hd should be fairly rare in function definitions which use pattern-matching (though if you flesh out the last case without using a pattern-matching let binding you will be forced to use it in at least one of the branches of the if).
On Edit: Since this isn't homework, here is a complete implementation:
fun split [] = [[]]
| split [x] = [[x]]
| split (x::y::zs) =
let val first::rest = split (y::zs) in
if x <= y then
(x::first) :: rest
else
[x]::first::rest
end;
I have seen some similar questions, but nothing that really helped me. Basically the title says it all. Using SML I want to take a string that I have, and make a list containing each letter found in the string. Any help would be greatly appreciated.
One possibility is to use the basic logic of quicksort to sort the letters while removing duplicates at the same time. Something like:
fun distinctChars []:char list = []
| distinctChars (c::cs) =
let val smaller = List.filter (fn x => x < c) cs
val bigger = List.filter (fn x => x > c) cs
in distinctChars smaller # [c] # distinctChars bigger
end
If the < and > in the definitions of smaller and bigger were to be replaced by <= and >= then it would simply be an implementation of quicksort (although not the most efficient one since it makes two passes over cs when a suitably defined auxiliary function could split into smaller and bigger in just one pass). The strict inequalities have the effect of throwing away duplicates.
To get what you want from here, do something like explode the string into a list of chars, remove non-alphabetical characters from the resulting list, while simultaneously converting to lower case, then invoke the above function -- ideally first refined so that it uses a custom split function rather than List.filter twice.
On Edit: # is an expensive operator and probably results in the naïve SML quicksort not being all that quick. You can use the above idea of a modified sort, but one that modifies mergesort instead of quicksort:
fun split ls =
let fun split' [] (xs,ys) = (xs,ys)
| split' (a::[]) (xs, ys) = (a::xs,ys)
| split' (a::b::cs) (xs, ys) = split' cs (a::xs, b::ys)
in split' ls ([],[])
end
fun mergeDistinct ([], ys) = ys:char list
| mergeDistinct (xs, []) = xs
| mergeDistinct (x::xs, y::ys) =
if x < y then x::mergeDistinct(xs,y::ys)
else if x > y then y::mergeDistinct(x::xs,ys)
else mergeDistinct(x::xs, ys)
fun distinctChars [] = []
| distinctChars [c] = [c]
| distinctChars chars =
let val (xs,ys) = split chars
in mergeDistinct (distinctChars xs, distinctChars ys)
end
You can get a list of all the letters in a few different ways:
val letters = [#"a",#"b",#"c",#"d",#"e",#"f",#"g",#"h",#"i",#"j",#"k",#"l",#"m",#"n",#"o",#"p",#"q",#"r",#"s",#"t",#"u",#"v",#"w",#"x",#"y",#"z"]
val letters = explode "abcdefghijklmnopqrstuvwxyz"
val letters = List.tabulate (26, fn i => chr (i + ord #"a"))
Update: Looking at your question and John's answer, I might have misunderstood your intention. An efficient way to iterate over a string and gather some result (e.g. a set of characters) could be to write a "foldr for strings":
fun string_foldr f acc0 s =
let val len = size s
fun loop i acc = if i < len then loop (i+1) (f (String.sub (s, i), acc)) else acc
in loop 0 acc0 end
Given an implementation of sets with at least setEmpty and setInsert, one could then write:
val setLetters = string_foldr (fn (c, ls) => setInsert ls c) setEmpty "some sentence"
The simplest solution I can think of:
To get the distinct elements of a list:
Take the head
Remove that value from the tail and get the distinct elements of the result.
Put 1 and 2 together.
In code:
(* Return the distinct elements of a list *)
fun distinct [] = []
| distinct (x::xs) = x :: distinct (List.filter (fn c => x <> c) xs);
(* All the distinct letters, in lower case. *)
fun letters s = distinct (List.map Char.toLower (List.filter Char.isAlpha (explode s)));
(* Variation: "point-free" style *)
val letters' = distinct o (List.map Char.toLower) o (List.filter Char.isAlpha) o explode;
This is probably not the most efficient solution, but it's uncomplicated.
I have a list of doubles(myList), which I want to add to a new List (someList), but once the new list reaches a set size i.e. 25, I want to stop adding to it. I have tried implementing this function using sum but was unsuccessful. Example code below.
someList = [(a)| a <- myList, sum someList < 30]
The way #DanielFischer phrased the question is compatible with the Haskell way of thinking.
Do you want someList to be the longest prefix of myList that has a sum < 30?
Here's how I'd approach it: let's say our list is
>>> let list = [1..20]
we can find the "cumulative sums" using:
>>> let sums = tail . scanl (+) 0
>>> sums list
[1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,136,153,171,190,210]
Now zip that with the original list to get pairs of elements with the sum up to that point
>>> zip list (sums list)
[(1,1),(2,3),(3,6),(4,10),(5,15),(6,21),(7,28),(8,36),
(9,45),(10,55),(11,66),(12,78),(13,91),(14,105),(15,120),
(16,136),(17,153),(18,171),(19,190),(20,210)]
Then we can takeWhile this list to get the prefix we want:
>>> takeWhile (\x -> snd x < 30) (zip list (sums list))
[(1,1),(2,3),(3,6),(4,10),(5,15),(6,21),(7,28)]
finally we can get rid of the cumulative sums that we used to perform this calculation:
>>> map fst (takeWhile (\x -> snd x < 30) (zip list (sums list)))
[1,2,3,4,5,6,7]
Note that because of laziness, this is as efficient as the recursive solutions -- only the sums up to the point where they fail the test need to be calculated. This can be seen because the solution works on infinite lists (because if we needed to calculate all the sums, we would never finish).
I'd probably abstract this and take the limit as a parameter:
>>> :{
... let initial lim list =
... map fst (takeWhile (\x -> snd x < lim) (zip list (sums list)))
... :}
This function has an obvious property it should satisfy, namely that the sum of a list should always be less than the limit (as long as the limit is greater than 0). So we can use QuickCheck to make sure we did it right:
>>> import Test.QuickCheck
>>> quickCheck (\lim list -> lim > 0 ==> sum (initial lim list) < lim)
+++ OK, passed 100 tests.
someList = makeList myList [] 0 where
makeList (x:xs) ys total = let newTot = total + x
in if newTot >= 25
then ys
else makeList xs (ys ++ [x]) newTot
This takes elements from myList as long as their sum is less than 25.
The logic takes place in makeList. It takes the first element of the input list and adds it to the running total, to see if it's greater than 25. If it is, we shouldn't add it to the output list, and we finish recursing. Otherwise, we put x on the end of the output list (ys) and keep going with the rest of the input list.
The behaviour you want is
ghci> appendWhileUnder 25 [1..5] [1..5]
[1,2,3,4,5,1,2,3]
because that sums to 21 and adding the 4 would bring it to 25.
OK, one way to go about this is by just appending them with ++ then taking the initial segment that's under 25.
appendWhileUnder n xs ys = takeWhileUnder n (xs++ys)
I don't want to keep summing intermediate lists, so I'll keep track with how much I'm allowed (n).
takeWhileUnder n [] = []
takeWhileUnder n (x:xs) | x < n = x:takeWhileUnder (n-x) xs
| otherwise = []
Here I allow x through if it doesn't take me beyond what's left of my allowance.
Possibly undesired side effect: it'll chop out bits of the original list if it sums to over 25. Workaround: use
appendWhileUnder' n xs ys = xs ++ takeWhileUnder (n - sum xs)
which keeps the entire xs whether it brings you over n or not.
I have to iterate over 2 lists. One starts off as a list of empty sublists and the second one has the max length for each of the sublists that are in the first one.
Example; list1 = [[];[];[];]; list2 = [1;2;3]
I need to fill out the empty sublists in list1 ensuring that the length of the sublists never exceed the corresponding integer in list2. To that end, I wrote the following function, that given an element, elem and 2 two lists list and list, will fill out the sublists.
let mapfn elem list1 list2=
let d = ref 1 in
List.map2 (fun a b -> if ((List.length a) < b) && (!d=1)
then (incr d ; List.append a [elem])
else a )
list1 list2
;;
I can now call this function repeatedly on the elements of a list and get the final answer I need
This function works as expected. But I am little bothered by the need to use the int ref d.
Is there a better way for me to do this.
I always find it worthwhile to split the problem into byte-sized pieces that can be composed together to form a solution. You want to pad or truncate lists to a given length; this is easy to do in two steps, first pad, then truncate:
let all x = let rec xs = x :: xs in xs
let rec take n = function
| [] -> []
| _ when n = 0 -> []
| x :: xs -> x :: take (pred n) xs
all creates an infinite list by repeating a value, while take extracts the prefix sublist of at most the given length. With these two, padding and truncating is very straightforwad:
let pad_trim e n l = take n (l # all e)
(it might be a bit surprising that this actually works in a strict language like OCaml). With that defined, your required function is simply:
let mapfn elem list1 list2 = List.map2 (pad_trim elem) list2 list1
that is, taking the second list as a list of specified lengths, pad each of the lists in the first list to that length with the supplied padding element. For instance, mapfn 42 [[];[];[]] [1;2;3] gives [[42]; [42; 42]; [42; 42; 42]]. If this is not what you need, you can tweak the parts and their assembly to suit your requirements.
Are you looking for something like that?
let fill_list elem lengths =
let rec fill acc = function
| 0 -> acc
| n -> fill (elem :: acc) (n - 1) in
let accumulators = List.map (fun _ -> []) lengths in
List.map2 fill accumulators lengths
(* toplevel test *)
# let test = fill_list 42 [1; 3];;
val test : int list list = [[42]; [42; 42; 42]]
(I couldn't make sense of the first list of empty lists in your question, but I suspect it may be the accumulators for the tail-rec fill function.)