So im still very new to programming and I'm struggling a lot with the Syntax of Haskell. I kind of know what I want to implement but im not really sure how to do it so I came here to ask.
So what I have is a "pile" of Numbers in no particular order that are defined by 3 different functions. An example for this would be:
lowestnumber = 4
highestnumber 5 = True
highestnumber _ = False
above 4 = 11
above 11 = 18
above 18 = 2
above 2 = 3
above 3 = 5
above 5 = error "highest Number"
above _ = error "Not part of the pile"
Now for one I want to write a function that checks if a certain number is part of this pile and a different function "sum' = " that sums up all the elements of the list without an input variable. First I solved these problems by defining a list and using listcommands in order to sum up and see if something is "elem" of that list but I am supposed to solve it without using lists.
So I have ideas of how to solve this but I have no idea of how to actually write it without receiving countless errors.
Some examples of what I've tried for the check function:
check x = if above x /= error "Not part of the stack" || lowestnumber == x then True else False
I also tried the checks with "_" like this but it wouldn't work either:
check x if above x == _ || lowestnumber == x then True else False
My idea for the sum function was this:
sum' = lowestnumber + above lowestnumber + above (above lowestnumber) + above (above (above lowestnumber))
or also something like
sum' = lowestnumber + (above sum')
Which I understand woul
and so on but I did not figure out how I could implement this using recursion which is apparently the way to go.
Well hopefully this question isnt too stupid! I hope you can help me :)
Edit: Ok, so these are the solutions to my 3 function-problems
sumup' a b
|highestNumber a == True = a+b
|otherwise = sumup' (above a) (a+b)
sumup = sumup' lowestNumber 0
check' a b
|a == b = True
|True == highestNumber a && a==b = True
|True == highestNumber a && a/=b = False
|check' (above a) (b) == True = True
|otherwise = False
check b = check' (lowestNumber) (b)
above' :: Integer -> Integer -> Bool
above' x y
| check x == False = False
| check y == False = False
| highestNumber y == True = False
| highestNumber x == True = True
| x==y = True
| above' x (above y) == True = True
| otherwise = False
If you want to do this without lists, keep a running total, and use recursion.
If you're at the highestnumber, just add that to your current total and stop,
otherwise, add the number to your total total + n and move on to the next one above n:
add n total |highestnumber n = total + n
|otherwise = add (above n) (total + n)
Then you can do
answer = add lowestnumber 0
You're supposed to do this without lists, well that's sad because it would be very much the idiomatic solution.
The nextmost idiomatic one would be something generic that is able to traverse your pile there. You basically want a fold over the numbers:
foldlMyPile :: (a -> Int -> a) -> a -> {- Pile -> -} a
foldlMyPile f = go lowestNumber
where go n accum
| highestNumber n = result
| otherwise = go (above n) result
where result = f accum n
Once you've got this, you can use it to define sum, element etc. much like they are defined on lists:
sumPile :: Int
sumPile = foldlMyPile (+) 0
elemPile :: Int -> Bool
elemPile n = foldlMyPile $ \alreadyFound n' -> alreadyFound || n==n'
Various higher order functions in Haskell capture various recursion (and corecursion†) patterns, like iterate, foldr, unfoldr, etc.
Here we can use until :: (a -> Bool) -> (a -> a) -> a -> a, where until p f x yields the result of iteratively applying f until p holds, starting with x:
sumPile = snd $
until (highestnumber . fst)
(\(a,b)->(above a, b + above a))
(lowestnumber, lowestnumber)
also,
inThePile p = p==until (\n-> highestnumber n || n==p) above lowestnumber
† basically, recursion with accumulator, building its result on the way forward from the starting case, whereas regular recursion builds its result on the way back from the base case.
About your three new functions.
sumup' a b
| highestNumber a == True = a+b
| otherwise = sumup' (above a) (a+b)
sumup = sumup' lowestNumber 0 -- sum up all numbers in the pile
this is almost exactly as in AndrewC'c answer. it is good, except == Temp is totally superfluous, not needed. sumup' also would usually be made an internal function, moved into a where clause. As such, it doesn't have to have a descriptive name. Some use (Scheme-inspired?) loop, some go (since do is a reserved syntax keyword). I personally started to use just g recently:
sumup = g lowestNumber 0 -- sum up all numbers in the pile
where
g n tot -- short, descriptive/suggestive var names
| highestNumber n = n + tot
| otherwise = g (above n) (n + tot)
check b = check' lowestNumber b -- don't need any parens here
check' a b
|a == b = True
|True == highestNumber a && a==b = True -- `True ==` not needed
|True == highestNumber a && a/=b = False -- `True ==` not needed
|check' (above a) (b) == True = True -- `== True` not needed
|otherwise = False
This usually would be written as
check' a b = (a == b) ||
(highestNumber a && a==b) ||
( not (highestNumber a && a/=b)
&& check' (above a) b )
in the 2nd test, if a==b were true, it'd already worked in the 1st rule, so we can assume that a/=b henceforth. so 2nd test is always false; and we get
check' a b = (a == b) ||
(not (highestNumber a) && check' (above a) b)
which is rather OK looking. It can be also written with guards again, as
check' a b | (a == b) = True
| highestNumber a = False
| otherwise = check' (above a) b
or, using short suggestive variable names, and with swapped order of arguments, for consistency,
check' n i | highestNumber i = i == n
| otherwise = i == n || check' n (above i)
which is rather similar to how the first, sumup code is structured.
Now, the third function. First of all, it can easily be defined in terms of check' too, just starting with the given low number instead of the lowest one:
higher top low = check low && not (highestNumber low)
&& check' top (above low)
("higher" is a more distinctive name, yes?). Your version:
higher :: Integer -> Integer -> Bool
higher x y
| check x == False = False -- not(check x == False) -- ==
| check y == False = False -- check x == True -- ==
| highestNumber y == True = False -- check x
| highestNumber x == True = True
| x==y = True
| higher x (above y) == True = True
| otherwise = False
again, simplifying,
higher x y = check x && check y
&& not (highestNumber y)
&& ( highestNumber x
|| x==y -- really?
|| higher x (above y) ) -- too strong
so this one seems buggy.
First I solved these problems by defining a list and using
listcommands in order to sum up and see if something is "elem" of that
list but I am supposed to solve it without using lists.
You can solve this by expanding elem, like so:
x `elem` [1,2,3]
is the same as
x == 1 || x == 2 || x == 3
And while your at it
sum' = 4 + 11 + 18 + 2 + 4 + 5
You could also construct a list of all your elements with something like
elements = takeUntil highestnumber (iterate above lowestnumber)
takeUntil p xs = foldr (\x r -> if p x then [x] else x:r) [] xs
This is the only way I see you can write your check and sum' functions without using constants.
we can't use takeWhile (not . highestnumber) because we'll miss the highest number. So, takeUntil must be defined this way to include the breaking element in its output.
Related
I'm trying the solve the first question in Advent of Code 2017, and come up with the following solution to calculate the needed value:
checkRepetition :: [Int] -> Bool
checkRepetition [] = False
checkRepetition (x:xs)
| x == ( head xs ) = True
| otherwise = False
test :: [Int] -> Int
test [] = 0
test [x] = 0
test xs
| checkRepetition xs == True = ((head xs)*a) + (test (drop a xs))
| otherwise = test (tail xs)
where
a = (go (tail xs)) + 1
go :: [Int] -> Int
go [] = 0
go xs
| checkRepetition xs == True = 1 + ( go (tail xs) )
| otherwise = 0
However, when I give an input that contains repetitive numbers such as [1,3,3], it gives the error
*** Exception: Prelude.head: empty list
However, for 1.5 hours, I couldn't figure out exactly where this error is generated. I mean any function that is used in test function have a definition for [], but still it throws this error, so what is the problem ?
Note that, I have checked out this question, and in the given answer, it is advised not to use head and tail functions, but I have tested those function for various inputs, and they do not throw any error, so what exactly is the problem ?
I would appreciate any help or hint.
As was pointed out in the comments, the issue is here:
checkRepetition (x:xs)
| x == ( head xs ) = True
xs is not guaranteed to be a non-empty list (a one-element list is written as x:[], so that (x:xs) pattern matches that xs = []) and calling head on an empty list is a runtime error.
You can deal with this by changing your pattern to only match on a 2+ element list.
checkRepetition [] = False
checkRepetition [_] = False
checkRepetition (x1:x2:_) = x1 == x2
-- No need for the alternations on this function, by the way.
That said, your algorithm seems needlessly complex. All you have to do is check if the next value is equal, and if so then add the current value to the total. Assuming you can get your String -> [Int] on your own, consider something like:
filteredSum :: [Int] -> Int
filteredSum [] = 0 -- by definition, zero- and one-element lists
filteredSum [_] = 0 -- cannot produce a sum, so special case them here
filteredSum xss#(first:_) = go xss
where
-- handle all recursive cases
go (x1:xs#(x2:_)) | x1 == x2 = x1 + go xs
| otherwise = go xs
-- base case
go [x] | x == first = x -- handles last character wrapping
| otherwise = 0 -- and if it doesn't wrap
-- this should be unreachable
go [] = 0
For what it's worth, I think it's better to work in the Maybe monad and operate over Maybe [Int] -> Maybe Int, but luckily that's easy since Maybe is a functor.
digitToMaybeInt :: Char -> Maybe Int
digitToMaybeInt '0' = Just 0
digitToMaybeInt '1' = Just 1
digitToMaybeInt '2' = Just 2
digitToMaybeInt '3' = Just 3
digitToMaybeInt '4' = Just 4
digitToMaybeInt '5' = Just 5
digitToMaybeInt '6' = Just 6
digitToMaybeInt '7' = Just 7
digitToMaybeInt '8' = Just 8
digitToMaybeInt '9' = Just 9
digitToMaybeInt _ = Nothing
maybeResult :: Maybe Int
maybeResult = fmap filteredSum . traverse digitToMaybeInt $ input
result :: Int
result = case maybeResult of
Just x -> x
Nothing -> 0
-- this is equivalent to `maybe 0 id maybeResult`
Thank you for the link. I went there first to glean the purpose.
I assume the input will be a string. The helper function below constructs a numeric list to be used to sum if predicate is True, that is, the zipped values are equal, that is, each number compared to each successive number (the pair).
The helper function 'nl' invokes the primary function 'invcap' Inverse Captcha with a list of numbers.
The nl function is a list comprehension. The invcap function is a list comprehension. Perhaps the logic in this question is at fault. Overly complicated logic is more likely to introduce errors. Proofs are very much easier when logic is not cumbersome.
The primary function "invcap"
invcap l = sum [ x | (x,y) <- zip l $ (tail l) ++ [head l], x == y]
The helper function that converts a string to a list of digits and invokes invcap with a list of numeric digits.
nl cs = invcap [ read [t] :: Int | t <- cs]
Invocation examples
Prelude> nl "91212129" ......
9 ' ' ' ' ' ' ' ' ' ' ' ' '
Prelude> nl "1122" ......
3
I have a piece of Haskell code below. The problem is the clause (enigmaInput,_) = (filter (\(a,b) -> b == cipherChar0) stecker)!!0 will fail for the first 2 guards. How can I assign it for the last 2 guards only. Thanks!
followMenu :: Crib->Menu->Stecker->Offsets->Maybe Stecker
followMenu c [] s o = Just s
followMenu crib menu stecker offsets
| (length stecker) == 1 && initAdd == Nothing = Nothing
| (length stecker) == 1 && initAdd /= Nothing = followMenu crib (tail menu) (fromMb initAdd) offsets
| (length stecker) /= 1 && normalAdd == Nothing = Nothing
| otherwise = followMenu crib (tail menu) (fromMb normalAdd) offsets
where (_,_,cipherChar0) = crib!!(menu!!0)
(_,_,cipherChar1) = crib!!(menu!!1)
(enigmaInput,_) = (filter (\(a,b) -> b == cipherChar0) stecker)!!0
enigmaOutput = enigmaEncode enigmaInput (SimpleEnigma rotor3 rotor2 rotor1 reflector1) offsets
(_,initInput) = stecker!!0
initOutput = enigmaEncode initInput (SimpleEnigma rotor3 rotor2 rotor1 reflector1) offsets
(_,_,initCipher) = crib!!(menu!!0)
initAdd = steckerAdd initOutput initCipher stecker
normalAdd = steckerAdd enigmaOutput cipherChar1 stecker
You don't really need to, since (filter (\(a,b) -> b == cipherChar0) stecker)!!0 won't be evaluated until the value of enigmaInput is needed, and you don't use enigmaInput in the first two guard cases. This is a nice feature of lazy evaluation.
There is no way to attach a where clause to some but not all of a set of guarded equations, besides restructuring your pattern matches and guards of course.
i recently picked up Haskell and i am having trouble putting in code the way to look if an element is in the rest of the list (x:lx) in this case in lx.
My code:
atmostonce:: [Int] -> Int -> Bool
atmostonce [] y = True
atmostonce (x:lx) y
| (x==y) && (`lx` == y) = False
| otherwise = True
The way it is now checks for the first element (x==y) but i don't know how to check if the element y exists in lx. The thing i am actually trying to accomplish is to find out if in the list of Intigers lx the number y contains 0 or 1 times and return True otherwise return False
There are several implementations you could use for this, one that I see which avoids applying length to a potentially infinite list is
atmostonce xs y
= (<= 1)
$ length
$ take 2
$ filter (== y) xs
This removes all elements from xs that are not equal to y, then takes at most 2 of those (take 2 [1] == [1], take 2 [] == []), calculates the length (it's safe to use here because we know take 2 won't return an infinite list), then checks if that is no more than 1. Alternatively you could solve this using direct recursion, but it would be best to use the worker pattern:
atmostonce = go 0
where
go 2 _ _ = False
go n [] _ = n <= 1
go n (x:xs) y =
if x == y
then go (n + 1) xs y
else go n xs y
The n <= 1 clause could be replaced by True, but ideally it'll short-circuit once n == 2, and n shouldn't ever be anything other than 0, 1, or 2. However, for your implementation I believe you are looking for the elem function:
elem :: Eq a => a -> [a] -> Bool
atmostonce [] y = True
atmostonce (x:ls) y
| (x == y) && (y `elem` ls) = False
| otherwise = True
But this won't return you the value you want, since atmostonce [1, 2, 2, 2] 2 would return True. Instead, you'd need to do recursion down the rest of the list if x /= y:
atmostonce (x:ls) y
| (x == y) && (y `elem` ls) = False
| otherwise = atmostonce ls y
You can do this using the elem function:
atmostonce:: [Int] -> Int -> Bool
atmostonce [] y = True
atmostonce (x:lx) y | x /= y = atmostonce lx y
| otherwise = not $ elem y lx
You better first check if the element x is not equal to y. If that is the case, you simply call the recursive part atmostonce lx y: you thus search further in the list.
In case x == y, (the otherwise case), you need to check if there is another element in lx (the remainder of the list), that is equal to x. If that is the case, you need to return False, because in that case there are multiple instances in the list. Otherwise you return True.
Furthermore you can generalize your function further:
atmostonce:: (Eq a) => [a] -> a -> Bool
atmostonce [] y = True
atmostonce (x:lx) y | x /= y = atmostonce lx y
| otherwise = not $ elem y lx
Eq is a typeclass, it means that there are functions == and /= defined on a. So you can call them, regardless of the real type of a (Int, String, whatever).
Finally in the first case, you can use an underscore (_) which means you don't care about the value (although in this case it doesn't matter). You can perhaps change the order of the cases, since they are disjunct, and this makes the function syntactically total:
atmostonce:: (Eq a) => [a] -> a -> Bool
atmostonce (x:lx) y | x /= y = atmostonce lx y
| otherwise = not $ elem y lx
atmostonce _ _ = True
The existing answers are good, but you can use dropWhile to do the part that's currently done via manual recursion:
atMostOnce xs y =
let afterFirstY = drop 1 $ dropWhile (/= y) xs
in y `notElem` afterFirstY
I can use let inside other expression.
foo n = (let a = True in (\x -> a)) 3
foo' n | n == 1 = let a = True in a
| n /= 1 = False
But I can't do the same with where
foo n = ((\x -> a) where a = True) 3
foo' n | n == 1 = a where a = True
| n /= 1 = False
1:20: parse error on input `where'
Is it really impossible in haskell or just my mistake?
let is an expression while where is a clause. where is bound to syntactic constructs, let can be used anywhere expressions can.
You could of course write it like this:
foo n = ((\x -> a)) 3 where a = True
foo' n | n == 1 = a
| n /= 1 = False
where a = True
or like this:
foo n = (\a -> (\x -> a) 3) True
You need to put the where clause at the end:
foo n = ((\x -> a)) 3
where a = True
foo' n | n == 1 = a
| n /= 1 = False
where a = True
The difference is that let is an expression, whereas where requires some other construct to be bound to. See let vs where
let ... in ... is for introducing name bindings in an expression.
where is convenience syntax for giving local auxiliary definitions along with an equation. You can only use it as part of an equation (at the end), not in the middle of an arbitrary expression.
Their usage is not the same.
The claim that let is an expression is a bit off, it seems to me; in a do block it is a statement, though we say that there it abbreviates let ... in. The thing to say, I think, is
let_in_ :: Statement -> Expression -> Expression
_where_ :: Statement -> Statement -> Statement
Thus the first part of a let is a statement and can be modified by a where. So for example
foo n = (let a = b where b = True in (\x -> a)) 3
bip = do
let a = b where b = let c = d where d = True in c
return a
Similarly we can maybe say something like this:
case_of_ :: Expression -> [Statement] -> Expression
so that e.g.
z x = case even x of
True -> d where d = x + 1
False -> w - 1 where w = let a = x in a + 1
I am doing yet another projecteuler question in Haskell, where I must find if the sum of the factorials of each digit in a number is equal to the original number. If not repeat the process until the original number is reached. The next part is to find the number of starting numbers below 1 million that have 60 non-repeating units. I got this far:
prob74 = length [ x | x <- [1..999999], 60 == ((length $ chain74 x)-1)]
factorial n = product [1..n]
factC x = sum $ map factorial (decToList x)
chain74 x | x == 0 = []
| x == 1 = [1]
| x /= factC x = x : chain74 (factC x)
But what I don't know how to do is to get it to stop once the value for x has become cyclic. How would I go about stopping chain74 when it gets back to the original number?
When you walk through the list that might contain a cycle your function needs to keep track of the already seen elements to be able to check for repetitions. Every new element is compared against the already seen elements. If the new element has already been seen, the cycle is complete, if it hasn't been seen the next element is inspected.
So this calculates the length of the non-cyclic part of a list:
uniqlength :: (Eq a) => [a] -> Int
uniqlength l = uniqlength_ l []
where uniqlength_ [] ls = length ls
uniqlength_ (x:xs) ls
| x `elem` ls = length ls
| otherwise = uniqlength_ xs (x:ls)
(Performance might be better when using a set instead of a list, but I haven't tried that.)
What about passing another argument (y for example) to the chain74 in the list comprehension.
Morning fail so EDIT:
[.. ((length $ chain74 x x False)-1)]
chain74 x y not_first | x == y && not_first = replace_with_stop_value_:-)
| x == 0 = []
| x == 1 = [1]
| x == 2 = [2]
| x /= factC x = x : chain74 (factC x) y True
I implemented a cycle-detection algorithm in Haskell on my blog. It should work for you, but there might be a more clever approach for this particular problem:
http://coder.bsimmons.name/blog/2009/04/cycle-detection/
Just change the return type from String to Bool.
EDIT: Here is a modified version of the algorithm I posted about:
cycling :: (Show a, Eq a) => Int -> [a] -> Bool
cycling k [] = False --not cycling
cycling k (a:as) = find 0 a 1 2 as
where find _ _ c _ [] = False
find i x c p (x':xs)
| c > k = False -- no cycles after k elements
| x == x' = True -- found a cycle
| c == p = find c x' (c+1) (p*2) xs
| otherwise = find i x (c+1) p xs
You can remove the 'k' if you know your list will either cycle or terminate soon.
EDIT2: You could change the following function to look something like:
prob74 = length [ x | x <- [1..999999], let chain = chain74 x, not$ cycling 999 chain, 60 == ((length chain)-1)]
Quite a fun problem. I've come up with a corecursive function that returns the list of the "factorial chains" for every number, stopping as soon as they would repeat themselves:
chains = [] : let f x = x : takeWhile (x /=) (chains !! factC x) in (map f [1..])
Giving:
take 4 chains == [[],[1],[2],[3,6,720,5043,151,122,5,120,4,24,26,722,5044,169,363601,1454]]
map head $ filter ((== 60) . length) (take 10000 chains)
is
[1479,1497,1749,1794,1947,1974,4079,4097,4179,4197,4709,4719,4790,4791,4907,4917
,4970,4971,7049,7094,7149,7194,7409,7419,7490,7491,7904,7914,7940,7941,9047,9074
,9147,9174,9407,9417,9470,9471,9704,9714,9740,9741]
It works by calculating the "factC" of its position in the list, then references that position in itself. This would generate an infinite list of infinite lists (using lazy evaluation), but using takeWhile the inner lists only continue until the element occurs again or the list ends (meaning a deeper element in the corecursion has repeated itself).
If you just want to remove cycles from a list you can use:
decycle :: Eq a => [a] -> [a]
decycle = dc []
where
dc _ [] = []
dc xh (x : xs) = if elem x xh then [] else x : dc (x : xh) xs
decycle [1, 2, 3, 4, 5, 3, 2] == [1, 2, 3, 4, 5]