LoginSignup
0
0

More than 1 year has passed since last update.

【Kotlin】Sleep FizzBuzz

Last updated at Posted at 2022-02-15

↑の記事にある Sleep FizzBuzz を Kotlin Coroutines でやってみた。

単純版

素直にやるとこんな感じ。

fun main() = runBlocking<Unit> {
    launch {
        for (i in 1..Int.MAX_VALUE) {
            delay(1_000)
            print("\n$i\r")
        }
    }
    launch {
        delay(100)
        while (true) {
            delay(3_000)
            print("Fizz\u001b[K")
        }
    }
    launch {
        delay(200)
        while (true) {
            delay(5_000)
            print("Buzz\u001b[K")
        }
    }
}

(元記事の方法とは少し変えて、
 出力され始めるまで1秒待つが
 その分読みやすいコードにした。)

結果。

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz

うまくいっているように見える。

しかし 100 くらいまで来るともうグダグダ。

FizzBuzz
90
91
Fizz
93
Buzz
Fizz
96
97
Fizz
Buzz
100

print 関数の呼び出し、その引数とする文字列の構築、それにスレッドの切り替えなどに時間が掛かって、
誤差が出てくるのだろう。

SharedFlow で Ticker を作る

お題の趣旨からは少し離れてしまうが、
SharedFlow を使っていわゆる Ticker を作り、
ズレが出ないようにしてみた。

fun main() = runBlocking<Unit> {
    val ticker =
        flow {
            for (sec in 1..Int.MAX_VALUE) {
                emit(sec)
                delay(1_000)
            }
        }.shareIn(this, SharingStarted.Lazily)

    ticker
        .onEach {
            print("\n$it\r")
        }.launchIn(this)
    ticker
        .filter { it % 3 == 0 }
        .onEach {
            delay(1)
            print("Fizz\u001b[K")
        }.launchIn(this)
    ticker
        .filter { it % 5 == 0 }
        .onEach {
            delay(2)
            print("Buzz\u001b[K");
        }.launchIn(this)
}

これはうまくいった。

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz

1000付近でも大丈夫。

FizzBuzz
991
992
Fizz
994
Buzz
Fizz
997
998
Fizz
Buzz

【Kotlin/JVM】 ScheduledThreadPoolExecutor.scheduleAtFixedRate を使う

Java の ScheduledThreadPoolExecutor.scheduleAtFixedRate を使うと次のようになる。

fun main() = runBlocking<Unit> {
    var i = 1
    ScheduledThreadPoolExecutor(1)
        .scheduleAtFixedRate(
            { print("\n${i++}\r") },
            1_000 + 0,
            1_000,
            TimeUnit.MILLISECONDS,
        )
    ScheduledThreadPoolExecutor(1)
        .scheduleAtFixedRate(
            { print("Fizz\u001b[K") },
            3_000 + 1,
            3_000,
            TimeUnit.MILLISECONDS,
        )
    ScheduledThreadPoolExecutor(1)
        .scheduleAtFixedRate(
            { print("Buzz\u001b[K") },
            5_000 + 2,
            5_000,
            TimeUnit.MILLISECONDS,
        )
}

これはお題の趣旨にも合っているし、
正しい結果が得られる。
(Kotlin らしさはほとんどないが。)

/以上

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0