How to repeat empty Mono with (roughly) constant delays between attempts? - kotlin

How to repeat empty Mono with (roughly) constant delays between attempts so that it subtracts time spent executing Mono from the delay? I tried this
val delay = Duration.ofSeconds(5)
var count = 0
val res = Mono.defer {
Mono.fromCallable {
count++
}.flatMap { c ->
println("${Instant.now()}: $c")
if (c < 3) {
// Thread.sleep(2000)
Mono.delay(Duration.ofMillis(1000)).then()
// Mono.empty()
} else
Mono.just("done")
}
}
.repeatWhen({ o ->
o
.index()
.map { it.t1 }
.timed()
.take(20)
.concatMap { t ->
val del = delay.minus(t.elapsed())
println("${Instant.now()}: ${t.get()}: e ${t.elapsed()} - ts ${t.timestamp()} - el ${t.elapsedSinceSubscription()} -> $del")
if (t.elapsed() < delay) {
Mono.delay(del).then(Mono.just(t.get()))
} else
Mono.just(t.get())
}
.concatWith(Flux.error(IllegalStateException("Exceeded maximum number of repeats")))
})
.next()
Strangely output is not what I expect
2022-07-21T15:58:24.664Z: 0
2022-07-21T15:58:25.770Z: 0: e PT1.134932033S - ts 2022-07-21T15:58:25.769Z - el PT1.134932033S -> PT3.865067967S
2022-07-21T15:58:29.644Z: 1
2022-07-21T15:58:30.645Z: 1: e PT4.87609502S - ts 2022-07-21T15:58:30.645Z - el PT6.011027053S -> PT0.12390498S
2022-07-21T15:58:30.770Z: 2
2022-07-21T15:58:31.771Z: 2: e PT1.125707497S - ts 2022-07-21T15:58:31.771Z - el PT7.13673455S -> PT3.874292503S
2022-07-21T15:58:35.646Z: 3
done
I expected second elapsed() to be ~6 seconds.
What can I do to measure elapsed time between elements correctly ?

Related

how to increase the size limit of a mutable list in kotlin?

I was attempting to solve the multiset question (https://codeforces.com/contest/1354/problem/D) on codeforces using Fenwick Tree Data structure. I passed the sample test cases but got the memory limit error after submitting, the testcase is mentioned below.
(Basically the testcase is:
1000000 1000000
1.............1 //10^6 times
-1...........-1 //10^6 times).
I tried similar testcase in my IDE and got the below mentioned error.
(Similar to above, the testcase I provided is:
1000000 1
1.............1 //10^6 times
-1
)
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 524289 out of bounds for length 524289
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:373)
at java.base/java.util.ArrayList.get(ArrayList.java:426)
at MultisetKt.main(multiset.kt:47)
at MultisetKt.main(multiset.kt)
Here is my code:
private fun readInt() = readLine()!!.split(" ").map { it.toInt() }
fun main() {
var (n, q) = readInt()
var list = readInt() //modify the list to store it from index 1
var finalList = listOf(0) + list
val query = readInt()
var bit = MutableList(n+1){0}
fun update(i:Int, value:Int) {
var index = i
while(index < n){
bit.set (index , bit[index] + value)
index += (index and -index)
}
}
fun rangefunc(i:Int): Int {
var su = 0
var index = i
while(index > 0){
su += bit[index]
index -= (index and -index)
}
return su
}
fun find(x:Int):Int {
var l = 1
var r = n
var ans = n
var mid = 0
while (l <= r) {
mid = (l + r) / 2
if (rangefunc(mid) >= x) {
ans = mid
r = mid - 1
} else {
l = mid + 1
}
}
return ans
}
for (i in 1..n) {
update(finalList[i], 1)
}
for (j in 0..q - 1) {
if (query[j] > 0) {
update(query[j], 1)
} else {
update(find(-query[j]), -1)
}
}
if(rangefunc(n) == 0){
println(0)
}else{
println(find(1))
}
}
I believe this is because the BITlist is not able to store 10^6 elements but not sure. Please let me know what changes should I make in my code also any additional advice on how to deal with such cases in the future.
Thank you in advance :)
An ArrayList can store over 2 billion items (2 * 10^9). That is not your issue. ArrayIndexOutOfBoundsException is for trying to access an index of an ArrayList that is less than zero or greater than or equal to its size. In other words, an index that it doesn't yet contain.
There's more code there than I have time to debug. But I would start at the line that the stack trace points to and see how it's possible for you to attempt to call bit[index] with an index that equals the size of the ArrayList.
To answer your literal question, you can use LinkedList explicitly as your type of MutableList to avoid the size restriction, but it is heavier and it is slower when accessing elements by index.

How to get columns of two dimesional array using functional style in kotlin

For example I have such a simple task: count all raws and columns which have all zeros in 2D array.
So for
0 0 0
0 0 0
1 0 1
answer is 2 raws and 1 column.
I can make it just like that for raws: var cntRaws = a.count { it.all { el -> el == 0 } }, but how to solve it for columns in same way?
val x = Array<IntArray>(3) { IntArray(3) { 0 } }
x[2][0] = 1
x[2][2] = 1
val raws = x.count { it.sum() == 0 }
val columns = (x.indices)
.map { columnIndex -> x.map { it[columnIndex] } }
.count { it.sum() == 0 }
println("total raws:$raws")
println("total col:$columns")
I couldn't think of any idomatic / functional style to do this, but I came up with an idea just create a lazily evaluated swapping function that swaps the columns with rows when it wants to pull without creating a new list.
fun <T> List<List<T>>.swapped() = sequence {
var index = 0
while (index < size) {
yield(map { it[index] })
index++
}
}
fun main() {
val list = listOf(
listOf(0, 0, 0),
listOf(0, 0, 0),
listOf(1, 0, 1)
)
val cntRows = list.count { it.all { el -> el == 0 } }
val cntCols = list.swapped().count { it.all { el -> el == 0 } }
println("cntRows: $cntRows")
println("cntCols: $cntCols")
}
I tried my best to optimize it and do it in same O(n*m) steps as done with the regular row counting, since Sequences are lazily evaluated.
This is a functional way of doing it that works if all rows are the same size:
fun <T>List<List<T>>.rowToColumn() = (0 until first().size).map{row -> (0 until size).map {col-> this[col][row] }}

Possibility to reduce nested loops

I want to bypass deep nesting of several for-loops when creating a list off all possible Transformations.
Right now, this block of code is used:
val allTransformations = ArrayList<Transformation>().apply {
for (moveZ in 0..4)
for (moveY in 0..4)
for (moveX in 0..4)
for (rotateZ in 0..3)
for (rotateY in 0..3)
for (rotateX in 0..3)
add(Transformation(rotateX, rotateY, rotateZ, moveX, moveY, moveZ))
}
Although this is quite straight forward, I was wondering if Kotlin provides other tools to write this in a single line.
I want to retrieve the same list, with less code and see if this results in less clutter.
This solution can be invoked with:
loopOverRanges(0..4, 0..4, 0..4, 0..3, 0..3, 0..3) { result ->
// result[0], result[1], result[2], result[3], result[4], result[5]
}
This is defined as such:
fun loopOverRanges(
vararg ranges: IntRange,
function: (IntArray) -> Unit
) {
val result = IntArray(ranges.size) { index -> ranges[index].first }
val productOfRangeLengths = ranges
.map { it.toList().size }
.product()
for (i in 0 until productOfRangeLengths) {
function(result)
result[0] += ranges[0].step
for (rangeIndex in 0 until ranges.size - 1) {
if (result[rangeIndex] == ranges[rangeIndex].last) {
result[rangeIndex] = ranges[rangeIndex].first
result[rangeIndex + 1] += ranges[rangeIndex].step
}
}
}
}
It's questionable to say the least if this improves readability. It removes the need for nesting, which can be useful for a large amount of ranges. It does not give the instant recognition of my initial nested loop; it also hides named parameters and may throw an IndexOutOfBounds when result[TOO_HIGH_INT] is retrieved.
It was a fun little investigation, but I lean towards not using it.
Here is how to do it with one loop. Just like incrementing a counter with 6 digits. When the first digit overflow, carry to the second digit and reset the first digit. etc.
fun loopOverRanges(a:IntRange,b:IntRange,c:IntRange,d:IntRange,e:IntRange,f:IntRange) : ArrayList<Transformation>
{
val x = a.count() * b.count() * c.count() * d.count() * e.count() * f.count()
val list : ArrayList<Transformation> = ArrayList()
var rx = f.first
var ry = e.first
var rz = d.first
var mx = c.first
var my = b.first
var mz = a.first
for(i in 0 until x)
{
list.add(Transformation(rx,ry,rz,mx,my,mz))
when{
rx < f.last -> rx += 1
ry < e.last -> {
rx = f.first
ry += 1
}
rz < d.last -> {
rx = f.first
ry = e.first
rz += 1
}
mx < c.last -> {
rx = f.first
ry = e.first
rz = d.first
mx += 1
}
my < b.last -> {
rx = f.first
ry = e.first
rz = d.first
mx = c.first
my += 1
}
mz < a.last -> {
rx = f.first
ry = e.first
rz = d.first
mx = c.first
my = b.first
mz += 1
}
}
}
}
return list
}
It can be simplified as
fun loopOverRanges(a:IntRange,b:IntRange,c:IntRange,d:IntRange,e:IntRange,f:IntRange) : ArrayList<Transformation>
{
data class Digit(var value :Int, val range:IntRange)
val list : ArrayList<Transformation> = ArrayList()
val digits = arrayOf(Digit(a.first,a),Digit(b.first,b),Digit(c.first,c),Digit(d.first,d),Digit(e.first,e),Digit(f.first,f))
val x = digits.fold(1){acc,digit -> acc * digit.range.count() }
for(i in 0 until x)
{
list.add(Transformation(digits[5].value,digits[4].value,digits[3].value,digits[2].value,digits[1].value,digits[0].value))
val j = digits.indexOfFirst { it.value < it.range.last }
if(j >= 0)
{
for(k in 0 until j )
{
digits[k].value = digits[k].range.first
}
digits[j].value += 1
}
}
return list
}

UIButton simultaneous clicks action depending count

If user clicks 1 and less than 5 times click/press then OneTimeClickAction func should called,
If User simultaneously or consecutively 5 times and less than 10 times click/press then FiveTimeClickAction func should get called
and If User simultaneously or consecutively more than 10 times click/press then tenTimeClickAction func should get called.
{
guard let tempDate = self.lastTappedAt else { return }
let elapsed = Date().timeIntervalSince(tempDate)
let duration = Int(elapsed)
print(duration)
if duration < 2 {
tapCount = tapCount + 1
// return
} else {
tapCount = 0
}
self.lastTappedAt = Date()
if tapCount > 9 {
let dispatchTime = DispatchTime.now() + 3.0
DispatchQueue.main.asyncAfter(deadline: dispatchTime) {
self.didTappedTenTimes(.happy)
}
return
}
if ((tapCount < 6) && (duration > 2)) {
let dispatchTime = DispatchTime.now() + 3.0
DispatchQueue.main.asyncAfter(deadline: dispatchTime) {
self.didTappedFiveTimes(.react)
}
return
}
if tapCount == 0{
let dispatchTime = DispatchTime.now() + 3.0
DispatchQueue.main.asyncAfter(deadline: dispatchTime) {
self.didTapped(.wink)
}
}
}
please feel free to let me know more about the same in depth and suggest me to deal this in better way.
Thanks
OK, I understand you don't want to track actual time when button is pressed, but only count taps in some reasonable time, assuming multiple taps one after another belonging to same action (wink, happy, react).
var tapCount = 0
var lastTappedAt: Date = Date()
func scheduleCheckResult() {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
let timePassedSinceLastTap = Int(Date().timeIntervalSince(self.lastTappedAt))
print("last tap was \(timePassedSinceLastTap) ago")
// Wait a bit more for resolving final reaction. Adjust if you want quicker/slower taps (more than 1s for slower, less for quiceker)
guard timePassedSinceLastTap > 1 else {
return self.scheduleCheckResult()
}
print("FINISHED WITH: \(self.tapCount)")
// Verify result
switch self.tapCount {
case let n where n >= 10:
print("Super duper happy")
case let n where n >= 5:
print("Very happy")
default:
print("Medium happy")
}
// Reset state
self.tapCount = 0
}
}
#IBAction func didTap() {
if tapCount == 0 {
scheduleCheckResult()
}
lastTappedAt = Date()
tapCount += 1
}

Return Option inside Loop

The program aims to use a loop to check if the index of a iterator variable meets certain criteria (i.g., index == 3). If find the desired index, return Some(123), else return None.
fn main() {
fn foo() -> Option<i32> {
let mut x = 5;
let mut done = false;
while !done {
x += x - 3;
if x % 5 == 0 {
done = true;
}
for (index, value) in (5..10).enumerate() {
println!("index = {} and value = {}", index, value);
if index == 3 {
return Some(123);
}
}
return None; //capture all other other possibility. So the while loop would surely return either a Some or a None
}
}
}
The compiler gives this error:
error[E0308]: mismatched types
--> <anon>:7:9
|
7 | while !done {
| ^ expected enum `std::option::Option`, found ()
|
= note: expected type `std::option::Option<i32>`
= note: found type `()`
I think the error source might be that a while loop evaluates to a (), thus it would return a () instead of Some(123). I don't know how to return a valid Some type inside a loop.
The value of any while true { ... } expression is always (). So the compiler expects your foo to return an Option<i32> but finds the last value in your foo body is ().
To fix this, you can add a return None outside the original while loop. You can also use the loop construct like this:
fn main() {
// run the code
foo();
fn foo() -> Option<i32> {
let mut x = 5;
loop {
x += x - 3;
for (index, value) in (5..10).enumerate() {
println!("index = {} and value = {}", index, value);
if index == 3 {
return Some(123);
}
}
if x % 5 == 0 {
return None;
}
}
}
}
The behaviour of while true { ... } statements is maybe a bit quirky and there have been a few requests to change it.