IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Sine Wave (plotting with digits)

    Numbers around us发表于 2023-10-17 08:51:37
    love 0
    [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.

    Excel BI’s Excel Challenge #305 — solved in R

    Defining the Puzzle

    Today task from ExcelBI which is under this link has another approach. We are not manipulate numbers or string to check their properties, but we are painting with them. That is why I will not upload exercise file today. Here it is:
    Print Sine Wave for Amplitudes given in B2
    Example for Amplitudes 2, 3 and 4 are given.
    Always 5 columns only need to be filled in.

    And it looks like this when ready:

    So let’s start it in R. Our pictures (sine waves) will be printed in console.

    library(tibble)
    library(purrr)
    library(data.table)

    Approach 1: Tidyverse with purrr

    generate_wave <- function(amp) {
     n_rows <- 2 * amp — 1
     generate_palindrome <- function(base) {
     sequence <- base:1
     number <- c(sequence, rev(sequence[-length(sequence)]))
     return(paste0(number, collapse = “”))
     }
    
    single_column <- rep(NA, n_rows)
     seq = c(1:amp, (amp-1):1)
     table = tibble(row = seq) %>%
     mutate(row_number = row_number(),
     col1 = map_chr(row, ~generate_palindrome(.x)),
     col2 = col1,
     col3 = col1,
     col4 = col1,
     col5 = col1) %>%
     mutate_at(vars(col1, col3, col5), 
     ~ifelse(row_number > amp, “ “, .)) %>%
     mutate_at(vars(col2, col4), 
     ~ifelse(row_number < amp, “ “, .)) %>%
     mutate_at(vars(col1, col2, col3, col4, col5), 
     ~str_pad(., max(nchar(.), na.rm = TRUE), side = “both”)) %>%
     select(-c(row_number, row))
     return(table)
    }
    
    x <- generate_wave(6)
    print(x, n = Inf)

    Approach 2: Base R

    generate_wave_base <- function(amp) {
     n_rows <- 2 * amp — 1
     
     generate_palindrome <- function(base) {
     sequence <- base:1
     number <- c(sequence, rev(sequence[-length(sequence)]))
     return(paste0(number, collapse = “”))
     }
     
     seq <- c(1:amp, (amp-1):1)
     table <- data.frame(row = seq)
     table$row_number <- seq_along(table$row)
     
     table$col1 <- sapply(table$row, generate_palindrome)
     table$col2 <- table$col1
     table$col3 <- table$col1
     table$col4 <- table$col1
     table$col5 <- table$col1
     
     condition_space <- table$row_number > amp
     condition_empty <- table$row_number < amp
     
     table$col1[condition_space] <- “ “
     table$col3[condition_space] <- “ “
     table$col5[condition_space] <- “ “
     
     table$col2[condition_empty] <- “ “
     table$col4[condition_empty] <- “ “
     
     max_length <- max(nchar(c(table$col1, table$col2, table$col3, table$col4, table$col5)), na.rm = TRUE)
     
     pad_string <- function(string, max_length) {
     current_length <- nchar(string)
     side_length <- (max_length — current_length) %/% 2
     return(paste0(paste(rep(“ “, side_length), collapse = “”), string))
     }
     
     table$col1 <- sapply(table$col1, pad_string, max_length = max_length)
     table$col2 <- sapply(table$col2, pad_string, max_length = max_length)
     table$col3 <- sapply(table$col3, pad_string, max_length = max_length)
     table$col4 <- sapply(table$col4, pad_string, max_length = max_length)
     table$col5 <- sapply(table$col5, pad_string, max_length = max_length)
     
     table$row_number <- NULL
     table$row <- NULL
     
     table = as_tibble(table)
     
     return(table)
    }
    
    x_base = generate_wave_base(6)
    print(x_base)

    Approach 3: Data.table

    generate_wave_dt <- function(amp) {
     n_rows <- 2 * amp — 1
     
     generate_palindrome <- function(base) {
     sequence <- base:1
     number <- c(sequence, rev(sequence[-length(sequence)]))
     return(paste0(number, collapse = “”))
     }
     
     seq <- c(1:amp, (amp-1):1)
     table <- data.table(row = seq)
     
     table[, row_number := .I] 
     table[, col1 := sapply(row, generate_palindrome)]
     
     table[, `:=` (col2 = col1, col3 = col1, col4 = col1, col5 = col1)]
     
     table[row_number > amp, `:=` (col1 = “ “, col3 = “ “, col5 = “ “)]
     table[row_number < amp, `:=` (col2 = “ “, col4 = “ “)]
    
    max_length <- max(nchar(c(table$col1, table$col2, table$col3, table$col4, table$col5)), na.rm = TRUE
    
    pad_string <- function(strings, max_length) {
     padded_strings <- vapply(strings, function(string) {
     current_length <- nchar(string)
     
     total_padding <- max_length — current_length
     
     if (total_padding <= 0) return(string)
     
     side_padding <- floor(total_padding / 2)
    
    padded_string <- paste0(
     strrep(“ “, side_padding), 
     string, 
     strrep(“ “, total_padding — side_padding) 
     )
     return(padded_string)
     }, FUN.VALUE = character(1)) 
     return(padded_strings)
     }
     
     table[, (c(“col1”, “col2”, “col3”, “col4”, “col5”)) := lapply(.SD, function(x) pad_string(x, max_length)), .SDcols = c(“col1”, “col2”, “col3”, “col4”, “col5”)]
     table[, c(“row_number”, “row”) := NULL]
     
     return(table)
    }
    
    x_dt = generate_wave_dt(6)
    print(x_dt)

    Validation

    As we don’t have to validate it another way than looking at them and confirm that it looks like sine wave, I can say, it works well. Let check how it will look with not 6 but 9 digits.

    However I make little bechmark as well to check which is best in time consumption:

    library(microbenchmark)
    microbenchmark(generate_wave(6), generate_wave_base(6), generate_wave_dt(6), times
     = 100)

    And what we see? Easiest to do are ussually not fast enough. Fastest one is base R approach, but it has very important cause: base approach is basing on simple, but computationally powerful data structure: matrix.

    Do not hesitate to show your approaches in R or even Python. Comment, share and come back for next puzzles.


    Sine Wave (plotting with digits) 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.
    Continue reading: Sine Wave (plotting with digits)


沪ICP备19023445号-2号
友情链接