The question states that we are given an empty list and 10^5 queries.For each query, we have two integers a and b.a can only be 1, 2 or 3.
if a=1, then append element b in the list.
if a=2, then add value b to every element of the list.
if a=3, then we have to print the bth smallest element in the list.
e.g. query = 5, list = []
q1 -> 1 2 -> list = [2]
q2 -> 1 4 -> list = [2,4]
q3 -> 2 5 -> list = [7,9]
q4 -> 3 1 -> print(7)
I have tried a brute force approach, which takes O(N logN) for each query. How can I improve this for large queries?
My brute force link
elif a==2:
for j in range(len(l)):
l[j]+=b
This step can be avoided and by doing the following
if a == 2
sum += b #value ToBe Added to every element at the end of all queries at once Last
l=[]
query =10**5
sum = 0
for _ in range(query):
if a==1:
l.append(b)
elif a==2:
sum += b
else:
l.sort()
print(l[b-1] + **sum**)
This can be further improved as below
l=[]
query =10**5
sum = 0
for _ in range(query):
if a==1:
// Place the element b in proper place O(n) operation increasing order
elif a==2:
sum += b
else:
print(l[b-1] + **sum**)
Related
I wonder if there's a cheap(performance wise) option to search an index of array element which meets certain criteria starting from an index?
Array.tryFindIndex method doesn't have an argument startIndex. I could do Array.skip(n) and then search there but it seems expensive to create an array just for search. How do I do this?
I looked List also doesn't have that argument.
Do I have to use while ... do? Is there a nicer way?
The base libraries try to provide functions for your convenience but they cannot possibly anticipate all use cases. Nothing wrong with writing your own if need be:
module Array =
let tryFindIndexFrom i p (a : _ []) =
let rec loop k =
if k >= a.Length then None
elif p a.[k] then Some k
else loop (k + 1)
if i < 0 then None else loop i
EDIT: p is the predicate testing the array elements. tryFindIndexFrom has the same signature as tryFindIndex but with the starting index added as first parameter.
EDIT 2: Added test for k < 0 for fool-proof usage.
EDIT 3: Moved test for k < 0 out of the loop as it needs to be checked only once.
Here's a way to do it using a lazy sequence of array indexes:
let input = [| 'a' .. 'z' |]
seq { 4 .. input.Length - 1 }
|> Seq.tryFind (fun i -> input |> Array.tryItem i = Some 'x')
I'll leave it to you to generalise this into a helper function if you think that's necessary.
The nice thing about the current form is that it's quite flexible. You can change the maximum index easily, or search backwards, e.g. seq { input.Length - 1 .. -1 .. 4 }.
Follow your instinct. Considering Array.skip but noting the obvious waste of allocating a second array, you can take it one step further and generalize to the lazily evaluated Seq.skip, compose it with the standard Seq.tryFindIndex function and add the offset, if applicable.
let tryFindIndexMin n p =
Seq.skip n
>> Seq.tryFindIndex p
>> Option.map ((+) n)
// val tryFindIndexMin : n:int -> p:('a -> bool) -> (seq<'a> -> int option)
[ for i in 0..3 ->
[|"a"; "b"; "a"; "b"|]
|> tryFindIndexMin i ((=) "a") ]
// val it : int option list = [Some 0; Some 2; Some 2; null]
I would like to convert a list of zeros and ones to a char.
example :
bitToChar([1,0,0,0,1,0,1]) = $Q
Thanks.
Another way to do it is to use a bit string comprehension:
X = [1,0,0,0,1,0,1],
<<C:7>> = << <<Bit:1>> || Bit <- lists:reverse(X) >>,
$Q == C.
That is, pick one element at a time from the list, and use each element as a bit in the binary being built, and finally extract a seven-bit number into the variable C.
You can add $0 to each of them (to make it a string with $0s and $1s), reverse the list, and use list_to_integer/2 with base 2:
1> list_to_integer(lists:reverse([N + $0 || N <- [1,0,0,0,1,0,1]]), 2) == $Q.
true
You can also use lists:foldl. The code is slightly longer but it doesn't use list_to_binary:
1> element(2, lists:foldl(fun(Digit, {Mul, Acc}) -> {Mul * 2, Acc + Digit * Mul} end, {1, 0}, Xs)) == $Q. true
This is basically equivalent to doing: 1 * 1 + 0 * 2 + 0 * 4 + 0 * 8 + 1 * 16 + 0 * 32 + 1 * 64.
$Q = lists:foldr(fun(X,Acc) -> X + (Acc bsl 1) end, 0,[1,0,0,0,1,0,1]).
Since $Q is integer value all you have to do is use in BitToChar conversion from binary based number to decimal based number.
Simplest conversion is:
to_decimal(X) ->
to_decimal(lists:reverse(X), 1, 0).
% you can validate that if H = 1 then add, if other not but I omitted this validation
to_decimal([H | T], Times, Acc) ->
to_decimal(T, 2 * Times, H * Times + Acc);
to_decimal([], _Times, Acc) -> Acc.
And then it will return integer.
In your case:
> $Q = 81.
81
> $Q == 81.
true
I'm messing around with F# and Fable, and trying to test my understanding. To do so, I tried creating a function to calculate e given a certain number of iterations. What I've come up with is
let eCalc n =
let rec internalECalc ifact sum count =
match count = n with
| true -> sum
| _ -> internalECalc (ifact / (float count)) (sum + ifact) (count+1)
internalECalc 1.0 0.0 1
Which works fine, returning 2.7182818284590455 when called with
eCalc 20
However, if I try using, what I think is, the more correct form
let eCalc n =
let rec internalECalc ifact sum count =
match count with
| n -> sum
| _ -> internalECalc (ifact / (float count)) (sum + ifact) (count+1)
internalECalc 1.0 0.0 1
I get a warning "[WARNING] This rule will never be matched (L5,10-L5,11)", and returned value of 0. (and the same thing happens if I swap 'n' and 'count' in the match statement). Is there a reason I can't use 'n' in the match statement? Is there a way around this so I can use 'n'?
Thanks
When you use a name in a match statement, you're not checking it against the value assigned to that variable the way you think you are. You are instead assigning that name. I.e.,
match someInt with
| n -> printfn "%d" n
will print the value of someInt. It's the equivalent of let n = someInt; printfn "%d" n.
What you wanted to do was use a when clause; inside a when clause, you're not pattern-matching, but doing a "standard" if check. So what you wanted was:
let eCalc n =
let rec internalECalc ifact sum count =
match count with
| cnt when cnt = n -> sum
| _ -> internalECalc (ifact / (float count)) (sum + ifact) (count+1)
internalECalc 1.0 0.0 1
Does that make sense, or do you need me to go into more detail?
P.S. In a case like this one where your match function looks like "x when (boolean condition involving x) -> case 1 | _ -> case 2", it's quite a bit more readable to use a simple if expression:
let eCalc n =
let rec internalECalc ifact sum count =
if count = n then
sum
else
internalECalc (ifact / (float count)) (sum + ifact) (count+1)
internalECalc 1.0 0.0 1
I am really new to F# and am struggling to adapt to the whole functional programming mindset. Basically I am trying to figure out how to iterate through a list of numbers and add them up while the sum is less than a certain number (200 for instance).
At the moment I have something along the lines of the following:
let nums = [20 .. 50]
let mutable total = 0
let addUp (num, (total : byref<int>)) =
if (num + total < 200) then
total <- total + num
for num in nums do
addUp (num, &total)
This does get the job done, but I feel like there must be a more appropriate way to do this while still remaining within the style of functional programming, and without out having to rely on a mutable. I still feel like I'm approaching things from an imperative mindset.
I was thinking I could somehow use List.fold to do this but after some experimentation I was unable to figure out how to utilize it in conjunction with the whole while < 200 thing. Any help would be hugely appreciated and I apologize in advance if this is a commonly asked and answered question (I couldn't find anything through my own search).
For educational purposes, the answer above is fine as it lets you see what exactly happens within the fold or reduce.
For a real project, it is better to use existing library functions. You can even separate summation and bound checking. Consider this:
let addUp threshold xs =
xs
|> Seq.scan (+) 0 // line 1
|> Seq.takeWhile (fun x -> x < threshold) // line 2
|> Seq.last // line 3
// Usage:
let nums = Seq.initInfinite ( (+) 20) // line 4
nums
|> addUp 200
|> printfn "%d" // prints "188"
A bit of explanation:
line 1 is a contraction of Seq.scan (fun state x -> state + x) 0 so it actually returns a sequence of intermediate sums (20, 41, 63, ...);
in line 2, we take only the elements that match or filtering predicate;
in line 3, we simply take the last element (that matched the filtering above);
in line 4, again, it's a contraction of Seq.initInfinite (fun x -> 20+x). I took my liberty to make your data an infinite sequence (20, 21, 22, ...), but it still works.
Note, the code looks like three calls, but the sequence is evaluated only once.
Note, in line 2, don't try contraction like above. The reason is that (<) threshold evaluates to fun x -> threshold < x which is wrong. If you. however, use (>) threshold, it reads counter-intuitive and confusing.
Note, there's no error checking in the function. Calling it with an empty source sequence will crash at Seq.last.
First, let's try to avoid mutable variable and one way to do it is to create a recursive function to iterate through the list with the latest total.
let rec addUp total nums =
match nums with
| [] -> total
| num::tl ->
let newTotal = num + total
if newTotal < 200 then
addUp newTotal tl
else
total
addUp 0 nums
We create a recursive function addUp which accepts total and the list of numbers. The function extracts the first number of the list and adds it to the total if the new total is less than 200. Since we might still have more numbers on the list, we call addUp again with the new total and the rest of the numbers. Otherwise, we stop and return the new total.
We can also use List.fold which makes the code cleaner, but the whole list will be iterated. Here is the code:
List.fold (fun total num ->
let newTotal = num + total
if newTotal < 200 then
newTotal
else
total
) 0 nums
Since the output is the same type as the member of the input, we can use List.reduce and get rid of initial state (0).
List.reduce (fun total num ->
let newTotal = num + total
if newTotal < 200 then
newTotal
else
total
) nums
Hope this helps.
I want to gather the non zero element of a matrix into a sequence<(row,column,value)>
This doesn't work
let getSparseMatrixCOO matrix =
seq {
matrix |> Array2D.iteri (fun row column elem ->
if elem <> 0.0 then yield (row, column, elem)
)
}
Do I have to give up the idea of using Array2D.iteri?
You cannot use yield inside a lambda function like this. The yield keyword is only usable directly in the scope of the sequence expression (although your attempt has a good logic).
I think the easiest option is to iterate over the elements of the array and write something like this:
let getSparseMatrixCOO matrix =
seq { for row in 0 .. Array2D.length1 matrix - 1 do
for column in 0 .. Array2D.length2 matrix - 1 do
let elem = matrix.[row, column]
if elem <> 0.0 then yield (row, column, elem) }
The Array2D module does not provide many functions, but it can be extended to include foldi function (similar to Array.foldi). The function aggregates elements of the array and calls a function you specify for every element. You can then choose elements you want and aggregate them in a way you want.
The following uses a list as a state and appends non-zero elements to the list during aggregation:
Array2D.foldi (fun row column elem state ->
if elem <> 0.0 then (row, column, elem)::state else state) []
The missing Array2D.foldi function can be implemented (imperatively, to keep it simple) like this:
module Array2D =
let foldi f a matrix =
let mutable state = a
for row in 0 .. Array2D.length1 matrix - 1 do
for column in 0 .. Array2D.length2 matrix - 1 do
state <- f row column (matrix.[row, column]) state
state
You may continue sticking to Array2D.iteri with something like
let getSparseMatrixCOO matrix =
let result = ref List<int*int*float>.Empty
matrix |> Array2D.iteri(fun i j elem -> if elem <> 0.0 then result := (i,j,elem)::!result)
!result |> List.rev
if laziness of your original intent does not matter as the snippet above will give you the same sequence, only eagerly.