Polling using expand in rxjs gives an unexpected result - rxjs

I am trying to setup a poller using expand but the behavior is not what I want
https://stackblitz.com/edit/rxjs-finalize-unsubscribe-6xy2yb?file=index.ts
checkExistence produces a random boolean - With the expand, I expect a recursive delayed call of the same checkExistence function producing random booleans every 5 seconds (after one initial call).
I also expect the stop to kick in 30seconds and stop the polling and 5 seconds later resume the random boolean stream. Any pointers will help.
Instead I get the same boolean value getting printed; also after the start is triggered, it produces batches of booleans together.

This isn't really a single question.
Assignment/function Invocation
A simplified example
The equals operator assigns a value to a variable. Function invocation returns a value
function inc(n){
return n + 1
}
const result = inc(5)
console.log(result); // 6
Here, the result holds the number value 6. Not a function that calculated 5 + 1. 5 + 1 only happens once here.
Now consider this function that randomly increments a number by either 1 or 2
function bump(n){
const nu = Math.random();
return nu < 0.5 ? n + 1 : n + 2
}
const result = bump(5);
console.log(result); // 7
console.log(result); // 7
console.log(result); // 7
console.log(result); // 7
console.log(result); // 7
Every time I print the result, it's the same. bump was only called once and only generated a random number once.
function bump(n){
const nu = Math.random();
return nu < 0.5 ? n + 1 : n + 2
}
console.log(bump(5)); // 7
console.log(bump(5)); // 7
console.log(bump(5)); // 6
console.log(bump(5)); // 7
console.log(bump(5)); // 6
Here, bump is called 5 times, and each time it generated a new random number.
Fixing checkExistence
There are two ways.
Instead of generating a value once and re-using it. Generate a new boolean in your poll every time you need one.
function checkExistencePoll(): Observable<boolean> {
const POLL = 5000;
return checkExistence().pipe(
expand(_ =>
timer(POLL).pipe(
switchMap(() => checkExistence()),
takeUntil(stop),
repeatWhen(() => start)
)
)
);
}
Have checkExistence return an observable that generates a new boolean on subscription
function checkExistence(): Observable<boolean> {
return defer(() => {
const nu = Math.random();
const rand = nu < 0.5;
console.log(nu, rand);
return of(rand);
});
}
Handling subscriptions
In your code, expand is generating an observable that subscribes to a subject ( called start) in order to decide when to repeat. Every observable expand creates does this. So each one repeats when start emits. You should expect batches of booleans equal to the number of concurrent observables you've created.

Related

counting pairs in a list

I've recently started on HackerRank and I'm attempting "Sales by Match". I've arrived at a solution I'm content with in terms of exploiting Kotlin's function programming capabilities. However, I'm not getting the expected answer...
Problem summary:
Given an Array:
-> find and return the total number of pairs.
i.e:
input -> [10, 20, 20, 10, 10, 30, 50, 10, 20]
number of pairs -> 3
here is my code and some comments to explain it:
fun sockMerchant(n: Int, pile: Array<Int>): Int{
var count = 0
mutableMapOf<Int, Int>().withDefault { 0 }.apply {
// the [attempted] logic behind this piece of code here is
// that as we iterate through the list, the 'getOrPut()'
// function will return either the value for the given [key]
// or throw an exception if there is no such key
// in the map. However, since our map was created by
// [withDefault], the function resorts to its `defaultValue` <-> 0
// instead of throwing an exception.
for (e in values) {
// this simplifies our code and inserts a zero [+1] where needed.
// if (key exists)
// // return its associated value and MOD it:
// case: even -> increment counter
// else -> do nothing
// else if (key dne)
// // insert default value <-> [0] + 1
// ....
// ....
// ....
if (getOrPut(e, { getValue(e) + 1 } ) % 2 == 0) count++
}
}
return count
}
fun main(args: Array<String>) {
val scan = Scanner(System.`in`)
val n = scan.nextLine().trim().toInt()
val ar = scan.nextLine().split(" ").map{ it.trim().toInt() }.toTypedArray()
val result = sockMerchant(n, ar)
println(result)
}
--
Any help or tips would go a long way here:)
I was able to do this by grouping the numbers together, taking the resulting lists, and summing how many pairs each one contains:
fun sockMerchant(n: Int, pile: Array<Int>): Int =
pile.groupBy { it }.values.sumBy { it.size / 2 }
After we do pile.groupBy { it }, we have this structure:
{10=[10, 10, 10, 10], 20=[20, 20, 20], 30=[30], 50=[50]}
We take the values, and sum by each of their size dividing by 2. This will round half-pairs down to 0 and full pairs to 1 each.
Note: I am not entirely clear what the purpose of n is in this case.
I modified it a bit to be more easily testable, but here is the fixes :
import java.util.*
fun sockMerchant(n: Int, pile: Array<Int>): Int{
var count = 0
mutableMapOf<Int, Int>().withDefault { 0 }.apply {
// the [attempted] logic behind this piece of code here is
// that as we iterate through the list, the 'getOrPut()'
// function will return either the value for the given [key]
// or throw an exception if there is no such key
// in the map. However, since our map was created by
// [withDefault], the function resorts to its `defaultValue` <-> 0
// instead of throwing an exception.
for (e in pile) {
// this simplifies our code and inserts a zero [+1] where needed.
// if (key exists)
// // return its associated value and MOD it:
// case: even -> increment counter
// else -> do nothing
// else if (key dne)
// // insert default value <-> [0] + 1
// ....
// ....
// ....
println(e)
put(e, getValue(e) + 1)
if (getValue(e) % 2 == 0) count++
println(entries)
}
}
return count
}
val n = 5
val ar = "10 10 10 10 20 20 30 40".split(" ").map{ it.trim().toInt() }.toTypedArray()
val result = sockMerchant(n, ar)
println(result)
Output :
10
[10=1]
10
[10=2]
10
[10=3]
10
[10=4]
20
[10=4, 20=1]
20
[10=4, 20=2]
30
[10=4, 20=2, 30=1]
40
[10=4, 20=2, 30=1, 40=1]
3
Pair.kts:3:18: warning: parameter 'n' is never used
fun sockMerchant(n: Int, pile: Array<Int>): Int{
^
Process finished with exit code 0
Explanation :
You looped over "values", which is at start empty, so you never did anything with your code
Even when looping over pile, your incrementation logic didn't go above 1, so the condition was never satisfied and the count was never incremented.
But the main reasoning behind was correct.

How to implement "i++ and i>=max ? 0: i" that only use atomic in Go

only use atomic implement the follow code:
const Max = 8
var index int
func add() int {
index++
if index >= Max {
index = 0
}
return index
}
such as:
func add() int {
atomic.AddUint32(&index, 1)
// error: race condition
atomic.CompareAndSwapUint32(&index, Max, 0)
return index
}
but it is wrong. there is a race condition.
can be implemented that don't use lock ?
Solving it without loops and locks
A simple implementation may look like this:
const Max = 8
var index int64
func Inc() int64 {
value := atomic.AddInt64(&index, 1)
if value < Max {
return value // We're done
}
// Must normalize, optionally reset:
value %= Max
if value == 0 {
atomic.AddInt64(&index, -Max) // Reset
}
return value
}
How does it work?
It simply adds 1 to the counter; atomic.AddInt64() returns the new value. If it's less than Max, "we're done", we can return it.
If it's greater than or equal to Max, then we have to normalize the value (make sure it's in the range [0..Max)) and reset the counter.
Reset may only be done by a single caller (a single goroutine), which will be selected by the counter's value. The winner will be the one that caused the counter to reach Max.
And the trick to avoid the need of locks is to reset it by adding -Max, not by setting it to 0. Since the counter's value is normalized, it won't cause any problems if other goroutines are calling it and incrementing it concurrently.
Of course with many goroutines calling this Inc() concurrently it may be that the counter will be incremented more that Max times before a goroutine that ought to reset it can actually carry out the reset, which would cause the counter to reach or exceed 2 * Max or even 3 * Max (in general: n * Max). So we handle this by using a value % Max == 0 condition to decide if a reset should happen, which again will only happen at a single goroutine for each possible values of n.
Simplification
Note that the normalization does not change values already in the range [0..Max), so you may opt to always perform the normalization. If you want to, you may simplify it to this:
func Inc() int64 {
value := atomic.AddInt64(&index, 1) % Max
if value == 0 {
atomic.AddInt64(&index, -Max) // Reset
}
return value
}
Reading the counter without incrementing it
The index variable should not be accessed directly. If there's a need to read the counter's current value without incrementing it, the following function may be used:
func Get() int64 {
return atomic.LoadInt64(&index) % Max
}
Extreme scenario
Let's analyze an "extreme" scenario. In this, Inc() is called 7 times, returning the numbers 1..7. Now the next call to Inc() after the increment will see that the counter is at 8 = Max. It will then normalize the value to 0 and wants to reset the counter. Now let's say before the reset (which is to add -8) is actually executed, 8 other calls happen. They will increment the counter 8 times, and the last one will again see that the counter's value is 16 = 2 * Max. All the calls will normalize the values into the range 0..7, and the last call will again go on to perform a reset. Let's say this reset is again delayed (e.g. for scheduling reasons), and yet another 8 calls come in. For the last, the counter's value will be 24 = 3 * Max, the last call again will go on to perform a reset.
Note that all calls will only return values in the range [0..Max). Once all reset operations are executed, the counter's value will be 0, properly, because it had a value of 24 and there were 3 "pending" reset operations. In practice there's only a slight chance for this to happen, but this solution handles it nicely and efficiently.
I assume your goal is to never let index has value equal or greater than Max. This can be solved using CAS (Compare-And-Swap) loop:
const Max = 8
var index int32
func add() int32 {
var next int32;
for {
prev := atomic.LoadInt32(&index)
next = prev + 1;
if next >= Max {
next = 0
}
if (atomic.CompareAndSwapInt32(&index, prev, next)) {
break;
}
}
return next
}
CAS can be used to implement almost any operation atomically like this. The algorithm is:
Load the value
Perform the desired operation
Use CAS, goto 1 on failure.

How to create an infinite Observable that produces random numbers at random intervals?

Given a function that generates random numbers, how would you create an infinite Observable that produces random numbers at random intervals?
function getRandomNumber() {
// Assume this function returns a random number, e.g. 198
}
function getRandomDelay() {
// Assume this function returns a random delay in ms, e.g. 2000
}
Here is an example of a desired Observable:
---198--------64-------3---2----------18-------> (indefinitely)
3ms 7ms 6ms 3ms 10ms
As an alternative, if you don't want to live in a confusing timeout-world, you could write this entirely as a stream:
// the stream
const randomizer$ = Rx.Observable.of("")
.switchMap(() => Rx.Observable
.timer(getRandomDelay())
.mapTo(getRandomNumber()))
.repeat();
// subscribe to it
randomizer$.subscribe(num => console.log("Random number after random delay" + num));
// your utility functions
function getRandomNumber() {
return ~~(Math.random() * 200)
}
function getRandomDelay() {
return Math.random() * 1000
}
Working example here: http://jsbin.com/zipocaneya/edit?js,console
Alternative: Create the random number first and then add a delay (if the time of execution does not matter)
// the stream
const randomizer$ = Rx.Observable.of("")
.switchMap(() => Rx.Observable
.of(getRandomNumber())
.delay(getRandomDelay()
)
.repeat();
// subscribe to it
randomizer$.subscribe(num => console.log("Random number after random delay" + num));
Additional note: Since there is no concurrency or async-operation going on outside of the stream, instead of switchMap you could just as well use concatMap or flatMap - in this case they all work the same.
const { Observable } = require("rxjs");
const ob = new Observable(sub => {
let timeout = null;
// recursively send a random number to the subscriber
// after a random delay
(function push() {
timeout = setTimeout(
() => {
sub.next(getRandomNumber());
push();
},
getRandomDelay()
);
})();
// clear any pending timeout on teardown
return () => clearTimeout(timeout);
});
ob.subscribe(console.log);
Would you take a look at https://github.com/cszredwan/crazyObservable?
I am sure it gonna be of help, this is a custom observable to emit (randomly!) a fixed amount of data over a fixed time horizon.
The problem with your question is that randomly is being used with imprecise meaning. crazyObservable draws a single stream of data of all possibilities of emitting data over the time horizon specified. Of course, you can concat multiples instances of crazyObservable to get desired behavior.
In RxPY 3.0 you can use the following construction:
res = rx.generate(0, lambda x: True, lambda x: x + 1).pipe(
ops.map(lambda x: rx.timer(random.random() * 0.4).pipe(ops.map(lambda y: x))),
ops.merge(max_concurrent=1),
ops.map(lambda x: {'count': x, 'value': random.randint(0, 5)}))
This produces an infinite stream of random integers between 0 and 5 at random times with interarrival time uniformly distributed on [0, 0.4].
In RxPY 3.0, operations like switchmap or concatmap are not implemented (as in #olsn's reply). The concat_all operation can be achieved by merge with max_concurrent=1.
Edit:
rx.generate(0, lambda x: True, lambda x: x + 1)
is blocking. Using an infinite vanilla python generator such as
import itertools
r = rx.from_iterable(_ for _ in itertools.count(start=0, step=1))
is also blocking. You can add some scheduler e.g.
from rx.scheduler.eventloop import AsyncIOScheduler
from rx.scheduler import ThreadPoolScheduler
import multiprocessing
scheduler = AsyncIOScheduler(asyncio.get_event_loop())
# scheduler = ThreadPoolScheduler(multiprocessing.cpu_count()) # alternatively
res = rx.generate(0, lambda x: True, lambda x: x + 1).pipe(
ops.map(lambda x: rx.timer(random.random() * 0.4).pipe(ops.map(lambda y: x))),
ops.merge(max_concurrent=1),
ops.map(lambda x: {'count': x, 'value': random.randint(0, 5)}),
ops.subscribe_on(scheduler)
)

Getting wrong answer when trying to get k subsets from Array in ActionScript

I'm working on a Texas Holdem game and i need to generate all possible k subsets from an Array of cards (represented as numbers in this example). This is how it looks so far:
public function getKSubsetsFromArray(arr:Array, k:int):Array {
var data:Array = new Array();
var result:Array = new Array();
combinations(arr, data, 0, arr.length - 1, 0, k, result, 0);
return result;
}
public function combinations(arr:Array, data:Array, start:int, end:int, index:int, r:int, resultArray:Array, resultIndex:int):int {
if (index == r) {
trace(resultIndex, data);
resultArray[resultIndex] = data;
return ++resultIndex;
}
for (var i:int = start; i<=end && end-i+1 >= r-index; i++) {
data[index] = arr[i];
resultIndex = combinations(arr, data, i + 1, end, index + 1, r, resultArray, resultIndex);
}
return resultIndex;
}
I am new to Actionscript, my idea is to have a function that takes an array of number and a parameter k, and returns an Array of arrays each of size k. However once i test the functions I get an array containing only the last combination nCk times. For example:
var testArray:Array = new Array(1, 2, 3, 4, 5);
trace(getKSubsetsFromArray(testArray, 3));
Returns:
0 1,2,3
1 1,2,4
2 1,2,5
3 1,3,4
4 1,3,5
5 1,4,5
6 2,3,4
7 2,3,5
8 2,4,5
9 3,4,5
The function output is
3,4,5,3,4,5,3,4,5,3,4,5,3,4,5,3,4,5,3,4,5,3,4,5,3,4,5,3,4,5
Of course it should print an array containing all the combinations listed before but it only prints the last one the right amount of times.
Thank your for your help.
The reason for the error is that when you are making array of arrays you are actually using the reference of the same array (data) so when the last combination is executed the contains of data array become 3,4,5 and each of index of resultArray points to data array so it prints out same values.
Solution :-
if (index == r) {
trace(resultIndex, data);
var result = new Array();
copy(result,data)
resultArray[resultIndex] = result;
return ++resultIndex;
}
Note :-
The above is pseudo code as i am not familiar with actionscript but you can implement copy function that copies values of data into result in actionscript syntax.

Recursive solution to finding patterns

I was solving a problem on recursion which is to count the total number of consecutive 8's in a number. For example:
input: 8801 output: 2
input: 801 output: 0
input: 888 output: 3
input: 88088018 output:4
I am unable to figure out the logic of passing the information to the next recursive call about whether the previous digit was an 8.
I do not want the code but I need help with the logic. For an iterative solution, I could have used a flag variable, but in recursion how do I do the work which flag variable does in an iterative solution. Also, it is not a part of any assignment. This just came to my mind because I am trying to practice coding using recursion.
A typical solution to this would be to add a new parameter to your function to pass along the "flag" state. This parameter is usually called an accumulator. If you're using a language that allows for nested functions, you often want to define an outer function that takes the actual parameters, then an inner, recursive function with an accumulator as a parameter. There's an example in Scheme here.
you can scan through your number digit by digit with this function
int totalConsecutive8(int digit, boolean last)
while boolean last indicate whether the last digit (which mean digit - 1) is 8 or not.
For example, in the last example 88088018, starting at digit 0, boolean last is false -> digit 1, as the last digit is 8, so last is true ...
Code in Java
public int numberOfConsecutive8(int val){
String number = "" + val;
return totalConsecutive8(number, 0, false, false);
}
public int totalConsecutive8(String number, int digit, boolean last, boolean first){
if(digit == number.length()){
return 0;
}
int result = 0;
if(number.charAt(digit) == '8'){
if(last){
if(first){
result += 2 + totalConsecutive8(number, digit + 1, true, false);
}else{
result += 1 + totalConsecutive8(number, digit + 1, true, false);
}
}else{
result += totalConsecutive8(number, digit + 1, true, true);
}
}else{
result += totalConsecutive8(number, digit + 1, false, false);
}
return result;
}
Barmar suggested approach:
int totalConsecutive8(int number, boolean last , boolean first){
if(number == 0){
return 0;
}
int result = 0;
if(number % 10 == 8){
if(last){
if(first){
result += 2 + totalConsecutive8(number/10, true , false){
}else{
result += 1 + totalConsecutive8(number/10, true , false){
}
} else{
result += totalConsecutive8(number/10, true , true){
}
}else{
result += totalConsecutive8(number/10, false , false){
}
return result;
}
here pseudo code for the above problem :-
int max = 0;
void cal_eight(char ch[],int i,int count) {
if(ch[i]=='\0') {
max = maximum(max,count);
}
else if(ch[i]=='8') {
cal_eight(ch,i+1,count+1);
}
else {
max = maximum(max,count);
cal_eight(ch,i+1,0);
}
}
call :- cal_eight(ch,0,0)
As you are focusing on recursion I'd mention that one of its specifics and benefits that there is no need at all to pass any additional parameter or count calls.
You perform call of your function from inside of its own with modified argument - say the string minus one digit which you check in your function - and then call it again until the string becomes empty.
May be multiple times - nested calls.
[UPDATE]
Below is the example in Python, verbose fore more readability.
We call our function with string, current chain of consecutive 8s which is flushed if the 1st char of current string is not '8' (which, and already known total cosecutive 8s
def f8_trace(s, chainlen=0, total=0, indent=0):
print ' '*indent, "invoked with s='%s', chainlen=%d, total=%d" % (s,chainlen, total)
if len(s) == 0:
if chainlen>1:
total += chainlen
retval = total
else:
if s[0] == '8':
chainlen += 1
else:
if chainlen>1:
total += chainlen
chainlen = 0
retval = f8_trace(s[1:],chainlen,total,indent+1)
print ' '*indent, 'returns %d' % (retval)
return retval
s = 'abc888d88e8f888'
print f8_trace( s )
Output:
invoked with s='abc888d88e8f888', chainlen=0, total=0
invoked with s='bc888d88e8f888', chainlen=0, total=0
invoked with s='c888d88e8f888', chainlen=0, total=0
invoked with s='888d88e8f888', chainlen=0, total=0
invoked with s='88d88e8f888', chainlen=1, total=0
invoked with s='8d88e8f888', chainlen=2, total=0
invoked with s='d88e8f888', chainlen=3, total=0
invoked with s='88e8f888', chainlen=0, total=3
invoked with s='8e8f888', chainlen=1, total=3
invoked with s='e8f888', chainlen=2, total=3
invoked with s='8f888', chainlen=0, total=5
invoked with s='f888', chainlen=1, total=5
invoked with s='888', chainlen=0, total=5
invoked with s='88', chainlen=1, total=5
invoked with s='8', chainlen=2, total=5
invoked with s='', chainlen=3, total=5
returns 8
returns 8
returns 8
returns 8
returns 8
returns 8
returns 8
returns 8
returns 8
returns 8
returns 8
returns 8
returns 8
returns 8
returns 8
returns 8
8
Here's an example in Haskell, a language often associated with recursive approaches.
xxs stands for the string, x and xs loosely mean, "first item" and "the rest" (so after we check x, we pass xs, the rest of the string, to the next function call).
previous set as True means the previous digit was an 8. I hope the rest of the code may seem more straight forward and self-explanatory. The guards, |, are like imperative "if" clauses (e.g., if previous then ...).
f xxs first8 previous count
| null xxs = count
| previous = if x == 8
then f xs 0 True (count + first8 + 1)
else g
| otherwise = if x == 8
then f xs 1 True count
else g
where x:xs = xxs
g = f xs 0 False count
Output:
*Main> f [8,0,1] 0 False 0
0
*Main> f [8,8,8] 0 False 0
3
*Main> f [8,8,0,8,8,0,1,8] 0 False 0
4

Resources