Rand5 () ถึง Rand7 () [ปิด]


29

คุณได้รับฟังก์ชั่น Rand5 () ฟังก์ชันนี้คืนค่าจำนวนเต็มแบบสุ่ม (การกระจายเท่ากัน) อย่างสมบูรณ์ระหว่าง 1 ถึง 5

จัดเตรียมฟังก์ชัน Rand7 () ซึ่งใช้ Rand5 () เพื่อสร้างจำนวนเต็มแบบสุ่มอย่างสมบูรณ์ระหว่าง 1 ถึง 7




รวม 1 และ 5 หรือไม่ คือจากชุด {1,2,3,4,5}
Aaron McDaid

1
เกณฑ์ใดที่กำหนดผู้ชนะหนึ่งคน
kojiro

ขณะนั้นเมื่อคุณตระหนักว่านี่เป็นคำถามเก่า
nyuszika7h

คำตอบ:


11

Java - 61 ตัวอักษร

int rand7(){int s=0,c=7;while(c-->0)s+=rand5();return s%7+1;}

ทดสอบไดรเวอร์สำหรับการตรวจสอบ:

class Rand {

    public static void main(String[] args) {
        int[] nums = new int[7];
        // get a lot of numbers
        for(int i = 0; i < 10000000; i++) nums[rand7()-1]++;
        // print the results
        for(int i = 0; i < 7; i++) System.out.println((i+1) + ": " + nums[i]);
    }

    // just for rand5()
    static java.util.Random r = new java.util.Random();

    static int rand5() {
        return r.nextInt(5)+1; // Random.nextInt(n) returns 0..n-1, so add 1
    }

    static int rand7(){int s=0,c=7;while(c-->0)s+=rand5();return s%7+1;}

}

ผล

C:\Documents and Settings\glowcoder\My Documents>java Rand
1: 1429828
2: 1429347
3: 1428328
4: 1426486
5: 1426784
6: 1429853
7: 1429374

C:\Documents and Settings\glowcoder\My Documents>

10
คะแนนพิเศษสำหรับ "ไปยังผู้ดำเนินการ"
Steve P

โกนถ่านหรือไม่? int rand7 () {สำหรับ (int s = 0, c = 7; c -> 0; s + = rand5 ()); return s% 7 + 1;}
Ron

3
คำตอบนี้ไม่ถูกต้อง: ความน่าจะเป็นของฟังก์ชันนี้ที่คืนค่าจาก 1 ถึง 7 คือ 0.1430656, 0.1430016, 0.1428224, 0.1426432, 0.1426432, 0.1428224 และ 0.1430016 ตามลำดับ ใช่ความแตกต่างระหว่างความน่าจะเป็นต่ำสุดและสูงสุดนั้นน้อยกว่า 0.0005 แต่ยังคงเป็นคำถามที่ระบุว่า "จำนวนเต็มแบบสุ่มสมบูรณ์"
Ilmari Karonen

@ilmari คุณถูกต้อง - ฉันเพิ่งจะทำการทดสอบและดูเหมือนว่าการกระจายไม่ได้ ... ให้ฉันคิดว่า ...
corsiKa

1
@userunknown: ใช่น่าจะเป็นผมโพสต์เป็นจริงไม่ได้ใกล้เคียงพวกเขาแน่นอน (0.1430656 = 11177/78125 ฯลฯ ) rand5สมมติให้มีการสุ่มอย่างสมบูรณ์แบบ ฉันคำนวณพวกมันใน Maple โดยใช้พีชคณิตเมทริกซ์อย่างง่าย แต่คุณสามารถทำได้ด้วยดินสอและกระดาษในเวลาไม่กี่นาทีถ้าคุณต้องการ อย่างไรก็ตามมันกลับกลายเป็นว่า Omar ได้โพสต์ตัวเลขเดียวกัน (sans normalizing factor) ในความคิดเห็นเพื่อตอบอีกสองสามวันก่อนหน้านี้ (เช่นกันคุณสามารถ @notify ผู้ใช้หนึ่งคนต่อความคิดเห็นเท่านั้นแม้ว่าผู้เขียนโพสต์จะได้รับแจ้งเสมอในทุกกรณี)
Ilmari Karonen

7

Perl - 47 (เป็น 52) ตัวอักษร

sub rand7{($x=5*&rand5+&rand5-3)<24?int($x/3):&rand7} 

ยิ่งไปกว่านั้นฉันจะใช้ผู้ประกอบการที่สามและการเรียกซ้ำ วันที่ดีที่สุดเท่าที่เคย!

ตกลง 47 ตัวอักษรถ้าคุณใช้ mod แทน div:

sub rand7{($x=5*&rand5+&rand5)<27?$x%7+1:&rand7} 

ใกล้ ... แทนที่ 30 ด้วย 27 (= 6 + 21) และคุณจะได้การกระจายแบบสมบูรณ์แบบ โอ้และคุณสามารถดร็อปสอง&สัญญาณสุดท้ายเพื่อลดระดับลงได้ถึง 46 ตัวอักษร (รวมถึงช่องว่างซึ่งทำให้เวอร์ชันปัจจุบันของคุณอยู่ที่ 48)
Ilmari Karonen

7

JavaScript, 42

Rand7=f=_=>(x=Rand5()+Rand5()*5-5)>7?f():x

สิ่งโบนัส ES5:

Rand7=eval.bind(0,'for(;x=Rand5()+Rand5()*5-5,x>7;);x')

6

Ruby - 54 ตัวอักษร (ขึ้นอยู่กับโซลูชัน Dan McGrath โดยใช้ loop)

def rand7;x=8;while x>7 do x=rand5+5*rand5-5 end;x;end

Ruby - 45 chars (โซลูชันเดียวกันโดยใช้การเรียกซ้ำ)

def rand7;x=rand5+5*rand5-5;x>7 ?rand7: x;end

สามารถสั้นลงโดย 1 (x=rand5+5*rand5-5)>7?ถ่านโดยใช้
ลาร์ส Haugseth


4

ใน Common Lisp 70 ตัวอักษร:

(defun rand7()(let((n(-(+(rand5)(* 5(rand5)))5)))(if(> n 7)(rand7)n)))

วงเล็บใช้เนื้อที่มากกว่าที่ฉันต้องการ


ดี คุณสามารถบีบตัวละครออกได้อีกสองตัวโดยสร้างตัวแปรระดับโลกขึ้นมา:(defun rand7()(setq n(-(+(rand5)(* 5(rand5)))5))(if(> n 7)(rand7)n))
ดร. ปวด

ดียิ่งขึ้น:(defun rand7()(if(>(setq n(-(+(rand5)(* 5(rand5)))5))7)(rand7)n))
ดร. ปวด

4

ใน c / c ++ โดยใช้การสุ่มตัวอย่างการปฏิเสธ

int rand7(){int x=8;while(x>7)x=rand5()+5*rand5()-5;return x;}

62 ตัวอักษร


@barrycarter: เงื่อนไขคือwhile(x>7)เพื่อที่จะได้รับความพึงพอใจจากตัวเลขในช่วงที่ถูกต้องเท่านั้น
mellamokb

ความผิดฉันเอง. ลบความคิดเห็นที่เป็นใบ้ของฉัน
barrycarter

@barry และจากนั้นคุณทิ้งอีก ;)
Mateen Ulhaq

ฉันใช้เวลาสองสามนาทีเพื่อทราบว่าคณิตศาสตร์ที่นี่สร้างการแจกแจงแบบสุ่มสม่ำเสมอซึ่งสามารถใช้สำหรับการสุ่มตัวอย่างการปฏิเสธได้อย่างไร
แดเนียล

3

การแปลเป็น PHP จากคำตอบที่โพสต์โดย Dan McGrath

function Rand7(){$x=8;while($x>7)$x=rand5()+5*rand5()-5;return $x;}

67 ตัวอักษร


ไม่ควรนำหน้าด้วยคำว่า "function" (และเว้นวรรค)?
jtjacques

ใช่ ... และตอนนี้ก็คือ 67 ตัวอักษร ...
Marc-François

3

R, 34 ตัวอักษร

ใน R (ภาษาที่สร้างขึ้นสำหรับการคำนวณเชิงสถิติ) ซึ่งเป็นวิธีแก้ปัญหาสิบแปดมงกุฎโดยเจตนา:

# Construct a Rand5 function
Rand5 <- function() sample(seq(5),1)
# And the golf
Rand7=function(r=Rand5())sample(1:(r/r+6),1)
# Or (same character count)
Rand7=function(r=Rand5())sample.int(r/r+6,1)
# Or even shorter(thanks to @Spacedman)
Rand7=function()sample(7)[Rand5()]

ขอบคุณการประเมินข้อโต้แย้งที่ขี้เกียจฉันกำจัดเครื่องหมายอัฒภาคและเครื่องหมายวงเล็บ

เอาท์พุทมากกว่า 10 ^ 6 ซ้ำ:

> test <- replicate(10^6,Rand7())
> table(test)
test
     1      2      3      4      5      6      7 
142987 142547 143133 142719 142897 142869 142848 

library(ggplot2)
qplot(test)

ฮิสโตแกรมของผลลัพธ์


2
หากคุณกำลังจะสิบแปดมงกุฎคุณอาจเป็นสิบแปดมงกุฎที่ดีที่สุดที่คุณสามารถเป็น:Rand7=function(){r=Rand5();sample(7)[r]}
Spacedman

หากคุณกำลังจะทำเช่นนั้นทำไมต้องกังวลกับที่เก็บข้อมูลระดับกลาง Rand7=function(){sample(7)[Rand5()]}
Brian Diggs

@BrianDiggs การพึ่งพาพา ธ ในการดำเนินการ .... :-)
Ari B. Friedman

3

สกาล่า, 47, 40 59 ตัวอักษร:

def rand7:Int={val r=5*(rand5-1)+rand5
if(r<8)r else rand7}

ด้วย 2 อินพุตจาก rand5:

\ 1 2 3 4 5 
1 1 2 3 4 5  
2 6 7 8 ..
3 11 ..
4 ..
5

ฉันคูณเลข 1 ตัวแรกด้วย 5 แล้วบวกอันที่สอง ผลลัพธ์ส่วนใหญ่จะถูกละเว้นและนำไปสู่การคำนวณใหม่ ผลลัพธ์ควรเป็นการกระจายค่าที่เท่ากันตั้งแต่ 1-25 ซึ่งฉันเลือก 7 อันแรกเท่านั้น ฉันยอมรับ 21 คนแรกด้วยการสร้างโมดูโล แต่สิ่งนี้จะนำไปสู่โค้ดที่ยาวขึ้น

รหัสทางประวัติศาสตร์ซึ่งล้มเหลว แต่ไม่ชัดเจนมาก ขอบคุณ Ilmari Karonen ที่ชี้ให้เห็น:

def rand7=(1 to 7).map(_=>rand5).sum%7+1

ขอบคุณ Yoshiteru Takeshita สำหรับวิธี scala-2.8.0 ซึ่งทำให้ 'sum' ง่ายมาก วิธีแก้ปัญหาของฉันก่อนหน้า:

def rand7=((0/:(1 to 7))((a,_)=>a+rand5-1))%7+1

rand5:

val rnd = util.Random 
def rand5 = rnd.nextInt (5) + 1


ผู้ใช้Yoshiteru Takeshitaเสนอให้ลด 40 ตัวอักษรสำหรับ Scala 2.8.0 หรือใหม่กว่าเป็นdef rand7=(1 to 7).map(_=>rand5).sum%7+1
Peter Taylor

การแก้ปัญหานี้ยังไม่ถูกต้องเห็นความคิดเห็นที่จะตอบ glowcoder ของ
Ilmari Karonen

@IlmariKaronen: ถูกต้อง - ฉันทำใหม่โซลูชันของฉัน
ผู้ใช้ที่ไม่รู้จัก

3

C ++

int Rand4()
{
    int r = Rand5();
    return r > 4 ? Rand4() : r;
}

inline int Rand8()
{    
    return (Rand4() - 1) << 2 + Rand4();
}

int Rand7()
{
    int r = Rand8();
    return r > 7 ? Rand7() : r;
}

C ++ (109)

แข็งแรงเล่นกอล์ฟ

int Rand4(){int r=Rand5();return r>4?Rand4():r;}int Rand7(){int r=Rand4()-1<<2+Rand4();return r>7?Rand7():r;}

ฉันไม่คิดว่าคุณจะเรียกมันว่า "หนึ่งซับ" เพราะเซมิโคลอนกำหนดบรรทัดของรหัสใน C ++
Peter Olson

@ ปีเตอร์โอ้มันไม่ต้องใช้ liners อีกต่อไปแล้ว
Mateen Ulhaq

มันส่งคืนตัวเลขตั้งแต่ 1 ถึง 8
jimmy23013

2

แปลเป็น Javascript จากคำตอบที่โพสต์โดย Dan McGrath

function Rand7(){x=8;while(x>7)x=rand5()+5*rand5()-5;return x}

62 ตัวอักษร


1
function Rand7(){for(x=8;x>7;x=rand5()+5*rand5()-5);return x}สั้นไปหน่อย: P
JiminP

2

JavaScript, 85

function Rand7(){for(x=0,i=1;i<8;x^=i*((k=Rand5())%2),i*=1+(k<5));return x?x:Rand7()}

ฉันรู้ว่ามีคำตอบที่สั้นกว่า แต่ฉันต้องการแสดงการทดสอบของปริศนานี้ ปรากฎว่ามีเพียงคำตอบของไคลด์โลโบที่ใช้การสุ่มตัวอย่างการปฏิเสธของแดน McGrath เท่านั้นที่ถูกต้อง (ระหว่างคำตอบของ JS)


2

С ++

int Rand7()
{
    int r = Rand5();
    int n = 5;
    do {
        r = (r - 1) * 5 + Rand5();
        int m = n * 5 / 7 * 7;
        if (r <= m) {
            return r % 7 + 1;
        }
        r -= m;
        n = n * 5 - m;
    } while (1);
}

การกระจายตัวเลข (จำนวนเต็ม 1000000):

142935 142751 142652 143299 142969 142691 142703

จำนวนการโทรหา Rand5 โดยเฉลี่ยต่อจำนวนเต็มที่สร้างขึ้นทั้งหมดคือประมาณ 2.2 (2 ถึง 10+)

1 2      3      4     5    6   7 8  9 10
0 840180 112222 44433 2212 886 0 60 6 1

2

ใน Java (หรือ C / C ++ ฉันคิดว่า)

  • ใช้สูตรการสร้างโดย Alexandru ด้วยตัวอักษร 65 ตัว:

    int rand7(){int x=rand5()*5+rand5()-6;return x>20?rand7():x/3+1;}
    
  • ใช้สูตรการสร้างโดย Dan McGrath ความยาว 60 ตัวอักษร

    int rand7(){int x=rand5()+5*rand5()-5;return x>7?rand7():x;}
    


1

Python 56 56ตัวอักษร

โซลูชันอื่นที่อาจผิดใน Python:

rand7 = lambda: sum(rand5() for i in range(7)) % 7 + 1

ดูเหมือนจะง่ายเกินไป แต่เมื่อฉันลอง:

counter = [0] * 7
for i in range(100000):
     counter[rand7()] += 1

ฉันได้รับการแจกแจงที่สมเหตุสมผล (ระหว่าง 14,000 ถึง 14,500)

โอเคตอนนี้มีคนโหวตให้กับโพสต์นี้: วิธีนี้ถูกต้องจริงหรือ ฉันโพสต์สิ่งนี้มากขึ้นที่นี่เพื่อให้ผู้คนวิจารณ์มัน ดีถ้ามันถูกต้องเวอร์ชัน golfed ของฉันจะเป็น:

rand7=lambda:eval("+rand5()"*7)%7+1

ซึ่งออกมาเป็น 37 ตัวอักษร


วิธีการแก้ปัญหาของคุณไม่ถูกต้อง: คุณยึดการตัดสินใจของคุณในการทอยลูกเต๋าแบบ 5 ด้าน 7 ชิ้นซึ่งหมายความว่าจะมีผลลัพธ์ที่น่าสังเวช 5 ^ 7 (5 ถึงพลังอันดับ 7) เนื่องจากนี่ไม่ใช่ผลคูณของ 7 คุณจึงไม่สามารถส่งคืนผลลัพธ์ที่น่าพอใจ 7 รายการ ฉันไม่คิดว่าจะมีสูตรง่าย ๆ สำหรับสิ่งที่คุณกลับมา คุณสามารถบังคับการคำนวณหรือทำมันออกมาด้วยมือในจำนวนที่น้อยกว่า (พลิก 3 เหรียญ (H = 1, T = 2) และรวมผลลัพธ์)
Gilles 'หยุดความชั่วร้าย'

1
ว้าวการแจกแจงที่คุณสร้างแม้ว่าจะไม่เหมือนกันนั้นใกล้เคียงกันอย่างน่าทึ่ง: สัดส่วนที่แน่นอนของความน่าจะเป็นของแต่ละหมายเลขคือ {1: 11177, 2: 11172, 3: 11158, 4: 11144, 5: 11144, 6: 11158 7: 11172}
โอมาร์


1

Python 70 ตัวอักษร

def rand7():
 while True:
  n=5*(rand5()-1)+(rand5()-1)
  if n<21:return n%7+1

แต่ขึ้นอยู่ที่ถูกต้องสมบูรณ์ในเหตุผลที่อยู่ที่นี่


1

Perl, 43 ตัวอักษร, การสุ่มตัวอย่างการปฏิเสธซ้ำ

sub rand7{1while($_=5*&rand5-rand5)>6;$_+1}

สิ่งนี้ให้คำเตือนเกี่ยวกับAmbiguous use of -rand5 resolved as -&rand5()แต่ทำงานได้อย่างถูกต้อง การ&เตรียมการrand5โทรสายที่สองจะแก้ไขด้วยค่าใช้จ่ายเท่ากับหนึ่งสโตรก (ตรงกันข้าม&สามารถลบอื่น ๆได้ rand5ได้หากถูกกำหนดด้วย()ต้นแบบ)

ps รุ่น 46-char ต่อไปนี้เร็วขึ้นสามเท่า:

sub rand7{1while($_=5*&rand5-rand5)>20;$_%7+1}

1

Java - 66 ตัวอักษร

int rand7(){int s;while((s=rand5()*5+rand5())<10);return(s%7+1);}

ยาวกว่าชุดคำสั่งก่อนหน้า แต่ฉันคิดว่าอันนี้คืนค่าตัวเลขที่กระจายอย่างสม่ำเสมอในเวลาที่น้อยลง


1

PostScript (46)

นี่ใช้การเข้ารหัสโทเค็นไบนารีดังนั้นนี่คือ hexdump:

00000000  2f 72 61 6e 64 37 7b 38  7b 92 38 37 92 61 7b 92  |/rand7{8{.87.a{.|
00000010  40 7d 69 66 92 75 32 7b  72 61 6e 64 35 7d 92 83  |@}if.u2{rand5}..|
00000020  35 92 6c 92 01 35 92 a9  7d 92 65 7d 92 33        |5.l..5..}.e}.3|
0000002e

หากต้องการลองใช้คุณสามารถดาวน์โหลดได้ดาวน์โหลดได้

นี่คือรหัสที่ไม่ได้บรรจุและแสดงความคิดเห็นพร้อมกับรหัสทดสอบ

% This is the actual rand7 procedure.
/rand7{
  8{                      % potentialResult
    % only if the random number is less than or equal to 7, we're done
    dup 7 le{             % result
      exit                % result
    }if                   % potentialResult
    pop                   % -/-
    2{rand5}repeat        % randomNumber1 randomNumber2
    5 mul add 5 sub       % randomNumber1 + 5*randomNumber2 - 5 = potentialResult
  }loop
}def

%Now, some testing code.

% For testing, we use the built-in rand operator; 
% Doesn't really give a 100% even distribution as it returns numbers
% from 0 to 2^31-1, which is of course not divisible by 5.
/rand5 {
  rand 5 mod 1 add
}def

% For testing, we initialize a dict that counts the number of times any number
% has been returned. Of course, we start the count at 0 for every number.
<<1 1 7{0}for>>begin

% Now we're calling the function quite a number of times 
% and increment the counters accordingly.
1000000 {
  rand7 dup load 1 add def
}repeat

% Print the results
currentdict{
  2 array astore ==
}forall

-1
int result = 0;

for (int i = 0; i++; i<7)
    if (((rand(5) + rand(5)) % 2) //check if odd
        result += 1;

return result + 1;

2
สิ่งนี้จะไม่ให้การกระจายแบบสม่ำเสมอ ดูการกระจายตัวของแรนด์ (5) + แรนด์ (5) มากกว่า 10,000 รอบซ้ำเพื่อดูว่าทำไม
gnibbler

ผลลัพธ์สามารถเป็นตัวเลขใดก็ได้ตั้งแต่ 1 ถึง 8 ในรหัสของคุณ ...
Omar

อีกอย่างที่ gnibbler กล่าวว่าการกระจายตัวไม่สม่ำเสมอ: (rand (5) + rand (5))% 2 จะเอนเอียงไปทาง 0 มันสร้าง 0 13 ครั้งต่อทุก ๆ 12 ครั้งมันสร้าง 1; เช่นความน่าจะเป็นเป็นสัดส่วนกับ {0: 13, 1: 12} ด้วยสัญกรณ์นั้นความไม่สมดุลของการทำงานของคุณจะเป็นสัดส่วนกับ {1: 62748517, 2: 405451956, 3: 1122790032, 4: 1727369280, 5: 1594494720, 6: 883104768, 7: 271724544, 8: 35831808} ตัวเลขขนาดใหญ่) หรือแก้ไขการวนซ้ำให้ทำงาน 6 ครั้ง {1: 4826809, 2: 26733096, 3: 61691760, 4: 75928320, 5: 52565760, 6: 19408896, 7: 2985984}
โอมาร์

-1

R (30 ตัวอักษร)

กำหนด rand7:

rand7=function(n)sample(7,n,T)

เนื่องจาก R เขียนขึ้นโดยมีการวิเคราะห์ทางสถิติอยู่ในใจงานนี้จึงเป็นเรื่องเล็กน้อยและฉันใช้ฟังก์ชั่นในตัวsampleพร้อมเปลี่ยนชุดเป็น TRUE

ตัวอย่างผลลัพธ์:

> rand7(20)
 [1] 4 3 6 1 2 4 3 2 3 2 5 1 4 6 4 2 4 6 6 1
> rand7(20)
 [1] 1 2 5 2 6 4 6 1 7 1 1 3 7 6 4 7 4 2 1 2
> rand7(20)
 [1] 6 7 1 3 3 1 5 4 3 4 2 1 5 4 4 4 7 7 1 5

1
มันบอกว่าคุณต้องใช้ Rand5 ไม่ได้พูดว่าอย่างไร แต่คุณต้องใช้ ...
Spacedman

@ Spacerman ใช่ฉันไม่สนใจมันอย่างชัดเจน นั่นคือการใช้งานโดยไม่อ้างอิง
Andrie

-1

Groovy

rand7={if(b==null)b=rand5();(b=(rand5()+b)%7+1)}

การกระจายตัวอย่างมากกว่า 35,000 ซ้ำ:

[1:5030, 2:4909, 3:5017, 4:4942, 5:5118, 6:4956, 7:5028]

มันไม่ดีใช่หรือไม่?



-1

แล้วเรื่องนี้ล่ะ

int Rand7()
{
    return Rand5()+ Rand5()/2;
}

ไม่ว่าภาษานั้นจะเป็นอะไร/ตัวดำเนินการของมันจะทำเลขจำนวนเต็มหรือไม่ จะเกิดอะไรขึ้นกับผลลัพธ์ของคุณหากเป็นเลขทศนิยมทศนิยมหรือเลขจำนวนเต็ม
kojiro

[2/25, 4/25, 5/25, 5/25, 5/25, 3/25, 1/25]สมมติว่าแบ่งจำนวนเต็มฟังก์ชั่นนี้มีการกระจายต่อไปนี้: ไม่เหมือนกันหมด
primo

พรีโม่ถูกต้อง การเพิ่มตัวเลขสุ่มโดยทั่วไปแล้วจะเป็นการเบี่ยงเบนความน่าจะเป็นไปที่ค่ากลาง
gnibbler

-1

Java - 54

int m=0;int rand7(){return(m=m*5&-1>>>1|rand5())%7+1;}

การทดสอบการกระจาย: [1000915, 999689, 999169, 998227, 1001653, 1000419, 999928]

ขั้นตอนวิธีการ:

  • เก็บตัวแปรทั่วโลก
  • ทวีคูณด้วย 5 ดังนั้นมี 5 สถานที่ฟรีที่จุดสิ้นสุดที่สำคัญที่สุด
  • ตัดบิตของเครื่องหมายเพื่อให้เป็นค่าบวก (ไม่จำเป็นหากสนับสนุนหมายเลขที่ไม่ได้ลงชื่อ)
  • Modulo 7 คือคำตอบ

> ตัวเลขจะไม่ถูกไม่เกี่ยวข้องกันอีกต่อไป แต่เป็นการสุ่มอย่างสมบูรณ์แบบเป็นรายบุคคล


-1

ทับทิม (43 ไบต์)

def rand7;(0..7).reduce{|i|i+rand5}%7+1;end

โซลูชันของ cemper93 ที่พอร์ตไปยัง Ruby สั้นกว่าสามไบต์;) (34 ไบต์)

def rand7;eval("+rand5"*7)%7+1;end

-3

รหัส C / C ++ รหัสหลักมีเพียงหนึ่งบรรทัดเท่านั้น!

static unsigned int gi = 0;

int rand7()
{
    return (((rand() % 5 + 1) + (gi++ % 7)) % 7) + 1;
}

//call this seed before rand7
//maybe it's not best seed, if yo have any good idea tell me please
//and thanks JiminP again, he remind me to do this
void srand7()
{
    int i, n = time(0);
    for (i = 0; i < n % 7; i++)
        rand7();
}

srand7 () เป็นเมล็ดพันธุ์ของ rand7 ต้องเรียกใช้ฟังก์ชันนี้ก่อน rand7 เช่นเดียวกับการเรียก srand ก่อน rand ใน C

นี่เป็นสิ่งที่ดีมากเพราะมันเรียกแรนด์ () เพียงครั้งเดียวเท่านั้นและไม่มีสิ่งใดวนซ้ำไม่มีความทรงจำเพิ่มเติม

ให้ฉันอธิบาย: พิจารณาอาร์เรย์จำนวนเต็มด้วยขนาด 5:

1st get one number from 1 2 3 4 5 by rand5
2nd get one number from 2 3 4 5 6
3rd get one number from 3 4 5 6 7
4th get one number from 4 5 6 7 1
5th get one number from 5 6 7 1 2
5th get one number from 6 7 1 2 3
7th get one number from 7 1 2 3 4

ดังนั้นเราจึงได้รับตารางแต่ละคนใน 1-7 ปรากฏ 5 ครั้งในนั้นและมีทั้งหมด 35 หมายเลขดังนั้นความน่าจะเป็นของแต่ละหมายเลขคือ 5/35 = 1/7 และครั้งต่อไป

8th get one number from 1 2 3 4 5
9th get one number from 2 3 4 5 6
......

หลังจากเวลาพอเราจะได้การแจกแจงแบบสม่ำเสมอ 1-7

ดังนั้นเราสามารถจัดสรรอาเรย์เพื่อเรียกคืนห้าองค์ประกอบของ 1-7 โดย loop-left-shift และรับหนึ่งหมายเลขจากอาเรย์ในแต่ละครั้งด้วย rand5 แต่เราสามารถสร้างทั้งเจ็ดอาร์เรย์มาก่อนและใช้มันเป็นวงกลม รหัสนั้นง่ายและมีรหัสย่อจำนวนมากที่สามารถทำได้

แต่เราสามารถใช้คุณสมบัติของการดำเนินการ% ได้ดังนั้นตาราง 1-7 แถวจึงเทียบเท่ากับ (rand5 + i)% 7 นั่นคือ: a = rand ()% 5 + 1 คือ rand5 ในภาษา C, b = gi ++ % 7 สร้างการเรียงสับเปลี่ยนทั้งหมดในตารางด้านบนและ 0 - 6 แทนที่ 1 - 7 c = (a + b)% 7 + 1, สร้าง 1 - 7 อย่างสม่ำเสมอ สุดท้ายเราได้รับรหัสนี้:

(((rand() % 5 + 1) + (gi++ % 7)) % 7) + 1 

แต่เราไม่สามารถรับ 6 และ 7 ได้ในการโทรครั้งแรกดังนั้นเราจึงต้องการเมล็ดพันธุ์เช่น srand สำหรับ rand ใน C / C ++ เพื่อจัดระเบียบการเรียงสับเปลี่ยนสำหรับการโทรอย่างเป็นทางการครั้งแรก

นี่คือรหัสการทดสอบเต็มรูปแบบ:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

static unsigned int gi = 0;

//a = rand() % 5 + 1 is rand5 in C language,
//b = gi++ % 7 generates all permutations,
//c = (a + b) % 7 + 1, generates 1 - 7 uniformly.
//Dont forget call srand7 before rand7
int rand7()
{
   return (((rand() % 5 + 1) + (gi++ % 7)) % 7) + 1;
}

//call this seed before rand7
//maybe it's not best seed, if yo have any good idea tell me please
//and thanks JiminP again, he remind me to do this
void srand7()
{
    int i, n = time(0);
    for (i = 0; i < n % 7; i++)
        rand7();
}

void main(void)
{
    unsigned int result[10] = {0};
    int k;

    srand((unsigned int)time(0)); //initialize the seed for rand
    srand7() //initialize the rand7

    for (k = 0; k < 100000; k++)
        result[rand7() - 1]++;

    for (k = 0; k < 7; k++)
        printf("%d : %.05f\n", k + 1, (float)result[k]/100000);
}

มัน 'ผ่าน' การทดสอบ 'แต่ไม่ได้หมายความว่านี่เป็นฟังก์ชั่นสุ่มที่ดี ฉันจะรับ6หรือ7โทรถึงครั้งเดียวได้หรือไม่
JiminP

แต่มีชนิดที่ดีและชนิดของการประมาณที่ไม่ดี และรหัสนี้ไม่ดี - เพราะมันไม่ให้การกระจายแบบสม่ำเสมอเมื่อถูกเรียกเพียงครั้งเดียว ถ้าใครเขียนอะไรทำนองint main(){if(rand7()==6) printf("Hello, world!");}นั้นการประมาณโดยใช้ลูปจะพิมพ์ 'Hello, world!' 1 ใน 7 ครั้ง แต่รหัสของคุณไม่ได้
JiminP

ขอบคุณ @JiminP! คุณถูกที่ 6,7 ครั้งแรก ฉันต้องการเมล็ดพันธุ์ที่จะทำให้เสียโฉมก่อนที่จะโทร rand7 เมล็ดเช่นเดียวกับ srand ใน C / C ++ ฉันแก้ไขรหัสของฉันและขอขอบคุณอีกครั้ง !!!
ฌอน

อืม .... srand10 ไม่ทำงานตัวเลข 3 ตัวสุดท้ายไม่สามารถรับตำแหน่งที่ 10, 20, 30 ... ขออภัย @JiminP แต่จะแก้ไขอย่างไร ฉันคิดว่านี่เป็นวิธีที่มีความหวัง
ฌอน

2
การเรียกฟังก์ชั่นนี้ไม่เหมือนกัน ข้อมูลจำเพาะที่นี่ไม่จำเป็นต้องใช้สิ่งนี้ แต่โดยทั่วไปแล้วจะเป็นตัวสร้างตัวเลขแบบสุ่ม มิฉะนั้นคุณอาจจะบอกว่ากลับมาเป็นจำนวนเครื่องแบบสุ่มครั้งแรกและในอนาคตเรียกเพียงผลตอบแทน (ก่อนหน้า + 1) 7% ...
โอมาร์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.