Menu
Coddy logo textTech

Monthly Summary

Part of the Logic & Flow section of Coddy's R journey. Lesson 61 of 64.

challenge icon

Challenge

Medium

Add the MONTH command. Keep every command from the previous steps working exactly as before.

  • MONTH <YYYY-MM>: consider only the expenses whose date starts with that month. Reply 2024-05: count 3, total 520.50, biggest rent with the number of expenses, the total to two decimals and the category of the largest expense of the month (the first one when several tie). With none, reply 2024-05: no expenses.

The supplied code passes every input line to tracker() as one command and prints each returned reply on its own line. Dates are written YYYY-MM-DD, categories are lower-case words, and the input holds only the commands described so far.

Try it yourself

tracker <- function(commands) {
  expenses <- data.frame(date = character(0), category = character(0), amount = numeric(0))
  replies <- c()
  for (cmd in commands) {
    parts <- strsplit(cmd, " ")[[1]]
    if (parts[1] == "ADD") {
      amount <- suppressWarnings(as.numeric(parts[4]))
      if (length(parts) != 4 || is.na(amount) || amount <= 0) {
        replies <- c(replies, paste("invalid:", cmd))
      } else {
        expenses <- rbind(expenses, data.frame(date = parts[2], category = parts[3], amount = amount))
        replies <- c(replies, sprintf("added %s %.2f", parts[3], amount))
      }
    } else if (parts[1] == "TOTAL") {
      replies <- c(replies, sprintf("total: %.2f, count: %d", sum(expenses$amount), nrow(expenses)))
    } else if (parts[1] == "CATEGORY") {
      if (nrow(expenses) == 0) {
        replies <- c(replies, "no expenses")
      } else {
        totals <- tapply(expenses$amount, expenses$category, sum)
        replies <- c(replies, sprintf("%s: %.2f", names(totals), totals))
      }
    } else if (parts[1] == "TOP") {
      n <- as.numeric(parts[2])
      ranked <- expenses[order(-expenses$amount, expenses$date), ]
      top <- head(ranked, n)
      if (nrow(top) == 0) {
        replies <- c(replies, "no expenses")
      } else {
        replies <- c(replies, sprintf("%s %s %.2f", top$date, top$category, top$amount))
      }
    }
  }
  replies
}

# Supplied input/output code: keep it as it is
input <- suppressWarnings(readLines(file("stdin")))
cat(tracker(input), sep = "\n")

All lessons in Logic & Flow

Practice on your own: Online R compiler