Finding the nearest defibrillator exercise from CodingGames
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
2
down vote
favorite
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
val playerLongitude = readLine
val playerLatitude = readLine
val defibrilatorCount = readInt
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 defib = readLine
val distance = distanceToPlayer(defib)
if(distance < smallestDistance)
smallestDistance = distance
closestDefibName = defib.split(";")(1)
println(closestDefibName)
beginner programming-challenge scala geospatial
add a comment |Â
up vote
2
down vote
favorite
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
val playerLongitude = readLine
val playerLatitude = readLine
val defibrilatorCount = readInt
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 defib = readLine
val distance = distanceToPlayer(defib)
if(distance < smallestDistance)
smallestDistance = distance
closestDefibName = defib.split(";")(1)
println(closestDefibName)
beginner programming-challenge scala geospatial
add a comment |Â
up vote
2
down vote
favorite
up vote
2
down vote
favorite
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
val playerLongitude = readLine
val playerLatitude = readLine
val defibrilatorCount = readInt
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 defib = readLine
val distance = distanceToPlayer(defib)
if(distance < smallestDistance)
smallestDistance = distance
closestDefibName = defib.split(";")(1)
println(closestDefibName)
beginner programming-challenge scala geospatial
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
val playerLongitude = readLine
val playerLatitude = readLine
val defibrilatorCount = readInt
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 defib = readLine
val distance = distanceToPlayer(defib)
if(distance < smallestDistance)
smallestDistance = distance
closestDefibName = defib.split(";")(1)
println(closestDefibName)
beginner programming-challenge scala geospatial
edited Jul 11 at 0:08
200_success
123k14143399
123k14143399
asked Jul 10 at 21:33
Stud
563113
563113
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
1
down vote
accepted
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 io.StdIn.readInt, readLine
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
val player = GeoObject(parseDouble(readLine), parseDouble(readLine), null)
val count = readInt
val nearest = (0 until count).map(_ => parseDefibrillator(readLine))
.minBy(distanceMetric(player, _))
println(nearest.name)
I was wondering how to remove the loops and you answered that question. Thank you for your answer, I find it very elegant.
â Stud
Jul 11 at 11:36
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
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 io.StdIn.readInt, readLine
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
val player = GeoObject(parseDouble(readLine), parseDouble(readLine), null)
val count = readInt
val nearest = (0 until count).map(_ => parseDefibrillator(readLine))
.minBy(distanceMetric(player, _))
println(nearest.name)
I was wondering how to remove the loops and you answered that question. Thank you for your answer, I find it very elegant.
â Stud
Jul 11 at 11:36
add a comment |Â
up vote
1
down vote
accepted
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 io.StdIn.readInt, readLine
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
val player = GeoObject(parseDouble(readLine), parseDouble(readLine), null)
val count = readInt
val nearest = (0 until count).map(_ => parseDefibrillator(readLine))
.minBy(distanceMetric(player, _))
println(nearest.name)
I was wondering how to remove the loops and you answered that question. Thank you for your answer, I find it very elegant.
â Stud
Jul 11 at 11:36
add a comment |Â
up vote
1
down vote
accepted
up vote
1
down vote
accepted
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 io.StdIn.readInt, readLine
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
val player = GeoObject(parseDouble(readLine), parseDouble(readLine), null)
val count = readInt
val nearest = (0 until count).map(_ => parseDefibrillator(readLine))
.minBy(distanceMetric(player, _))
println(nearest.name)
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 io.StdIn.readInt, readLine
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
val player = GeoObject(parseDouble(readLine), parseDouble(readLine), null)
val count = readInt
val nearest = (0 until count).map(_ => parseDefibrillator(readLine))
.minBy(distanceMetric(player, _))
println(nearest.name)
answered Jul 11 at 0:29
200_success
123k14143399
123k14143399
I was wondering how to remove the loops and you answered that question. Thank you for your answer, I find it very elegant.
â Stud
Jul 11 at 11:36
add a comment |Â
I was wondering how to remove the loops and you answered that question. Thank you for your answer, I find it very elegant.
â Stud
Jul 11 at 11:36
I was wondering how to remove the loops and you answered that question. Thank you for your answer, I find it very elegant.
â Stud
Jul 11 at 11:36
I was wondering how to remove the loops and you answered that question. Thank you for your answer, I find it very elegant.
â Stud
Jul 11 at 11:36
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f198247%2ffinding-the-nearest-defibrillator-exercise-from-codinggames%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password