-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbetter_shapes.R
115 lines (103 loc) · 3.45 KB
/
better_shapes.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
###
# This is an improvement on shapes.R, not necessarily the best/only
# way to complete the exercise
# I've gone a bit overkill on documentation for demonstration purposes.
# Also, both the for loops can be "simplified" with lapply
# which would make the code more compact, but not necessarily more readable.
##
#' Parse a single line of shape definitions string into a shape definition
#'
#' @param shape_definition_line a string that defines a single shape
#' (see details of process function)
#' @return a list with elements shape_name, shape_type, and parameters:w
#' @example
#' parse_shape_definition_line("redrect: rectangle (l=45,w=100)")
#' returns list(
#' shape_name = 'redrect',
#' shape_type='rectangle',
#'. params =list (
#' l = 45,
#' w = 100
# )
#' )
parse_shape_definition_line <- function(shape_definition_line){
split_line <- unlist(strsplit(
x = shape_definition_line,
# this regex matches one or more of
# colon, open parens, close parens, comma, or space
# does *not* split on equals sign.
split = '[: \\(,\\)]+'
))
# result is something like c('redrect', 'rectangle', 'l=45', 'w=100')
params <- list()
# start with the 3rd element
for(param_string in split_line[3:length(split_line)]){
# break apart param name and value
split_param_string <- unlist(strsplit(param_string, '='))
# e.g. parsed_line[["l"]] <- 45
params[[split_param_string[1]]] <- as.numeric(split_param_string[2])
}
return(list(
# e.g. redrect
shape_name = split_line[1],
# e.g. rectangle
shape_type = split_line[2],
params = params
))
}
#' Calculate shape area
#'
#' @param shape_type must be one of: 'square', 'circle', 'rectangle'
#' @param params list of parameters (see details of process function)
#'
#' @return single numeric value representing shape area
calculate_shape_area <- function(shape_type, params){
if(shape_type == 'circle'){
area <- params$r ^2 * pi
} else if(shape_type == 'rectangle'){
area <- params$l * params$w
} else if(shape_type == 'square'){
area <- 6 * params$l - 5
}
return(area)
}
#'Calculate Area of Shapes
#'
#'@param shape_definitions_string a string where each line defines a shape like
#' `shape_name: shape_type (shape_params)`. (See Details)
#'
#'@return dataframe with columns: `name`, `type`, and `area` name and type
#' coming from input definitions and area calculated based on params.
#'@export
#'
#'@details `shape_name` can be any alpha numeric string, but should not contain
#'whitespace or symbols `shape_type` must be one of square, circle, and
#'rectangle. `shape_params` must be comma separated `param_name=param_values`
#'Each shape has required shape params as follows: .
#'
#'. - `square`: `l` (length)
#'. - `rectangle`: `l` (length), `w` (width) .
#'. - `circle`: `r` (radius)
process <- function(shape_definitions_string) {
output_df <- data.frame()
# split into lines
for (line in unlist(strsplit(shape_definitions_string, '\n'))){
# parse the line
shape_definition <- parse_shape_definition_line(line)
shape_name <- shape_definition$shape_name
shape_type <- shape_definition$shape_type
# calculate area
area <- calculate_shape_area(
shape_definition$shape_type,
shape_definition$params
)
# append to dataframe
output_df <- rbind(output_df,
data.frame(
shape_name = shape_name,
shape_type = shape_type,
area = area
))
}
return(output_df)
}