haskell repeat all chars in a string - loops

i just started with Haskell and wanted to do a little function that takes an integer and a String to repeat each char in the String as often as the integer implies.
e.g.: multiply 3 "hello" would output "hhheeelllooo"
My problem now is that i am not sure how to iterate over all the chars.
multiply::Int->String->String
multiply 1 s = s
multiply i s = multiply (i-1) (take 1 s ++ s)
so what i would get is "hhhello". so basically i need to do something like:
mult::Int->String->String
mult 0 s = []
mult 1 s = s
mult i s = "iterate over s, take each char and call a modified version of the multiply method that only takes chars above"
Thank you for helping me out

This gets easier when you use the standard library. First off, repeating an item is done with replicate:
Prelude> replicate 3 'h'
"hhh"
You can then partially apply this function and map it over the string:
Prelude> map (replicate 3) "hello"
["hhh", "eee", "lll", "lll", "ooo"]
And finally concat that list of strings into one string:
Prelude> concat (map (replicate 3) "hello")
"hhheeellllllooo"
The composition of concat and map can be abbreviated as concatMap (this is a library function, not a language feature).
Prelude> concatMap (replicate 3) "hello"
"hhheeellllllooo"
So your function becomes
mult n s = concatMap (replicate n) s
For extra brevity, write this in point-free style as
mult = concatMap . replicate

There are many ways to achieve the same effect as you would with a loop in other languages, and larsmans has shown you one way, using map. Another common way is with recursion. You already know what to do with the first character, so you can recurse through the list like so:
multiply n [] = []
multiply n (x:xs) = replicate n x ++ multiply n xs
larsmans has explained how replicate works. For your homework, maybe you're not supposed to use library functions like replicate, so you can replace the call to replicate with your own version.

Another way based on monadic's nature of list.
You'd like to apply a function to each element of a list.
To do this just bind the list to the function, like this
# "hello" >>= replicate 3
Or,
# let f = flip (>>=) . replicate
To remove flip,
# let g = (=<<) . replicate

You can use applicative functors for this:
import Control.Applicative
multiply n = (<* [1..n])
--- multiply 3 "hello" --> "hhheeellllllooo"

Related

Repeat array rows specified number of times

New to julia, so this is probably very easy.
I have an n-by-m array and a vector of length n and want to repeat each row of the array the number of times in the corresponding element of the vector. For example:
mat = rand(3,6)
v = vec([2 3 1])
The result should be a 6-by-6 array. I tried the repeat function but
repeat(mat, inner = v)
yields a 6×18×1 Array{Float64,3}: array instead so it takes v to be the dimensions along which to repeat the elements. In matlab I would use repelem(mat, v, 1) and I hope julia offers something similar. My actual matrix is a lot bigger and I will have to call the function many times, so this operation needs to be as fast as possible.
It has been discussed to add a similar thing to Julia Base, but currently it is not implemented yet AFAIK. You can achieve what you want using the inverse_rle function from StatsBase.jl:
julia> row_idx = inverse_rle(axes(v, 1), v)
6-element Array{Int64,1}:
1
1
2
2
2
3
and now you can write:
mat[row_idx, :]
or
#view mat[row_idx, :]
(the second option creates a view which might be relevant in your use case if you say that your mat is large and you need to do such indexing many times - which option is faster will depend on your exact use case).

Haskell - Sum of the differences between each element in each matrix

I am very new to Haskell (and functional programming in general) and I am trying to write a function called
"profileDistance m1 m2" that takes two matrices as parameters and needs to calculate the sum of the differences between each element in each matrix... I might have not explained that very well. Let me show it instead.
The matrices are on the form of: [[(Char,Int)]]
where each matrix might look something like this:
m1 = [[('A',1),('A',2)],
[('B',3),('B',4)],
[('C',5),('C',6)]]
m2 = [[('A',7),('A',8)],
[('B',9),('B',10)],
[('C',11),('C',12)]]
(Note: I wrote the numbers in order in this example but they can be ANY numbers in any order. The chars in each row in each matrix will however match like shown in the example.)
The result (in the case above) would look something like (psuedo code):
result = ((snd m1['A'][0])-(snd m2['A'][0]))+((snd m1['A'][1])-(snd m2['A'][1]))+((snd m1['B'][0])-(snd m2['B'][0]))+((snd m1['B'][1])-(snd m2['B'][1]))+((snd m1['C'][0])-(snd m2['C'][0]))+((snd m1['C'][1])-(snd m2['C'][1]))
This would be easy to do in any language that has for-loops and is non-functional but I have no idea how to do this in Haskell. I have a feeling that functions like map, fold or sum would help me here (admittedly I am not a 100% sure on how fold works). I hope there is an easy way to do this... please help.
Here a proposal:
solution m1 m2 = sum $ zipWith diffSnd flatM1 flatM2
where
diffSnd t1 t2 = snd t1 - snd t2
flatM1 = concat m1
flatM2 = concat m2
I wrote it so that it's easier to understand the building blocks.
The basic idea is to iterate simultaneously on our two lists of pairs using zipWith. Here its type:
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
It means it takes a function with type a -> b -> c, a list of a's and a list of b's, and it returns a list of c's. In other words, zipWith takes case of the iteration, you just have to specify what you want to do with every item the iteration yields, that in your case will be a pair of pairs (one from the first matrix, another one from the second).
The function passed to zipWith takes the snd element from each pair, and computes the difference. Looking back at zipWith signature you can deduce it will return a list of numbers. So the last thing we need to do is summing them, using the function sum.
There's one last problem. We actually do not have two lists of pairs to be passed to zipWith!, but two matrices. We need to "flatten" them in a list, preserving the order of the elements. That's exactly what concat does, hence the calls to that function in the definitions of flatM1 and flatM2.
I suggest you look into the implementation of every function I mentioned to have a better grasp of how iteration is expressed by mean of recursion. HTH

Yielding a modified Ruby array to a block

I'm trying to turn 2 lines of ruby code into 1. For example:
def average(numbers)
result = numbers.compact
numbers.reduce(+) / numbers.length
end
I've been looking through array methods and can't find an appropriate one to turn this function into a one-liner. I had hoped something like this would work:
def average(numbers)
numbers.compact.<tap or another method> { |arr| arr.reduce(+) / arr.length }
end
Basically, I'm modifying the array (in the example I have to call compact to rid nil values), so I don't have access to the array variable, and I don't want an iterator, because I don't want to call reduce(+) and length on individual elements of the array.
Does anyone have an idea of methods I could look into?
I believe you mean for your method to be the following (reduce(:+), not reduce(+) and use result rather than numbers in the second line).
def average(numbers)
result = numbers.compact
result.reduce(:+) / result.length
end
average [1,2,3]
#=> 2
If you wish the average to be a float, change the second line to
result.reduce(0.0, :+) / result.length
There are various ways to combine the two lines of the method, but I don't prefer any of them to the above. Here are a few. (I don't see how Object#tap could be used here.)
numbers.compact.reduce(:+) / numbers.compact.length
(result = numbers.compact).reduce(:+) / result.compact.length
numbers.map(&:to_i).reduce(:+) / numbers.compact.length
Note that, even if numbers can be mutated, one cannot write
numbers.compact!.reduce(:+) / numbers.length
because numbers.compact! returns nil if numbers contains no nil elements.
In Ruby v2.4+ you can use Array#sum:
result.sum / result.length
You could change the way you call average
def average(numbers)
numbers.reduce(:+) / numbers.length
end
average(num_array.compact)

Combining array into one string (matlab)

I have something like the following:
A = [1 2 5; 1 5 7];
B = A(1,:);
I output B:
B = A(1,:);
B =
1 2 5
I am looking to combine what is contained in B into one single string:
1/2/5
You can use sprintf:
sprintf('%d/',B)
This will give you almost what you want, it will have unnecessary / in the end.
>> sprintf('%d/',B)
ans =
1/2/5/
If you want to remove it:
st = sprintf('%d/',B);
st(end) = [];
As #hmuster points out correctly, it is possible to do it with \b , the backspace character.
st = [sprintf('%d/',B) sprintf('\b')];
However, as #AndrewJanke points out correctly, it could become a problem if this string is written into a pipe or a file. So use it with caution.
If you want it done properly (IE reusable), there are two steps:
Convert your numbers to strings (this will allow later crazy values to be converted properly with num2str http://www.mathworks.com/help/matlab/ref/num2str.html
Concatenate your strings horizontally (you can use MATLAB concatenation property A = [B C]), but the functional way is strcat http://www.mathworks.com/help/matlab/ref/strcat.html

Growing arrays in Haskell

I have the following (imperative) algorithm that I want to implement in Haskell:
Given a sequence of pairs [(e0,s0), (e1,s1), (e2,s2),...,(en,sn)], where both "e" and "s" parts are natural numbers not necessarily different, at each time step one element of this sequence is randomly selected, let's say (ei,si), and based in the values of (ei,si), a new element is built and added to the sequence.
How can I implement this efficiently in Haskell? The need for random access would make it bad for lists, while the need for appending one element at a time would make it bad for arrays, as far as I know.
Thanks in advance.
I suggest using either Data.Set or Data.Sequence, depending on what you're needing it for. The latter in particular provides you with logarithmic index lookup (as opposed to linear for lists) and O(1) appending on either end.
"while the need for appending one element at a time would make it bad for arrays" Algorithmically, it seems like you want a dynamic array (aka vector, array list, etc.), which has amortized O(1) time to append an element. I don't know of a Haskell implementation of it off-hand, and it is not a very "functional" data structure, but it is definitely possible to implement it in Haskell in some kind of state monad.
If you know approx how much total elements you will need then you can create an array of such size which is "sparse" at first and then as need you can put elements in it.
Something like below can be used to represent this new array:
data MyArray = MyArray (Array Int Int) Int
(where the last Int represent how many elements are used in the array)
If you really need stop-and-start resizing, you could think about using the simple-rope package along with a StringLike instance for something like Vector. In particular, this might accommodate scenarios where you start out with a large array and are interested in relatively small additions.
That said, adding individual elements into the chunks of the rope may still induce a lot of copying. You will need to try out your specific case, but you should be prepared to use a mutable vector as you may not need pure intermediate results.
If you can build your array in one shot and just need the indexing behavior you describe, something like the following may suffice,
import Data.Array.IArray
test :: Array Int (Int,Int)
test = accumArray (flip const) (0,0) (0,20) [(i, f i) | i <- [0..19]]
where f 0 = (1,0)
f i = let (e,s) = test ! (i `div` 2) in (e*2,s+1)
Taking a note from ivanm, I think Sets are the way to go for this.
import Data.Set as Set
import System.Random (RandomGen, getStdGen)
startSet :: Set (Int, Int)
startSet = Set.fromList [(1,2), (3,4)] -- etc. Whatever the initial set is
-- grow the set by randomly producing "n" elements.
growSet :: (RandomGen g) => g -> Set (Int, Int) -> Int -> (Set (Int, Int), g)
growSet g s n | n <= 0 = (s, g)
| otherwise = growSet g'' s' (n-1)
where s' = Set.insert (x,y) s
((x,_), g') = randElem s g
((_,y), g'') = randElem s g'
randElem :: (RandomGen g) => Set a -> g -> (a, g)
randElem = undefined
main = do
g <- getStdGen
let (grownSet,_) = growSet g startSet 2
print $ grownSet -- or whatever you want to do with it
This assumes that randElem is an efficient, definable method for selecting a random element from a Set. (I asked this SO question regarding efficient implementations of such a method). One thing I realized upon writing up this implementation is that it may not suit your needs, since Sets cannot contain duplicate elements, and my algorithm has no way to give extra weight to pairings that appear multiple times in the list.

Resources