[出题]求56以内和为60的5个随机数

头像
523066680
Administrator
Administrator
帖子: 404
注册时间: 2016年07月19日 12:14
拥有现金: 锁定
储蓄: 锁定
Has thanked: 38 times
Been thanked: 52 times
联系:

[出题]求56以内和为60的5个随机数

帖子 #1 523066680 » 2018年11月14日 08:57

求56以内和为60的5个随机数
随机数可以有重复项

要求:输出多个结果,尽可能随机分布。

zzz19760225
渐入佳境
渐入佳境
帖子: 41
注册时间: 2017年12月25日 11:12
拥有现金: 锁定
储蓄: 锁定
Has thanked: 37 times
Been thanked: 1 time
联系:

Re: [出题]求56以内和为60的5个随机数

帖子 #2 zzz19760225 » 2018年11月14日 16:52

自带板凳等楼下

头像
523066680
Administrator
Administrator
帖子: 404
注册时间: 2016年07月19日 12:14
拥有现金: 锁定
储蓄: 锁定
Has thanked: 38 times
Been thanked: 52 times
联系:

一、 Re: [出题]求56以内和为60的5个随机数

帖子 #3 523066680 » 2018年11月15日 21:59

我先抛个砖头,随机取n次,逐次缩减范围。
缺点:由于范围逐次递减,会呈现越往后数值越小的趋势。

our $R = 56;
our $n = 5; # the number you need
our $m = 60;

grep { test() } (1 .. 10);

sub test
{
my $get;
my $left = $m;
my @poss;
for ( my $t = $n; $t > 1; $t-- )
{
$get = int(rand($left-$t))+1;
push @poss, $get;
$left -= $get;
}
push @poss, $left;

printf "%s\n", join(",", @poss);
}

输出示例:
29,9,15,1,6
32,16,3,4,5
51,2,2,3,2
29,6,13,8,4
38,17,2,1,2
23,13,18,3,3
35,6,1,12,6
45,9,3,1,2
54,1,2,1,2
40,16,1,1,2


可以看到每一个都有明显特征

头像
523066680
Administrator
Administrator
帖子: 404
注册时间: 2016年07月19日 12:14
拥有现金: 锁定
储蓄: 锁定
Has thanked: 38 times
Been thanked: 52 times
联系:

二、Re: [出题]求56以内和为60的5个随机数

帖子 #4 523066680 » 2018年11月15日 22:31

第二种,假设有n个容器,初始值为1,随机对这些容器 (m-n-1) 次 叠加1 的计算

our $R = 56;
our $n = 5; # the number you need
our $m = 60;

grep { test() } (1 .. 10);

sub test
{
my @cup = (1) x $n ;
grep { $cup[int(rand $n)]++ } ( $n+1 .. $m );
printf "%s\n", join(",", @cup);
}

输出示例:
12,10,10,15,13
12,12,15,12,9
12,8,12,15,13
12,14,15,9,10
11,12,13,11,13
10,10,11,10,19
12,10,17,7,14
14,13,10,12,11
13,10,11,12,14
11,8,10,15,16

这样又显得比较均匀,有没有更随机的?

zzz19760225
渐入佳境
渐入佳境
帖子: 41
注册时间: 2017年12月25日 11:12
拥有现金: 锁定
储蓄: 锁定
Has thanked: 37 times
Been thanked: 1 time
联系:

Re: [出题]求56以内和为60的5个随机数

帖子 #5 zzz19760225 » 2018年11月15日 22:58

:diggingnoise7 不明觉厉
我以前想过取电脑的系统时间,然后奇偶数判断,选择时间微秒的最后两位之一。
后来因为电脑需要系统权限什么的,没继续折腾(需要一个好折腾的工具和环境)。

our 是什么语言啊
our$有点像linux或服务器

头像
523066680
Administrator
Administrator
帖子: 404
注册时间: 2016年07月19日 12:14
拥有现金: 锁定
储蓄: 锁定
Has thanked: 38 times
Been thanked: 52 times
联系:

Re: [出题]求56以内和为60的5个随机数

帖子 #6 523066680 » 2018年11月16日 08:45

zzz19760225 写了::diggingnoise7 不明觉厉
我以前想过取电脑的系统时间,然后奇偶数判断,选择时间微秒的最后两位之一。
后来因为电脑需要系统权限什么的,没继续折腾(需要一个好折腾的工具和环境)。

our 是什么语言啊
our$有点像linux或服务器

我和另一个用户 Rubyish 用的是 Perl 语言。our 是一种变量声明,声明这个变量全局的。
听描述感觉你所在的计算机环境非常限制;但是应该有私人电脑可以用呀?

zzz19760225
渐入佳境
渐入佳境
帖子: 41
注册时间: 2017年12月25日 11:12
拥有现金: 锁定
储蓄: 锁定
Has thanked: 37 times
Been thanked: 1 time
联系:

Re: [出题]求56以内和为60的5个随机数

帖子 #7 zzz19760225 » 2018年11月16日 17:08

怎么说呢,当现在没有电脑。
等有余钱了,心定了,就有电脑了。

头像
523066680
Administrator
Administrator
帖子: 404
注册时间: 2016年07月19日 12:14
拥有现金: 锁定
储蓄: 锁定
Has thanked: 38 times
Been thanked: 52 times
联系:

三、Re: [出题]求56以内和为60的5个随机数

帖子 #8 523066680 » 2018年11月16日 18:56

另一种方案,是枚举1-56范围内,5个数字的所有组合形式,组合内允许有重复数字。
拥有了所有组合类型,我们可以从组合中随机提取一种,这样应该足够随机了吧?

参考 combinations-permutations
最后的部分 Combinations with Repetition
附件
Combinations with Repetition.png

24game
渐入佳境
渐入佳境
帖子: 47
注册时间: 2016年09月02日 22:09
拥有现金: 锁定
Has thanked: 3 times
Been thanked: 22 times
联系:

Re: [出题]求56以内和为60的5个随机数

帖子 #9 24game » 2018年11月16日 23:01

一个环周长为60, 其上分布60个位置, 且为位置分布定义一个正方向, 在正方向上位置标号依次为0到59, 两个位置间的距离以标号按负方向来计算, 位置A到位置B的距离以位置B的标号减去位置A的标号来计算, 结果必须为非负数, 如果计算结果为负数, 就加上一个周长成为正数.

比如位置0到位置1的距离是1, 位置5到位置12的距离是7, 位置58到位置1的距离是3(距离为负数(1-58=-57)时, 加上周长60)

5次在环上60个位置中取一个随机位置,每次选取后将已选过的位置剪除, 第1次有60个位置可选, 第2次有59个位置可选,...第5次56个位置可选. 选满5个位置后, 每2个相邻位置的距离即为题目所求的随机数之一.

此算法只有在5次选位结束后, 随机数才能被确定下来, 在所有5个选位完成前, 任何2个相邻的位置都可能被下一次的选位插入其间, 换言之, 所有选位完成前, 没有任何一个随机数被确定下来. 任何一次选位都不受之前选位的约束(重复选位不算, 重复选位意味着允许0作为随机数结果)

代码: 全选

@echo off & setlocal enabledelayedexpansion & mode 100

for /L %%t in (1 1 20) do (
    >nul (for /f "tokens=1 delims==" %%a in ('2^>nul set ##') do set "%%a=")

    set "pool="
    for /L %%a in (100 1 159) do  set "t=%%a" & set "pool=!pool!#!t:~-2!"

    set len=60
    for /L %%a in (1 1 5) do (
        set /a "r = !random! %% len * 3, len-=1"
        for %%r in (!r!) do (
            set "c%%a=!pool:~%%r,3!"
            set "#!pool:~%%r,3!=1"
            for %%b in (!c%%a!) do set "pool=!pool:%%b=!"
        )
    )

    set /a "last=0,ind=1"
    for /f "tokens=1 delims=#=" %%a in ('set ##') do (
        set /a "t=$$!ind!=1%%a-100-last, last=1%%a-100,ind+=1"
        if !t! lss 0 (set /a "t+=60, $$!ind!=t")
    )
    set /a "$$1-=last"
    if !$$1! lss 0 (set /a "$$1+=60")

    set "out=" & set "sum=0"
    for /L %%a in (1 1 5) do (
        set "out=!out!!$$%%a! "
        set /a "sum+=$$%%a"
    )
    if !sum!==60 (REM set "out=!out!  OK" & REM OK
    ) else (set "out=!out! ERR")
    echo;!out!
)

pause


输出示例

代码: 全选

33 2 21 2 2
20 5 8 9 18
40 3 1 6 10
17 11 23 2 7
33 5 5 16 1
24 16 2 10 8
29 4 5 1 21
22 14 15 3 6
7 1 1 17 34
35 7 7 7 4
19 11 1 19 10
9 7 1 7 36
34 3 10 6 7
22 1 13 17 7
36 4 7 3 10
13 2 18 18 9
46 4 1 2 7
27 16 2 2 13
5 14 5 27 9
12 7 33 4 4

24game
渐入佳境
渐入佳境
帖子: 47
注册时间: 2016年09月02日 22:09
拥有现金: 锁定
Has thanked: 3 times
Been thanked: 22 times
联系:

Re: 二、Re: [出题]求56以内和为60的5个随机数

帖子 #10 24game » 2018年11月17日 15:44

523066680 写了:第二种,假设有n个容器,初始值为1,随机对这些容器 (m-n-1) 次 叠加1 的计算

our $R = 56;
our $n = 5; # the number you need
our $m = 60;

grep { test() } (1 .. 10);

sub test
{
my @cup = (1) x $n ;
grep { $cup[int(rand $n)]++ } ( $n+1 .. $m );
printf "%s\n", join(",", @cup);
}

输出示例:
12,10,10,15,13
12,12,15,12,9
12,8,12,15,13
12,14,15,9,10
11,12,13,11,13
10,10,11,10,19
12,10,17,7,14
14,13,10,12,11
13,10,11,12,14
11,8,10,15,16

这样又显得比较均匀,有没有更随机的?


每个容器每次获得加1的概率为 1/5=20%, 总共55次加1机会, 每个容器均有趋近11(=55/5)次机会, 在大样本统计情况下, 1+11=12 应是频率最高的数字, 偏离 12 越远的数字出现频率都会极低
此例输出, 数字的频率分布如下:

代码: 全选

8:2
9:2
10:10
11:6
12:11
13:6
14:4
15:5
16:1
17:1
19:1


回到 “算法和编码”

在线用户

用户浏览此论坛: 没有注册用户 和 1 访客