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.
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 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!