How to find minimum distance person name and corresponding distance using bash script?

Viewed 46

File 1 : sampleInputFile

Name, Xloc, YLoc, Zloc
John, 10.5, 80.1, 5.80
Mary, 30.4, 20.5, 9.20
Paul, 10, 1000.0, 10.6

File 2 : proj01.sh (bash script file)
File 3 : correspondingOutputFile (output would shown in this file)


If input cmd         : proj01.sh sampleInputFile 1   (In 3rd param, 1 is john, 2 is Mary, 3 is Paul)
Format of the output : Mary 62.9                     (as Mary is near to John, and we can round that to 63.0 also)

 **challenge** : 
1) Check if filename passed in 1st parameter exists, if not stop with some message.
2) check that the index passed in 2nd parameter is an integer and is valid, which means is it less or equally to the number of entries and > 0.
3) bash script (proj01.sh) is going to find the min dist from the index person to another person.
    calculate distances using :  d = sqrt ( (x1-x2)^2 + (y1-y2)^2 + (z1-z2)^2 )

Note : All files are in same directory.

tried to read values and not sure how to compare all lines by given index line:

{
    read
    while IFS=, read -r n x y z
    do 
        echo "n: $n x: $x y: $y z: $z"
    done
} < $inputFile

I highly appreciate for any kind of help.

1 Answers

Here I'm using the awk to perform the calculation, and at the end I'm rounding the result, as you said. The variables are prefixed with a letter 'l', wich means 'local scope'.

The function receives the data file, and a origin record, using the same format as we can find on your data file (Name, x_loc, y_loc, z_loc).

You need to create more code to make the validations. I didn't supply the complete code because I understood that you are practicing with this challenge.

This function skips the same record supplied as the origin, this way it is more comfortable to use it:

######################################################################
# Finds the person with the shortest distance from a specified origin
# Arguments:
#  l_data_file - Data file to get the information
#  l_origin - Origin record. (Format: Mary, 30.4, 20.5, 9.20)
######################################################################
function finds_the_person_with_shortest_distance() {
  local l_data_file="$1"
  local l_origin_data="$2"

  local l_origin_name
  local l_origin_x_loc
  local l_origin_y_loc
  local l_origin_z_loc

  local l_name
  local l_x_loc
  local l_y_loc
  local l_z_loc

  local l_current_distance
  local l_min_distance
  local l_min_distance_person_name

  read l_origin_name l_origin_x_loc l_origin_y_loc l_origin_z_loc < <(echo "${l_origin_data}" | tr -d ',')

  local l_flag_first_record=true

  while read l_name l_x_loc l_y_loc l_z_loc ; do

    # Skips the first record
    if [[ "${l_flag_first_record}" == "true" ]]; then
      l_flag_first_record=false
      continue
    fi

    # Skips the person at the same location as the origin
    if [[ "${l_origin_name}" == "${l_name}" ]] &&
       [[ "${l_origin_x_loc}" == "${l_x_loc}" ]] &&
       [[ "${l_origin_y_loc}" == "${l_y_loc}" ]] &&
       [[ "${l_origin_z_loc}" == "${l_z_loc}" ]]; then
      continue
    fi

    ##### calculates the distance #####
    l_current_distance=$(
       echo "${l_origin_x_loc} ${l_origin_y_loc} ${l_origin_z_loc} ${l_x_loc} ${l_y_loc} ${l_z_loc}" | \
         awk '{ print int( sqrt( ($1-$4)^2 + ($2-$5)^2 + ($3-$6)^2 ) ) }'
    )

    if [[ -z "${l_min_distance}" ]] ||
       [[ ${l_current_distance} -lt ${l_min_distance} ]]; then
      l_min_distance=${l_current_distance}
      l_min_distance_person_name="${l_name}"
    fi

  done < <(cat "${l_data_file}" | tr -d ',')

  echo "${l_min_distance_person_name} ${l_min_distance}"
}
Related