Menu
Coddy logo textTech

תבנית Strategy

חלק מהיחידה תכנות מונחה עצמים במסלול ה-R של Coddy. שיעור 45 מתוך 57.

תבנית האסטרטגיה מאפשרת להחליף אלגוריתם: הקוד שזקוק לו מקבל אותו כארגומנט. ב-R פונקציה היא ערך, ולכן האסטרטגיה היא פונקציה שמועברת פנימה, והקוד הקורא בוחר באיזו להשתמש:

no_discount <- function(total) total
half_price <- function(total) total / 2
checkout <- function(total, discount = no_discount) {
  paste("pay", discount(total))
}
print(checkout(80))
print(checkout(80, half_price))

פלט:

[1] "pay 80"
[1] "pay 40"

רשימה בעלת שמות של אסטרטגיות מאפשרת לתוכנית לבחור אחת לפי שם בזמן הריצה, למשל מתוך קלט של משתמש:

pricing <- list(
  regular = function(p) p,
  member = function(p) p * 0.9,
  staff = function(p) p * 0.7
)
for (who in c("regular", "member", "staff")) cat(who, pricing[[who]](50), "\n")

פלט:

regular 50 
member 45 
staff 35 

אסטרטגיות עם הגדרות נבנות באמצעות מפעלים. percent_off(10) מחזירה פונקציית אסטרטגיה חדשה שזוכרת את האחוז שלה:

percent_off <- function(pct) function(total) total * (1 - pct / 100)
fixed_off <- function(amount) function(total) max(0, total - amount)
rules <- list(percent_off(10), percent_off(25), fixed_off(30))
print(vapply(rules, function(r) r(100), numeric(1)))

פלט:

[1] 90 75 70

אובייקט יכול להחזיק את האסטרטגיה שלו בשדה ולהחליף אותה מאוחר יותר. שאר האובייקט נשאר ללא שינוי:

new_sorter <- function(key) structure(list(key = key), class = "sorter")
sort_with <- function(s, words) words[order(s$key(words))]
by_length <- function(w) nchar(w)
by_last_letter <- function(w) substring(w, nchar(w))
s <- new_sorter(by_length)
words <- c("pear", "fig", "banana")
print(sort_with(s, words))
s$key <- by_last_letter
print(sort_with(s, words))

פלט:

[1] "fig"    "pear"   "banana"
[1] "banana" "fig"    "pear"  
challenge icon

אתגר

קל

המשלוח נבחר לפי אסטרטגיה: פונקציה של המשקל הכולל של העגלה ושל סכום הביניים שלה, שמחזירה את עלות המשלוח. כתוב ב-Strategies.R:

  • standard(kg, subtotal): ‏4.99 ועוד 1 לכל ק״ג;
  • express(kg, subtotal): פי שניים מעלות המשלוח הרגילה;
  • free_over(limit): מחזירה אסטרטגיה שעלותה 0 כאשר סכום הביניים הוא לפחות limit, ואת העלות הרגילה אחרת.

ב-Cart.R, הפונקציות new_cart(strategy) ו-add_item() נתונות; השלם את subtotal(cart) ואת shipping_cost(cart), שקוראת לאסטרטגיה של העגלה. הקוד שסופק קורא את האסטרטגיה (standard, express או free_over 50), ולאחר מכן פריטים book 12 0.5 (שם, מחיר, ק״ג), ומדפיס את הסכומים הכוללים.

הקוד שלך ייכתב ב-Strategies.R וב-Cart.R. הקובץ main.R מכיל את קוד הקלט/פלט שסופק, ואי אפשר לערוך אותו.

נסו בעצמכם

source("Strategies.R")
source("Cart.R")

# קוד קלט/פלט שסופק: יש להשאיר אותו כפי שהוא
input <- suppressWarnings(readLines(file("stdin")))
p <- strsplit(input[1], " ")[[1]]
rule <- if (p[1] == "free_over") free_over(as.numeric(p[2])) else get(p[1])
cart <- new_cart(rule)
for (line in input[-1]) {
  q <- strsplit(line, " ")[[1]]
  cart <- add_item(cart, q[1], as.numeric(q[2]), as.numeric(q[3]))
}
cat(sprintf("items: %.2f, shipping: %.2f, total: %.2f", subtotal(cart), shipping_cost(cart), subtotal(cart) + shipping_cost(cart)), "\n", sep = "")
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר R אונליין