I am learning functional programming Haskell.
I have the requirement that I need to read an integer value and max value from the command line, and I need to determine if the integer value is in the range from [1 to max value]. I need to determine if any range's value is divided by the integer value.
For example:
program 5 20
then I need to check if any value from [1, 2, ..., 20] is divisible by 5 in sorted order.
How to write such function?
I have read the argument as
main = do
args <- getArgs
let first_divisor = args !! 0
let upper_bound = args !! 1
let x = read first_divisor :: Integer
let y = read upper_bound :: Integer
--print args
--putStrLn first_divisor
--putStrLn second_divisor
--putStrLn upper_bound
isDivisible x y
I need to write this isDivisible function which loops from 1 to y and if rem of (1/x 2/x ....y/x), it prints success or failed.
I have figured the loop as:
repeatNTimes 0 = return ()
repeatNTimes n =
do
-- my stuff
repeatNTimes (n-1)
However, this will iterate from n to 0, I want to iterate from 1 to 20.
How can I do this in Haskell so that I can check my even odd value?
You don't need loop when you have a list
Use map and mapM
isDivisible :: Int -> Int -> [String]
isDivisible firstDivisor upperBound = map (isDivided firstDivisor) [1 .. upperBound]
isDivided :: Int -> Int -> String
isDivided 0 _ = "Failed"
isDivided d x = if mod x d == 0
then "Success"
else "Failed"
main :: IO ()
main = do
input <- getLine
let args = words input
let first_divisor = args !! 0
let upper_bound = args !! 1
let x = read first_divisor :: Int
let y = read upper_bound :: Int
let results = isDivisible x y
mapM_ putStrLn results
Related
I have built a function in which the user will insert the array size and then proceed to insert its values
let array_builder =
let coin = Array.make (10000) 0 in
let number_coins = read_int() in
for i=0 to (number_coins-1) do
let k = read_int() in
coin.(i) <- (k);
done;
The input looks something like this:
3 ---> Array size
10 ---> coin.(0)
9 ---> coin.(1)
8 ---> coin.(2)
Is there anyway to pass the array, coin, as an argument to another function?
In OCaml array are regular value and can be passed to other function without specific syntax.
Maybe you want an example. I have created a dummy function that do like your loop.
let rec array_filler coin_array current_index size =
if current_index < size then
let k = read_int() in
let () = coin_array.(current_index) <- k in
array_filler coin_array (current_index + 1) size
else
coin_array
let array_builder =
let number_coins = read_int() in
let coin = Array.make number_coins 0 in
array_filler coin 0 number_coins
I also switched 2 lines so number_coins is available when creating the array (to not reserve more cell if the user don't need more than 10000)
This is a school assignment. I'm trying to make a function which takes an array A and makes a new array B, which is telling how many repeated numbers there are in an array. For example A is this:
A = [|2;9;9;2;2;4|]
The B would be:
B = [|3;2;2;3;3;1|]
Ny code is right now like this and working perfectly:
let A = [|2;9;9;2;2;4|]
let n = A.Length - 1
let B = Array.create A.Length 0
for i = 0 to n do
Array.iter (fun j -> if i <> j && A.[i]=j then B.[i] <- (B.[i] + 1)) A
printfn "%A" B
My question is, how much would asymptotic time be? I know the first for loop is O(n), but what about Array.iter? And is there any way to switch the first for loop with an array function?
Array.iter is linear in the array length, so your for loop is essentially O(n²) in time complexity. Replacing the loop with another Array.iter is possible but would not change the time complexity.
If you can solve the problem whichever way you want, I suggest using a Map to aggregate the numbers and their frequencies, then mapping the original array into one showing these frequencies. Since this is a school assignment, you should probably wait until after your submission deadline before you look at the following code:
let numFrequency (a : _ []) =
let m =
(Map.empty, a)
||> Array.fold (fun m n ->
Map.tryFind n m
|> Option.defaultValue 0
|> fun x -> Map.add n (x + 1) m)
Array.map (fun n -> Map.find n m) a
let A = [|2; 9; 9; 2; 2; 4|]
let B = numFrequency A
printf "%A\n%A\n" A B
I was checking Microsoft f# guide on for...in loops and was wondering how could the for in loop be randomized.
For example:
let list1 = [ 1; 5; 100; 450; 788 ]
for i in list1 do
printfn "%d" i
output:
1
5
100
450
788
If I want to have the elements to be printed in a random order using for in loop, what could I do?
We have established that, essentially, there's only the Fisher–Yates shuffle for randomizing a given collection. Easy to get wrong; here's a C# discussion of Dos and Don'ts.
The freedoms we have left in implementation: we can count upwards or downwards when performing the random swaps, and we may decide to either mutate the array in place, or create a copy of the input data.
// Mutate in place, count downwards
let shuffle arr =
let rnd = System.Random()
for i in Array.length arr - 1 .. -1 .. 1 do
let tmp, j = arr.[i], rnd.Next(0, i)
arr.[i] <- arr.[j]; arr.[j] <- tmp
let a = [|1; 5; 100; 450; 788|]
shuffle a
// Create a copy, count upwards
let copyShuffle source =
let arr = Seq.toArray source
let rnd, len = System.Random(), arr.Length
for i in 0 .. len - 2 do
let tmp, j = arr.[i], rnd.Next(i, len)
arr.[i] <- arr.[j]; arr.[j] <- tmp
arr
copyShuffle [1; 5; 100; 450; 788]
|> Array.iter (printfn "%i")
Here is an easy way to do it using the random function
let random= new Random()
let randomizeList lst =
lst
|> List.sortBy (fun (_) -> random.Next(lst.Length * 1000))
let list1 = [ 1; 5; 100; 450; 788 ]
|> randomizeList
for i in list1 do
printfn "%d" i
Please see notes on the Random number generator with regards to randomness - there are better algorithms for producing a more pure random distribution, Dotnet Core Docs -
The chosen numbers are not completely random because a mathematical algorithm is used to select them, but they are sufficiently random for practical purposes.
I wrote a function to scramble an array and map an array of arrays to scramble each one different but they are scrambled the same way
let rand = System.Random()
let shuffle (rand : System.Random)(array :int[] ) = let rng = new Random()
let mutable n = array.Length
while (n > 1) do
let k = rng.Next(n)
n <- n - 1
let temp = array.[n]
array.[n] <- array.[k]
array.[k] <- temp
array
let playsarray = shuffle rand
let scrambledarray = Array.map (fun x -> playsarray x )
let playsarra = fun (array : int[]) -> array |> playsarray
let smallarray = [1..10].ToArray()
let megaarray = Array.create 10 smallarray
let megarrayscrambled = megaarray |> scrambledarray
megarrayscrambled |> Seq.iter (fun y -> printfn "Ar: %A" y)
after running the code all the 10 arrays have the same order in the data ej
Ar: [|5; 1; 7; 2; 8; 10; 6; 3; 9; 4|]
Ar: [|5; 1; 7; 2; 8; 10; 6; 3; 9; 4|] and so on ...
There are two problems with your code.
First, your shuffle function takes a rand parameter but isn't actually using it: inside the function you create a new System.Random instance and use it instead of using the one passed in. The docs for the System.Random constructor mention (in the examples) that the default constructor uses the current time as a seed, so if two Random objects are created in quick succession, they would have the same seed and thus produce the same values. To fix this problem, you just need to stop creating a new Random instance in your shuffle function and instead use the one passed in (I renamed it from rand to rng so that the rest of your code wouldn't need changing). Here's your shuffle function with that change made (and with much easier-to-read indentation: you don't have to start the first line of the function on the same line as the = sign; you can put it on the next line and just indent one indentation level, four spaces):
let shuffle (rng : System.Random) (array : int[]) =
let mutable n = array.Length // The number of items left to shuffle (loop invariant).
while (n > 1) do
let k = rng.Next(n) // 0 <= k < n.
n <- n - 1 // n is now the last pertinent index;
let temp = array.[n] // swap array[n] with array[k] (does nothing if k == n).
array.[n] <- array.[k]
array.[k] <- temp
array
BUT that won't solve your issues just yet, because you've also misunderstood how Array.create works. It creates an array of a given size, where each item in the array contains the value you passed in. I.e., every entry in your megarrayscrambled array contains a reference to the same smallarray. If you did megarrayscrambled.[0].[0] <- 999 you'd see that this changed every one of the ten entries in megarrayscrambled, because they're the same array.
What you actually wanted was to use Array.init, not Array.create. Array.init takes a function and runs that function once per item it's creating in the array you're building. This means that if that function returns [1..10].ToArray(), then each time it's called it will return a different array, and you'll therefore get the results you expect. (By the way, you can create an array more simply by doing [|1..10|], and that's what I'll use in the sample code below).
So just change your let megaarray line to:
let megaarray = Array.init 10 (fun _ -> [|1..10|])
and then you should see the results you were expecting.
BTW, one more little detail: in one line you have Array.map (fun x -> playsarray x), but that is just equivalent to Array.map playsarray, which is a little simpler to read.
I got an int, lets say 6 and I want to convert it to a bit array.
bArr.(0) = 1
bArr.(1) = 1
bArr.(2) = 0
Is there any function that does this for me ?
I needed it to be an array so that I can then pass it to other function that receives a boolean array.
The n-th bit of an integer x can be computed with the following function:
let nth_bit x n = x land (1 lsl n) <> 0
An array can be created and initialized with Array.init function:
let bitarray length x = Array.init length (nth_bit x)
This will create an array of booleans in a LSB (Least Significant Bit) first order. If you need an array of integers, then you can use a function nth_bit_value instead of nth_bit:
let nth_bit_value x n = if nth_bit x n then 1 else 0
I will leave it as an exercise, to get an array in the MSB-order.
let int_to_bArr i =
let rec int_to_bit acc i =
if i=0 then acc
else int_to_bit (i land 1::acc) (i lsr 1)
in
let l=int_to_bit [] i in
Array.of_list l
;;
Test
# int_to_bArr 6;;
- : int array = [|1; 1; 0|]
Or
let int_to_bArr i =
let rec int_to_bool acc i =
if i=0 then acc
else int_to_bool (((i land 1)=1)::acc) (i lsr 1)
in
let l=int_to_bool [] i in
Array.of_list l
;;
# int_to_bArr 6;;
- : bool array = [|true; true; false|]