Quine สุ่ม


15

เขียนโปรแกรมที่สามารถสร้างตัวเองแบบสุ่ม

ต้องทำสิ่งนี้ตามโทเค็นที่ใช้ในซอร์สโค้ด หากซอร์สโค้ดของโปรแกรมของคุณประกอบด้วยโทเค็นที่ไม่ซ้ำกัน 50 อันและมีความยาว 60 โทเค็นจากนั้นโปรแกรมควรจะส่งออก 60 โทเค็นที่โทเค็นแต่ละอันสุ่มเลือกจากหนึ่งใน 50 โทเค็นที่ไม่ซ้ำกัน

ตัวอย่างเช่นโปรแกรมนี้จะมีโอกาสหนึ่งใน 50 ^ 60 ที่จะทำซ้ำตัวเอง

โทเค็นคืออะไร ขึ้นอยู่กับภาษา ตัวอย่างเช่นตัวระบุ ( foo_bar) คำหลัก ( while) และตัวเลข ( 42) จะนับเป็นโทเค็นในภาษาส่วนใหญ่ ช่องว่างจะไม่นับในภาษาส่วนใหญ่

กฎเพิ่มเติม:

  • ผลลัพธ์อาจมีโทเค็นที่พบในซอร์สโค้ดโปรแกรมเท่านั้นคั่นด้วยตัวคั่นที่เหมาะสม
  • เอาต์พุตจะต้องมีความยาวเท่ากับซอร์สโค้ดของโปรแกรมซึ่งนับด้วยโทเค็น
  • อาจใช้ภาษาการเขียนโปรแกรมเดียวเท่านั้น
  • ซอร์สโค้ดต้องมีโทเค็นที่ไม่ซ้ำกันอย่างน้อย 3 ตัว
  • ไม่รวมความคิดเห็นจากซอร์สโค้ด
  • โปรแกรมควรมีโอกาสหนึ่งใน U ^ L ที่จะทำซ้ำตัวเอง

การให้คะแนน:โปรแกรมที่มีโอกาสดีที่สุดในการทำซ้ำตัวเองชนะ


@MathieuRodic: คุณกำลังสมมติว่าโปรแกรมดึงโทเค็นโดยไม่ต้องทำซ้ำ
user2357112 รองรับ Monica

@MathieuRodic: ให้ฉันใช้ถ้อยคำใหม่ คุณสมมติว่าโปรแกรมสุ่มสัญญาณหลายชุดของโทเค็นแทนที่จะวาดโทเค็น L ด้วยการทำซ้ำจากชุดของโทเค็น U ที่ใช้ในแหล่งที่มา
user2357112 รองรับ Monica

@ user2357112: ฉันเข้าใจ ความผิดพลาดของฉันคือการพิจารณาปัญหานี้ว่าเป็นการจับโดยไม่ต้องเปลี่ยน
Mathieu Rodic

1
กฎ # 1 และ # 5 ดูเหมือนจะขัดแย้งกับฉัน
Cruncher

4
คุณสามารถสันนิษฐานได้ว่าฟังก์ชั่นการสุ่มในตัวเป็น TRNGs หรือไม่ การใช้งานทั่วไปมีเมล็ดขนาดเล็กเกินไปที่จะสร้างผลผลิตทั้งหมดและอาจไม่สามารถสร้างใหม่ได้
CodesInChaos

คำตอบ:


11

Python 2, 3 ^ -3 = 0.037

execการละเมิดค่อนข้างมีประโยชน์ในการลดจำนวนโทเค็น อัปเดตตอนนี้เพื่ออ่านไฟล์ต้นฉบับไม่ได้!

exec '' """
s = '''{a}
s = {b}
s = s.format(a='"'*3, b="'"*3+s+"'"*3)
import random
tokens = ['exec', "''", s]
print random.choice(tokens), random.choice(tokens), random.choice(tokens),
{a}'''
s = s.format(a='"'*3, b="'"*3+s+"'"*3)
import random
tokens = ['exec', "''", s]
print random.choice(tokens), random.choice(tokens), random.choice(tokens),
"""

ความพิเศษ''ระหว่างexecและสตริงที่ยกมาสามยักษ์คือเพียงการนับจำนวน token ขั้นต่ำที่ต้องการ 3 มันจะได้รับการรวมเข้ากับสายที่สองเนื่องจากการเรียงตัวอักษรตามนัยสตริง

ต้นฉบับเวอร์ชันการเปิดไฟล์ต้นฉบับ:

exec '''
# String literals are one token!
import random
import tokenize

with open(__file__) as f:
    tokens = [x[1] for x in tokenize.generate_tokens(f.readline)][:-1]

''' '''
# Splitting the string into two strings pads the token count to the minimum of 3.

print random.choice(tokens), random.choice(tokens), random.choice(tokens),
'''

พูดอย่างเคร่งครัดไวยากรณ์ของ Python จะวางโทเค็น ENDMARKER ไว้ท้ายไฟล์ต้นฉบับและเราไม่สามารถสร้างไฟล์ต้นฉบับที่มี ENDMARKERs สุ่มเกลื่อนกลาดได้ เราแกล้งทำเป็นว่ามันไม่มีอยู่จริง


@ Cruncher นั่นคือความน่าจะเป็น 3 ^ -3 == 1/3 ^ 3
Austin Henley

2
+1 สำหรับแฮ็กกฎที่ยอดเยี่ยม ความคิดเดียวกันการดำเนินการใน ".]';(?3 3 3){]`".;~({:,],{:,],6#{:)'';(?3 3 3){]`".;~({:,],{:,],6#{:)'''''''J:
algorithmshark

5

Javascript, 102 โทเค็น, 33 ที่ไม่ซ้ำกัน, 7.73 × 10 -154

หมายเหตุนี่เป็นควินจริง มันไม่ได้อ่านไฟล์หรือใช้งานevalหรือFunction.toString

meta = "meta = ; out = '' ; tokens = meta . split ( '\\u0020' ) ; tokens . push ( '\"' + meta + '\"' ) ; length = tokens . length ; tmp = length ; unique = { } ; while ( tmp -- ) unique [ tokens [ tmp ] ] = unique ; unique = Object . keys ( unique ) ; tmp = unique . length ; while ( length -- ) out += tokens [ ~~ ( Math . random ( ) * tmp ) ] + '\\u0020' ; console . log ( out )"; 
out = '';
tokens = meta.split('\u0020');
tokens.push('"' + meta + '"');
//console.log(tokens);
length = tokens.length;
tmp = length;
unique = { };
while(tmp--) unique[tokens[tmp]] = unique;
unique = Object.keys(unique);
//console.log(unique);
tmp = unique.length;
while(length--)
    out += unique[~~(Math.random() * tmp)] + '\u0020';
console.log(out)

4

Python: P (สร้างโปรแกรมในการทดลอง 1 ครั้ง) = 3.0317 * 10 ^ -123

34 โทเค็นที่ไม่ซ้ำกัน 80 รวมโทเค็น โปรดทราบว่ามีช่องว่างที่ท้ายของแต่ละบรรทัด

import tokenize , random 
tokens = [ x [ 1 ] for x in tokenize . generate_tokens ( open ( __file__ , 'r' ) . readline ) ] [ : -1 ] 
s = '' 
for x in tokens : s += random . choice ( list ( set ( tokens ) ) ) ; s += [ ' ' , '' ] [ s [ -1 ] == '\n' ] 
print s 

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

' ' random len set 'r' , for ( list , import ] ] tokens : random [ for '\n' import readline readline 'r' tokens [ len 'r' import '' choice '' '' for in ( readline ( = open readline , list 1 list s += for s 1 , '' : 1 += list len - __file__ ; open __file__ print . - ] 'r' for import [ print . , 

; . [ [ print print __file__ generate_tokens ] ; open ] , readline 

ขอบคุณโซลูชัน Python อื่น ๆ โดย user2357112 ที่เตือนให้ฉันทิ้งโทเค็นสุดท้ายและใช้__file__สิ่งที่ฉันไม่เคยรู้มาก่อน


3

J - 1 ใน 11 17 = 1.978 x 10 -18

;(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)';(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)'''

J มีเครื่องมือเล็ก ๆ น้อย ๆ ที่มีประโยชน์สำหรับการทำงานประเภทนี้

  • แรกของทุกพื้นที่ใดแยกสตริงของตัวเลขเป็นหนึ่งโทเค็น มันหมายถึงอาร์เรย์หนึ่งมิติของตัวเลขเหล่านั้น นี่คือวิธี lexer ของ J ทำงาน โดยวิธีการที่สิบเจ็ด11ถ้าใครอยากรู้อยากเห็น

  • (,,,{:,{:)'QUINE'''เป็นเคล็ดลับ quine ทั่วไปใน J ทำให้ใช้โทเค็นน้อยที่สุดเท่าที่จะทำได้: {:หมายถึงTailดังนั้นจึงผนวกสตริงเข้ากับตัวเองแล้วเพิ่มสองสำเนาของอักขระตัวสุดท้ายไปยังจุดสิ้นสุด ตั้งแต่ตัวอักษรตัวสุดท้ายคือคำพูดเดียว (J ใช้สตริง Pascal สไตล์) QUINE'QUINE'''ผลที่ได้คือ

  • ;:เป็น tokenizer และแยกสตริงอินพุตราวกับว่าเป็นรหัส J ส่งคืนรายการกล่อง ความยาวของผลลัพธ์นี้คือ 17

  • ~.ใช้องค์ประกอบที่ไม่ซ้ำกันทั้งหมดของอาร์เรย์นี้ ความยาวของผลลัพธ์นี้คือ 11

  • ?เรียกว่าม้วน สำหรับแต่ละจำนวนเต็มในอาร์กิวเมนต์มันเลือกจำนวนบวกแบบสุ่มที่มากกว่าหรือเท่ากับศูนย์น้อยกว่าจำนวนนั้น ดังนั้นที่นี่ J จะสร้างตัวเลข 17 จาก 0 ถึง 10 รวม

  • { ใช้ดัชนีสุ่มเพื่อเลือกรายการจากรายการโทเค็นเฉพาะในกล่องของเรา

  • ; เปิดช่องเหล่านี้ทั้งหมดและเรียกใช้ผลลัพธ์ร่วมกัน

ตัวอย่างบางส่วนปฏิบัติตาม บรรทัดที่เยื้องคือพรอมต์อินพุตและบรรทัดที่ล้างด้วยด้านซ้ายเป็นเอาต์พุตของล่าม

   ;(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)';(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)'''
~.~.(?;;:11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11';(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)'''(){11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){(;:;
   ;(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)';(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)'''
{';(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)''',?{:;:{:';(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)'''11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11{:{;(;:{:,~.

2

ป.ล.

นี่เป็นเรื่องสนุก

/cvx /cvx cvx /exec /exec cvx /dup /rand /mod /get /== /array /astore /realtime
/srand /repeat 6 17 54 17 /array cvx exec /astore cvx exec 54 /dup cvx /rand
cvx 17 /mod cvx /get cvx /== cvx 6 /array cvx exec /astore cvx exec cvx /realtime
cvx exec /srand cvx exec /repeat cvx exec

มีโทเค็นที่ไม่ซ้ำกัน 17 อันและโทเค็น 54 รวมสำหรับโอกาส 1 ใน 3.6e-67


2

ช่องว่าง3 ^ -205 3 ^ -189 3 ^ -181 3 ^ -132 ~ = 10 ^ -63

นี่เป็นโปรแกรมช่องว่างที่เมื่อมีการสุ่มตัวอักษรมีโอกาส 1 ใน 3 ^ 132 ในการทำซ้ำตัวเอง (โทเค็นที่แตกต่างกัน 3 ครั้ง, ซ้ำ 132 ครั้ง) มันจะต้องมีเมล็ดอย่างน้อย 132 ตัวอักษรแบบสุ่มเมื่อทำงาน (ช่องว่างไม่มีฟังก์ชั่นการสุ่มหรือวันที่ในการเพาะด้วย) เช่นsome_whitespace_interpreter my_quine.ws <some_random_source >quine_output.wsเช่น คะแนนจะได้รับการปรับปรุงหากโปรแกรมสามารถเล่นกอล์ฟได้มากกว่านี้ แต่นี่เป็นโปรแกรม Whitespace "ของจริง" ตัวแรกของฉันดังนั้นฉันจะทิ้งมันไว้กับจำนวนกอล์ฟที่น้อยลง

รหัสพื้นที่ว่างเปล่าหรือเห็นมันเรียกใช้ : (หากต้องการลองคลิก "แก้ไข" คัดลอกเนื้อหาภายในแท็ก <pre> ควรเป็นอักขระ 132 ตัวพร้อม EOL สไตล์ Unix)

    

























โค้ดที่มีคำอธิบายประกอบกับคำสั่ง what คืออะไร (ไม่ใช่ทางเทคนิค quine เนื่องจากมันจะไม่ทำซ้ำความคิดเห็น):

stack push_number + 0 end
stack push_number + 1 0 0 1 สิ้นสุด
heap store stack push_number + 1 end
stack push_number + 1 0 0 0 0 0 สิ้นสุด
heap store stack push_number + 1 0 จบ
stack push_number + 1 0 1 0 สิ้นสุด
heap store stack push_number + 1 0 0 0 0 0 1 1 สิ้นสุด
ไหล
make_label loop_begin  
stack push_number + 1 1 end
IO  
อ่านสแต็กอักขระ push_number + 1 1 end
heap ดึงสแต็ก push_number + 1 1 ปลาย
heap การคำนวณทางคณิตศาสตร์ modulo heap เรียก IO  
พิมพ์ char stack push_number + 1 end
ลบสแต็กเลขคณิตซ้ำกัน
 ไหล
jump_if_zero end_prog
ไหล
jump_to 
loop_begin  
ไหล
make_label end_prog
ไหล
end_program

หากเมล็ดพันธุ์นั้นมีค่าเทียบเท่า (ตัวละครจะถูกดัดแปลง mod 3 เพื่อถูกแปลงเป็นโทเค็น) เป็นสิ่งนี้มันจะประสบความสำเร็จ:

CCCCACCCBCCBABBCCCCBACCCBCCCCCABBCCCCBCACCCBCBCABBCCCCBCCCCCBBAACCBACCCBBABABCCCCBBABBBCCCBBABCBBBBBBACCCCCBABCCBCACABBAACABAACCAAAA

มันเป็นโปรแกรมที่ค่อนข้างง่ายซึ่งเทียบเท่ากับโปรแกรม Ruby นี้:

i = 131
while true
    print '\t \n'[STDIN.getc.ord % 3]
    i = i - 1
    break if i < 0
end

1

Perl, 27 โทเค็น, P = 1.4779 x 10 -34

@ARGV=$0;print$W[rand@W]for@W=split/(\W)/,readline

แก้ไขล่าสุด: ใช้@ARGV=$0แทนopen*ARGV,$0การบันทึกโทเค็น

  • 15 โทเค็นที่ไม่ซ้ำกัน
  • 4 ราชสกุลปรากฏ 2 ครั้ง ( =, /, @, $)
  • 1 โทเค็นปรากฏขึ้น 4 ครั้ง ( W)

ดังนั้นฉันคิดว่านั่นทำให้ความน่าจะเป็น (pow (2,2 * 4) * pow (4,4)) / pow (27,27) ประมาณ 1.48E-34

หากซอร์สโค้ดอยู่ในไฟล์ชื่อARGVคุณสามารถใช้โทเค็นโซลูชัน 26 รายการด้วย P = ~ 2.193 x 10 -31 :

@ARGV=ARGV;print$ARGV[rand@ARGV]for@ARGV=split/(\W)/,readline

ที่จริงแล้วP = (4 * 2! + 4!) / 27!มีค่าประมาณ 1.7632684538487448 x 10 ^ -26
Mathieu Rodic

0

เพิร์ล 6 ,1 ใน 33 = 0.037037 ...

(ฉันรู้ว่านี่ไม่ใช่โค้ดกอล์ฟ แต่ ... )

q[say |roll <<~~"q[$_]".EVAL>>: 3]~~.EVAL

ลองออนไลน์!

เหมือนกับคำตอบของ Python โดยที่โทเค็นแรกเป็นตัวอักษรสตริงที่ถูกประเมิน โทเค็นคือ

q[say |roll <<~~"q[$_]".EVAL>>: 3]   String literal
~~                                   Smartmatch operator
.EVAL                                Function call

คำอธิบาย:

q[say |roll <<~~"q[$_]".EVAL>>: 3]         # Push as string literal
                                  ~~       # Smartmatch by setting $_ to the string literal
                                    .EVAL  # Eval the string
            <<~~"q[$_]".EVAL>>             # From the list of tokens
       roll                   : 3          # Pick 3 times with replacement
  say |                                    # Join and print
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.