Converting an int to bit array in OCaml - arrays

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|]

Related

Ocaml - Passing an array as an argument of a function

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)

How to create matrix in matlab that adds cells horizontally

I want to create a matrix, for example, a 1xn, where n is determined by another input.
For example, I have the following:
Example = [3 5 7 9];
New_matrix = [int_col(Example (1)) int_col(Example (2)) int_col(Example (3)) int_col(Example (4))];
This New_matrix is how I want my outputs.
However, for my actual data input, my Example matrix is 1x47. How can I put this in a for loop so it gives the outputs of 1 to a specified number for all of the length Example? (keeping it horizontal as well)
Help function I used is added here:
% Helper function added as well
function v = int_col(n)
v = zeros(1,n);
for index=1:n
val = randi(n);
while (val == index || any(val == v))
val = randi(n);
if (index == n && (any(v == n) ~= 1))
val = n;
break
end
end
v(index) = val;
if (index == n && val == n)
% v(n) = v(n-1);
% v(n-1) = n;
end
if n == 1
v = 1;
end
end
v = v';
v = (sortrows(v))';
end
Are you trying to reimplement randperm() in int_col()? I'm not sure what the purpose of running sortrows() on each column separately is, but I guess this may be what you wanted:
% Make up vector of column lengths
Example=randi(60,[1 47]);
% Create matrix
New_matrix=nan([max(Example) numel(Example)]);
for i=1:numel(Example)
New_matrix(1:Example(i),i)=randperm(Example(i));
end
% Sort matrix rows from left to right
New_matrix=sortrows(New_matrix);
Please note that all columns in a matrix must have the same number of entries, so you will need to pad shorter columns with some value; a typical choice is NaN, which is treated as a special value by sortrows() and some other functions.
~
If my guess is incorrect and you do mean your code as it currently is, you just need:
New_matrix=[];
for i=1:numel(Example)
New_matrix=[New_matrix 1:Example(i)];
end
Changing the size of New_matrix on every iteration is generally not good practice, but for 47 iterations only this should be fine.

How to change for loop with an array module function?

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

F# why arrays are not scrambled in a different way when mapping a function to scramble each array in an array

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.

creating a for loop in Haskell

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

Resources