Haskell check integer first element to process an ID number - list

I'm a newbie in haskell!
I need to write a function that process an ID number. I need to check the first digit of the integer number. If the number is 1 or 3 then the client is male, if the number is 2 or 4 then female. I think I need a helper function which splitting the long integer number to an integer list.
The fuction called szemelyinem, it has one parameter/argument which is a 11 long integer number.
This is the spliting function:
split :: Integral x => x -> [x]
split 0 = []
split x = split (x `div` 10) ++ [x `mod` 10]
In my head the notion is Split the long number then load it to the function, then check the first element in the list and return with one string. But I don't know how to start this :/
I have an example like this:
szemelyinem 40504291247
Result: "female"

This is the first step.
split :: Integral x => x -> [x]
split 0 = []
split x = split (x `div` 10) ++ [x `mod` 10]
This is the second.
rev:: [Integer] -> [Integer]
rev [] = []
rev (h:t) = rev t ++ [h]
This is the third step
nemdel :: [Integer] -> [Integer]
nemdel [] = []
nemdel (h:t) = drop 10 (h:t)
This is the fourth.
listtonumb:: [Integer] -> Integer
listtonumb = foldl addDigit 0
where addDigit num d = 10*num + d
And the last one.
szemelyinem :: Integer -> [Char]
szemelyinem szam =
if listtonumb(nemdel(rev(split szam))) == 1 || listtonumb(nemdel(rev(split szam))) == 3
then "male"
else if listtonumb(nemdel(rev(split szam))) == 2 || listtonumb(nemdel(rev(split szam))) == 4
then "Female"
else error "Bad ID"
I'm sure about that is a complex way to do this shit.

Related

Show all numbers at prime indexes in a list - haskell - filter error

This is for a class
We're supposed to write 3 functions :
1 : Prints list of fibbonaci numbers
2 : Prints list of prime numbers
3 : Prints list of fibonacci numbers whose indexes are prime
EG : Let this be fibbonaci series
Then In partC - certain elements are only shown
1: 1
*2: 1 (shown as index 2 is prime )
*3: 2 (shown as index 3 is prime )
4: 3
*5: 5 (shown )
6: 8
*7: 13 (shown as index 7 prime and so on)
I'm done with part 1 & 2 but I'm struggling with part 3. I created a function listNum that creates a sort of mapping [Integer, Integer] from the Fibbonaci series - where 1st Int is the index and 2nd int is the actual fibbonaci numbers.
Now my function partC is trying to stitch snd elements of the fibonaci series by filtering the indexes but I'm doing something wrong in the filter step.
Any help would be appreciated as I'm a beginner to Haskell.
Thanks!
fib :: [Integer]
fib = 0 : 1 : zipWith (+) fib (tail fib)
listNum :: [(Integer, Integer)]
listNum = zip [1 .. ] fib
primes :: [Integer]
primes = sieve (2 : [3,5 ..])
where
sieve (p:xs) = p : sieve [x | x <- xs , x `mod` p > 0]
partC :: [Integer] -- Problem in filter part of this function
partC = map snd listNum $ filter (\x -> x `elem` primes) [1,2 ..]
main = do
print (take 10 fib) -- Works fine
print (take 10 primes) --works fine
print (take 10 listNum) --works fine
print ( take 10 partC) -- Causes error
Error :
prog0.hs:14:9: error:
• Couldn't match expected type ‘[Integer] -> [Integer]’
with actual type ‘[Integer]’
• The first argument of ($) takes one argument,
but its type ‘[Integer]’ has none
In the expression:
map snd listNum $ filter (\ x -> x `elem` primes) [1, 2 .. ]
In an equation for ‘partC’:
partC
= map snd listNum $ filter (\ x -> x `elem` primes) [1, 2 .. ]
|
14 | partC = map snd listNum $ filter (\x -> x `elem` primes) [1,2 ..]
Here's what I think you intended as the original logic of partC. You got the syntax mostly right, but the logic has a flaw.
partC = snd <$> filter ((`elem` primes) . fst) (zip [1..] fib)
-- note that (<$>) = fmap = map, just infix
-- list comprehension
partC = [fn | (idx, fn) <- zip [1..] fib, idx `elem` primes]
But this cannot work. As #DanRobertson notes, you'll try to check 4 `elem` primes and run into an infinite loop, because primes is infinite and elem tries to be really sure that 4 isn't an element before giving up. We humans know that 4 isn't an element of primes, but elem doesn't.
There are two ways out. We can write a custom version of elem that gives up once it finds an element larger than the one we're looking for:
sortedElem :: Ord a => a -> [a] -> Bool
sortedElem x (h:tl) = case x `compare` h of
LT -> False
EQ -> True
GT -> sortedElem x tl
sortedElem _ [] = False
-- or
sortedElem x = foldr (\h tl -> case x `compare` h of
LT -> False
EQ -> True
GT -> tl
) False
Since primes is a sorted list, sortedElem will always give the correct answer now:
partC = snd <$> filter ((`sortedElem` primes) . fst) (zip [1..] fib)
However, there is a performance issue, because every call to sortedElem has to start at the very beginning of primes and walk all the way down until it figures out whether or not the index is right. This leads into the second way:
partC = go primeDiffs fib
where primeDiffs = zipWith (-) primes (1:primes)
-- primeDiffs = [1, 1, 2, 2, 4, 2, 4, 2, 4, 6, ...]
-- The distance from one prime (incl. 1) to the next
go (step:steps) xs = x:go steps xs'
where xs'#(x:_) = drop step xs
go [] _ = [] -- unused here
-- in real code you might pull this out into an atOrderedIndices :: [Int] -> [a] -> [a]
We transform the list of indices (primes) into a list of offsets, each one building on the next, and we call it primeDiffs. We then define go to take such a list of offsets and extract elements from another list. It first drops the elements being skipped, and then puts the top element into the result before building the rest of the list. Under -O2, on my machine, this version is twice as fast as the other one when finding partC !! 5000.

Haskell. Trouble with list of lists

I have list of lists of Int and I need to add an Int value to the last list from the list of lists. How can I do this? My attempt is below
f :: [[Int]] -> [Int] -> Int -> Int -> Int -> [[Int]]
f xs [] cur done total = [[]]
f xs xs2 cur done total = do
if total >= length xs2 then
xs
else
if done == fib cur then
f (xs ++ [[]]) xs2 (cur + 1) 0 total
else
f ((last xs) ++ [[xs2!!total]]) xs2 cur (done + 1) (total + 1)
The problem is:
We have a list A of Int
And we need to slpit it on N lists B_1 ,..., B_n , length of B_i is i-th Fibonacci number.
If we have list [1 , 2 , 3 , 4 , 5 , 6 , 7] (xs2 in my code)
The result should be [[1] , [2] , [3 , 4] , [5 , 6 , 7]]
The easy way to deal with problems like this is to separate the problem into sub-problems. In this case, you want to change the last item in a list. The way you want to change it is by adding an item to it.
First let's tackle changing the last item of a list. We'll do this by applying a function to the last item, but not to any other items.
onLast :: [a] -> (a -> a) -> [a]
onLast xs f = go xs
where
go [] = []
go [x] = [f x]
go (x:xs) = x:go xs
You want to change the last item in the list by adding an additional value, which you can do with (++ [value]).
Combining the two with the value you want to add (xs2!!total) we get
(onLast xs (++ [xs2!!total]))
f :: [[Int]] -> Int -> [[Int]]
f [] _ = []
f xs i = (take n xs) ++ [[x + i | x <- last xs]]
where n = (length xs) - 1
last = head . (drop n)
For example,
*Main> f [[1, 2, 3], [], [4, 5, 6]] 5
[[1,2,3],[],[9,10,11]]
*Main> f [[1, 2, 3]] 5
[[6,7,8]]
*Main> f [] 3
You approach uses a do block, this is kind of weird since do blocks are usually used for monads. Furthermore it is rather unclear what cur, done and total are doing. Furthermore you use (!!) :: [a] -> Int -> a and length :: [a] -> Int. The problem with these functions is that these run in O(n), so it makes the code inefficient as well.
Based on changed specifications, you want to split the list in buckets with length the Fibonacci numbers. In that case the signature should be:
f :: [a] -> [[a]]
because as input you give a list of numbers, and as output, you return a list of numbers. We can then implement that as:
f :: [a] -> [[a]]
f = g 0 1
where g _ _ [] = []
g a b xs = xa : g b (a+b) xb
where (xa,xb) = splitAt b xs
This generates:
*Main> f [1,2,3,4,5,6]
[[1],[2],[3,4],[5,6]]
*Main> f [1,2,3,4,5,6,7]
[[1],[2],[3,4],[5,6,7]]
*Main> f [1,2,3,4,5,6,7,8]
[[1],[2],[3,4],[5,6,7],[8]]
*Main> f [1,2,3,4,5,6,7,8,9]
[[1],[2],[3,4],[5,6,7],[8,9]]
The code works as follows: we state that f = g 0 1 so we pass the arguments of f to g, but g also gets an 0 and a 1 (the first Fibonacci numbers).
Each iteration g checks whether we reached the end of the list. If so, we return an empty list as well. Otherwise we determine the last Fibonacci number that far (b), and use a splitAt to obtain the first b elements of the list we process, as well as the remainder. We then emit the first part as head of the list, and for the tail we calculate the next Fibonacci number and pass that to g with the tail of splitAt.

Finding sublists with a specified sum

I'm working on a function in Haskell where it receives a list of Ints and an Int.
sublistSum :: [Ints] -> Int -> [[Ints]]
What it returns is a sublist containing lists of numbers in the original list that adds up to the Int.
For example:
sublistSums [1, 5, -2, 4, 3, 2] 2
[[1,-2,3],[-2,4],[2]]
What I worked up to:
sublistSums [] num = []
sublistSums (x:xs) num
| findSum x xs num == num = findSum x xs num 0 : sublistSums (x:xs) num
| otherwise = sublistSums xs num
findSum x [] num count = []
findSum x (y:ys) num count
| ...
so findSum is a helper function I made that should return a list of such numbers (that add up to the number).
I'm a bit confused up to this point. How can I mark it so that findSum doesn't repeatedly give me the same list of numbers over and over again?
You could first produce a list of all possible sublists using the function subsequences from Data.List. Then it is just a matter of filtering the list by their sum.
import Data.List
sublistSum :: [Int] -> Int -> [[Int]]
sublistSum list target =
filter (\x -> sum x == target) $ subsequences list

Kaprekar's Routine - Haskell Implementation

I am having a little trouble with Haskell. I am doing an implemenation of Kaprekar's routine (http://en.wikipedia.org/wiki/6174_%28number%29) and I have done everything but being able to successfully print the list of numbers that the routine produces. So, if I put in the number 5432, I would like the output to be [5432, 3087, 8352, 6174].
Here is the code I have:
kaprekarList :: Integer -> [Integer]
kaprekarList x = n
where p = kaprekar x
n =
if p == 6174
then [p]
else
-- add to list of kaprekar numbers
kaprekarList p
Any help is greatly appreciated!
While not the most beautiful routine (and having a small problem see below) yours seems to work (if the kaprekar function does), so I guess your problem is really there.
Here is a simple implementation together with your function:
kaprekar :: Integer -> Integer
kaprekar n = big - small
where big = read digits
small = read (reverse digits)
digits = take 4 $ (reverse . sort . show $ n) ++ "0000"
kaprekarList :: Integer -> [Integer]
kaprekarList x = n
where p = kaprekar x
n =
if p == 6174
then [x, p]
else
-- add to list of kaprekar numbers
x : kaprekarList p
Please mind the small changes so that you can see the complete derivation instead of just the last element (that is always fixed).
alternative versions
kaprekarList :: Integer -> [Integer]
kaprekarList x = x : if x == 6174 then [] else kaprekarList (kaprekar x)
this one seems to be a bit more idiomatic but will not include the last 6174
kaprekarList :: Integer -> [Integer]
kaprekarList x = takeWhile (/= 6174) $ iterate kaprekar x
this one will (but is ugly - maybe someone knows something like takeUntil in the prelude?):
kaprekarList :: Integer -> [Integer]
kaprekarList x = (takeWhile (/= 6174) $ iterate kaprekar x) ++ [6174]
Here an implementation:
import Data.List (sort)
-- Convert a number to a list of digits
digits :: Integral x => x -> [x]
digits 0 = []
digits x = digits (x `div` 10) ++ [x `mod` 10]
-- Convert a list of digits to a number
undigits :: Integral x => [x] -> x
undigits = foldl (\ a b -> a * 10 + b) 0
-- Compute the next Kaprekar number
nextKapNumber :: Integral x => x -> x
nextKapNumber x = b - a
where n = sort . digits $ x
a = undigits n
b = undigits . reverse $ n
-- Compute the Kaprekar list for a number
kapList :: Integral x => x -> [x]
kapList x = genList [x]
where genList as#(6174:_) = reverse as
genList as#(a:_) = genList $ nextKapNumber a : as
main :: IO ()
main = putStrLn . show $ kapList 5432

Haskell List Generator

I've been working with problems (such as pentagonal numbers) that involve generating a list based on the previous elements in the list. I can't seem to find a built-in function of the form I want. Essentially, I'm looking for a function of the form:
([a] -> a) -> [a] -> [a]
Where ([a] -> a) takes the list so far and yields the next element that should be in the list and a or [a] is the initial list. I tried using iterate to achieve this, but that yields a list of lists, which each successive list having one more element (so to get the 3000th element I have to do (list !! 3000) !! 3000) instead of list !! 3000.
If the recurrence depends on a constant number of previous terms, then you can define the series using standard corecursion, like with the fibonacci sequence:
-- fibs(0) = 1
-- fibs(1) = 1
-- fibs(n+2) = fibs(n) + fibs(n+1)
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
-- foos(0) = -1
-- foos(1) = 0
-- foos(2) = 1
-- foos(n+3) = foos(n) - 2*foos(n+1) + foos(n+2)
foos = -1 : 0 : 1 : zipWith (+) foos
(zipWith (+)
(map (negate 2 *) (tail foos))
(tail $ tail foos))
Although you can introduce some custom functions to make the syntax a little nicer
(#) = flip drop
infixl 7 #
zipMinus = zipWith (-)
zipPlus = zipWith (+)
-- foos(1) = 0
-- foos(2) = 1
-- foos(n+3) = foos(n) - 2*foos(n+1) + foos(n+2)
foos = -1 : 0 : 1 : ( ( foos # 0 `zipMinus` ((2*) <$> foos # 1) )
`zipPlus` foos # 2 )
However, if the number of terms varies, then you'll need a different approach.
For example, consider p(n), the number of ways in which a given positive integer can be expressed as a sum of positive integers.
p(n) = p(n-1) + p(n-2) - p(n-5) - p(n-7) + p(n-12) + p(n-15) - ...
We can define this more simply as
p(n) = ∑ k ∈ [1,n) q(k) p(n-k)
Where
-- q( i ) | i == (3k^2+5k)/2 = (-1) ^ k
-- | i == (3k^2+7k+2)/2 = (-1) ^ k
-- | otherwise = 0
q = go id 1
where go zs c = zs . zs . (c:) . zs . (c:) $ go ((0:) . zs) (negate c)
ghci> take 15 $ zip [1..] q
[(1,1),(2,1),(3,0),(4,0),(5,-1),(6,0),(7,-1),(8,0),(9,0),(10,0),(11,0),(12,1),
(13,0),(14,0),(15,1)]
Then we could use iterate to define p:
p = map head $ iterate next [1]
where next xs = sum (zipWith (*) q xs) : xs
Note how iterate next creates a series of reversed prefixes of p to make it easy to use q to calculate the next element of p. We then take the head element of each of these reversed prefixes to find p.
ghci> next [1]
[1,1]
ghci> next it
[2,1,1]
ghci> next it
[3,2,1,1]
ghci> next it
[5,3,2,1,1]
ghci> next it
[7,5,3,2,1,1]
ghci> next it
[11,7,5,3,2,1,1]
ghci> next it
[15,11,7,5,3,2,1,1]
ghci> next it
[22,15,11,7,5,3,2,1,1]
Abstracting this out to a pattern, we can get the function you were looking for:
construct :: ([a] -> a) -> [a] -> [a]
construct f = map head . iterate (\as -> f as : as)
p = construct (sum . zipWith (*) q) [1]
Alternately, we could do this in the standard corecursive style if we define a helper function to generate the reversed prefixes of a list:
rInits :: [a] -> [[a]]
rInits = scanl (flip (:)) []
p = 1 : map (sum . zipWith (*) q) (tail $ rInits p)