Excel BI - Excel Challenge 632

Published

January 16, 2025

Challenge Description

Give a formula to create triangle from alphabets in a word. First row would have first alphabet, second row would have two alphabets and so on. To ensure symmetry, if you run out of alphabets, then use # for padding.

🔗 Link to Excel file: 👉https://lnkd.in/dwitwkm3

Solutions

library(tidyverse)
library(readxl)

path <- "Excel/632 Create Triangle from Words.xlsx"
test1 <- read_excel(path, range = "B2:D3", col_names = FALSE) %>% as.matrix()
test2 <- read_excel(path, range = "B5:F7", col_names = FALSE) %>% as.matrix()
test3 <- read_excel(path, range = "B9:F11", col_names = FALSE) %>% as.matrix()
test4 <- read_excel(path, range = "B13:H16", col_names = FALSE) %>% as.matrix()
test5 <- read_excel(path, range = "B18:J23", col_names = FALSE) %>% as.matrix()

triangular_numbers <- function(n) {
  n * (n + 1) / 2
}

draw_triangle_from_word <- function(word) {
  n <- 1
  while (triangular_numbers(n) < nchar(word)) {
    n <- n + 1
  }
  
  padded_word <- paste0(word, strrep("#", triangular_numbers(n) - nchar(word)))
  word_chars <- strsplit(padded_word, "")[[1]]
  word_split <- split(word_chars, rep(1:n, 1:n))
  
  formatted_lines <- map(word_split, ~str_pad(paste0(.x, collapse = " "), n * 2 - 1, side = "both")) %>%
    map(~strsplit(.x, "")) %>%
    unlist() %>%
    matrix(nrow = n, ncol = n * 2 - 1, byrow = TRUE) %>%
    replace(., . == " ", NA) %>%
    as.data.frame() %>% 
    filter(!if_all(everything(), is.na)) %>%  
    as.matrix()
  
  formatted_lines
}

words = c("thu", "moon", "excel", "skyjacking", "embezzlements")

all.equal(draw_triangle_from_word(words[1]), test1, check.attributes = FALSE) # TRUE
all.equal(draw_triangle_from_word(words[2]), test2, check.attributes = FALSE) # TRUE
all.equal(draw_triangle_from_word(words[3]), test3, check.attributes = FALSE) # TRUE
all.equal(draw_triangle_from_word(words[4]), test4, check.attributes = FALSE) # TRUE
all.equal(draw_triangle_from_word(words[5]), test5, check.attributes = FALSE) # TRUE
  • Logic:

    • triangular_numbers: Computes the required length for the triangle.

    • strrep("#", ...): Pads the word with # to meet the triangle’s requirements.

    • strsplit and split: Divides characters into rows based on triangular numbers.

    • str_pad: Centers each row for symmetry.

  • Strengths:

    • Compact Logic: The use of tidyverse functions ensures clarity and conciseness.

    • Symmetry Handling: Padding and alignment achieve perfect symmetry.

  • Areas for Improvement:

    • The triangle formatting could directly handle NA or empty spaces instead of filtering them later.
  • Gem:

    • The use of triangular_numbers to dynamically calculate the required triangle size is a standout.
import pandas as pd
import numpy as np

path = "632 Create Triangle from Words.xlsx"
test1 = pd.read_excel(path, usecols="B:D", skiprows=1, nrows=2, header=None).fillna(' ').values
test2 = pd.read_excel(path, usecols="B:F", skiprows=4, nrows=3, header=None).fillna(' ').values
test3 = pd.read_excel(path, usecols="B:F", skiprows=8, nrows=3, header=None).fillna(' ').values
test4 = pd.read_excel(path, usecols="B:H", skiprows=12, nrows=4, header=None).fillna(' ').values
test5 = pd.read_excel(path, usecols="B:J", skiprows=17, nrows=6, header=None).fillna(' ').values

def triangular_numbers(n):
    return n * (n + 1) // 2

def draw_triangle_from_word(word):
    n = 1
    while triangular_numbers(n) < len(word):
        n += 1
    
    padded_word = word + "#" * (triangular_numbers(n) - len(word))
    word_chars = list(padded_word)
    word_split = [word_chars[triangular_numbers(i-1):triangular_numbers(i)] for i in range(1, n+1)]
    
    formatted_lines = []
    for line in word_split:
        formatted_line = ' '.join(line).center(n * 2 - 1)
        formatted_lines.append(list(formatted_line))
    
    formatted_matrix = np.array(formatted_lines, dtype=object)
    
    return formatted_matrix

words = ["thu", "moon", "excel", "skyjacking", "embezzlements"]

print((draw_triangle_from_word(words[0]) == test1).all())
print((draw_triangle_from_word(words[1]) == test2).all())
print((draw_triangle_from_word(words[2]) == test3).all())
print((draw_triangle_from_word(words[3]) == test4).all())
print((draw_triangle_from_word(words[4]) == test5).all())
  • Logic:

    • triangular_numbers: Calculates the size of the triangle.

    • Padding with #: Ensures the triangle is complete.

    • List slicing: Splits characters into rows dynamically.

    • center: Ensures rows are symmetric.

  • Strengths:

    • Modularity: Functions are well-structured for clarity and reuse.

    • Symmetry Handling: Padding and centering achieve proper formatting.

  • Areas for Improvement:

    • Iterating over rows for formatting could be optimized using numpy.
  • Gem:

    • The combination of list slicing and centering ensures both correctness and clarity.

Difficulty Level

This task is moderate:

  • Requires understanding of triangular numbers.

  • Involves string manipulation, dynamic slicing, and formatting for symmetry.