feat(scala): m01–m06 port with shared fixtures
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
045029639e
commit
1e186733d1
23 files changed
+771
-2
No files matched your search
@@ -0,0 +1,36 @@
|
||||
package snake
|
||||
|
||||
/**
|
||||
* m04 random: a tiny "state monad" for randomness. A Random[A] is a function seed => (A, nextSeed),
|
||||
* so every draw is a pure function and the seed is passed along explicitly instead of hidden.
|
||||
* Seeds and values are unsigned 32-bit numbers kept in a Long.
|
||||
*/
|
||||
final case class Random[A](run: Long => (A, Long)):
|
||||
|
||||
def map[B](f: A => B): Random[B] =
|
||||
Random { seed =>
|
||||
val (a, next) = run(seed)
|
||||
(f(a), next)
|
||||
}
|
||||
|
||||
def flatMap[B](f: A => Random[B]): Random[B] =
|
||||
Random { seed =>
|
||||
val (a, next) = run(seed)
|
||||
f(a).run(next)
|
||||
}
|
||||
|
||||
object Random:
|
||||
|
||||
def pure[A](a: A): Random[A] = Random(seed => (a, seed))
|
||||
|
||||
// The mulberry32 arithmetic is done in Int: `*` wraps like 32-bit multiplication and `>>>` is unsigned.
|
||||
// `& 0xFFFFFFFFL` turns the result back into an unsigned value held in a Long.
|
||||
lazy val nextUint32: Random[Long] = Random { seed =>
|
||||
val s = seed.toInt + 0x6d2b79f5
|
||||
val t1 = (s ^ (s >>> 15)) * (s | 1)
|
||||
val t2 = t1 ^ (t1 + (t1 ^ (t1 >>> 7)) * (t1 | 61))
|
||||
val value = t2 ^ (t2 >>> 14)
|
||||
(value.toLong & 0xffffffffL, s.toLong & 0xffffffffL)
|
||||
}
|
||||
|
||||
def intBelow(n: Int): Random[Int] = nextUint32.map(v => (v % n).toInt)
|
||||
Reference in new issue
Block a user