免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3393 | 回复: 11
打印 上一主题 下一主题

请教一个先进先出算法的实现 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-05-20 15:44 |只看该作者 |倒序浏览
10可用积分
有个问题,想用shell或者perl解决,折腾几天也没弄出来,麻烦指点一下,问题如下:
从下表第2列的原始铅笔数量中里取一定数量的铅笔(x),先取批次靠前的,计算每次取出铅笔的总价值f(x),取得铅笔是哪个批次,就选择相应批次的单价。
铅笔批次 原始铅笔数量 单价 本次取出数量 剩余铅笔数量
1 150 0.6 0 150
2 150 0.7 0 150
3 100 0.5 0 150
4 10 0.6 0 10
5 100 0.7 0 100
6 120 0.55 0 120

例子如下:
如果在第1次取100支铅笔,上表中铅笔数量变化如下:
铅笔批次 原始铅笔数量 单价 本次取出数量 剩余铅笔数量
1 150 0.6 100 50
2 150 0.7 0 150
3 100 0.5 0 150
4 10 0.6 0 10
5 100 0.7 0 100
6 120 0.55 0 120
相应的f(100)=100*0.6=60
如果在第2次取120支铅笔,即f(120),上表中铅笔数量变化如下:
铅笔批次 原始铅笔数量 单价 剩余铅笔数量
1 150 0.6 50 0
2 150 0.7 70 80
3 100 0.5 0 150
4 10 0.6 0 10
5 100 0.7 0 100
6 120 0.55 0 120
f(120)=50*0.6+50*0.7=65
如果在第3次取250支铅笔,即f(250),上表中铅笔数量变化如下:
铅笔批次 原始铅笔数量 单价 剩余铅笔数量
1 150 0.6 0 0
2 150 0.7 80 0
3 100 0.5 150 0
4 10 0.6 10 0
5 100 0.7 10 90
6 120 0.55 0 120
f(250)=80*0.7+150*0.5+10*0.6+10*0.7

[ 本帖最后由 xyzlsh 于 2009-5-20 16:11 编辑 ]

最佳答案

查看完整内容

单句awk处理。每次处理输出本次的购货款,更新原文件状态。可以处理任意情况(为显示清楚每次处理手动加空行):[ 本帖最后由 kwokcn 于 2009-5-20 18:52 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-05-20 15:44 |只看该作者
单句awk处理。每次处理输出本次的购货款,更新原文件状态。


  1. awk -v n=100 'NR==1{print > FILENAME".bak";next}n>$4{n=n-$4;$NF=$4;$4="0"}n<=$4{$NF=n;$4=$4-n;n="0"}{print > FILENAME".bak";s=s+$3*($NF)}END{printf("%0.2f\n",s); system("mv "FILENAME".bak "FILENAME)}' URFILE
复制代码


可以处理任意情况(为显示清楚每次处理手动加空行):

  1. [root]# cat aa
  2. 铅笔批次 原始铅笔数量 单价 剩余铅笔数量 本次取出数量
  3. 1 150 0.6 150 0
  4. 2 150 0.7 150 0
  5. 3 100 0.5 100 0
  6. 4 10 0.6 10 0
  7. 5 100 0.7 100 0
  8. 6 120 0.55 120 0

  9. [root]# awk -v n=280 'NR==1{print > FILENAME".bak";next}n>$4{n=n-$4;$NF=$4;$4="0"}n<=$4{$NF=n;$4=$4-n;n="0"}{print > FILENAME".bak";s=s+$3*($NF)}END{printf("%0.2f\n",s); system("mv "FILENAME".bak "FILENAME)}' aa
  10. 181.00

  11. [root]# cat aa
  12. 铅笔批次 原始铅笔数量 单价 剩余铅笔数量 本次取出数量
  13. 1 150 0.6 0 150
  14. 2 150 0.7 20 130
  15. 3 100 0.5 100 0
  16. 4 10 0.6 10 0
  17. 5 100 0.7 100 0
  18. 6 120 0.55 120 0

  19. [root]# awk -v n=280 'NR==1{print > FILENAME".bak";next}n>$4{n=n-$4;$NF=$4;$4="0"}n<=$4{$NF=n;$4=$4-n;n="0"}{print > FILENAME".bak";s=s+$3*($NF)}END{printf("%0.2f\n",s); system("mv "FILENAME".bak "FILENAME)}' aa
  20. 167.50

  21. [root]# cat aa
  22. 铅笔批次 原始铅笔数量 单价 剩余铅笔数量 本次取出数量
  23. 1 150 0.6 0 0
  24. 2 150 0.7 0 20
  25. 3 100 0.5 0 100
  26. 4 10 0.6 0 10
  27. 5 100 0.7 0 100
  28. 6 120 0.55 70 50

  29. [root]# awk -v n=280 'NR==1{print > FILENAME".bak";next}n>$4{n=n-$4;$NF=$4;$4="0"}n<=$4{$NF=n;$4=$4-n;n="0"}{print > FILENAME".bak";s=s+$3*($NF)}END{printf("%0.2f\n",s); system("mv "FILENAME".bak "FILENAME)}' aa
  30. 38.50

  31. [root]# cat aa
  32. 铅笔批次 原始铅笔数量 单价 剩余铅笔数量 本次取出数量
  33. 1 150 0.6 0 0
  34. 2 150 0.7 0 0
  35. 3 100 0.5 0 0
  36. 4 10 0.6 0 0
  37. 5 100 0.7 0 0
  38. 6 120 0.55 0 70

  39. [root]# awk -v n=280 'NR==1{print > FILENAME".bak";next}n>$4{n=n-$4;$NF=$4;$4="0"}n<=$4{$NF=n;$4=$4-n;n="0"}{print > FILENAME".bak";s=s+$3*($NF)}END{printf("%0.2f\n",s); system("mv "FILENAME".bak "FILENAME)}' aa
  40. 0.00

  41. [root]# cat aa
  42. 铅笔批次 原始铅笔数量 单价 剩余铅笔数量 本次取出数量
  43. 1 150 0.6 0 0
  44. 2 150 0.7 0 0
  45. 3 100 0.5 0 0
  46. 4 10 0.6 0 0
  47. 5 100 0.7 0 0
  48. 6 120 0.55 0 0
复制代码

[ 本帖最后由 kwokcn 于 2009-5-20 18:52 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2009-05-20 15:54 |只看该作者

回复 #1 xyzlsh 的帖子

变量a为你要抽取的数量


a=50;awk '{print $1,$2,$3,$3*'"$a"',$2-'"$a"'}' 2
1 150 0.6 30 100
2 150 0.7 35 100
3 100 0.5 25 50
4 10 0.6 30 -40
5 100 0.7 35 50
6 120 0.55 27.5 70

[ 本帖最后由 wtuter 于 2009-5-20 15:57 编辑 ]

论坛徽章:
0
4 [报告]
发表于 2009-05-20 15:56 |只看该作者
最后要求输出什么呢?
表的最终状态还有f(n)的值吗?

论坛徽章:
0
5 [报告]
发表于 2009-05-20 16:06 |只看该作者

回复 #3 kwokcn 的帖子

至少要输出如下的信息:
1.每批铅笔的单价;
2.每次出货后,铅笔的剩余数量。

论坛徽章:
0
6 [报告]
发表于 2009-05-20 16:08 |只看该作者

回复 #4 xyzlsh 的帖子

a=50;awk '{print $1,$2,$3,$3*'"$a"',$2-'"$a"'}' 2


$1 $2 $3 $4  $5   
           单价   剩余数量
1 150 0.6 30 100
2 150 0.7 35 100
3 100 0.5 25 50
4 10 0.6 30 -40
5 100 0.7 35 50
6 120 0.55 27.5 70

论坛徽章:
0
7 [报告]
发表于 2009-05-20 16:15 |只看该作者

回复 #5 wtuter 的帖子

问题好像没这么简单,不能用$2直接减去a。因为是按照批次取货,如果上批还有剩余,会把上批取到0,再取本批。还要注意每次出货后都要更新存货的状态,所以理论上每次函数计算的结果可能会有不同。

[ 本帖最后由 xyzlsh 于 2009-5-20 16:22 编辑 ]

论坛徽章:
0
8 [报告]
发表于 2009-05-20 16:35 |只看该作者
改进后写在8楼了。

[ 本帖最后由 kwokcn 于 2009-5-20 18:54 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2009-05-20 17:10 |只看该作者
  1. awk -v total=$total '{a[NR]=$1" "$2" "$3;b[NR]=$4;c[NR]=$5}END{for(i=1;i<=NR;i++){sum+=c[i];if(total){if(sum>total){b[i]=c[i];c[i]=sum-total;b[i]-=c[i];total=0;}else{b[i]=c[i];c[i]=0}}print a[i]" "b[i]" "c[i]}}' file
复制代码

上次处理的没写入文件
  1. total=600
  2. [root@mip-123456 shell]# awk -v total=$total '{a[NR]=$1" "$2" "$3;b[NR]=$4;c[NR]=$5}END{for(i=1;i<=NR;i++){sum+=c[i];if(total){if(sum>total){b[i]=c[i];c[i]=sum-total;b[i]-=c[i];total=0;}else{b[i]=c[i];c[i]=0}}print a[i]" "b[i]" "c[i]}}' file
  3. 1 150 0.6 150 0
  4. 2 150 0.7 150 0
  5. 3 100 0.5 150 0
  6. 4 10 0.6 10 0
  7. 5 100 0.7 100 0
  8. 6 120 0.55 40 80
复制代码

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
10 [报告]
发表于 2009-05-20 17:41 |只看该作者
shell和awk混合的,每次备份原来的文件,未考虑库存不足时的情况:
  1. #!/bin/sh
  2. [ $# -lt 2 ] &&  { echo "Usage: $0 amount file" ;exit 1; }

  3. awk -v zl=$1 'BEGIN{over=start=0;}
  4. $5!=0&&!over{
  5.   dj[NR]=$3;
  6.   if (start==0) start=NR;
  7.   sl[NR]=($5>=zl)?zl:$5;
  8.   $4=sl[NR];
  9.   $5=$5-sl[NR];
  10.   zl-=sl[NR];
  11.   if(zl==0){
  12.     for(i=start;i<=NR;i++) {
  13.       je+=sl[i]*dj[i];
  14.     }
  15.     print je;
  16.     over=1;
  17.   };
  18. }
  19. {print > "file-new";}' $2

  20. mv $2 ${2}-"$(date)"
  21. mv file-new $2
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP