• 如何发放优惠券的一个小项目


    需求分析:

    公司里有很多客户,客户之所以不继续用我们的产品了,是因为他账户余额是负的,所以,为了重新赢回这些客户,公司决定发放优惠券cover掉客户账户的负余额。

    具体细节:

    1. 只有8元,80元,200元的优惠券
    2. 发放给一个客户的优惠券总张数不能超过15张
    3. 要既能cover掉客户的负余额,又要保证发放给客户的优惠券张数最少
    4. 发放给客户的总金额-客户的亏损额不能大于8,且越小越好。(不能送太多便宜了)

    思路:

    开始把这个问题理解为线性规划,觉得不好解,遂放弃。之后想用一大堆的逻辑判断来解决这个问题,总能解出来了吧(实在是烦 写一堆的 if else,最后都被绕晕了,遂放弃)。最后的思路,先列出所有送券的组合,然后把亏损和送券金额相加(亏损是负值),得到gap最小的券组合,就可以搞定了。有点暴力破解法的味道。

    下面是代码:

    ## 检查是否安装 sqldf 和 reshape2  这两个包,若没有则安装,若已安装,则跳过。
    if(!'sqldf' %in% installed.packages()[,1]) (install.packages('sqldf'))
    if(!'reshape2' %in% installed.packages()[,1]) (install.packages('reshape2'))
    ## 如何发优惠券
    ## step 1
    ####################### 构造一个数据框,里面包含所有可能的送券组合################################
    x=data.frame(x=rep(0:15,1)) # 表示 200的券 的张数
    y=data.frame(y=rep(0:15,1))  # 表示 80的券 的张数
    z=data.frame(z=rep(0:15,1))  # 表示 8的券 的张数
    library(sqldf)
    # 做笛卡尔积
    df <- sqldf('select * from x,y,z')
    df$coupon_sum <-apply(df,1,sum)
    df$amt_sum <- df$x*200+df$y*80+df$z*8
    #过滤掉 sum>15的 组合
     df <- sqldf('select * from df where coupon_sum<=15 order by amt_sum asc')
     ## step 2
    #######################################################
    ### 下面是给出任意一个 亏损 比如 loss=-987,则 fun2(-987) 返回出用200,80,8各几张,能获得gap最小
    fun2 <- function(i){
        if(i< -3000){
        return(data.frame(loss=i,x=15,y=0,z=0,coupon_sum=15,amt_sum=3000,gap=3000+i))
        } else {
            df$gap <- i+df$amt_sum
            df_positive <- sqldf('select * from df where gap>=0')
            res <- sqldf('select * from df 
                         where gap in (select gap from df_positive order by gap limit 1)
                         order by gap,coupon_sum
                         limit 1')
            return(cbind(loss=i,res))
        }
    }
     ## step 3
    # #### 建一个 函数 fun3,其中调用了fun2
    fun3 <- function(original.df){
        final.res <- data.frame()
        for(m in 1:length(original.df[,1])){
            row.res <- cbind(original.df[m,],fun2(original.df[m,2]))
            final.res <- rbind(final.res,row.res)
        } 
        return(final.res)
    }
    
    #  n <- length(test.df[,2])
    #  res <- lapply(test.df[2:100,2],fun2)
    #  do.call(rbind,res)
     
     
     
    ## step 4
    # 构造一个测试数据集 test.df  进行测试
    test.df <- data.frame(phone_num=rep(1:200,1),loss=abs(rnorm(200))*(-2000))
    final_res <- fun3(dd)
    
    ## step 5 
    ## 变换数据形式 宽表变窄表,然后写出结果数据集
    library(reshape2)
    final <- melt(final_res[,c(1,3:5)],id=c('phone_num'))
    ## 重新排序一下
    final <- sqldf('select * from final order by phone_num')
    # final
    # write.csv() 
    
    for(i in 1:length(dd[,2])){
        print(paste0('round ',i))
        print(fun2(dd[i,2]))
    }

    总结:

    • 由于代码是发给别人用的,但是经常别人有些包没安装,用不了。所以学会了一句code,搞定。
    ## 检查是否安装 sqldf 和 reshape2  这两个包,若没有则安装,若已安装,则跳过。
    if(!'sqldf' %in% installed.packages()[,1]) (install.packages('sqldf'))
    if(!'reshape2' %in% installed.packages()[,1]) (install.packages('reshape2'))
  • 相关阅读:
    [对对子队]会议记录4.10(Scrum Meeting 1)
    [对对子队]团队任务拆解Alpha
    [对对子队]功能规格说明书
    [对对子队]技术规格说明书
    团队项目选择
    团队作业第四次—项目系统设计与数据库设计
    团队作业第三次—项目需求分析
    团队作业第二次——团队Github实战训练
    团队作业第一次—团队展示和项目展示
    贡献分分配规则
  • 原文地址:https://www.cnblogs.com/litao1105/p/5039138.html
Copyright © 2020-2023  润新知