diff --git a/nmcb/src/main/scala/examples/VampireNumber.scala b/nmcb/src/main/scala/examples/VampireNumber.scala index f0d911d5..361031f3 100644 --- a/nmcb/src/main/scala/examples/VampireNumber.scala +++ b/nmcb/src/main/scala/examples/VampireNumber.scala @@ -9,20 +9,34 @@ object VampireNumber: def possibleFangs(length: Int): Iterator[String] = digits.combinations(length).flatMap(_.permutations).distinct - def isVampireNumber(n: Int): Boolean = - val digits: String = n.toString + def isVampireNumber(number: Int): Boolean = + val digits: String = number.toString if digits.length % 2 != 0 then false else - val fangLength = digits.length / 2 - digits.possibleFangs(fangLength).exists: left => - digits.diff(left).possibleFangs(fangLength).exists: right => - n == left.toInt * right.toInt + val fangWidth = digits.length / 2 + digits.possibleFangs(fangWidth).exists: leftDigits => + val leftFang = leftDigits.toInt + if leftFang != 0 then + val rightFang = number / leftFang + if leftFang % 10 == 0 && rightFang % 10 == 0 then + false + else + if rightFang * leftFang == number then + val rightDigits = rightFang.toString + digits.sorted == (leftDigits + rightDigits).sorted + else false + else + false + + def sieve(max: Int): Seq[Int] = + (0 to max).filter(isVampireNumber) + def main(args: Array[String]): Unit = val max: Int = Try(args(0).toInt).getOrElse(1000000) val start: Long = currentTimeMillis - val result: Seq[Int] = (0 to max).filter(isVampireNumber) + val result: Seq[Int] = sieve(max) println(s"vampire numbers up to $max:") println(result.mkString(", ")) diff --git a/nmcb/src/test/scala/examples/TestVampireNumber.scala b/nmcb/src/test/scala/examples/TestVampireNumber.scala new file mode 100644 index 00000000..b199c753 --- /dev/null +++ b/nmcb/src/test/scala/examples/TestVampireNumber.scala @@ -0,0 +1,17 @@ +package examples + +import org.scalatest.funsuite.AnyFunSuite + +class TestVampireNumber extends AnyFunSuite: + + /** [OEIS-A014575](https://oeis.org/A014575) */ + test("VampireNumber") { + println(VampireNumber.sieve(135837)) + assertResult( + Vector( + 1260, 1395, 1435, 1530, 1827, 2187, 6880, 102510, 104260, 105210, 105264, 105750, 108135, + 110758, 115672, 116725, 117067, 118440, 120600, 123354, 124483, 125248, 125433, 125460, + 125500, 126027, 126846, 129640, 129775, 131242, 132430, 133245, 134725, 135828, 135837 + ) + )(VampireNumber.sieve(135837)) + }