R Solution for Excel Puzzles

[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. 554–558

Puzzles

Author: ExcelBI

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

Puzzle #554

Another interesting number called after Indian mathematician. We need to find first 50 Kaprekar numbers of any order. What does it mean? We need to find numbers which square cut in any point (after first, second or any other digit) give us two numbers that sums up to original number. So we need to cut numbers (not divide, not subtract, but cut). It is terribly slow if we iterate over long numbers treating it as characters. But today I found out how to do it using numbers only. Check it out.

PS. And I threw all hands on board, which mean that I used parallel computing.

Loading libraries and data

library(tidyverse)
library(readxl)
library(parallel)

path = "Excel/554 Kaprekar Numbers.xlsx"
test = read_excel(path, range = "A1:A51")

Transformation

check_kaprekar_fast = function(n) {
  nsqr = n^2
  digits = floor(log10(nsqr)) + 1
  for (split_pos in 1:(digits - 1)) {
    right_part = nsqr %% 10^split_pos
    left_part = nsqr %/% 10^split_pos
    if (right_part > 0 && left_part + right_part == n) {
      return(TRUE)
    }
  }
  return(FALSE)
}

parallel_kaprekar_check = function(n_values) {
  num_cores = detectCores() - 1
  cl = makeCluster(num_cores)
  clusterExport(cl, "check_kaprekar_fast")
  result = parLapply(cl, n_values, check_kaprekar_fast)
  stopCluster(cl)
  return(unlist(result))
}

n_values = 4:1000000
kaprekar_flags = parallel_kaprekar_check(n_values)

df = data.frame(n = n_values, is_kaprekar = kaprekar_flags) %>%
  filter(is_kaprekar) %>%
  head(50) %>%
  select(n)

Validation

all.equal(df, test, check.attributes = FALSE) 
# TRUE

Puzzle #555

It looks like somebody wrote down cities to visit, but it would be to easy just to sort them. We are given special way of sorting first row should be sorted descending, second — ascending, and so on even and odd rows. This is quite tricky, but let me show you how I did it.

Loading libraries and data

library(tidyverse)
library(readxl)

path = "Excel/555 Order Cities.xlsx"
input = read_excel(path, range = "A1:E19")
test  = read_excel(path, range = "G2:K19", col_names = FALSE)
names(test)  = c("1", "2", "3", "4", "5")

Transformation

result = input %>%
  mutate(rn = row_number()) %>%
  select(rn, everything()) %>%
  pivot_longer(-rn, names_to = "key", values_to = "value") %>%
  group_by(rn) %>%
  arrange(
    rn,
    desc(if_else(rn %% 2 == 0, value, NA_character_)),
    if_else(rn %% 2 != 0, value, NA_character_)
  ) %>% 
  mutate(rn2 = row_number(),
         key = if_else(is.na(value), NA, key)) %>%
  ungroup() %>%
  select(-value) %>%
  pivot_wider(names_from = rn2, values_from = key) %>%
  select(-rn)

Validation

all.equal(result, test)
# [1] TRUE

Puzzle #556

We built many structures so far, and pyramids along them were numerous as well. Today we have triangle made of triangular numbers. Each step up is made of next element of sequence of triangular numbers. We already discussed this kind of numbers many time. So we could say many things are the same as many time before. And as before I will do it using matrix.

Loading libraries and data

library(tidyverse)
library(readxl)

path = "Excel/556 Generate Triangle Cumsum.xlsx"
input = read_excel(path, range = "A1:A1", col_names = FALSE) %>% pull()
test  = read_excel(path, range = "B2:T11:", col_names = FALSE) %>% as.matrix()

Transformation

M = matrix(NA_real_, nrow = input, ncol = 2 * input - 1)
p = 1:input %>% cumsum()

for (i in 1:10) {
  M[i, (input - i + 1):(input + i - 1)] = rev(p)[i]  
}

Validation

all.equal(M, test, check.attributes = FALSE) 
# TRUE

Puzzle #557

We have three main tasks today all based on fact that RegEx is pretty freshly available in Excel. So let get heavy weapon called regular expressions ready for our puzzle today.

Loading libraries and data

library(tidyverse)
library(readxl)

path = "Excel/557 Regex Challenges 2.xlsx"
input = read_excel(path, range = "A1:A6")
test  = read_excel(path, range = "C1:C6") %>%
  mutate(`Answer Expected` = as.numeric(`Answer Expected`))

Transformation

q1 = input %>%
  filter(row_number() == 1) %>%
  mutate(Answer = str_extract(String, "\\d+(?!.*\\d)") %>% as.numeric())

q2 = input %>%
  filter(row_number() %in% c(2, 3)) %>% 
  mutate(Answer = str_detect(String,  "(?=.*a)(?=.*e)(?=.*i)(?=.*o)(?=.*u)") %>% as.numeric())

q3 = input %>%
  filter(row_number() %in% c(4, 5)) %>%
   mutate(Answer = str_detect(String,  "^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[^A-Za-z0-9])(?=\\S+$).{8,}$") %>% as.numeric())

answer = bind_rows(q1, q2, q3)

Validation

all.equal(answer$Answer, test$`Answer Expected`, check.attributes = FALSE)
#> [1] TRUE

Puzzle #558

I like the way how structures similar to Python dictionaries can be packed and unpacked to series of keys and values. And we have it today as our puzzle. We need to split dictionary type string to strings made of keys and values respectivelly.

Loading libraries and data

library(tidyverse)
library(readxl)

path = "Excel/558 Unpack Dictionary.xlsx"
input = read_excel(path, range = "A2:A7")
test  = read_excel(path, range = "B2:C7")

Transformation

result = input %>%
  mutate(rn = row_number()) %>%
  separate_rows(Dictionary, sep = ", ") %>%
  separate(Dictionary, c("Key", "Value"), sep = ":|;", extra = "merge") %>%
  summarise(Key = str_c(Key, collapse = ", "),
            Value = str_c(Value, collapse = ", "), .by = rn) %>%
  select(Key, Value)

Validation

all.equal(test, result)
#> [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.
On my Github repo there are also solutions for the same puzzles in Python. Check it out!


R Solution for Excel Puzzles 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)