From 5f4cc4139c7596a1cab66807ea0913d0ebd5b44b Mon Sep 17 00:00:00 2001 From: Thanh Le Date: Sun, 5 Nov 2023 12:35:23 +0100 Subject: [PATCH] Fix findLast, add last function for Bitboard Also add tests --- src/main/scala/bitboard/Bitboard.scala | 13 ++++++++-- .../test/scala/bitboard/BitboardTest.scala | 25 +++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/main/scala/bitboard/Bitboard.scala b/src/main/scala/bitboard/Bitboard.scala index 77c17cf2c..e7d4c980b 100644 --- a/src/main/scala/bitboard/Bitboard.scala +++ b/src/main/scala/bitboard/Bitboard.scala @@ -111,6 +111,7 @@ object Bitboard: inline def isDisjoint(o: Bitboard): Boolean = (a & o).isEmpty + // return list of square that sorted ascendingly def squares: List[Square] = var b = a val builder = List.newBuilder[Square] @@ -129,6 +130,15 @@ object Bitboard: b &= (b - 1L) result + def last[B](f: Square => Option[B]): Option[B] = + var b = a + var result: Option[B] = None + while b != 0L && result.isEmpty + do + result = f(b.msb) + b &= ~b.msb.bl + result + def find(f: Square => Boolean): Option[Square] = var b = a var result: Option[Square] = None @@ -138,14 +148,13 @@ object Bitboard: b &= (b - 1L) result - // tests def findLast(f: Square => Boolean): Option[Square] = var b = a var result: Option[Square] = None while b != 0L && result.isEmpty do if f(b.msb) then result = Some(b.msb) - b &= (b - 1L) + b &= ~b.msb.bl result def fold[B](init: B)(f: (B, Square) => B): B = diff --git a/test-kit/src/test/scala/bitboard/BitboardTest.scala b/test-kit/src/test/scala/bitboard/BitboardTest.scala index 48de39f94..a3d609c75 100644 --- a/test-kit/src/test/scala/bitboard/BitboardTest.scala +++ b/test-kit/src/test/scala/bitboard/BitboardTest.scala @@ -54,6 +54,27 @@ class BitboardTest extends ScalaCheckSuite: def f = (p: Square) => if p == x then Some(p) else None Bitboard(xs + x).first(f) == Some(x) + test("last with a function that always return None should return None"): + forAll: (bb: Bitboard) => + assertEquals(bb.last(_ => None), None) + + test("last with a function that always return Some should return the last square"): + forAll: (bb: Bitboard) => + assertEquals(bb.last(Some(_)), bb.last) + + test("last returns the correct square"): + forAll: (xs: Set[Square], x: Square) => + def f = (p: Square) => if p == x then Some(p) else None + Bitboard(xs + x).last(f) == Some(x) + + test("find"): + forAll: (bb: Bitboard, f: Square => Boolean) => + bb.find(f) == bb.squares.find(f) + + test("findLast"): + forAll: (bb: Bitboard, f: Square => Boolean) => + bb.findLast(f) == bb.squares.reverse.find(f) + test("bitboard created by set of square should contains and only contains those square"): forAll: (xs: Set[Square]) => val bb = Bitboard(xs) @@ -147,6 +168,10 @@ class BitboardTest extends ScalaCheckSuite: forAll: (b: Bitboard, f: Square => Option[Int]) => b.first(f) == b.squares.map(f).find(_.isDefined).flatten + property("last"): + forAll: (b: Bitboard, f: Square => Option[Int]) => + b.last(f) == b.squares.map(f).findLast(_.isDefined).flatten + property("foreach"): forAll: (b: Bitboard, f: Square => Int) => var s1 = 0L