このところ本業が忙しくてpepsiと遊ぶ時間がないのですが合間にサンプルを作りました。年度末に学生さんに出したプログラミング課題の一つ、「1000までの整数からユニークに100個を選ぶ」です。
別に凝ってもいないし人に見せるようなものでもないのですが…
{ import: st80 } "----------------------------------------------------------------" Random : Object ( seed a m q r ) Random new [ ^super new init ] Random init [ [seed := (Time millisecondClockValue bitAnd: 16r3FFFFFFF) bitXor: self hash. seed = 0] whileTrue. a := 16807 asFloat. m := 1073741823 asFloat * 2.0. q := (m quo: a) asFloat. r := (m ?? a) asFloat. ] Random next [ ^(seed := self nextValue) / m. ] Random nextValue [ | lo hi aLoRHi | hi := (seed quo: q) asFloat. lo := seed - (hi * q). " = seed rem: q" aLoRHi := (a * lo) - (r * hi). ^(aLoRHi > 0.0) ifTrue: [aLoRHi] ifFalse: [aLoRHi + m]. ] Random nextInt: anInteger [ ^(self next * anInteger) truncated ] Time : Magnitude ( _seconds _nanoseconds ) Time seconds [ ^SmallInteger value_: _seconds ] Time nanoseconds [ ^SmallInteger value_: _nanoseconds ] Time millisecondClockValue { struct timeval tv; gettimeofday(&tv, 0); return (oop)(((tv.tv_sec * 1000 + tv.tv_usec / 1000) &0x3fffffff) << 1 | 1); } "----------------------------------------------------------------" [ | r c v start msec | start := Time millisecondClockValue. r := Random new. c := Set new. [ v := r nextInt: 1000. c add: v. c size < 100] whileTrue. msec := Time millisecondClockValue - start. c println. msec println. ]
乱数生成がst80になく、joltから引っ張ってきたのでえらく長いですが、本体は一番最後のブロックです(いたって素直なコード?)。種の生成にミリ秒を使っているんでついでに実行時間も測ってみました。(startとmsecのところです)
実行するとこんな感じです。
Set(512 259 775 263 778 523 268 13 526 787 533 21 281 282 795 540 26 28 799 546 804 550 808 302 305 821 822 55 317 61 320 68 587 591 593 851 852 596 341 87 597 601 343 348 97 101 616 106 877 366 115 630 119 632 889 378 127 134 137 907 909 912 656 914 144 662 153 665 921 163 167 939 431 944 177 688 436 182 697 698 191 706 965 710 967 455 977 724 988 991 738 484 999 493 496 499 759 506 253 765) 9
9msですか。結構かかってます。最後のブロックをsqueakのworkspaceに貼付けて実行すると2msです。まあ、この程度のコードで実行時間を測っても意味ないですけどね。