Angry Professor

See the original problem on HackerRank.

Solutions

We can count the on time students. If the count is less than k, the professor is angry.

A possible optimization is to stop when k positive elements are found, avoiding to iterate more elements. Finding a solution that combines efficiency with succinctness is another possible target.

Also, since this challenge is simple, you can work on it using other languages or approaches you are not comfortable with.

PHP

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?php
function angryProfessor($k, $a) {
    $count = 0;
    foreach ($a as $time) {
        if ($time <= 0) {
            $count++;
        }
    }

    if ($count >= $k) {
        return 'NO';
    }
    else {
        return 'YES';
    }
}

Javascript by Enrico Scantamburlo

1
const angryProfessor = (k, a) => a.filter(v => v < 1).length < k ? 'YES' : 'NO'

Ruby by Davide Pettenon

1
2
3
def angryProfessor(k, a)
  a.select { |x| x <= 0 }.size < k ? 'YES' : 'NO'
end

Python by Beatrice Liberi

1
2
3
4
5
def angryProfessor(k, a):
    if len(list(filter(lambda x: x <=0, a))) >= k :
        return 'NO'
    else:
        return 'YES'

Haskell

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import Data.List.Split

fromLines lines = (k, a)
  where
    _:k:a = read <$> concatMap words lines

countOnTime = length . filter (<= 0)

angryProfessor (k, a) = countOnTime a < k

output True = "YES"
output False = "NO"

main = do
  _ <- getLine
  testCases <- fmap fromLines . chunksOf 2 . lines <$> getContents
  putStr . unlines $ output . angryProfessor <$> testCases

The algorithm can be optimized: just stop reading the array when at least k students are on time.

1
angryProfessor (k, a) = k /= (length . take k $ filter (<= 0) a)

Rust

1
2
3
fn angry_professor(k: usize, a: &[i32]) -> bool {
    k !=  a.iter().filter(|&&x| x <= 0).take(k).count()
}

Elixir by Tommaso Bertagnin

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
defmodule Solution do
    [[_n_of_cases] | cases ] = 
        Enum.map(IO.stream(:stdio, :line), fn line ->
            line
            |> String.trim
            |> String.split(" ", trim: true)
            |> Enum.map(&String.to_integer/1)
        end)

    cases
    |> Enum.chunk_every(2)
    |> Enum.each(fn [[_n_students, min_attendance], entry_times] ->
        arrived_on_time =
            entry_times
            |> Enum.filter(fn t -> t <= 0 end)
            |> Enum.count()

        professor_says =
            if arrived_on_time >= min_attendance do "NO" else "YES" end

        IO.write(professor_says <> "\n")
    end)
end

C#

1
2
3
4
public static string angryProfessor(int k, List<int> a)
{
    return a.Where(x => x <= 0).Take(k).Count() == k ? "NO" : "YES";
}

C++

1
2
3
4
string angryProfessor(int k, const vector<int>& times) 
{    
    return count_if(begin(times), end(times), [](int i){return i<=0;}) >=k ? "NO" : "YES";
}

C++ with ranges:

1
2
3
4
5
6
string angryProfessor(int k, const vector<int>& times)
{
    return distance(times 
        | views::filter([](int i){ return i<=0; }) 
        | views::take(k)) == k ? "NO" : "YES";
}

A recursive solution

By Antonio D’Angelico:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
string fun(int k, vector<int> a, int i) 
{
    if (i == (int)a.size())
        return "YES";
    if (k == 0)
        return "NO";
    
    
    if (a[i] <= 0)
        return fun(k - 1, a, i + 1);
    return fun(k, a, i + 1);
}
We've worked on this challenge in these gyms: turin  padua  milan  modena 
comments powered by Disqus