HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Project Euler #17

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
projecteulerstackoverflow

Problem

Project Euler presents problem 17:


If the numbers 1 to 5 are written out in words: one, two, three,
four, five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in
total. If all the numbers from 1 to 1000 (one thousand) inclusive
were written out
in words, how many letters would be used?

Please review my answer. In particular, please comment on my usage of the Applicative.

```
import scalaz.syntax.applicative._
import scalaz.std.option._
import scala.util.matching.Regex
import scala.annotation.tailrec

object Problem17 {

val oneDigit: Regex = "^[1-9]$".r
val twoDigit: Regex = "^[1-9][0-9]$".r
val threeDigit: Regex = "^[1-9][0-9][0-9]$".r
val fourDigit: Regex = "^[1-9][0-9][0-9][0-9]$".r

private def isOneToFourDigitNum(x: String): Boolean =
x.matches(oneDigit.toString) |
x.matches(twoDigit.toString) |
x.matches(threeDigit.toString) |
x.matches(fourDigit.toString)

// If all the numbers from 1 to 1000 (one thousand) inclusive were written out
// in words, how many letters would be used?
def runProblem: Option[Int] = {
val oneToThousand: List[Int] = (1 to 1000).toList
val numberList: List[String] = oneToThousand.map(_.toString)
val wordLengths: List[Option[Int]] = numberList.map(getLengthOfMaybeNumberWord)
wordLengths match {
case Nil => None
case x :: xs => xs.foldLeft[Option[Int]](x) {
(acc: Option[Int], elem: Option[Int]) => ^(acc, elem)(_ + _)
}
}
}

def getLengthOfMaybeNumberWord(number: String): Option[Int]= {
if (isOneToFourDigitNum(number)) {
val numberAsWord: Option[String] = getNumberAsWord(number)
val wordFiltered: Option[String] = numberAsWord.flatMap(a => Some(a.filter(x => x != ' ').filter(x => x != '-')))
wordFiltered.map(_.length)
}
else None
}

def getNumberAsWord(num: String): Option[String] = {

Solution

Not to be a pain here, but this code is an example of how to complicate something that is reasonably simple.

First, converting the numbers to strings and then using regular expressions is just wrong. Numbers should be dealt with as numbers. Changing them to strings will do nothing but add awkwardness and complication to the algorithm.

Second, it is not necessary to actually create the string in order to calculate it's length.

Third, the method runProblem is a perfect example of when NOT to use a list because a plain, ordinary loop will work just fine, and use far less memory and CPU time.

Context

StackExchange Code Review Q#63485, answer score: 6

Revisions (0)

No revisions yet.