# Finding the nearest defibrillator exercise from CodingGames

For my first attempt at Scala I decided to solve a simple exercise on codingame.com.

Based on a string input containing the user location, the defibrillators count and a list of defibrillators entries (id, name, address, phone number, longitude, latitude), I have to print the closest defibrillator from the user. The distance formula is given in the rules.

An example of input:

3,879483
43,608177
3
1;Maison de la Prevention Sante;6 rue Maguelone 340000 Montpellier;;3,87952263361082;43,6071285339217
2;Hotel de Ville;1 place Georges Freche 34267 Montpellier;;3,89652239197876;43,5987299452849
3;Zoo de Lunaret;50 avenue Agropolis 34090 Mtp;;3,87388031141133;43,6395872778854

import math._
import scala.util._

object Solution extends App {

def sanitizeString(string : String) : String = string.replace(',', '.')
def stringToDouble(string : String) : Double =  sanitizeString(string).toDouble

val playerLongitudeValue = stringToDouble(playerLongitude)
val playerLatitudeValue = stringToDouble(playerLatitude)

def distanceToPlayer(long : Double, lat : Double) :  Double = {
val x = (long - playerLongitudeValue) * cos((playerLatitudeValue + lat) / 2)
val y  = lat - playerLatitudeValue
sqrt(x * x + y * y) * 6371;
}

def distanceToPlayer(stringInput : String) : Double = {
val tokens = sanitizeString(stringInput).split(";")
distanceToPlayer(tokens(4).toDouble, tokens(5).toDouble)
}

var smallestDistance = Double.MaxValue
var closestDefibName = ""

for(i <- 0 until defibrilatorCount) {
val distance = distanceToPlayer(defib)
if(distance < smallestDistance) {
smallestDistance = distance
closestDefibName = defib.split(";")(1)
}
}

println(closestDefibName)
}


The main observation I would make is that this code — particularly the for loop — looks very procedural. To find the minimum of some collection as determined by some metric, use .minBy[B](f: (A) ⇒ B): A.

For readability, avoid interleaving function definitions with the execution flow. Put all of the definitions first, if possible.

You potentially split each defibrillator input line twice: once to extract the coordinates, then maybe again if you are interested in extracting the name. I suggest parsing each line once and constructing a case class object from it.

Your sanitizeString function is rather heavy-handed. To parse French-formatted decimals, use java.text.NumberFormat.

Note that defibrilatorCount is misspelled.

## Suggested solution

import math.{cos, sqrt}
import java.text.NumberFormat
import java.util.Locale

object Solution extends App {
val frenchFmt = NumberFormat.getInstance(Locale.FRANCE)
def parseDouble(s: String): Double = frenchFmt.parse(s).doubleValue

case class GeoObject(long: Double, lat: Double, name: String)

def parseDefibrillator(line: String): GeoObject = {
val fields = line.split(";")
GeoObject(parseDouble(fields(4)), parseDouble(fields(5)), fields(1))
}

def distanceMetric(a: GeoObject, b: GeoObject): Double = {
val x = (a.long - b.long) * cos((a.lat + a.lat) / 2)
val y = a.lat - b.lat
6371 * sqrt(x * x + y * y)
// Note: 6371 * sqrt is optional, if just comparing distances
}