From 4c7947182e4e879be1fd886d08c9b712933f4bd3 Mon Sep 17 00:00:00 2001 From: Kaio Silveira Date: Sun, 19 Nov 2023 21:10:12 +0000 Subject: [PATCH] service-lane: wip --- service-lane/README.md | 117 +++++++++++++++++++++++++++++++++ service-lane/algorithm.rb | 13 ++++ service-lane/algorithm.spec.rb | 28 ++++++++ service-lane/benchmarking.rb | 22 +++++++ service-lane/challenge.rb | 9 +++ service-lane/index.rb | 18 +++++ 6 files changed, 207 insertions(+) create mode 100644 service-lane/README.md create mode 100644 service-lane/algorithm.rb create mode 100644 service-lane/algorithm.spec.rb create mode 100644 service-lane/benchmarking.rb create mode 100644 service-lane/challenge.rb create mode 100644 service-lane/index.rb diff --git a/service-lane/README.md b/service-lane/README.md new file mode 100644 index 0000000..1075604 --- /dev/null +++ b/service-lane/README.md @@ -0,0 +1,117 @@ +# Challenge name + +Challenge URL: https://www.hackerrank.com/challenges/service-lane/problem + +A driver is driving on the freeway. The check engine light of his vehicle is on, and the driver wants to get service immediately. Luckily, a service lane runs parallel to the highway. It varies in width along its length. + +You will be given an array of widths at points along the road (indices), then a list of the indices of entry and exit points. Considering each entry and exit point pair, calculate the maximum size vehicle that can travel that segment of the service lane safely. + +**Example** + +| array with lane widths | (entry, exit) pairs | Expected result | +| ---------------------- | -------------------------------------- | --------------- | +| 2, 3, 2, 1 | [1, 2], [2, 4] | 2, 1 | +| 2, 3, 1, 2, 3, 2, 3, 3 | [0, 3], [4, 6], [6, 7], [3, 5], [0, 7] | 1, 2, 3, 2, 1 | + +**Constraints** + +- $2 \leq n \leq 100000 $ +- $1 \leq t \leq 1000 $ +- $0 \leq t < j < n $ + +## Test suite ๐Ÿงช + +The test suite for this challenge covers the constraints described above and a happy path using the example's data. The tests are: + +- `test_raises_ex` +- `test_happy_path` + +For the full test suite, see [algorithm.spec.rb](./algorithm.spec.rb). + +## Algorithm resolution description ๐Ÿ“„ + +Algorithm resolution description + +```ruby +# some ruby code here +``` + +The final code, including constraint validations, is available [here](./algorithm.rb). + +## Samples ๐Ÿฅฏ + +The samples used to run a quick sanity check on the implementation are: + +```ruby +samples = [ + # add samples here +] +``` + +Which, after feeding it into our runner: + +```ruby +HackerRank::Runner.new(samples).run do |n| + HackerRank::Challenges.challenge_fn(n) +end +``` + +Gives the following output: + +``` +โžœ ruby ./challenge/index.rb + +challenge output +``` + +A good indicative that the solution looks reasonable. + +## Implementation benchmarking & time complexity analysis ๐Ÿ“ˆ + +Let's now take a look at this implementation and see how it stands from a performance point of view. Below, we have a code analysis and a benchmarking of the solution. + +### Code analysis ๐Ÿ•ต๐Ÿฝโ€โ™‚๏ธ + +To perform a time complexity analysis of our code, we can scan it from top to bottom, writing the big $O$ notation for each line (the code was slightly modified to allow for individual line comments): + +```ruby +# some code here +``` + +Which translates to the following expression: + +[expression breakdown] + +Which means **CONSTANT|LINEAR|QUADRATIC** time complexity. + +### Benchmarking ๐Ÿ“Š + +To get a visual feeling of how the function behaves as $n$ increases, a benchmark was run from **BENCHMARK_N_ZERO** up to **BENCHMARK_N_MAX**, resulting in the following chart: + +```console +โžœ cat ./challeng/results.csv | uplot line -d, -w 50 -h 15 -t Results --canvas ascii --xlabel n --ylabel "T(n)" + Results + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + 0.03 โ”‚ โ”‚ + โ”‚ โ”‚ + โ”‚ โ”‚ + โ”‚ โ”‚ + โ”‚ .. โ”‚ + โ”‚ || โ”‚ + โ”‚ || โ”‚ + T(n) โ”‚ /\ โ”‚ + โ”‚ .|lr--/โ”‚ + โ”‚ _.--/"` โ”‚ + โ”‚ .__r-`/" โ”‚ + โ”‚ /__\^/"` โ”‚ + โ”‚ .__--/""` โ”‚ + โ”‚ ..\r-""` โ”‚ + 0 โ”‚__r-/""` โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + 0 100000 + n +``` + +Which, ignoring eventual CPU fluctuations, matches the given time complexity pattern theoretically demonstrated by the code analysis above. + +For the full benchmarking code, see [benchmarking.rb](./benchmarking.rb). diff --git a/service-lane/algorithm.rb b/service-lane/algorithm.rb new file mode 100644 index 0000000..30ba4c0 --- /dev/null +++ b/service-lane/algorithm.rb @@ -0,0 +1,13 @@ +require_relative "../_utils/exceptions/exceptions.rb" + +module HackerRank + module Algorithms + include HackerRank::Exceptions + + def self.find_minimum_values_in_slices(arr:, slices:) + return [] unless arr.any? + return [] unless slices.any? + slices.map { |first, last| arr.slice(first..last).min } + end + end +end diff --git a/service-lane/algorithm.spec.rb b/service-lane/algorithm.spec.rb new file mode 100644 index 0000000..83afb12 --- /dev/null +++ b/service-lane/algorithm.spec.rb @@ -0,0 +1,28 @@ +require "test/unit" +require_relative "./algorithm.rb" +require_relative "../_utils/algorithm-test/index.rb" +require_relative "../_utils/exceptions/exceptions.rb" + +module HackerRank + module Algorithms + class ChallengeAlgorithmTests < AlgorithmTest + def test_returns_an_empty_result_for_empty_input_arrays + assert_equal [], Algorithms.find_minimum_values_in_slices(arr: [], slices: [[0, 1]]) + end + + def test_returns_an_empty_result_for_empty_slices + assert_equal [], Algorithms.find_minimum_values_in_slices(arr: [1, 1], slices: []) + end + + def test_returns_the_minimum_value_in_slice + assert_equal [1], Algorithms.find_minimum_values_in_slices(arr: [1, 2], slices: [[0, 1]]) + end + + def test_returns_the_minimum_values_for_multiple_slices + assert_equal [1, 1], Algorithms.find_minimum_values_in_slices( + arr: [1, 2, 1, 3], slices: [[0, 1], [2, 3]], + ) + end + end + end +end diff --git a/service-lane/benchmarking.rb b/service-lane/benchmarking.rb new file mode 100644 index 0000000..469a8ae --- /dev/null +++ b/service-lane/benchmarking.rb @@ -0,0 +1,22 @@ +require "benchmark" +require_relative './algorithm.rb' +require_relative '../_utils/benchmark.rb' +require_relative '../_utils/number/number.rb' + +include NumberUtils + +MAX_N_SIZE = 100 + +ENV["CONSTRAINT_ENFORCEMENT_ENABLED"] = "disabled" + +def invoke_algorithm_n_times(n) + HackerRank::Algorithms.algorithm_name(args: n) +end + +HackerRank::Benchmarking.create_time_complexity_analysis( + method_name: :invoke_algorithm_n_times, + n0: 1, + n_max: MAX_N_SIZE, + n_incrementation_step: 1, + file_name: "#{File.expand_path File.dirname(__FILE__)}/results.csv" +) diff --git a/service-lane/challenge.rb b/service-lane/challenge.rb new file mode 100644 index 0000000..084c41a --- /dev/null +++ b/service-lane/challenge.rb @@ -0,0 +1,9 @@ +require_relative "./algorithm.rb" + +module HackerRank + module Challenges + def self.service_lane(input, cases) + Algorithms.find_minimum_values_in_slices(arr: input, slices: cases) + end + end +end diff --git a/service-lane/index.rb b/service-lane/index.rb new file mode 100644 index 0000000..2a545c0 --- /dev/null +++ b/service-lane/index.rb @@ -0,0 +1,18 @@ +require_relative "./challenge.rb" +require_relative "../_utils/hacker-rank/hacker-rank.rb" + +samples = [ + HackerRank.create_sample( + expected_result: [2, 1], + params: [[2, 3, 2, 1], [[1, 2], [2, 4]]], + ), + HackerRank.create_sample( + expected_result: [1, 2, 3, 2, 1], + params: [[2, 3, 1, 2, 3, 2, 3, 3], [[0, 3], [4, 6], [6, 7], [3, 5], [0, 7]]], + ), +] + +HackerRank::Runner.new(samples).run do |*params| + input, cases = params + HackerRank::Challenges.service_lane(input, cases) +end