Last active
August 29, 2015 13:56
-
-
Save AndrewTweddle/9177615 to your computer and use it in GitHub Desktop.
A solver using Scala's foldLeft to solve the Johnny Hates Math problem found at http://www.spoj.com/problems/ANARC07J/ (NB: this is to find all solutions to the problem, not to satisfy the SPOJ IO specification)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package jhm | |
| case class SolverUsingFoldLeft( digits: String, total: Int, maxDigitsPerNumber: Int = 5 | |
| ) extends JHMSolver(digits, total, maxDigitsPerNumber) { | |
| case class PartialSolution( val partialStr: String, val partialNumber: Int, | |
| val subTotal: Int, val numbersInReverse: List[Int] ) | |
| { | |
| def runningSubTotal = subTotal + partialNumber | |
| def isInitialSolution = partialStr == "" | |
| def isZero = partialStr == "0" | |
| def isMaxLength = partialStr.length == maxDigitsPerNumber | |
| } | |
| override def solve(digits: String, total: Int, maxDigitsPerNumber: Int = 5): List[List[Int]] = { | |
| def StartNewPartialNumber(par: PartialSolution, newPartialStr: String, | |
| newPartialNumber: Int)= PartialSolution( | |
| partialStr = newPartialStr, | |
| partialNumber = newPartialNumber, | |
| subTotal = par.runningSubTotal, | |
| numbersInReverse = if (par.isInitialSolution) List.empty // don't prepend zero | |
| else par.partialNumber :: par.numbersInReverse | |
| ) | |
| def buildUpSolutions(partialSolutions: List[PartialSolution], nextDigit: Char): List[PartialSolution] = { | |
| def expandSolution(par: PartialSolution): List[PartialSolution] = { | |
| val nextDigitAsStr = nextDigit.toString | |
| val nextDigitAsInt = nextDigitAsStr.toInt | |
| val parSolWithStartOfNewNumber = StartNewPartialNumber(par, nextDigitAsStr, nextDigitAsInt) | |
| if (parSolWithStartOfNewNumber.runningSubTotal > total) | |
| List.empty // No point in trying an even bigger number | |
| else { | |
| if (par.isZero || par.isMaxLength || par.isInitialSolution) List(parSolWithStartOfNewNumber) | |
| else { | |
| val parSolWithLargerNumber = PartialSolution( | |
| partialStr = par.partialStr + nextDigit, | |
| partialNumber = 10 * par.partialNumber + nextDigit.toString.toInt, | |
| subTotal = par.subTotal, | |
| numbersInReverse = par.numbersInReverse | |
| ) | |
| if (parSolWithLargerNumber.runningSubTotal > total) List(parSolWithStartOfNewNumber) | |
| else List(parSolWithStartOfNewNumber, parSolWithLargerNumber) | |
| } | |
| } | |
| } | |
| partialSolutions flatMap expandSolution | |
| } | |
| val initialPartialSolution = PartialSolution( | |
| partialStr = "", partialNumber = 0, subTotal = 0, numbersInReverse = List()) | |
| val allSolutions = digits.foldLeft(List(initialPartialSolution))(buildUpSolutions) | |
| def completePartialSolution(par: PartialSolution): PartialSolution = PartialSolution( | |
| partialStr = "", | |
| partialNumber = 0, | |
| subTotal = par.runningSubTotal, | |
| numbersInReverse = par.partialNumber :: par.numbersInReverse | |
| ) | |
| allSolutions map completePartialSolution filter (_.subTotal == total) map (_.numbersInReverse.reverse) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment