Puzzles no. 409–413

[This article was first published on Numbers around us - Medium, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Puzzles no. 409–413

Puzzles

Author: ExcelBI

All files (xlsx with puzzle and R with solution) for each and every puzzle are available on my Github. Enjoy.

Puzzle #409

This puzzle is like splitting rock. Sometimes tables in Excel and other documents have merged cells or headers. It is not really comfortable for R, because we love clear tabular view the most. But nature of readxl package is useful for us. If we have merged row headers (like one header for multiple rows, we get first row with value, and the rest with NA’s. And that is easy to fix. Let’s do it.

Load libraries and data

library(tidyverse)
library(readxl)

input = read_excel("Excel/409 Table_Regular.xlsx", range = "A1:E12")
test  = read_excel("Excel/409 Table_Regular.xlsx", range = "G1:K29")

Transformation

result = input %>%
  fill(c(1,5), .direction = "down") %>%
  mutate(Items = str_split(Items, ", ")) %>%
  unnest_longer(Items)

Validation

identical(result, test)  
#> [1] TRUE

Puzzle #410

Today’s puzzle is not really hard. We already had both elements of the story in our journey. We had converting to Roman Numerals and detecting palindromes. Let’s mix it together to find palindromic Roman Numerals.

Loading libraries and data

library(tidyverse)
library(readxl)
library(stringi)

input = read_excel("Excel/410 Palindromic Roman Numerals.xlsx", range = "A2:A10")
test  = read_excel("Excel/410 Palindromic Roman Numerals.xlsx", range = "B2:C5")

Transformation

to_roman <- function(number) {
  if (!is.numeric(number) || number <= 0 || number != as.integer(number)) {
    return(NA)
  }
  
  roman_symbols <- c("M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I")
  arabic_values <- c(1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1)
  
  numeral <- ""
  for (i in seq_along(roman_symbols)) {
    while (number >= arabic_values[i]) {
      numeral <- paste0(numeral, roman_symbols[i])
      number <- number - arabic_values[i]
    }
  }
  
  return(numeral)
}

is_palindrome = function(string) {
  string == stri_reverse(string)
}

result = input %>%
  mutate(roman = map_chr(`Decimal Number`, to_roman)) %>%
  mutate(palindrome = map_lgl(roman, is_palindrome)) %>%
  filter(palindrome) %>%
  select(`Decimal Number`, `Roman Number` = roman)

Validation

identical(result, test)
# [1] TRUE

Puzzle #411

We already splitted text on many ocassions, but today we have one twist. We need to cut sentence on spaces, but… except of spaces that are quoted. It complicate case a little, but not extremely.

Load libraries and data

library(tidyverse)
library(readxl)

input = read_excel("Excel/411 Split String at other than Space.xlsx", range = "A1:A10")
test  = read_excel("Excel/411 Split String at other than Space.xlsx", range = "B1:E10") %>%
  set_names(c("1", "2", "3", "4"))

Transformation

extract = function(input) {
  
pattern = "([^\\s\"]+|\"[^\"]*\")"
  
input %>% 
    str_extract_all(pattern) %>% 
    unlist() %>%
    tibble(string = .)  
}

result = input %>%
  mutate(extracted = map(Sentences, extract)) %>%
  unnest_longer(extracted) %>%
  group_by(Sentences) %>%
  mutate(row = row_number()) %>%
  pivot_wider(names_from = row, values_from = extracted) %>%
  ungroup() %>%
  select(-Sentences) %>%
  as.matrix() %>%
  as.data.frame() %>%
  mutate(across(everything(), ~str_remove_all(., "\"")))

Puzzle #412

On image we see some kind of cyclic transformation and that what we are doing in this puzzle. For each inputed number we have to make cycle of: squaring digits separately and sum it up, then the same for result and so on until we reach only one digit. Pretty nice task, but one input produced wrong result at the beginning, single digit input. To wrangle this edge case I added a portion of code, causing that if we get single digit input we have to square it before moving a loop.
Let’s get into.

Loading libraries and data

library(tidyverse)
library(readxl)

input = read_excel("Excel/412 Square Sum Iterate till a Single Digit .xlsx", range = "A2:A11")
test  = read_excel("Excel/412 Square Sum Iterate till a Single Digit .xlsx", range = "B2:C11")

Transformation

sum_square <- function(x) {
  iter <- 0
  
  if (nchar(x) == 1) {
    y <- x^2
    iter <- iter + 1
  } else {
    y <- x
  }
  
  while (nchar(y) > 1) {
    digits <- as.numeric(strsplit(as.character(y), "")[[1]])
    y <- sum(digits^2)
    iter <- iter + 1
  }
  return(c(iter, y))
}

result = input %>%
  mutate( r = map(Number, sum_square), 
          FSD = map_dbl(r, 2),
          Iterations = map_dbl(r, 1)) %>%
  select(-c(r, Number))

Validation

all.equal(result, test, check.attributes = FALSE, ignore.names = TRUE)
# [1] TRUE

Puzzle #413

Pivoting in R is little bit tricky, but also really pleasant thing to do. At least for me. And this puzzle was like walk in the park after hard week. Pivot it.

Loading libraries and data

library(tidyverse)
library(readxl)

input = read_excel("Excel/413 Pivot.xlsx", range = "A1:B15")
test  = read_excel("Excel/413 Pivot.xlsx", range = "D1:I5")

Transformation

result = input %>%
  group_by(ID) %>%
  mutate(rn = row_number()) %>%
  pivot_wider(names_from = rn, names_prefix = "Num ", values_from = Num) %>%
  ungroup() %>%
  arrange(ID)

Validation

identical(result, test)
# [1] TRUE

Feel free to comment, share and contact me with advices, questions and your ideas how to improve anything. Contact me on Linkedin if you wish as well.


Puzzles no. 409–413 was originally published in Numbers around us on Medium, where people are continuing the conversation by highlighting and responding to this story.

To leave a comment for the author, please follow the link and comment on their blog: Numbers around us - Medium.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)