Mirko at the Construction Site – HackerRank Solution

In this post, we will solve Mirko at the Construction Site HackerRank Solution. This problem (Mirko at the Construction Site) is a part of HackerRank Functional Programming series.

Task

Mirko is monitoring a construction site. He monitors N buildings enumerated from 1 to N, starting from the left. For each building, he knows the current number of floors and the number of floors built on each day. He needs to know the answer to Q queries. The answer to each query is the index of the tallest building after T days, as defined by the query. Your task is to help Mirko find the answers to these queries.

Input Format

The first line consists of the numbers N and Q. The second line consists of N integers, where the ith integer represents the initial height of the ith building. The third line consists of N integers, where the ith integer represents the number of floors erected in one day for the ith building. The following Q lines consist of the integer, T, representing the day in the query.

Output Format

For each query, output one number which represents the index of the tallest building after T days. If there is more than one building, output the building with the greatest index in the input array (with indexes starting at 1).

Constraints

  • 1 <= N <= 105
  • 1 <= Q <= 105
  • Every other integer in the input will fit in a 32-bit signed integer. And they will be non-negative integers.

Sample Input

3 6
7 5 1
1 2 3
0
1
2
3
4
5

Sample Output

1
1
2
2
3
3  

Explanation

Query #1: The height at the end of the 0th day will be {7, 5, 1}. Here, the 1st building is the tallest.
Query #2: The height at the end of the 1st day will be {8, 7, 4}. Here, the 1st building is the tallest.
Query #3: The height at the end of 2nd day will be {9, 9, 7}. Here, the 1st and 2nd buildings are the tallest, while the 2nd is the larger index.
Query #4: The height at the end of 3rd day will be {10, 11, 10}. Here, the 2nd building is the tallest.
Query #5: The height at the end of 4th day will be {11, 13, 13}. Here, the 2nd and 3rd buildings are the tallest, while the 3rd is the larger index.
Query #6: The height at the end of 5th day will be {12, 15, 16}. Here, the 3rd building is the tallest.

Solution – Mirko at the Construction Site – HackerRank Solution

Scala

import java.util.Scanner

object Solution {
  def main(args: Array[String]): Unit = {
    val sc = new Scanner(System.in)

    sc.nextInt
    val q = sc.nextInt
    sc.nextLine
    val initials = sc.nextLine.split(" ").map(_.toInt)
    val steps = sc.nextLine.split(" ").map(_.toInt)

    case class Query(index: Int, time: Int)
    val queries = (0 until q).map(Query(_, sc.nextInt)).sortBy(_.time)

    sc.close()

    case class Building(index: Int, initial: Long, step: Long) extends Ordered[Building] {
      override def compare(that: Building): Int = {
        if (this.step < that.step) -1
        else if (this.step > that.step) 1
        else if (this.initial < that.initial) -1
        else if (this.initial > that.initial) 1
        else this.index.compareTo(that.index)
      }

      def height(time: Long): Long = initial + step * time
    }

    val buildings: List[Building] = initials.indices.map(i => Building(i + 1, initials(i), steps(i)))
      .groupBy(_.step)
      .map { case (_, list) => list.maxBy(_.initial) }
      .toList
      .sorted

    def intersection(b0: Building, b1: Building) = (b1.initial.toDouble - b0.initial) / (b0.step.toDouble - b1.step)

    @scala.annotation.tailrec
    def prepare(buildings: List[Building], acc: List[Building]): List[Building] = buildings match {
      case Nil => acc
      case v :: Nil => v :: acc
      case v0 :: v1 :: vs =>
        val highest = acc.head
        val inter0 = intersection(highest, v0)
        val inter1 = intersection(highest, v1)

        if (inter0 < inter1 || inter0 == inter1 && v0.index > v1.index)
          prepare(v1 :: vs, v0 :: acc)
        else if (acc.tail.isEmpty)
          prepare(v1 :: vs, acc)
        else
          prepare(acc.head :: v1 :: vs, acc.tail)
    }

    val highBuildings = prepare(buildings.tail, List(buildings.head)).reverse

    case class Pair(queryIndex: Int, highestIndex: Int)
    case class Acc(buildings: List[Building], highestIndices: List[Pair])
    val answer = queries.foldLeft(Acc(highBuildings, Nil))((acc, q) => {
      @scala.annotation.tailrec
      def findHighest(buildings: List[Building]): Acc = buildings match {
        case b :: Nil => Acc(acc.buildings, Pair(q.index, b.index) :: acc.highestIndices)
        case b0 :: b1 :: bs =>
          val inter = intersection(b0, b1)
          if (inter > q.time || inter == q.time && b0.index > b1.index)
            Acc(buildings, Pair(q.index, b0.index) :: acc.highestIndices)
          else
            findHighest(b1 :: bs)
        case Nil => throw new Exception("Impossible")
      }

      findHighest(acc.buildings)
    })

    println(answer.highestIndices
      .sortBy(_.queryIndex)
      .map(_.highestIndex)
      .mkString("\n")
    )
  }
}

Note: This problem (Mirko at the Construction Site) is generated by HackerRank but the solution is provided by CodingBroz. This tutorial is only for Educational and Learning purpose.

Leave a Comment

Your email address will not be published. Required fields are marked *