сумма квадратов четных цифр из рекурсии правого хвоста
def sumOfEvenDigitsTailRecursion(num: Int): Int = {
@tailrec def impl(num: Int, idx: Int, acc: Int): Int = {
if (num == 0) acc
else if (idx % 2 == 0) impl(num / 10, idx + 1, acc + ((num % 10) * (num % 10)))
else impl(num / 10, idx + 1, acc)
}
impl(num, 1, 0)
}
assert(sumOfEvenDigitsTailRecursion(123456) == 5*5 + 3*3 +1*1)
сумма квадратов четных цифр из рекурсии левого хвоста
def sumOfEvenDigitsTailRecursion(num: Int): Int = {
@tailrec def impl(num: Int, idx: Int, acc: Int, length: Int = -1): Int = {
if (length % 2 == 0) {
impl(num / 10, idx, acc + ((num % 10) * (num % 10)))
} else {
if (num == 0) acc
else if (idx % 2 == 0) impl(num / 10, idx + 1, acc + ((num % 10) * (num % 10)))
else impl(num / 10, idx + 1, acc)
}
}
impl(num, 1, 0, (Math.log10(num) + 1).toInt)
}
assert(sumOfEvenDigitsTailRecursion(123456) == 2*2 + 4*4 + 6*6)
сумма квадратов четных цифры слева - итераторы
def sumOfEvenDigitsIterators(num: Int): Int =
num
.toString
.iterator
.map(_.asDigit)
.grouped(2)
.collect{ case ArraySeq(_, b) => b }
.map(x => x * x)
.sum
Тест: sbt "jmh:run -i 10 -wi 10 -f 2 -t 1 bench.So59627557"
@State(Scope.Benchmark)
@BenchmarkMode(Array(Mode.Throughput))
class So59627557 {
def _sumOfEvenDigitsIterators(num: Int): Int =
num
.toString
.iterator
.map(_.asDigit)
.grouped(2)
.collect{ case ArraySeq(_, b) => b }
.map(x => x * x)
.sum
def _sumOfEvenDigitsTailRecursion(num: Int): Int = {
@tailrec def impl(num: Int, idx: Int, acc: Int, length: Int = -1): Int = {
if (length % 2 == 0) {
impl(num / 10, idx, acc + ((num % 10) * (num % 10)))
} else {
if (num == 0) acc
else if (idx % 2 == 0) impl(num / 10, idx + 1, acc + ((num % 10) * (num % 10)))
else impl(num / 10, idx + 1, acc)
}
}
impl(num, 1, 0, (Math.log10(num) + 1).toInt)
}
val num: Int = (math.random * 100000000).toInt
@Benchmark def sumOfEvenDigitsIterators: Int = _sumOfEvenDigitsIterators(num)
@Benchmark def sumOfEvenDigitsTailRecursion: Int = _sumOfEvenDigitsTailRecursion(num)
}
результаты
[info] Benchmark Mode Cnt Score Error Units
[info] So59627557.sumOfEvenDigitsIterators thrpt 20 2033487.342 ± 187156.764 ops/s
[info] So59627557.sumOfEvenDigitsTailRecursion thrpt 20 27431255.610 ± 835429.506 ops/s
Хвост-рекурсивное решение, кажется, имеет больше пропускная способность в 10 раз выше, чем у решений на основе итераторов.