If I had a known list A :: [Int], and wanted to get a new list B = newList A with newList defined as the following:
newList :: [Int] -> [Int]
newList [] = []
newList (a:as) | a==0 = f(a) : newList (as)
| a==1 = g(a) : newList (as)
| otherwise = h(a) : newList (as)
where f, g, h :: Int -> Int are unimportant functions.
Other than B, I also wanted to know how many 0, 1 are there in A respectively.
But since when producing B recursively, it has already checked whether a== (0 or 1) for each elements in A, so it's a redundancy to check it again separably.
Is it possible to get B but at the same time get how many 0, 1 are there in A with checking only once?
This is not an answer you are looking for, but there is a nice abstract structure behind your function, so I'll leave it here:
import Data.Monoid
import Data.Functor
import Data.Traversable
import Control.Arrow
import Control.Monad.Trans.Writer
wr :: Int -> Writer (Sum Int, Sum Int) Int
wr 0 = tell (Sum 1, Sum 0) $> f 0
wr 1 = tell (Sum 0, Sum 1) $> g 1
wr n = return $ h n
collect :: [Int] -> ([Int], (Int, Int))
collect = second (getSum *** getSum) . runWriter . traverse wr
Summing is a monoid, double summing is a monoid, the Writer monad handles monoids, traverse maps a list with an effectful function and performs all effects.
This:
f = (+ 1)
g = (+ 2)
h = (+ 3)
main = print $ collect [0, 1, 2, 3, 0, 0, 0, 4, 1]
prints ([1,3,5,6,1,1,1,7,3],(4,2)) — four zeros and two ones.
Related
I need get neighbours of cells on 1D closed field
for example:
neighbours [1,2,3,4,5,-1] (6 elements)
must return [[-1,1,2],[1,2,3],[2,3,4],[3,4,5],[4,5,-1],[5,-1,1]] (6 elements)
my code of neighbours
neighbours :: [a] -> [[a]]
neighbours l = concat [[[last l, head l, last $ take 2 l]], neighbours' l, [[l !! (length l - 2), last l, head l]]] where
neighbours' :: [a] -> [[a]]
neighbours' (a:b:c:xs) = [a, b, c]:neighbours (b:c:xs)
neighbours' _ = []
main = print $ neighbours [1, 2, 3, 4]
returns [[4,1,2],[1,2,3],[4,2,3],[2,3,4],[4,3,4],[3,4,3],[3,4,2],[3,4,1]] (8 elements), but expected [[4,1,2],[1,2,3],[2,3,4],[3,4,1]] (4 elements)
if I comment neighbours' l it return
[[4,1,2],[3,4,1]] as expected (2 elements)
if you leave only neighbours' l it return
[[1,2,3],[2,3,4]] as expected (2 elements)
2+2=4, but in this case for some reason it is 8
why it happens?
P.s.
neighbours' create middle of list
neighbours' [1,2,3,4,5,-1] == [[1,2,3],[2,3,4],[3,4,5],[4,5,-1]]
[last l, head l, last $ take 2 l] create head of list [-1,1,2]
[l !! (length l - 2), last l, head l] create last element of list [5,-1,1]
Your code is somewhat hard to grasp because your two functions, neighbour and neighbour', are mutually recursive, which is sort of unusual.
The key line in your code is:
neighbours' (a:b:c:xs) = [a, b, c] : neighbours (b:c:xs)
If we assume that this is NOT intentional, and you just meant to write:
neighbours' (a:b:c:xs) = [a, b, c] : neighbours' (b:c:xs)
-----------------------------------------------+---------
then the code works as you seem to expect.
Note that having long (over 80 characters) lines of code makes the thing very difficult to debug.
Suggested code:
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ExplicitForAll #-}
import qualified Data.List as L
neighbours :: [a] -> [[a]]
neighbours l = concat [
[[last l, head l, last $ take 2 l]],
neighbours' l,
[[l !! (length l - 2), last l, head l]]
]
where
neighbours' :: [a] -> [[a]]
neighbours' (a:b:c:xs) = [a, b, c] : neighbours' (b:c:xs)
neighbours' _ = []
-- neighbour is British English, neighbor is US English
neighbors :: [a] -> [[a]]
neighbors xs =
take count $ drop (count-1) allTriplets -- section of infinite list
where
count = length xs
allTriplets = map (take 3) (L.tails (cycle xs)) -- raw material
main :: IO ()
main = do
print $ "res1 = " ++ (show $ neighbours [1, 2, 3, 4])
print $ "res2 = " ++ (show $ neighbors [1, 2, 3, 4])
Program output:
"res1 = [[4,1,2],[1,2,3],[2,3,4],[3,4,1]]"
"res2 = [[4,1,2],[1,2,3],[2,3,4],[3,4,1]]"
I am trying to write a pseudo-random generator in Elm (to generate points on a screen) but not so easy since it interferes with the ``purity" of the Elm compiler.
OK, so why not write our own function? We can get sort-of random behavior if we write stuff like:
-- initial state
randomNumbers = [ 1 ]
x = 1
b = 2
n = 2017
-- generate random numbers
x = (x*b) % n
randomNumbers = x :: randomNumbers
This does not follow Elm's rule of variable assignments. Something is wrong.
All I am doing is finding the power of 2 mod 2017. The first few are easy but then the sequence gets unpredictible. So I need to keep track of the last number computed.
[ 1, 2, 4, 8, ... , 1024, 31, 62, 124, ...]
Even if I try to use special properties of arithmetic I still have to compute this sparse list of powers
[ 1, 2^1, 2^2, 2^4, 2^8, 2^16, ... ]
can I can solve by successive squaring, but I still need some way to memorize the last step.
I thought... as long as I write my own code, I don't have to import randomness from the "real world" to generate my fair numbers. This way respecting the pureness of Elm. However, I end up writing something that is stateful.
Elm does have a random-number generator now - an implementation of some algorithm - in the Random library, returning a generator type.
This repl session has been quite instructive:
> import Random exposing (..)
>
> initialSeed 0
Seed {
state = State 1 1 ,
next = <function>,
split = <function>,
range = <function>
}
: Random.Seed
> seed0 = initialSeed 101
Seed {
state = State 102 1, ,
next = <function>,
split = <function>,
range = <function>
}
: Random.Seed
> step ( int 0 10 ) seed0
(10,Seed { state = State 4081428 40692, ,
next = <function>,
split = <function>,
range = <function>
}
: ( Int, Random.Seed )
Even with my simplified baby random number generator, what is so stateful here?
My apologies in advance if I say memoizaton when I mean dynamic programming or the other way around
What is the difference between memoization and dynamic programming?
If I could write a stateful function f that remembered things, I could generate all my values with just one line:
List.map f [1..100]
two candidates:
A
https://github.com/elm-community/list-extra/blob/3.1.0/src/List/Extra.elm
iterate : (a -> Maybe a) -> a -> List a
iterate f x =
case f x of
Just x' -> x :: iterate f x'
Nothing -> [x]
B
https://github.com/elm-community/elm-lazy-list/blob/1.3.0/src/Lazy/List.elm
{-| Create an infinite list of applications of a function on some value.
Equivalent to:
x ::: f x ::: f (f x) ::: f (f (f x)) ::: ... -- etc...
-}
iterate : (a -> a) -> a -> LazyList a
iterate f a =
lazy <|
\() ->
Cons a (iterate f (f a))
Below I have defined a function that converts a list of base-3 digits to the corresponding numerical value. For example:
f "201" = (2 * 3^2) + (0 * 3^1) + (1 * 3^0) = 19
f "12" = 5
f "1202" = 47
f "120221" = 430
Here is a definition using comprehension:
f :: String -> Int
f str = sum (listToFinal (stringToTuples str))
Helper functions:
-- 1) converts "201" to "102"
reverse "str"
-- 2) converts "102" to 102
stringToInt :: String -> Int
stringToInt str = read str :: Int
-- 3) converts 102 to ['1','0','2']
intToList :: Int -> [Int]
intToList 0 = []
intToList x = intToList (x `div` 10) ++ [x `mod` 10]
-- 4) converts "201" to [(1,0),(0,1),(2,2)] using reverse, stringToInt, intToList
stringToTuples :: String -> [(Int,Int)]
stringToTuples str = zip (intToList (stringToInt (reverse str))) [0..]
-- 5) converts [(1,0),(0,1),(2,2)] to [1*3^0, 0*3^1, 2*3^2]
listToFinal :: [(Int,Int)] -> [Int]
listToFinal list = [ x * (3^y) | (x,y) <- list ]
Now I'd like to do it with recursion only (well, using basic & library functions too, of course).
An idea: I was thinking of taking the head of each element in the list and simply multiplying it with 3^(length of string - 1). The only problem is, with each recursive call the power of three would have to decrease by 1, e.g. given:
recursive_version "201" = (2 * 3^2) + (0 * 3^1) + (1 * 3^0)
How to implement this?
Here is a much simpler approach; note that, through the use of foldl, it's only "implicitly" recursive, though. For information, digitToInt is exported by Data.Char.
import Data.Char
import Data.List ( foldl' )
--- horner x xs : the value of polynomial 'xs' at point 'x'
horner :: Int -> [Int] -> Int
horner x = foldl' (\c1 c0 -> c1 * x + c0) 0
-- f s : the integer whose representation in base 3 is string 's'
f :: String -> Int
f = horner 3 . map digitToInt
When you define it recursively, the natural way to decrement the length is trimming the array from the head. For example:
base3 x = base3' x 0 where
base3' (d:ds) v = base3' ds $ v + d * 3 ^ length ds
base3' [] v = v
I need to generate an infinite stream of random integers, with numbers to be in range [1..n]. However the probability for each number p_i is given in advance thus the distribution is not uniform.
Is there a library function to do it in Haskell?
As people have pointed out there is a function in Control.Monad.Random, but it has pretty poor complexity. Here is some code that I by some coincidence wrote this morning. It uses the beautiful Alias algorithm.
module Data.Random.Distribution.NonUniform(randomsDist) where
import Data.Array
import Data.List
import System.Random
genTable :: (Num a, Ord a) => [a] -> (Array Int a, Array Int Int)
genTable ps =
let n = length ps
n' = fromIntegral n
(small, large) = partition ((< 1) . snd) $ zip [0..] $ map (n' *) ps
loop ((l, pl):ls) ((g, pg):gs) probs aliases =
let prob = (l,pl)
alias = (l,g)
pg' = (pg + pl) - 1
gpg = (g, pg')
in if pg' < 1 then loop (gpg:ls) gs (prob:probs) (alias:aliases)
else loop ls (gpg:gs) (prob:probs) (alias:aliases)
loop ls gs probs aliases = loop' (ls ++ gs) probs aliases
loop' [] probs aliases = (array (0,n-1) probs, array (0,n-1) aliases)
loop' ((g,_):gs) probs aliases = loop' gs ((g,1):probs) ((g, -1):aliases)
in loop small large [] []
-- | Generate an infinite list of random values with the given distribution.
-- The probabilities are scaled so they do not have to add up to one.
--
-- Uses Vose's alias method for generating the values.
-- For /n/ values this has O(/n/) setup complexity and O(1) complexity for each
-- generated item.
randomsDist :: (RandomGen g, Random r, Fractional r, Ord r)
=> g -- | random number generator
-> [(a, r)] -- | list of values with the probabilities
-> [a]
randomsDist g xps =
let (xs, ps) = unzip xps
n = length xps
axs = listArray (0, n-1) xs
s = sum ps
(probs, aliases) = genTable $ map (/ s) ps
(g', g'') = split g
is = randomRs (0, n-1) g'
rs = randoms g''
ks = zipWith (\ i r -> if r <= probs!i then i else aliases!i) is rs
in map (axs!) ks
Just to expand on dflemstr's answer, you can create an infinite list of weighted values using Control.Monad.Random like this:
import Control.Monad.Random
import System.Random
weightedList :: RandomGen g => g -> [(a, Rational)] -> [a]
weightedList gen weights = evalRand m gen
where m = sequence . repeat . fromList $ weights
And use it like this:
> let values = weightedList (mkStdGen 123) [(1, 2), (2, 5), (3, 10)]
> take 20 values
[2,1,3,2,1,2,2,3,3,3,3,3,3,2,3,3,2,2,2,3]
This doesn't require the IO monad, but you need to provide the random number generator that's used for the stream.
Control.Monad.Random offers this function in form of fromList:: MonadRandom m => [(a, Rational)] -> m a
You can use it in the IO Monad with:
import Control.Monad.Random
-- ...
someNums <- evalRandIO . sequence . repeat . fromList $ [(1, 0.3), (2, 0.2), (3, 0.5)]
print $ take 200 someNums
There are other ways of running the Rand Monad as you can see in that package. The weights do not have to add up to 1.
EDIT: Rand is apparently lazier than I thought, so replicateM n can be replaced by sequence . repeat, as #shang suggested.
There is also System.Random.Distributions.frequency
frequency :: (Floating w, Ord w, Random w, RandomGen g) => [(w, a)] -> g -> (a, g)
See https://hackage.haskell.org/package/Euterpea-1.0.0/docs/System-Random-Distributions.html
I am trying to build a smallish haskell app that will translate a few key phrases from english to french.
First, i have a list of ordered pairs of strings that represent and english word/phrase followed by the french translations:
icards = [("the", "le"),("savage", "violent"),("work", "travail"),
("wild", "sauvage"),("chance", "occasion"),("than a", "qu'un")...]
next i have a new data:
data Entry = Entry {wrd, def :: String, len :: Int, phr :: Bool}
deriving Show
then i use the icards to populate a list of Entrys:
entries :: [Entry]
entries = map (\(x, y) -> Entry x y (length x) (' ' `elem` x)) icards
for simplicity, i create a new type that will be [Entry] called Run.
Now, i want to create a hash table based on the number of characters in the english word. This will be used later to speed up searchings. So i want to create a function called runs:
runs :: [Run]
runs = --This will run through the entries and return a new [Entry] that has all of the
words of the same length grouped together.
I also have:
maxl = maximum [len e | e <- entries]
It just so happens that Hackage has a hashmap package! I'm going to create a small data type based on that HashMap, which I will call a MultiMap. This is a typical trick: it's just a hash map of linked lists. I'm not sure what the correct name for MultiMap actually is.
import qualified Data.HashMap as HM
import Data.Hashable
import Prelude hiding (lookup)
type MultiMap k v = HM.Map k [v]
insert :: (Hashable k, Ord k) => k -> a -> MultiMap k a -> MultiMap k a
insert k v = HM.insertWith (++) k [v]
lookup :: (Hashable k, Ord k) => k -> MultiMap k a -> [a]
lookup k m = case HM.lookup k m of
Nothing -> []
Just xs -> xs
empty :: MultiMap k a
empty = HM.empty
fromList :: (Hashable k, Ord k) => [(k,v)] -> MultiMap k v
fromList = foldr (uncurry insert) empty
I mimicked only the essentials of a Map: insert, lookup, empty, and fromList. Now it is quite easy to turn entries into a MutliMap:
data Entry = Entry {wrd, def :: String, len :: Int, phr :: Bool}
deriving (Show)
icards = [("the", "le"),("savage", "violent"),("work", "travail"),
("wild", "sauvage"),("chance", "occasion"),("than a", "qu'un")]
entries :: [Entry]
entries = map (\(x, y) -> Entry x y (length x) (' ' `elem` x)) icards
fromEntryList :: [Entry] -> MutiMap Int Entry
fromEntryList es = fromList $ map (\e -> (len e, e)) es
Loading that up into ghci, we can now lookup a list of entries with a given length:
ghci> let m = fromEntryList entries
ghci> lookup 3 m
[Entry {wrd = "the", def = "le", len = 3, phr = False}]
ghci> lookup 4 m
[Entry {wrd = "work", def = "travail", len = 4, phr = False},
Entry {wrd = "wild", def = "sauvage", len = 4, phr = False}]
(Note that this lookup is not the one defined in Prelude.) You could similarly use the English word as a key.
-- import Data.List (find) -- up with other imports
fromEntryList' :: [Entry] -> MultiMap String Entry
fromEntryList' es = fromList $ map (\e -> (wrd e, e)) es
eLookup :: String -> MultiMap String Entry -> Maybe Entry
eLookup str m = case lookup str m of
[] -> Nothing
xs -> find (\e -> wrd e == str) xs
Testing...
ghci> let m = fromEntryList' entries
ghci> eLookup "the" m
Just (Entry {wrd = "the", def = "le", len = 3, phr = False})
ghci> eLookup "foo" m
Nothing
Notice how in eLookup we first perform the Map lookup in order to determine if anything has been placed in that slot. Since we are using a hash set, we need to remember that two different Strings might have the same hash code. So in the event that the slot is not empty, we perform a find on the linked list there to see if any of the entries there actually match the correct English word. If you are interested in performance, you should consider using Data.Text instead of String.
groupBy and sortBy are both in Data.List.
import Data.List
import Data.Function -- for `on`
runs :: [Run]
runs = f 0 $ groupBy ((==) `on` len) $ sortBy (compare `on` len) entries
where f _ [] = []
f i (r # (Entry {len = l} : _) : rs) | i == l = r : f (i + 1) rs
f i rs = [] : f (i + 1) rs
Personally, I would use a Map instead
import qualified Data.Map as M
runs :: M.Map String Entry
runs = M.fromList $ map (\entry -> (wrd entry, entry)) entries
and lookup directly by English word instead of a two step length-of-English-word and then English-word process.