Skip to content

Commit

Permalink
Merge pull request #1429 from jbgi/digits
Browse files Browse the repository at this point in the history
Add digitsFrom{Int, Long, BigInt}: extract digits of a number,
  • Loading branch information
jbgi committed Jan 28, 2018
2 parents 5f915b8 + 18848b7 commit cd7d850
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 20 deletions.
40 changes: 20 additions & 20 deletions core/src/main/scala/scalaz/Digit.scala
Expand Up @@ -51,33 +51,33 @@ object Digit extends DigitInstances {
override val toInt = 9
}

val digits: IList[Digit] = IList(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9)
private val digitsArray: Array[Digit] = Array(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9)

val digits: IList[Digit] = IList(digitsArray : _*)

implicit def DigitLong(d: Digit): Long = d.toLong

def digitFromChar(c: Char): Option[Digit] =
digits.find(_.toChar == c)
def digitFromChar(c: Char): Option[Digit] = digitFromInt(c.toInt - 48)

def digitFromInt(i: Int): Option[Digit] =
digits.find(_.toInt == i)
if (0 <= i && i <= 9) Some(digitsArray(i)) else None

def digitFromLong(i: Long): Option[Digit] =
digits.find(_.toLong == i)

def mod10Digit(i: Int): Digit =
i match {
case 0 => _0
case 1 => _1
case 2 => _2
case 3 => _3
case 4 => _4
case 5 => _5
case 6 => _6
case 7 => _7
case 8 => _8
case 9 => _9
case _ => mod10Digit(scala.math.abs(i) % 10)
}
if (0L <= i && i <= 9L) Some(digitsArray(i.toInt)) else None

def digitsFromInt(i: Int): NonEmptyList[Digit] = digitsFromNumberString(i.toString)

def digitsFromLong(l: Long): NonEmptyList[Digit] = digitsFromNumberString(l.toString)

def digitsFromBigInt(b: BigInt): NonEmptyList[Digit] = digitsFromNumberString(b.toString)

private def digitsFromNumberString(number: String): NonEmptyList[Digit] = {
val (head, tail) = number.stripPrefix("-").splitAt(1)
NonEmptyList.nel(
digitsArray(head.charAt(0).toInt - 48), tail.foldRight(IList.empty[Digit]) ((c, ds) => digitsArray(c.toInt - 48) :: ds))
}

def mod10Digit(i: Int): Digit = digitsArray(scala.math.abs(i % 10))

def longDigits[F[_]](digits: F[Digit])(implicit F: Foldable[F]): Long =
F.foldLeft(digits, 0L)((n, a) => n * 10L + (a: Digit))
Expand Down
21 changes: 21 additions & 0 deletions tests/src/test/scala/scalaz/DigitTest.scala
@@ -1,9 +1,30 @@
package scalaz

import Scalaz._
import scalaz.scalacheck.ScalazProperties._
import scalaz.scalacheck.ScalazArbitrary._
import org.scalacheck.Prop.forAll

object DigitTest extends SpecLite {
checkAll(enum.laws[Digit])
checkAll(monoid.laws[Digit])

"correctly extract int digits" ! forAll {
(i: Int) => {
Digit.digitsFromInt(i).longDigits must_===(scala.math.abs(i.toLong))
}
}

"correctly extract long digits" ! forAll {
(i: Long) => {
Digit.digitsFromLong(i).map(_.toInt.toString).suml must_===(i.toString.stripPrefix("-"))
}
}

"correctly extract bigint digits" ! forAll {
(i: BigInt) => {
Digit.digitsFromBigInt(i).map(_.toInt.toString).suml must_===(i.toString.stripPrefix("-"))
}
}

}

0 comments on commit cd7d850

Please sign in to comment.