Finding the nearest defibrillator exercise from CodingGames

The name of the pictureThe name of the pictureThe name of the pictureClash 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)







share|improve this question



























    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)







    share|improve this question























      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)







      share|improve this question













      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)









      share|improve this question












      share|improve this question




      share|improve this question








      edited Jul 11 at 0:08









      200_success

      123k14143399




      123k14143399









      asked Jul 10 at 21:33









      Stud

      563113




      563113




















          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)






          share|improve this answer





















          • 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










          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          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






























          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)






          share|improve this answer





















          • 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














          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)






          share|improve this answer





















          • 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












          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)






          share|improve this answer













          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)







          share|improve this answer













          share|improve this answer



          share|improve this answer











          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
















          • 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












           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          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













































































          Popular posts from this blog

          Chat program with C++ and SFML

          Function to Return a JSON Like Objects Using VBA Collections and Arrays

          Will my employers contract hold up in court?