免费注册 查看新帖 |

Chinaunix

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

[数值计算] 可递归次数的计算 [复制链接]

论坛徽章:
18
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之深圳
日期:2016-12-23 13:51:3815-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:202015亚冠之塔什干棉农
日期:2015-08-17 19:49:492015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年亚洲杯之沙特阿拉伯
日期:2015-03-02 15:55:40处女座
日期:2014-05-25 10:34:0020周年集字徽章-年
日期:2023-04-23 11:17:52
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2018-03-25 09:20 |只看该作者 |倒序浏览
本帖最后由 bikkuri 于 2018-03-25 09:23 编辑

大家好!
我有一个问题向大家请教。
假设有一个函数f(abc...n)=a*b*c*...*n,即函数值为变量的各数位数字的乘积,例如:
f(234)=2*3*4=24
继续以函数值为变量代入函数进行递归预算,可以得到f(24)=2*4=8;
而再次递归,可以得到f(8)=8;
当函数值等于变量时停止运算。
这样我们可以得到一条递归路径:
234 - 24 - 8
类似地我们可以计算出任何整数的函数递归路径:
678 - 336 - 54 - 20 - 0
1589 - 360 - 0
27893 - 3024 - 0
6393 - 486 - 192 - 18 - 8
88 - 64 - 24 - 8
78 - 56 - 30 - 0
-----------------------------------------
现在要求的是计算出1-100之内递归路径最长的数,并将其递归路径按以上格式打印出来,如果有并列最长的,则将多个并列最长的递归路径全部打印出来。
谢谢大家!

论坛徽章:
0
2 [报告]
发表于 2018-03-25 17:06 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
3 [报告]
发表于 2018-03-25 17:28 |只看该作者
本帖最后由 jason680 于 2018-03-26 10:06 编辑

$ awk -f get_mul.awk
77 - 49 - 36 - 18 - 8


$ cat get_mul.awk

func get_path(str, path) {
  path = str
  while(length(str)>1) {
    str = get_mul(str);
    path = path " - " str
  }
  return path
}

func get_mul(str,  item, val, cnt, aStr) {
  item = split(str,aStr,"");
  val = 1;
  for (cnt=1; cnt<=item; cnt+=1)
    val *= aStr[cnt];
  return val;
}
BEGIN{
  for (cnt=0; cnt<=99 ;cnt+=1) {
    path = get_path(cnt);
    item = split(path, aPath, "-");
    if (max == item) {
      path_all = path_all "\n" path
    }
    if (max < item) {
      max = item
      path_all = path
    }
  }
  print path_all
}


论坛徽章:
25
程序设计版块每日发帖之星
日期:2016-05-03 06:20:0015-16赛季CBA联赛之八一
日期:2018-07-05 10:34:09黑曼巴
日期:2018-07-06 15:19:5015-16赛季CBA联赛之佛山
日期:2018-08-03 13:19:3315-16赛季CBA联赛之山西
日期:2018-08-07 19:46:2315-16赛季CBA联赛之广夏
日期:2018-08-08 19:31:5015-16赛季CBA联赛之青岛
日期:2018-11-26 15:21:5015-16赛季CBA联赛之上海
日期:2018-12-11 09:45:3219周年集字徽章-年
日期:2020-04-18 23:54:5215-16赛季CBA联赛之深圳
日期:2020-04-19 21:40:19黑曼巴
日期:2022-04-03 17:55:1315-16赛季CBA联赛之八一
日期:2018-07-03 16:56:46
4 [报告]
发表于 2018-03-26 13:48 |只看该作者
本帖最后由 wh7211 于 2018-03-26 13:56 编辑

回复 1# bikkuri


<<<awk4.0+
  1. seq 100|awk 'function w(x){a="";b++;l=split(x,t,"");if(l>1){for(i=1;i<=l;i++){a=a?a*t[i]:t[i]};c=c?c" - "a:$0" - "a;w(a)}else{d[b]=d[b]?d[b]"\n"c:c}}{b=c="";w($0)}END{PROCINFO["sorted_in"]="@ind_num_desc";for(i in d){print d[i];exit}}'
复制代码

输出:
77 - 49 - 36 - 18 - 8

论坛徽章:
18
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之深圳
日期:2016-12-23 13:51:3815-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:202015亚冠之塔什干棉农
日期:2015-08-17 19:49:492015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年亚洲杯之沙特阿拉伯
日期:2015-03-02 15:55:40处女座
日期:2014-05-25 10:34:0020周年集字徽章-年
日期:2023-04-23 11:17:52
5 [报告]
发表于 2018-03-27 22:20 |只看该作者
谢谢大家的帮助!

论坛徽章:
7
戌狗
日期:2013-12-15 20:43:38技术图书徽章
日期:2014-03-05 01:33:12技术图书徽章
日期:2014-03-15 20:31:17未羊
日期:2014-03-25 23:48:20丑牛
日期:2014-04-07 22:37:44巳蛇
日期:2014-04-11 21:58:0915-16赛季CBA联赛之青岛
日期:2016-03-17 20:36:13
6 [报告]
发表于 2018-03-28 17:18 |只看该作者
perl abc.pl
  1. 77 - 49 - 36 - 18 - 8
复制代码


perl abc.pl 100
  1. 77 - 49 - 36 - 18 - 8
复制代码


perl abc.pl 100000
  1. 68889 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  2. 68898 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  3. 68988 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  4. 69888 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  5. 86889 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  6. 86898 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  7. 86988 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  8. 88689 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  9. 88698 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  10. 88869 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  11. 88896 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  12. 88968 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  13. 88986 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  14. 89688 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  15. 89868 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  16. 89886 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  17. 96888 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  18. 98688 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  19. 98868 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  20. 98886 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
复制代码


abc.pl
  1. #!/usr/bin/perl
  2. # version 26, subversion 1 (v5.26.1)
  3. use 5.010;

  4. my $MAX = shift || 100; # default = 100
  5. explore($MAX);

  6. # ____________________SUB____________________

  7. sub explore {
  8.     my $end = shift;
  9.     my ( $long, @the, @solu ) = 0;

  10.     for my $numba ( 0 .. $end ) {
  11.         my $next = 1;
  12.         $next *= $_ for split '', $numba;
  13.         my $path = $the[$numba] = 1 + ( $the[$next] // 0 );
  14.         next if $path < $long;
  15.         ( $long, @solu ) = $path if $path > $long;
  16.         push @solu, $numba;
  17.     }

  18.     say join ' - ', @{ S_( $_, [] ) } for @solu;
  19. }

  20. sub S_ {
  21.     my ( $num, $his ) = @_;
  22.     return [ @$his, $num ] if $num < 10;
  23.     my $next = 1;
  24.     $next *= $_ for split '', $num;
  25.     S_( $next, [ @$his, $num ] );
  26. }

  27. __DATA__
  28. $_
复制代码

论坛徽章:
18
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之深圳
日期:2016-12-23 13:51:3815-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:202015亚冠之塔什干棉农
日期:2015-08-17 19:49:492015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年亚洲杯之沙特阿拉伯
日期:2015-03-02 15:55:40处女座
日期:2014-05-25 10:34:0020周年集字徽章-年
日期:2023-04-23 11:17:52
7 [报告]
发表于 2018-03-28 19:46 |只看该作者
花了差不多一天时间算出1千万以内递归路径最长的数。

recursion10000000.txt (301.84 KB, 下载次数: 11)

论坛徽章:
12
子鼠
日期:2014-10-11 16:46:482016科比退役纪念章
日期:2018-03-16 10:24:0515-16赛季CBA联赛之山东
日期:2017-11-10 14:32:142016科比退役纪念章
日期:2017-09-02 15:42:4715-16赛季CBA联赛之佛山
日期:2017-08-28 17:11:5515-16赛季CBA联赛之浙江
日期:2017-08-24 16:55:1715-16赛季CBA联赛之青岛
日期:2017-08-17 19:55:2415-16赛季CBA联赛之天津
日期:2017-06-29 10:34:4315-16赛季CBA联赛之四川
日期:2017-05-16 16:38:55黑曼巴
日期:2016-07-19 15:03:112015亚冠之萨济拖拉机
日期:2015-05-22 11:38:5315-16赛季CBA联赛之北京
日期:2019-08-13 17:30:53
8 [报告]
发表于 2018-07-09 10:50 |只看该作者
本帖最后由 523066680 于 2018-07-09 11:32 编辑

回复 7# bikkuri

附件结果中有一行重复

  1. 3768876 - 338688 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
  2. 3768876 - 338688 - 27648 - 2688 - 768 - 336 - 54 - 20 - 0
复制代码

----------------------------------------------分割线----------------------------------------------

回复 6# rubyish

rubyish 的代码在我的电脑上一千万内只需要19秒 (不含 printf 打印的时间)
代码有一处非常巧妙的地方,

my $path = $the[$numba] = 1 + ( $the[$next] // 0 );

@the 数组积累了从初始数字到当前数字的“可迭代次数”,反复利用,避免了对每个数字执行递归函数" S_() "。


论坛徽章:
4
15-16赛季CBA联赛之青岛
日期:2018-07-09 14:17:2815-16赛季CBA联赛之八一
日期:2018-08-06 15:30:0515-16赛季CBA联赛之广东
日期:2018-08-09 09:11:2115-16赛季CBA联赛之佛山
日期:2019-02-14 09:26:31
9 [报告]
发表于 2018-07-31 16:29 |只看该作者
本帖最后由 christmas1102 于 2018-07-31 17:27 编辑
  1. seq 100 | awk 'func b(x){split(x,a,"");if(a[2]){x=a[1]*a[2];c=c?c"-"x:$0"-"x;b(x)}}{b($0);d=d?d"\n"c:c;e=length(c);max=max>e?max:e;c=""}END{split(d,f,"\n");for(i in f){if(length(f[i])==max){print f[i]}}}'
  2. 执行结果:
  3. 77-49-36-18-8
复制代码

论坛徽章:
60
20周年集字徽章-20	
日期:2020-10-28 14:04:3015-16赛季CBA联赛之北京
日期:2016-07-06 15:42:0715-16赛季CBA联赛之同曦
日期:2016-06-12 10:38:0915-16赛季CBA联赛之佛山
日期:2016-05-27 11:54:56黄金圣斗士
日期:2015-12-02 11:44:35白银圣斗士
日期:2015-11-25 14:32:43白银圣斗士
日期:2015-11-23 12:53:352015亚冠之布里斯班狮吼
日期:2015-10-21 16:55:482015亚冠之首尔
日期:2015-09-01 16:46:052015亚冠之德黑兰石油
日期:2015-08-31 11:39:192015亚冠之萨济拖拉机
日期:2015-08-28 21:06:5315-16赛季CBA联赛之广东
日期:2016-07-12 14:58:53
10 [报告]
发表于 2018-08-01 14:40 |只看该作者
本帖最后由 reyleon 于 2018-08-01 17:03 编辑

gawk 4.0+, 主要用到了 gawk 4.0+ 版本 asorti 函数排序的特性

[root@hk ~]# cat f.awk

function rec(n) {
    v=1;
    t=split(n,a,"");
    for(i=1;i<=t;i++) v*=a;
    if(v==n)return s;
    s=s?s" - "v:v;
    rec(v);
}

{
    for(k=1;k<=$1;k++){ s="";x=sprintf("%s - %s",k,rec(k));L=split(x,b);c[L]=c[L]?c[L]"\n"x:x }
    # 这里排序选最大长度
    asorti(c,d,"@ind_num_desc");
    print c[d[1]];
}


[root@hk ~]# echo 100 | awk -f f.awk
77 - 49 - 36 - 18 - 8
[root@hk ~]#
[root@hk ~]# echo 1000 | awk -f f.awk
679 - 378 - 168 - 48 - 32 - 6
688 - 384 - 96 - 54 - 20 - 0
697 - 378 - 168 - 48 - 32 - 6
769 - 378 - 168 - 48 - 32 - 6
796 - 378 - 168 - 48 - 32 - 6
868 - 384 - 96 - 54 - 20 - 0
886 - 384 - 96 - 54 - 20 - 0
967 - 378 - 168 - 48 - 32 - 6
976 - 378 - 168 - 48 - 32 - 6
[root@hk ~]# echo 10000 | awk -f f.awk
6788 - 2688 - 768 - 336 - 54 - 20 - 0
6878 - 2688 - 768 - 336 - 54 - 20 - 0
6887 - 2688 - 768 - 336 - 54 - 20 - 0
7688 - 2688 - 768 - 336 - 54 - 20 - 0
7868 - 2688 - 768 - 336 - 54 - 20 - 0
7886 - 2688 - 768 - 336 - 54 - 20 - 0
8678 - 2688 - 768 - 336 - 54 - 20 - 0
8687 - 2688 - 768 - 336 - 54 - 20 - 0
8768 - 2688 - 768 - 336 - 54 - 20 - 0
8786 - 2688 - 768 - 336 - 54 - 20 - 0
8867 - 2688 - 768 - 336 - 54 - 20 - 0
8876 - 2688 - 768 - 336 - 54 - 20 - 0
[root@hk ~]#


------------------------

代码重发下, 上面的代码 因为CU会隐藏掉[i ]:

[root@hk ~]# cat f.awk

function rec(n) {
    v=1;
    t=split(n,a,"");
    for(p=1;p<=t;p++) v*=a[p];
    if(v==n)return s;
    s=s?s" - "v:v;
    rec(v);
}

{
    for(k=1;k<=$1;k++){ s="";x=sprintf("%s - %s",k,rec(k));L=split(x,b);c[L]=c[L]?c[L]"\n"x:x }
    asorti(c,d,"@ind_num_desc");
    print c[d[1]];
}

------------------
再次更新, 以下是经过优化的代码, 一千万的计算大概花了 1分多钟, 比上面最原始的快了 NNNNNNN 倍... 基本上与3楼的代码 相当, 稍慢一丢丢

[root@hk ~]# time echo 10000000 | awk -f f.awk  > /tmp/1qw

real    1m35.637s
user    1m35.521s
sys     0m0.082s


[root@hk ~]# cat f.awk

function rec(n) {
    v=1;
    t=split(n,a,"");
    for(p=1;p<=t;p++) v*=a[p];
    if(v==n)return s;
    s=s?s" - "v:v;
    rec(v);
}

{
    for(k=1;k<=$1;k++){
        s="";x=sprintf("%s - %s",k,rec(k));L=split(x,b);c[L]=c[L]?c[L]"\n"x:x;
        asorti(c,d,"@ind_num_desc");
        var=c[d[1]];
        delete c;
        c[d[1]]=var;

    }
    print var;
}

[root@hk ~]# awk --version
GNU Awk 4.2.1, API: 2.0
Copyright (C) 1989, 1991-2018 Free Software Foundation.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
[root@hk ~]#







您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP