patternMinor
Project Euler #17
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] = {
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
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.