Related
Hello every body im training some SMLs and im creating a code to get deviation of a int list . in the process of it , i need to get a Real list out of some numbers in a int list , which it doesnt let me get them. heres my code :
fun mean [] = 0.0
| mean (first::rest) =
let
fun sum [] = 0
| sum (x::xs) = x + sum xs
fun counter [] = 0
| counter (y::ys) = 1 + counter ys
in
Real.fromInt (sum (first::rest)) / Real.fromInt (counter (first::rest))
end;
fun deviation [] = 0.0
| deviation (first::rest) =
let
fun diff (x::xs) = (x - mean (x::xs)) :: diff xs;
in
diff (first , first::rest) + deviation rest
end;
the problem is here :
fun diff (x::xs) = (x - mean (x::xs) ) :: diff xs;
diff is a recursive function, but the base case is never defined. When you try to run diff on an empty list, you will get a pattern match error.
You also define diff to accept a list, but you call it with a tuple.
You define diff as returning a list, given that you are using ::, but then you use addition on the result of that function, which will not work.
Improving mean
You can simplify your sum and counter functions with folds.
fun mean [] = 0.0
| mean lst =
let
val sum = foldl op+ 0 lst
val counter = foldl (fn (_, c) => c + 1) 0 lst
in
Real.fromInt sum / Real.fromInt counter
end;
But this requires iterating the entire list twice, when both pieces of information can be ascertained at the same time.
fun sumLen(lst) =
foldl (fn (x, (sum, len)) => (sum+x, len+1)) (0, 0) lst
mean can now be implemented as:
fun mean(lst) =
let
val (sum, len) = sumLen(lst)
in
Real.fromInt sum / Real.fromInt len
end
Deviation
To get the differences from the mean for a list, you need only use map.
fun diffs(lst) =
let
val m = mean(lst)
in
map (fn x => Real.fromInt x - m) lst
end
Consider evaluating the following.
diffs [1, 2, 3, 4, 5, 6, 7, 8]
The result is:
[~3.5, ~2.5, ~1.5, ~0.5, 0.5, 1.5, 2.5, 3.5]
From there you can use map and Math.pow to square those differences, foldl to sum them, divide by the length of the list, and then Math.sqrt to get the standard deviation.
I am trying to write a simple function in OCaml
let rec pell (i: int) =
(if i <= 2 then i (*if given n is less tahn 2 then return 2, else return previous n-1 th term and n-2 nd term recursively*)
else if i>2 then
2 * pell i - 1 + pell i - 2
else failwith "unimplemented" (*else fail with unimplemented message*)
);;
Write an infinite precision version of the pell function from before
pell2 0 = []
pell2 1 = [1]
pell2 7 = [9; 6; 1]
pell2 50 = [2; 2; 5; 3; 5; 1; 4; 2; 9; 2; 4; 6; 2; 5; 7; 6; 6; 8; 4]
I have written below code for this:
let rec pell2 i =
(if i <= 2 then
[] -> i;
else if i=0 then [];
else if i>2 then (*finding pell number and using sum function to
output list with infinite precision...*)
[] -> pell2 i-1 + pell2 i-2;
else failwith "unimplemented"
);;
but still has some syntax errors. Can someone help me with this please.
if i <= 2 then
[] -> i
In snippets like this, the -> is invalid. It looks like you might be mixing pattern matching with match ... with ... and if/else up.
Also, you're first checking if i is less than or equal to 2, but then you have an else to test for i being equal to zero. The first check means the second is never going to happen.
First, let's look at the examples for the output of pell2. We see that pell2 has a single integer parameter, and returns a list of integers. So, we know that the function we want to create has the following type signature:
pell2: int -> int list
Fixing (some but not all of) the syntax errors and trying to maintain your logic,
let rec pell2 i =
if i=0 then []
else if i <= 2 then i
else if i>2 then pell2 i-1 + pell2 i-2
Note that I removed the semicolons at the end of each expression since OCaml's use of a semicolon in its syntax is specifically for dealing with expressions that evaluate to unit (). See ivg's excellent explanation on this. The major flaw with this code is that it does not type check. We see that we conditionally return a list, and otherwise return an int. Notice how above we defined that pell2 should return an int list. So, we can begin fixing this by wrapping our int results in a list:
let rec pell2 n =
if n = 0 then []
else if n <= 2 then [n]
else ... something that will return the Pell number as a list ...
As you have already written, the else branch can be written using recursive calls to the pell2 function. However, we can't write it as you did previously, because pell2 evaluates to a list, and the binary operator + only works on two integers. So, we will have to define our own way of summing lists. Calling this sum_lists, we are left with the following code:
We can now fully define our function pell2:
let rec pell2 n =
if n = 0 then []
else if n <= 2 then [n]
else (* Pell(n) = (2 * Pell(n-1)) + Pell(n-2) *)
let half_of_first_term = pell2 n-1 in
let first_term = sum_lists half_of_first_term half_of_first_term in
let second_term = pell2 n-2 in
sum_lists first_term second_term
So, all that is left is to define sum_lists, so that we are properly summing together two lists of the same format as the return type of pell2. The signature for sum_lists would be
sum_lists: int list -> int list -> int list
I'll give a basic outline of the implementation, but will leave the rest for you to figure out, as this is the main crux of the assignment problem.
let sum_lists lst1 lst2 =
let rec sum_lists_helper lst1 lst2 carry =
match lst1, lst2 with
| [], [] -> if carry = 1 then [1] else []
| h::t, []
| [], h::t -> ...
| h1::t1, h2::t2 -> ...
in
sum_lists_helper lst1 lst2 0
for example, if I have a list [1,1,2,3,5,1], I want to count the number of 1's in this list, how would I do that?
I wrote something like:
count([], 0).
count([H|T], N) :-
count(T, X),
( H =:= 1
-> N is X+1
; N is X
),
N > 0.
In this recursion, I want to do if Head equals 1, then the counting + 1, if Head is not 1, then counting stays the same. However, it returns false if I have things that are not 1 in the list. I know the problem is that it'd fail as soon as an element does not satisfy the if statement; and it can never reach the else statement. How do I fix this? Please help!!!!
Try this:
count([],0).
count([1|T],N) :- count(T,N1), N is N1 + 1.
count([X|T],N) :- X \= 1, count(T,N).
Alternative solution, which uses foldl/4 and defines higher order predicate (the one which takes another predicate as a parameter):
count_step(Condition, Item, CurrentCount, NewCount) :-
call(Condition, Item) ->
NewCount is CurrentCount + 1 ;
NewCount = CurrentCount.
count(List, Condition, Count) :-
foldl(count_step(Condition), List, 0, Count).
is_one(Expr) :-
Expr =:= 1.
Usage example:
?- count([0, 2, 3, 0], is_one, Count).
Count = 0.
?- count([1, 2, 3, 1], is_one, Count).
Count = 2.
Another (rather dirty) approach is to use include/3 combined with length/2:
count(List, Condition, Count) :-
include(Condition, List, Filtered),
length(Filtered, Count).
Let’s start with your code and ask some queries!
I added comments on the side showing the result I would have expected...
?- count([0,2,3,0], Count).
false % bad: expected Count = 0
?- count([1,2,3,1], Count).
Count = 2 % ok
?- count([1,2,3], Count).
false % bad: expected Count = 1
If my expectation matches yours, the minimal fix for your code is tiny: just remove the goal N > 0!
count([], 0).
count([H|T], N) :-
count(T, X),
( H =:= 1
-> N is X+1
; N is X
).
Let’s run above queries again:
?- count([0,2,3,0], Count).
Count = 0 % was “false”, now ok
?- count([1,2,3,1], Count).
Count = 2 % was ok, still is ok
?- count([1,2,3], Count).
Count = 1. % was “false”, now ok
The bottom line: your original code failed whenever the last list item was not equal to 1.
Since you've already opted to use (;)/2 - if-then-else, you might find the following variant with if_/3 interesting:
list_1s(L,X) :-
length(L,Len),
list_1s_(L,X,0,Len).
list_1s_([],X,X,0).
list_1s_([Y|Ys],X,Acc0,Len1) :-
if_(Y=1, Acc1 is Acc0+1, Acc1 is Acc0),
Len0 is Len1-1,
list_1s_(Ys,X,Acc1,Len0).
The goal length/2 in the calling predicate list_1s/2 together with the 4th argument of the actual relation list_1s_/4 is used to make sure the result lists are listed in a fair manner if the predicate is called with the first argument being variable. The 3rd argument of list_1s_/4 is an accumulator that's used to count the number of 1s up from zero, in order to make the predicate tail recursive. Consequently the 2nd and 3rd arguments of list_1s_/4 are equal if the list is empty. Now let's see some example queries. In the list to number direction the predicate yields the desired results and succeeds deterministically (it doesn't leave unnecessary choice points open, no need to press ; after the single answer) in doing so:
?- list_1s([],X).
X = 0.
?- list_1s([1,2,3],X).
X = 1.
?- list_1s([1,2,3,1],X).
X = 2.
?- list_1s([0,2,3,0],X).
X = 0.
In the number to list direction there are infinitely many lists for any given number and, as mentioned above, they are listed in a fair manner, that is, all possibilities of lists of length n are listed before moving on to length n+1:
?- list_1s(L,0).
L = [] ; % <- empty list
L = [_G386], % <- length 1
dif(_G386, 1) ;
L = [_G442, _G445], % <- length 2
dif(_G442, 1),
dif(_G445, 1) ;
L = [_G498, _G501, _G504], % <- length 3
dif(_G498, 1),
dif(_G501, 1),
dif(_G504, 1) ;
.
.
.
?- list_1s(L,1).
L = [1] ; % <- length 1
L = [1, _G404], % <- length 2
dif(_G404, 1) ;
L = [_G401, 1], % <- length 2
dif(_G401, 1) ;
L = [1, _G460, _G463], % <- length 3
dif(_G460, 1),
dif(_G463, 1) ;
L = [_G457, 1, _G463], % <- length 3
dif(_G457, 1),
dif(_G463, 1) ;
L = [_G457, _G460, 1], % <- length 3
dif(_G457, 1),
dif(_G460, 1) ;
.
.
.
And the most general query is listing the results in a fair manner as well:
?- list_1s(L,X).
L = [], % <- empty list
X = 0 ;
L = [1], % <- length 1
X = 1 ;
L = [_G413], % <- length 1
X = 0,
dif(_G413, 1) ;
L = [1, 1], % <- length 2
X = 2 ;
L = [1, _G431], % <- length 2
X = 1,
dif(_G431, 1) ;
L = [_G428, 1], % <- length 2
X = 1,
dif(_G428, 1) ;
.
.
.
Suppose I have the following nested list:
list =
[[0, 1, 0],
[1, 9, 1],
[1, 1, 0]]
Assuming you are only given the x and y coordinate of 9. How do I use Haskell code to find out how many 1's surrounds the number 9?
Let me clarify a bit more, assume the number 9 is positioned at (0, 0).
What I am trying to do is this:
int sum = 0;
for(int i = -1; i <= 1; i++){
for(int j = -1; j <= 1; j++){
if(i == 0 || j == 0) continue;
sum += list[i][j];
}
}
The positions surrounding (0,0) are the following coordinates:
(-1, -1) (0, -1) (1, -1)
(-1, 0) (1, 0)
(-1, 1) (0, 1) (1, 1)
list = [[0,1,0],[1,9,1],[1,1,0]]
s x y = sum [list !! j !! i | i <- [x-1..x+1], j <- [y-1..y+1], i /= x || j /= y]
--s 1 1 --> 5
Note that I there is no error correction if the coordinates are at the edge. You could implement this by adding more conditions to the comprehension.
A list of lists isn't the most efficient data structure if things get bigger. You could consider vectors, or a Map (Int,Int) Int (especially if you have many zeros that could be left out).
[Edit]
Here is a slightly faster version:
s x y xss = let snip i zs = take 3 $ drop (i-1) zs
sqr = map (snip x) $ snip y xss
in sum (concat sqr) - sqr !! 1 !! 1
First we "snip out" the 3 x 3 square, then we do all calculations on it. Again, coordinates on the edges would lead to wrong results.
Edit: switched to summing surrounding 8 rather than surrounding 4
How often do you just want the surrounding count for just one entry? If you want it for all the entries, lists still perform fairly well, you just have to look at it holistically.
module Grid where
import Data.List (zipWith4)
-- given a grid A, generate grid B s.t.
-- B(x,y) = A(x-1,y-1) + A(x,y-1) + A(x+1,y-1)
-- + A(x-1,y) + A(x+1,y)
-- + A(x-1,y+1) + A(x,y+1) + A(x+1,y+1)
-- (where undefined indexes are assumed to be 0)
surrsum :: [[Int]] -> [[Int]]
surrsum rs = zipWith3 merge rs ([] : init rs') (tail rs' ++ [[]])
where -- calculate the 3 element sums on each row, so we can reuse them
rs' = flip map rs $ \xs -> zipWith3 add3 xs (0 : xs) (tail xs ++ [0])
add3 a b c = a+b+c
add4 a b c d = a+b+c+d
merge [] _ _ = []
-- add the left cell, right cell, and the 3-element sums above and below (zero-padded)
merge as bs cs = zipWith4 add4 (0 : init as) (tail as ++ [0]) (bs ++ repeat 0) (cs ++ repeat 0)
-- given a grid A, replace entries not equal to 1 with 0
onesOnly :: [[Int]] -> [[Int]]
onesOnly = map . map $ \e -> if e == 1 then 1 else 0
list :: [[Int]]
list = [[0, 1, 0]
,[1, 9, 1]
,[1, 1, 0]]
Now you can drop down to ghci to see it work:
*Grid Control.Monad> mapM_ (putStrLn . unwords . map show) list
0 1 0
1 9 1
1 1 0
*Grid Control.Monad> mapM_ (putStrLn . unwords . map show) $ onesOnly list
0 1 0
1 0 1
1 1 0
*Grid Control.Monad> mapM_ (putStrLn . unwords . map show) . surrsum $ onesOnly list
2 2 2
3 5 2
2 3 2
I am trying to write a function
row :: Int -> Int -> [Int]
row n v
that returns a list of n integers, all 0's, except for the vth element, which needs to be a 1.
For instance,
row 0 0 = []
row 5 1 = [1,0,0,0,0]
row 5 3 = [0,0,1,0,0]
I am new to Haskell and having a lot of difficulty with this. In particular I can't figure out how to make it repeat 0's. I understand the concept of building a list from let's say [1..n], but I just get [1,2,3,4,5]
Any help with this would be greatly appreciated. Thank you.
Try:
let row n v = map (\x -> if x == v then 1 else 0) [1..n]
Here a "monadic" solution:
row n v = [(v-1, 0), (1, 1), (n-v, 0)] >>= (uncurry replicate)
The replicate function repeats a given value a number of times, e.g. replicate (v-1) 0 gives a list of v-1 zeros. The uncurry is used to modify the replicate in order to accept a tuple instead of two single arguments. The funny operator >>= is the heart of a monad; for lists it is the same as concatMap with flipped arguments.
With a comprehensive list :
row n v = [if x == v then 1 else 0 | x <- [1..n]]
Or using fromEnum (thanks dave4420)
row n v = [fromEnum (x == v) | x <- [1..n]]
This should also work:
row n v = replicate (v-1) 0 ++ [1] ++ replicate (n-v) 0
And yet another solution, recursively building up the list:
row :: Int -> Int -> [Int]
row 0 _ = []
row n 1 = 1 : (row (n-1) 0)
row n m = 0 : (row (n-1) (m-1))
And a more readable one, where zeros are "taken":
row :: Int -> Int -> [Int]
row 0 _ = []
row n m = take (m - 1) zeros ++ [1] ++ take (n - m) zeros
where zeros = (iterate id 0)
A simple recursive loop with two temporary variables c and lst . c is for counting and lst is list which we have to return.
row :: Int -> Int -> [ Int ]
row 0 0 = []
row n v = rowHelp n v 1 [] where
rowHelp n v c lst
| c > n = lst
| v == c = rowHelp n v ( c + 1 ) ( lst ++ [ 1 ] )
| otherwise = rowHelp n v ( c + 1 ) ( lst ++ [ 0 ] )
~
~
the fun with haskell is that it let's you write your program very much the way you would express the algorithm. So try:
row n v = [if (x `mod` v==0) then 1 else 0 | x <- [1..n] ]
At first you create a list from 1,2 to n.
Then you check if the number is divisible by v, if it is, 1 is inserted in the output list, if not 0.
Examples:
> row 0 0
[]
> row 5 1
[1,0,0,0,0]
> row 5 3
[0,0,1,0,0]
> row 15 3
[0,0,1,0,0,1,0,0,1,0,0,1,0,0,1]
HTH Chris
I like to demonstrate a top down approach, based on Chris's solution:
row n v = result
where
result = take n numbers -- our result will have a length of n
numbers = map trans [1,2,..] -- and is some transformation of
-- the list of natural numbers
trans e
| e `mod` v == 0 = 1 -- let every v-th element be 1
| otherwise = 0 -- 0 otherwise
This style emphasizes the idea in functional programming that one writes down what a certain value like row n v is supposed to be, rather than trying to write down what a function does. In reminiscence of a well known joke about the lesser known pragramming language Sartre one could say that in pure functional programming functions do nothing, they just are.