😜
Sleep FizzBuzz
Twitter で散歩していたら、昨日こんなツイートを見付けました。
コードはこんな感じ。(ツイート主がメンションで修正している内容を反映済み)
main.rs
use std::{
thread::{self, sleep},
time::Duration,
};
fn main() {
thread::spawn(|| {
sleep(Duration::from_millis(2100));
loop {
print!("Fizz\x1b[K");
sleep(Duration::from_secs(3));
}
});
thread::spawn(|| {
sleep(Duration::from_millis(4200));
loop {
print!("Buzz\x1b[K");
sleep(Duration::from_secs(5));
}
});
for i in 1.. {
print!("\n{i}\r");
sleep(Duration::from_secs(1));
}
}
このコード、動かすとちゃんと FizzBuzz が表示されます。
コードが読める方であればおおよそ検討が付くはず。1秒間隔で数字を表示するループ、そしてスレッドで 3秒毎に Fizz を表示するループと、スレッドで 5秒毎に Buzz を表示するループで構成されます。毎秒数字を表示する部分は \n{i}\r
なので数字を表示した直後にカーソルを行の先頭に戻します。
このコードのミソは3秒毎に Fizz を表示するループには初期ウエイトとして 2100 ミリ秒、5秒毎に Buzz を表示するループには初期ウエイトとして 4200 ミリ秒が与えられています。これにより、Fizz を表示するループでは毎秒表示される数字の 3 の倍数秒の時、数字が表示された 100 ミリ秒後に Fizz で上書きます。また 5 の倍数秒の時、数字が表示された 200 ミリ秒後に Buzz で上書きます。ウエイトは Fizz のスレッドよりも Buzz のスレッドの方が1秒単位で言うと 100 ミリ秒多いので、15の倍数秒の時は Fizz と Buzz が連続で表示されます。
これにより FizzBuzz が動くという仕組みです。
おもしろいですね。コード面接で FizzBuzz 書いてと言われた時にこんなコードを書いたら驚かれるんじゃないでしょうか。(FizzBuzz をコード面接で書かせる所なんて無いと思いますが)
追記
ちなみに Go で書くとこんな感じ
main.go
package main
import (
"fmt"
"time"
"github.com/mattn/go-colorable"
)
func main() {
t1 := time.NewTicker(1)
t3 := time.NewTicker(1)
t5 := time.NewTicker(1)
t1.Stop()
t3.Stop()
t5.Stop()
t1.Reset(time.Second)
time.Sleep(time.Millisecond * 5)
t3.Reset(time.Second * 3)
time.Sleep(time.Millisecond * 5)
t5.Reset(time.Second * 5)
out := colorable.NewColorableStdout()
var i int
for {
select {
case <-t5.C:
fmt.Fprint(out, "Buzz\x1b[K")
case <-t3.C:
fmt.Fprint(out, "Fizz\x1b[K")
case <-t1.C:
i++
fmt.Fprintf(out, "\n%d\r", i)
}
}
}
Discussion