Skip to content

Instantly share code, notes, and snippets.

@mizuhara
Created April 21, 2015 11:44
Show Gist options
  • Save mizuhara/5c808d11a1d0fb3ddda3 to your computer and use it in GitHub Desktop.
Save mizuhara/5c808d11a1d0fb3ddda3 to your computer and use it in GitHub Desktop.
trait FareChart {
def baseFare: Int
def baseDistance: Int
def extraFare: Int
}
class EnraiFareChart extends FareChart {
def baseFare: Int = 400
def baseDistance: Int = 995
def extraFare: Int = 60
}
class TansuFareChart extends FareChart {
def baseFare: Int = 350
def baseDistance: Int = 845
def extraFare: Int = 50
}
class FareChartFactory {
def create(s: String): FareChart = {
s match {
case "A" | "B" | "C" | "AB" | "AC" | "BC" | "CF" | "BG"=>
new EnraiFareChart()
case _ =>
new TansuFareChart()
}
}
}
object Distance {
def between(from: String, to: String): Int = {
val interval = Array(from, to).sorted.mkString
interval match {
case "AB" => 1090
case "AC" => 180
case "AD" => 540
case "BC" => 960
case "BG" => 1270
case "CD" => 400
case "CF" => 200
case "DE" => 720
case "DF" => 510
case "EG" => 1050
case "FG" => 230
}
}
}
class Taxi {
def calculateFare(route: String): Int = {
val chart = (new FareChartFactory).create(route.substring(0, 1))
calculateFareImpl(route, chart.baseFare, chart.baseDistance)
}
private val BaseDistance = 200
@scala.annotation.tailrec
private def calculateFareImpl(route: String, fare: Int, distance: Int): Int = {
if(route.length == 1) {
return fare
}
val (from, to) = (route.substring(0, 1), route.substring(1, 2))
val runningDistance = Distance.between(from, to)
if(isMeterClicked(distance, runningDistance)) {
val chart = (new FareChartFactory).create(Array(from, to).sorted.mkString)
val counts = meterClickedCount(distance, runningDistance)
val curDist = BaseDistance - (runningDistance - distance) % BaseDistance
calculateFareImpl(route.drop(1), fare + chart.extraFare * counts, curDist)
} else {
calculateFareImpl(route.drop(1), fare, distance - runningDistance)
}
}
private def isMeterClicked(meterClickedDistance: Int, runningDistance: Int): Boolean =
meterClickedDistance < runningDistance
private def meterClickedCount(meterClickedDistance: Int, runningDistance: Int): Int =
(runningDistance - meterClickedDistance) / BaseDistance + 1
}
class Solver {
def main(args: Array[String]) {
testAll
}
def test(src: String, expected: String) {
val actual = (new Taxi).calculateFare(src).toString
actual match {
case `expected` => println("ok")
case _ => println("***NG***")
}
}
def testAll {
/*0*/ test( "ADFC", "510" )
/*1*/ test( "CFDA", "500" )
/*2*/ test( "AB", "460" )
/*3*/ test( "BA", "460" )
/*4*/ test( "CD", "400" )
/*5*/ test( "DC", "350" )
/*6*/ test( "BG", "520" )
/*7*/ test( "GB", "530" )
/*8*/ test( "FDA", "450" )
/*9*/ test( "ADF", "450" )
/*10*/ test( "FDACB", "750" )
/*11*/ test( "BCADF", "710" )
/*12*/ test( "EDACB", "800" )
/*13*/ test( "BCADE", "810" )
/*14*/ test( "EGFCADE", "920" )
/*15*/ test( "EDACFGE", "910" )
/*16*/ test( "ABCDA", "960" )
/*17*/ test( "ADCBA", "1000" )
/*18*/ test( "BADCFGB", "1180" )
/*19*/ test( "BGFCDAB", "1180" )
/*20*/ test( "CDFC", "460" )
/*21*/ test( "CFDC", "450" )
/*22*/ test( "ABGEDA", "1420" )
/*23*/ test( "ADEGBA", "1470" )
/*24*/ test( "CFGB", "640" )
/*25*/ test( "BGFC", "630" )
/*26*/ test( "ABGEDFC", "1480" )
/*27*/ test( "CFDEGBA", "1520" )
/*28*/ test( "CDFGEDABG", "1770" )
/*29*/ test( "GBADEGFDC", "1680" )
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment