Hacker Rank

So I’ve been coding in R for a little bit, and I started looking at some of the coding problems on the website Hacker Rank.

After playing around with the website, I noticed that there’s only one problem that they have implemented for R. It’s a sort of “Hello World” problem, and moreover, you can’t even really do the problem in an R-like way. Like, you can’t even load the library dplyr.

If you’re new to R, then you should know that dplyr (from the tidyverse) is a package that makes work with data frames easy. Well, not just easy. Easy, clean, efficient, and fun.

I’m going to try to work my way through some of these Hacker Rank problems, but I’ll be doing it with a tidyverse mentality. And with that, I’ll load the key member of the tidyverse.

library(dplyr)

1. Solve Me First

Complete the function solveMeFirst to compute the sum of two integers.

Function prototype:

int solveMeFirst(int a, int b);

where,

a is the first integer input.
b is the second integer input

Return values

sum of the above two integers

Sample Input

2
3

Sample Output

5

Solution

The website tells you to build a function for doing a task, and to name it something. I’m going to ignore these recommendations, and we can just run a script without building a function in the script first.

This website wants things written to stdout, which is kinda awkward for R, but we’ll live. As you’ll soon be aware, we have to use the function write.table for almost everything that writes to stdout. Print commands won’t work. To complicate the matter further, write.table is pre-set to print row and column names for all outputs.

I could make a wrapper to write to stdout in a different way, or change some options in my .Rprofile so as to not deal with some of this, but I’d like to make my work as close to the experience of a newbie as possible, so it’s easy to understand what’s happening.

Also, it’s supposed to be reading files in from \dev\stdin, but I don’t have access to their files, so I’ll be reading from a local copy of their example problems.

One further note that’s essential before solving our first problem: R has a function that makes me very happy the ‘pipe’ operator %>%. It takes the output of what’s written on the left, and gives it (as the first input) to what’s written next.

Anyways, let’s add some numbers, R style.

read.table("hr1.txt") %>% # read the numbers into a data frame of dimension n x 1 
      sum() %>% # sum the numbers in the data frame
      write.table(row.names = FALSE, col.names = FALSE) # write output to stdout
## 5

2. Simple Array Sum

Hmm, so it turns out this website has a bunch of latex equations that I don’t feel like copying and pasting, so I’ll just post a screen-shot of the problem.

Solution

So it turns out our code from problem 1 is almost exactly what we need for problem 2. The only difference being they give us this irrelevant piece of information on the first line. So, we’ll just skip reading the first line.

read.table("hr2.txt", skip = 1) %>% # skip reading the array length 
      sum() %>% 
      write.table(col.names = FALSE, row.names = FALSE)
## 31

Easy as pi. err, pie. Well you get it, it’s easy.

3. Compare the Triplets

Solution

This time we are going to start using some fun R. Also, we’ll be doing our first code tidying.

We’ll also deal with a weird circumstance of row and column vectors interacting with write.table. write.table transposes vectors that aren’t already in a data frame. This means that if we give it a column vector, we’ll get out a row vector.

It’s weird, but that’s how it is. As a result, I sometimes use t(), transpose function, to make my result match the orientation of the sample output. In this problem, the result should be a row vector, so I’ll need to give write.table a column vector.

df <- read.table("hr3.txt") %>% # read the table
      t() %>% # make rows into observations, and columns into variables (the tidy way)
      as_tibble() # make into a dplyr data frame

colnames(df) <- c("Alice", "Bob") # change the column names from the default values

df %>% 
      mutate(AliceWins = Alice > Bob, # Alice wins whenever her number is bigger than Bob's
             BobWins   = Bob > Alice) %>% # And vice versa.
      select(AliceWins, BobWins) %>% # select only the columns of wins
      sapply(sum) %>% # apply the sum function to each column of wins, return a row vector
      t() %>% # transpose to a column vector
      write.table(row.names = FALSE, col.names = FALSE) # write a row vector 
## 1 1

This problem featured a new function sapply which applies another function to it’s elements. We’re apply-ing the function sum to each column of the data frame that was input. We’re summing over the times Alice has won in one column, and the number of times Bob has won in another column.

The s in sapply stands for simplify. We started out with a data frame, but we’re interested in returning a vector. We end up with a row vector whose elements Alice’s total wins and Bob’s total wins, respectively.

In our example they each won once.

4. A Very Big Sum

In this challenge, you are required to calculate and print the sum of the elements in an array, keeping in mind that some of those integers may be quite large.

Function Description

Complete the aVeryBigSum function in the editor below. It must return the sum of all array elements.

aVeryBigSum has the following parameter(s):

int ar[n]: an array of integers .

Return

long: the sum of all array elements

Input Format

The first line of the input consists of an integer n. The next line contains nspace-separated integers contained in the array.

Output Format

Return the integer sum of the elements in the array.

Sample Input

5
1000000001 1000000002 1000000003 1000000004 1000000005

Output

5000000015

Solution

This is very straightforward for us.

If we mutate things around, R will try to simplify down to be in scientific notation, and we’d have to do work to get the output format to be what we’re looking for. But if, on the other hand, we work with the vectors directly, we’ll get the results we’re looking for.

read.table("hr4.txt", skip = 1) %>% # skip the first line
      sum() %>% 
      write.table(row.names = FALSE, col.names = FALSE)
## 5000000015

That was easy. The exact same Solution as Problem 2.

5. Diagonal Difference

Given a square matrix, calculate the absolute difference between the sums of its diagonals.

For example, the square matrix

is shown below:

1 2 3
4 5 6
9 8 9  

The left-to-right diagonal is 15. The right to left diagonal is 17. Their absolute difference is 2.

Function description

Complete the diagonalDifferencefunction in the editor below.

diagonalDifference takes the following parameter:

int arr[n][m]: an array of integers

Return

int: the absolute diagonal difference

Input Format

The first line contains a single integer, n, the number of rows and columns in the square matrix . Each of the next n lines describes a row array, and consists of space-separated integers.

Output Format

Return the absolute difference between the sums of the matrix’s two diagonals as a single integer.

Sample Input

3
11 2 4
4 5 6
10 8 -12

Sample Output

15

Solution

base R comes with a method (diag) for extracting the diagonal of a matrix. We’ll build another function for extracting the other diagonal, the anti_diag of a matrix.

the function c() is a special function in R. It is how we call a vector. In the anti_diag function, we use a vector to select a subset of a matrix. You give the indicies of the subset in square brackets next to the name of the object.

m[2] is the second element of m. In our case, we’re subsetting the elements where the row index + the column index - the total number of rows is equal to 1. This happens to give all the elements of the “other diagonal”.

After we have the elements of both diagonals, solving the rest of the problem is easy.

anti_diag <- function(m){
      m[c(row(m) + col(m) - nrow(m) == 1)]
}

m <- read.table("hr5.txt", skip = 1) %>% 
      as.matrix()

abs(
      sum(diag(m)) - sum(anti_diag(m)) # find the absolute difference between the diagonals
      ) %>% 
      write.table(row.names = FALSE, col.names = FALSE)
## 15

Giddyup little cowboy, and Yee-Haw! This is getting fun.

6. Plus Minus

Solution

We can create boolean vectors that fulfill the conditions of the problem, and then find the mean of each of those vectors.

A weird thing about fixing a set number of decimal places is that the results end up as a character string. We don’t want to have quotes around our result, so we’ll set that flag as false on write.table.

v <- read.table("hr6.txt", skip = 1) %>% 
      as.vector()

c(
      mean(v>0),
      mean(v==0),
      mean(v<0)
) %>% # a horizontal vector
      t() %>% # make the vector vertical
      formatC(digits = 6, format = "f") %>% # make sure to include only 6 digits
      write.table(row.names = F, col.names = F, quote = FALSE) # don't include any quotes
## 0.500000 0.166667 0.333333

That wasn’t the cleanest, but R doesn’t have a great way of adding trailing 0s to numeric quantities.

7. Staircase

Staircase detail

This is a staircase of size 4:

   #
  ##
 ###
####

Its base and height are both equal to 4. It is drawn using # symbols and spaces. The last line is not preceded by any spaces.

Write a program that prints a staircase of size n.

Function Description

Complete the staircase function in the editor below.

staircase has the following parameter(s):

int n: an integer

Print

Print a staircase as described above.

Input Format

A single integer, n, denoting the size of the staircase.

Output Format

Print a staircase of size

using # symbols and spaces.

Note: The last line must have 0 spaces in it.

Sample Input

6 

Sample Output

     #
    ##
   ###
  ####
 #####
######

Solution

paste0 is a function that concatenates the elements of a vector together with no spaces between.

rep repeats something a specified number of times.

n <- readLines("hr7.txt") %>% as.integer()

if (n == 0) return("")

tree <- character()

for (i in 1:n) { #the tree has n layers
      
      tree[i] <- 
            paste0( # concatenate the elements of the following vector
                  c( 
                        # R behaves oddly when you tell it to repeat 0 times.
                        # so I check that I'm going to have a positive number of spaces.
                        if (i < n) {rep(" ", times = n - i )}, # add spaces
                        rep("#", times = i) # add number signs
                  ),
                  
                  collapse = "") # collapse it from a vector to a string
}

tree %>% 
      write.table(quote = F, row.names = F, col.names = F)
##        #
##       ##
##      ###
##     ####
##    #####
##   ######
##  #######
## ########

What a nice looking tree! Got me thinking about Christmas carols and eggnog.

8. Mini-Max Sum

Sample Input

1 2 3 4 5

Sample Output

10 14

Solution

This is fairly straight forward. To get the minimal sum, we just find the sum and subtract off the maximum element. To get the maximial sum, we subtract off the minimal element.

v <- read.table("hr8.txt") 

c(sum(v) - min(v), sum(v) - max(v)) %>% # row vector of results
      t() %>% # make column vector
      write.table(row.names = F, col.names = F)
## 14 10

The mastery of these problems flows through me.

9. Birthday Cake Candles

Sample Input 0

4
3 2 1 3

Sample Output 0

2

Solution

This problem uses two great dplyr functions: filter and count. filter let’s us find data the match some specific condition(s). In this case, we want only the tallest candles.

count groups the common elements of some vector, and then adds a new vector n that tallies how many common elements of each type that vector contained. Here’s we’ll be counting the tallest candles. There’s only 1 unique value, but it could be listed many times.

pull is another great function, it pulls a specified column from a data frame. In this case, we’re pulling the n column, which contains the tally of tallest candles.

read.table("hr9.txt", skip = 1) %>% 
      t() %>% # make into a column
      as_tibble() %>% # put the column in a data frame
      filter(V1 == max(V1)) %>% # shrink the df to only have rows of max V1 (tallest candles) 
      nrow() %>% # find the number of rows of that df 
      write.table(row.names = F, col.names = F)
## 2

We’re using such fun methods to accomplish our goals! This is really fun!

10. Time Conversion

Sample Input 0

07:05:45PM

Sample Output 0

19:05:45

Solution

Here we’re using strptime to parse the time from a 12 hour clock, and then format to cast it to 24 hour time. There’s not much to say here.

readLines("hr10.txt") %>% 
      strptime("%I:%M:%S %p") %>% 
      format("%H:%M:%S") %>% 
      write.table(quote = F, row.names = F, col.names = F)
## 19:05:45

With that we’re done all our warmup problems!