ความน่าจะเป็นที่ไม่ได้วาดคำจากถุงตัวอักษรใน Scrabble


27

สมมติว่าคุณมีถุงที่มีกระเบื้องแต่ละคนมีตัวอักษรบนมัน มีมีตัวอักษร 'A',พร้อมด้วย 'B' และอื่น ๆ และ 'ไวด์การ์ด' (เรามี ) สมมติว่าคุณมีพจนานุกรมที่มีจำนวนคำ จำกัด คุณเลือกไพ่จากกระเป๋าโดยไม่มีการเปลี่ยน คุณจะคำนวณ (หรือประมาณ) ความน่าจะเป็นที่คุณสามารถจัดรูปแบบศูนย์คำจากพจนานุกรมที่ให้การเรียงตัวnnAnBn* * * *n=nA+nB+...+nZ+n* * * *kk

สำหรับผู้ที่ไม่คุ้นเคยกับ Scrabble (TM) สามารถใช้อักขระตัวแทนเพื่อจับคู่กับตัวอักษรใดก็ได้ ดังนั้นคำว่า [ BOOT ] จึงสามารถ 'สะกด' ด้วย 'B', '*', 'O', 'T'

เพื่อให้เข้าใจถึงระดับของปัญหามีขนาดเล็กเช่น 7,ประมาณ 100 และพจนานุกรมมีขนาดประมาณ 100,000 คำที่มีขนาดหรือเล็กกว่าknk

แก้ไข:โดย 'ในรูปแบบคำว่า' ผมหมายถึงคำที่มีความยาวไม่มากขึ้นกว่าkดังนั้นถ้าคำ [ A ] อยู่ในพจนานุกรมจากนั้นโดยการวาดแม้แต่หนึ่ง 'A' จากถุงหนึ่งมี 'เกิดคำ' ปัญหาของไวลด์การ์ดจะลดความซับซ้อนลงอย่างมากหากสามารถสันนิษฐานได้ว่ามีความยาว 1 ในพจนานุกรม สำหรับหากมีการจับสัญลักษณ์ไวด์การ์ดใด ๆ สามารถจับคู่ความยาว 1 คำได้โดยอัตโนมัติดังนั้นจึงสามารถมีสมาธิกับกรณีที่ไม่มีไวด์การ์ด ดังนั้นรูปแบบที่ลื่นมากขึ้นของปัญหาจึงไม่มีคำ 1 ตัวอักษรในพจนานุกรมk

นอกจากนี้ฉันควรระบุอย่างชัดเจนว่าลำดับที่ตัวอักษรถูกดึงออกมาจากถุงไม่มีความสำคัญ เราไม่จำเป็นต้องวาดตัวอักษรตามลำดับ 'ถูกต้อง' ของคำ


มันควรจะเป็น 'เลือกกระเบื้อง k โดยไม่มีการเปลี่ยน' หรือไม่? คำถามที่น่าสนใจมาก

อุ่ย แน่นอนมันควร
shabbychef

เท่าที่ผมจำได้ว่าข่วนไม่อนุญาตให้มีตัวอักษรคำหนึ่งดังนั้นอย่างน้อยส่วนหนึ่งของปัญหาที่แก้ไขได้;)
นิโก้

1
@ จุดที่ดีของนิโก้ แต่ฉันคิดว่านี่เป็นเพียงช่วงกลางเกม 1 ตัวอักษรคำไม่จำเป็นต้องเล่นด้วยตัวอักษรหนึ่งตัวหรือจะอนุญาตให้หนึ่งตัวอักษรที่ใดก็ได้บนกระดานทั้งที่ยอมรับไม่ได้อย่างชัดเจน อย่างไรก็ตามฉันคิดถึงการเปิดงาน ในความเป็นจริงคำถามสามารถถูกกล่าวอย่างรัดกุมสำหรับผู้ที่คุ้นเคยกับ Scrabble ในขณะที่ "สิ่งที่เป็นไปได้ที่ผู้เล่นคนแรกจะต้องผ่านคืออะไร"
shabbychef

@nico ขอบคุณสำหรับการชี้แจง ในทางทฤษฎีปัญหาที่คล้ายกันเกี่ยวข้องในพจนานุกรมที่มีการรวมกันสองตัวอักษรที่เป็นไปได้ทั้งหมดเป็นคำ: เมื่อเป็นกรณีนี้มือใด ๆ ของ 2 ตัวอักษรหรือมากกว่านั้นมีคำโดยอัตโนมัติ ความคิดเห็นของ @ shabbychef เกี่ยวกับเกมกลางแสดงให้เห็นว่าคำถามเดิมนั้นไม่เกี่ยวข้องกับ Scrabble ส่วนใหญ่เพราะในเกมกลางคุณมีอาร์เรย์ของส่วนคำ (คำนำหน้าคำต่อท้ายและส่วนกลาง) นอกเหนือจาก 7 ตัวอักษรในของคุณ มือ. สิ่งนี้จะเพิ่มโอกาสในการสร้างคำศัพท์อย่างมาก
whuber

คำตอบ:


14

นี่คือความคิดเห็น (ยาว!) ในการทำงานที่ดี @vqv ได้โพสต์ในหัวข้อนี้ มันมีจุดมุ่งหมายเพื่อให้ได้คำตอบที่ชัดเจน เขาทำงานอย่างหนักเพื่อลดความซับซ้อนของพจนานุกรม สิ่งที่เหลืออยู่ก็คือการใช้ประโยชน์อย่างเต็มที่ ผลของเขาชี้ให้เห็นว่าการแก้ปัญหาแรงเดรัจฉานเป็นไปได้ ที่สุดรวมทั้งไวด์การ์ดด้วยกันมากที่สุดมีคำที่สามารถสร้างด้วย 7 ตัวอักษรและดูเหมือนว่าน้อยกว่า 1/10000 ของพวกเขา - พูดประมาณล้าน - จะไม่รวมบางส่วนที่ถูกต้อง คำ. 277=10,460,353,203

ขั้นตอนแรกคือการเพิ่มพจนานุกรมน้อยที่สุดด้วยอักขระตัวแทน "," 22 ตัวอักษรปรากฏในคำสองตัวอักษร (ทั้งหมดยกเว้น c, q, v, z) รวมไวด์การ์ดเข้ากับตัวอักษรเหล่านั้น 22 ตัวและเพิ่มเข้าไปในพจนานุกรม: {a ?, b ?, d ?, ... , y?} ได้เข้ามาแล้วในทำนองเดียวกันเราสามารถตรวจสอบคำสามตัวอักษรน้อยที่สุดทำให้เกิดคำเพิ่มเติมบางคำ เพื่อปรากฏในพจนานุกรม สุดท้ายเราเพิ่ม "??" ไปที่พจนานุกรม หลังจากลบการทำซ้ำที่เป็นผลลัพธ์จะมีคำน้อยที่สุด 342 คำ

วิธีที่สง่างามเพื่อดำเนินการต่อ - หนึ่งที่ใช้เป็นจำนวนเงินที่น้อยมากของการเข้ารหัสแน่นอน - คือการดูปัญหานี้เป็นพีชคณิตหนึ่ง คำที่ถือว่าเป็นชุดตัวอักษรที่ไม่มีการเรียงลำดับเป็นเพียงชื่อเดียว ยกตัวอย่างเช่น "ทะเลาะวิวาท" คือ monomialตัน ดังนั้นพจนานุกรมจึงเป็นชุดสะสมของ monomials ดูเหมือนว่าaps2t

{a2,ab,ad,...,ozψ,wxψ,ψ2}

(เพื่อหลีกเลี่ยงความสับสนฉันได้เขียนสำหรับอักขระไวด์การ์ด)ψ

ชั้นวางมีคำที่ถูกต้องถ้าหากคำนั้นแบ่งชั้นวางเท่านั้น

นามธรรมที่ทรงพลังกว่า แต่มีพลังอย่างมากในการพูดแบบนี้ก็คือพจนานุกรมสร้างอุดมคติของในพหุนามแหวนและชั้นวางที่ใช้ได้ คำกลายเป็นศูนย์ในแหวนหารความฉลาดในขณะที่ชั้นวางไม่มีคำที่ถูกต้องยังคงไม่ใช่ศูนย์ในความฉลาด หากเราสร้างผลรวมของชั้นวางทั้งหมดในและคำนวณในวงแหวนผลหารนี้จำนวนของชั้นวางที่ไม่มีคำเท่ากับจำนวนของชื่อย่อที่แตกต่างกันในความฉลาดR = Z [ a , b , , z , ψ ] R / I RIR=Z[a,b,,z,ψ]R/IR

นอกจากนี้ผลรวมของชั้นวางทั้งหมดในตรงไปตรงมาเพื่อแสดง ให้เป็นผลรวมของตัวอักษรทั้งหมดในตัวอักษร มีหนึ่ง monomial สำหรับแต่ละชั้นวาง (ในฐานะโบนัสที่เพิ่มเข้ามาสัมประสิทธิ์ของมันจะนับจำนวนวิธีที่แต่ละชั้นสามารถสร้างขึ้นได้ทำให้เราสามารถคำนวณความน่าจะเป็นของมันได้หากต้องการ)α = + B + + Z + ψ α 7Rα=a+++Z+ψα7

เป็นตัวอย่างง่ายๆ (เพื่อดูวิธีการทำงาน) สมมติว่า (a) เราไม่ใช้สัญลักษณ์แทนและ (b) ตัวอักษรทั้งหมดจาก "a" ถึง "x" ถือเป็นคำ ดังนั้นชั้นวางเท่านั้นที่เป็นไปได้ซึ่งคำไม่สามารถสร้างได้จะต้องประกอบด้วย y's และ z ทั้งหมด เราคำนวณ modulo อุดมคติที่สร้างขึ้นโดยทีละขั้นตอนดังนั้น: { a , b , c , , x }α=(a++++x+Y+Z)7{a,,,...,x}

α0=1α1=a++++x+Y+ZY+Zพอควรผมα2(Y+Z)(a+++Y+Z)(Y+Z)2พอควรผมα7(Y+Z)6(a+++Y+Z)(Y+Z)7พอควรผม.

เราสามารถอ่านโอกาสที่จะได้แร็คที่ไม่ใช่คำจากคำตอบสุดท้าย : สัมประสิทธิ์แต่ละตัวนับวิธีที่ชั้นวางที่เกี่ยวข้องสามารถวาดได้ ตัวอย่างเช่นมีวิธี 21 (จาก 26 ^ 7 ที่เป็นไปได้) ในการวาด 2 y และ 5 z's เพราะสัมประสิทธิ์เท่ากับ 21y 2 z 5Y7+7Y6Z+21Y5Z2+35Y4Z3+35Y3Z4+21Y2Z5+7YZ6+Z7Y2Z5

จากการคำนวณเบื้องต้นมันชัดเจนว่านี่คือคำตอบที่ถูกต้อง ประเด็นทั้งหมดคือกระบวนการนี้ทำงานโดยไม่คำนึงถึงเนื้อหาของพจนานุกรม

โปรดสังเกตว่าการลดพลังงานโมดูล่าแบบอุดมคติในแต่ละขั้นตอนจะช่วยลดการคำนวณได้อย่างไร: นั่นเป็นวิธีลัดที่เปิดเผยโดยวิธีนี้ (สิ้นสุดตัวอย่าง)

ระบบพีชคณิตพหุนามดำเนินการคำนวณเหล่านี้ ตัวอย่างเช่นนี่คือรหัสMathematica :

alphabet =  a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + 
            p + q + r + s + t + u + v + w + x + y + z + \[Psi];
dictionary = {a^2, a b, a d, a e, ..., w z \[Psi], \[Psi]^2};
next[pp_] := PolynomialMod[pp alphabet, dictionary];
nonwords = Nest[next, 1, 7];
Length[nonwords]

(พจนานุกรมสามารถสร้างได้อย่างตรงไปตรงมาจาก min.dict ของ @ vqv; ฉันใส่บรรทัดที่นี่เพื่อแสดงว่าสั้นพอที่จะระบุโดยตรงหากคุณต้องการ)

ผลลัพธ์ - ซึ่งใช้เวลาในการคำนวณสิบนาที - คือ 577958 ( NBในข้อความก่อนหน้านี้ฉันทำผิดเล็กน้อยในการเตรียมพจนานุกรมและได้รับ 577940 ฉันได้แก้ไขข้อความเพื่อสะท้อนสิ่งที่ฉันหวังตอนนี้ ผลลัพธ์ที่ถูกต้อง!) น้อยกว่าหนึ่งล้านหรือน้อยกว่าที่ฉันคาดไว้ แต่มีขนาดเท่ากัน

ในการคำนวณโอกาสในการได้รับชั้นวางดังกล่าวเราจำเป็นต้องคำนึงถึงจำนวนวิธีที่สามารถดึงชั้นวางได้ ขณะที่เราเห็นในตัวอย่างนี้เท่ากับค่าสัมประสิทธิ์ใน 7 โอกาสของการวาดภาพบางชั้นดังกล่าวเป็นผลรวมของค่าสัมประสิทธิ์เหล่านี้พบได้ง่ายโดยการตั้งค่าตัวอักษรทั้งหมดเท่ากับ 1:α7

nonwords /. (# -> 1) & /@ (List @@ alphabet)

คำตอบเท่ากับ 1066056120 ให้โอกาส 10.1914% ของการวาดชั้นซึ่งไม่มีคำที่ถูกต้องสามารถเกิดขึ้นได้ (ถ้าตัวอักษรทั้งหมดมีโอกาสเท่ากัน)

เมื่อความน่าจะเป็นของตัวอักษรแตกต่างกันเพียงแทนที่ตัวอักษรแต่ละตัวด้วยโอกาสที่จะถูกดึง:

tiles = {9, 2, 2, 4, 12, 2, 3, 2, 9, 1, 1, 4, 2, 6, 8, 2, 1, 6, 4, 6, 
         4, 2, 2, 1, 2, 1, 2};
chances = tiles / (Plus @@ tiles);
nonwords /. (Transpose[{List @@ alphabet, chances}] /. {a_, b_} -> a -> b)

ผลลัพธ์คือ1.079877553303% ซึ่งเป็นคำตอบที่แน่นอน (แม้ว่าจะใช้โมเดลโดยประมาณ, การวาดภาพพร้อมการแทนที่) เมื่อมองย้อนกลับไปมันต้องใช้สี่บรรทัดในการป้อนข้อมูล (ตัวอักษรพจนานุกรมและความถี่ของตัวอักษร) และมีเพียงสามบรรทัดเท่านั้นที่จะทำงาน: อธิบายวิธีการใช้พลังต่อไปของ moduloใช้พลังงานอันดับที่ 7 ซ้ำและทดแทน ความน่าจะเป็นสำหรับตัวอักษรIαผม


+1 ติดกับศัพท์และจากนั้นย่อเล็กสุดใหม่เป็นความคิดที่ฉลาด พีชคณิตอยู่เหนือฉัน แต่รู้สึกว่าคุณกำลังคำนวณความน่าจะเป็นแบบหลายส่วนแทนที่จะเป็นไฮเพอร์เมตริก ดังนั้นความน่าจะเป็นสำหรับการสุ่มตัวอย่างด้วยการแทนที่ ฉันคิดว่าอธิบายว่าทำไมคำตอบของคุณที่ 1.08% นั้นใหญ่กว่าที่ฉันคาดการณ์ไว้ถึง 0.4% มีวิธีแก้ไขแนวทางของคุณในการจัดการกับการสุ่มตัวอย่างโดยไม่ต้องเปลี่ยนหรือไม่
vqv

2
@vqv ใช่ ตอนนี้เรามีรายการของราวครึ่งล้านหรือมากกว่านั้นโดยไม่มีคำพูดใด ๆ มันตรงไปตรงมา (โดยการเปลี่ยนรหัสสองบรรทัดสุดท้าย) เพื่อคำนวณโอกาสของแต่ละชั้น (โดยไม่ต้องแทนที่) และรับผล hypergeometric คำตอบที่แน่นอนเท่ากับ 349870667877/80678106432000 = 0.43366% ด้วยการทดลอง N = 100K SE ของคุณคือ 0.021% ดังนั้นคำตอบของคุณควรอยู่ระหว่าง 0.38% และ 0.49% (สองด้าน 99% CI) ฉันดีใจที่คำตอบของเราเห็นด้วย!
whuber

@whuber คุณสามารถเรียกใช้การคำนวณโดยใช้การกระจายไทล์ Words With Friends (WWF) ได้หรือไม่? ประมาณการของฉันที่ 0.4% ขึ้นอยู่กับการกระจายคำศัพท์ WWF และการแจกแจงแบบ WWF ฉันคิดว่าคุณกำลังใช้การกระจายไทล์ Scrabble กับคำศัพท์ WWF
vqv

อุ่ย คำตอบที่แท้จริงคือ 349870675899 (ฉันปิด 8022 เนื่องจากข้อผิดพลาดในพจนานุกรมของฉัน) สิ่งนี้ทำให้ไม่มีความแตกต่างในทางปฏิบัติโชคดี
whuber

@ vqv ฉันไม่คุ้นเคยกับการกระจายไทล์ต่างๆ ฉันคัดลอกของฉันโดยตรงจากรหัสของคุณ (และฉันใช้พจนานุกรมของคุณ) :-) หากคุณหมายถึงการแจกจ่ายที่osxreality.com/2010/01/01/…แล้วฉันจะได้รับ1.15444% (พร้อมการทดแทน), 0.43366% (โดยไม่ต้องเปลี่ยนใหม่) หมายเลขที่สองจริง ๆ แล้วแตกต่างจากความถี่ Scrabble ที่ตัวเลขนัยสำคัญที่ 8
whuber

14

มันยากมากที่จะวาดชั้นวางที่ไม่มีคำที่ถูกต้องใน Scrabble และตัวแปร ด้านล่างนี้เป็นโปรแกรม R ที่ฉันเขียนเพื่อประมาณความน่าจะเป็นที่แร็ค 7 กระเบื้องเริ่มต้นไม่มีคำที่ถูกต้อง มันใช้วิธีมอนเต้คาร์โลและพจนานุกรมคำศัพท์ With With Friends (ฉันไม่พบพจนานุกรมศัพท์อย่างเป็นทางการในรูปแบบที่ง่าย) การทดลองแต่ละครั้งประกอบด้วยการวาดชั้นวาง 7 แผ่นจากนั้นตรวจสอบว่าชั้นวางมีคำที่ถูกต้องหรือไม่

คำน้อยที่สุด

คุณไม่ต้องสแกนทั้งพจนานุกรมเพื่อตรวจสอบว่าชั้นวางมีคำที่ถูกต้องหรือไม่ คุณเพียงแค่ต้องสแกนพจนานุกรมน้อยที่สุดประกอบด้วย คำน้อยที่สุด คำมีค่าน้อยที่สุดหากไม่มีคำอื่น ๆ ในฐานะส่วนย่อย ตัวอย่างเช่น 'em' เป็นคำย่อ 'ว่างเปล่า' ไม่ได้ จุดนี้คือว่าถ้าชั้นมีคำว่าxแล้วก็ยังต้องประกอบด้วยชุดย่อยของx กล่าวอีกนัยหนึ่ง: แร็คไม่มีคำใด ๆ ถ้ามันไม่มีคำน้อยที่สุด โชคดีที่คำศัพท์ส่วนใหญ่ในพจนานุกรมมีไม่น้อยจึงสามารถกำจัดได้ นอกจากนี้คุณยังสามารถรวมคำที่เทียบเท่าการเรียงสับเปลี่ยน ฉันสามารถลดคำศัพท์ Words With Friends จาก 172,820 เป็น 201 คำน้อยที่สุด

สามารถใช้สัญลักษณ์แทนได้อย่างง่ายดายโดยการจัดการชั้นวางและคำเป็นการกระจายตัวอักษร เราตรวจสอบว่าชั้นวางมีคำหรือไม่โดยการลบหนึ่งการกระจายจากที่อื่น นี่ทำให้เรามีจำนวนตัวอักษรแต่ละตัวที่หายไปจากชั้นวาง หากผลรวมของจำนวนเหล่านั้นคือจำนวนอักขระตัวแทนดังนั้นคำนั้นจะอยู่ในชั้นวาง

ปัญหาเดียวกับวิธี monte carlo คือเหตุการณ์ที่เราสนใจนั้นหายากมาก ดังนั้นจึงควรใช้การทดลองจำนวนมากหลายครั้งเพื่อรับการประเมินโดยมีข้อผิดพลาดมาตรฐานน้อยพอ ฉันวิ่งโปรแกรมของฉัน (วางที่ด้านล่าง) กับ ทดลองและเตรียมพร้อมน่าจะประมาณ 0.004 ว่าแร็คเริ่มต้นไม่ได้มีคำที่ถูกต้อง ข้อผิดพลาดมาตรฐานโดยประมาณของการประมาณนั้นคือ 0.0002 ใช้เวลาสองสามนาทีในการเรียกใช้บน Mac Pro ของฉันรวมถึงการดาวน์โหลดพจนานุกรมยังไม่มีข้อความ=100,000

ฉันสนใจที่จะดูว่ามีใครสามารถสร้างอัลกอริทึมที่มีประสิทธิภาพที่แน่นอนได้หรือไม่ วิธีการที่ไร้เดียงสาที่อิงกับการรวมการแยกดูเหมือนว่าอาจเกี่ยวข้องกับการระเบิดแบบ combinatorial

รวมยกเว้น

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

ความน่าจะเป็นที่เราต้องการคำนวณคือ เหตุการณ์ภายในความน่าจะเป็นทางด้านขวาคือการรวมกันของเหตุการณ์: ที่เป็นพจนานุกรมน้อยที่สุด เราสามารถขยายได้โดยใช้สูตรการรวมการยกเว้น มันเกี่ยวข้องกับการพิจารณาจุดตัดที่เป็นไปได้ทั้งหมดของเหตุการณ์ข้างต้น Letแสดงชุดพลังของคือชุดของส่วนย่อยที่เป็นไปได้ทั้งหมดของMแล้วก็

P(k-tile rack ไม่มีคำ)=1-P(k-tile rack มีคำศัพท์).
P(k-tile rack มีคำศัพท์)=P(xM{k-tile แร็คมี x}),
MP(M)MM
P(k-tile rack contains a word)=P(xM{k-tile rack contains x})=j=1|M|(1)j1SP(M):|S|=jP(xS{k-tile rack contains x})

สิ่งสุดท้ายที่ระบุคือวิธีการคำนวณความน่าจะเป็นในบรรทัดสุดท้ายด้านบน มันเกี่ยวข้องกับ hypergeometric หลายมิติ เป็นเหตุการณ์ที่ชั้นมีคำในทุกSนี่เป็นความเจ็บปวดที่ต้องจัดการเพราะสัญลักษณ์แทน เราจะต้องพิจารณาตามเงื่อนไขแต่ละกรณีดังต่อไปนี้: ชั้นวางไม่มีสัญลักษณ์แทนชั้นวางมี 1 สัญลักษณ์แทนชั้นวางมีอักขระตัวแทน 2 ชุด ...

xS{k-tile rack contains x}
S

จากนั้น

P(xS{k-tile แร็คมี x})=ΣW=0n* * * *P(xS{k-tile แร็คมี x}|k-tile แร็คมี W สัญลักษณ์)×P(k-tile แร็คมี W สัญลักษณ์).

ฉันจะหยุดที่นี่เพราะการขยายตัวนั้นคดเคี้ยวที่จะเขียนออกมาและไม่ได้ตรัสรู้เลย การเขียนโปรแกรมคอมพิวเตอร์ทำได้ง่ายกว่า แต่ถึงตอนนี้คุณควรเห็นว่าวิธีการรวมการคัดออกนั้นเป็นสิ่งที่รักษาไม่ได้ มันเกี่ยวข้องกับเงื่อนไขซึ่งแต่ละข้อก็มีความซับซ้อนเช่นกัน สำหรับผมพจนานุกรมการพิจารณาข้างต้น{60}2|M|2|M|3.2×1060

สแกนชั้นวางที่เป็นไปได้ทั้งหมด

ฉันคิดว่ามันง่ายกว่าการคำนวณเพราะมีชั้นวางที่เป็นไปได้น้อยกว่าชุดย่อยของคำที่น้อยที่สุด เราลดชุดเป็นไปได้อย่างต่อเนื่องk-tile racks จนกว่าเราจะได้ชุดของ racks ซึ่งไม่มีคำใด ๆ สำหรับ Scrabble (หรือ Words With Friends) จำนวนชั้นวางไพ่ 7 ใบที่เป็นไปได้นั้นอยู่ในจำนวนหมื่นล้านแผ่น การนับจำนวนของคำที่ไม่ประกอบด้วยคำที่เป็นไปได้ควรจะสามารถทำได้ด้วยโค้ด R สองสามบรรทัด แต่ฉันคิดว่าคุณควรจะทำได้ดีกว่าเพียงแค่ระบุชั้นวางที่เป็นไปได้ทั้งหมด ตัวอย่างเช่น 'aa' เป็นคำย่อ ๆ ที่จะกำจัดชั้นวางทั้งหมดที่มีมากกว่า 'a' ทันที คุณสามารถพูดซ้ำด้วยคำอื่น ๆ หน่วยความจำไม่ควรเป็นปัญหาสำหรับคอมพิวเตอร์ที่ทันสมัย ชั้น Scrabble แบบ 7 แผ่นต้องใช้พื้นที่จัดเก็บน้อยกว่า 7 ไบต์ ที่แย่ที่สุดเราจะใช้สักสองสามกิกะไบต์เพื่อเก็บแร็คที่เป็นไปได้ทั้งหมด แต่ฉันไม่คิดว่าเป็นความคิดที่ดี บางคนอาจต้องการคิดเพิ่มเติมเกี่ยวกับเรื่องนี้

โปรแกรม Monte Carlo R

# 
#  scrabble.R
#  
#  Created by Vincent Vu on 2011-01-07.
#  Copyright 2011 Vincent Vu. All rights reserved.
# 

# The Words With Friends lexicon
# http://code.google.com/p/dotnetperls-controls/downloads/detail?name=enable1.txt&can=2&q=
url <- 'http://dotnetperls-controls.googlecode.com/files/enable1.txt'
lexicon <- scan(url, what=character())

# Words With Friends
letters <- c(unlist(strsplit('abcdefghijklmnopqrstuvwxyz', NULL)), '?')
tiles <- c(9, 2, 2, 5, 13, 2, 3, 4, 8, 1, 1, 4, 2, 5, 8, 2, 1, 6, 5, 7, 4, 
           2, 2, 1, 2, 1, 2)
names(tiles) <- letters

# Scrabble
# tiles <- c(9, 2, 2, 4, 12, 2, 3, 2, 9, 1, 1, 4, 2, 6, 8, 2, 1, 6, 4, 6, 4, 
#            2, 2, 1, 2, 1, 2)


# Reduce to permutation equivalent words
sort.letters.in.words <- function(x) {
  sapply(lapply(strsplit(x, NULL), sort), paste, collapse='')
}

min.dict <- unique(sort.letters.in.words(lexicon))
min.dict.length <- nchar(min.dict)

# Find all minimal words of length k by elimination
# This is held constant across iterations:
#   All words in min.dict contain no other words of length k or smaller
k <- 1
while(k < max(min.dict.length))
{
  # List all k-letter words in min.dict
  k.letter.words <- min.dict[min.dict.length == k]

  # Find words in min.dict of length > k that contain a k-letter word
  for(w in k.letter.words)
  {
    # Create a regexp pattern
    makepattern <- function(x) {
      paste('.*', paste(unlist(strsplit(x, NULL)), '.*', sep='', collapse=''), 
            sep='')
    }
    p <- paste('.*', 
               paste(unlist(strsplit(w, NULL)), 
                     '.*', sep='', collapse=''), 
               sep='')

    # Eliminate words of length > k that are not minimal
    eliminate <- grepl(p, min.dict) & min.dict.length > k
    min.dict <- min.dict[!eliminate]
    min.dict.length <- min.dict.length[!eliminate]
  }
  k <- k + 1
}

# Converts a word into a letter distribution
letter.dist <- function(w, l=letters) {
  d <- lapply(strsplit(w, NULL), factor, levels=l)
  names(d) <- w
  d <- lapply(d, table)
  return(d)
}

# Sample N racks of k tiles
N <- 1e5
k <- 7
rack <- replicate(N,
                  paste(sample(names(tiles), size=k, prob=tiles), 
                        collapse=''))

contains.word <- function(rack.dist, lex.dist)
{
  # For each word in the lexicon, subtract the rack distribution from the 
  # letter distribution of the word.  Positive results correspond to the 
  # number of each letter that the rack is missing.
  y <- sweep(lex.dist, 1, rack.dist)

  # If the total number of missing letters is smaller than the number of 
  # wildcards in the rack, then the rack contains that word
  any(colSums(pmax(y,0)) <= rack.dist[names(rack.dist) == '?'])
}

# Convert rack and min.dict into letter distributions
min.dict.dist <- letter.dist(min.dict)
min.dict.dist <- do.call(cbind, min.dict.dist)
rack.dist <- letter.dist(rack, l=letters)

# Determine if each rack contains a valid word
x <- sapply(rack.dist, contains.word, lex.dist=min.dict.dist)

message("Estimate (and SE) of probability of no words based on ", 
        N, " trials:")
message(signif(1-mean(x)), " (", signif(sd(x) / sqrt(N)), ")")

ว้าว ... การติดตามดีมาก
Matt Parker

ฉันค่อนข้างแปลกใจที่ลดลงเหลือ 201 คำ แม้ว่าสำหรับคำแรกที่เล่นกฎของบ้านเรายอมรับ 'I' และ 'A' เป็นคำซึ่งอาจจะลดจำนวนคำที่น้อยที่สุด ผมหวังที่จะเห็นใครบางคนหน้าอกออกการวิเคราะห์รวมยกเว้นซึ่งควรจะมีขนสวย ...
shabbychef

@shabbychef ไม่มีคำ 1 ตัวอักษรในพจนานุกรม คำที่น้อยที่สุดส่วนใหญ่คือคำที่ 2 และ 3 ตัวอักษร นี่คือการแจกแจงเต็มของความยาวคำน้อยที่สุด: 2: 73, 3:86, 4:31, 5: 9, 6: 2 คำ 6 ตัวอักษรคือ: GLYCYL และ SYZYGY
vqv

@shabbychef ฉันได้อัปเดตคำตอบของฉันเพื่อรวมร่างของวิธีการรวมการยกเว้นที่แน่นอน มันเลวร้ายยิ่งกว่าขนดก
vqv

การทำงานที่ดี! ฉันรักที่คำถามนี้ซึ่งอาจถูกวางเป็นประโยคเดียว (สำหรับผู้ที่มีพื้นฐานเพียงพอ) ได้นำ monte carlo, การรวมการแยก, DAG, การค้นหาต้นไม้, พีชคณิตพหุนามและการจำลองของคุณได้รับการยืนยันโดยทฤษฎีของ @ whuber ไชโย!
shabbychef

7

Srikant ถูกต้อง: การศึกษา Monte Carlo เป็นวิธีที่จะไป มีสองเหตุผล ประการแรกคำตอบขึ้นอยู่อย่างยิ่งกับโครงสร้างของพจนานุกรม สองขั้วคือ (1) พจนานุกรมมีคำเดียวที่เป็นไปได้ทั้งหมด ในกรณีนี้โอกาสที่จะไม่สร้างคำโดยใช้ตัวอักษรหรือมากกว่านั้นเป็นศูนย์ (2) พจนานุกรมมีเพียงคำที่ประกอบด้วยตัวอักษรเดียว ( เช่น "a", "aa", "aaa" ฯลฯ ) โอกาสในการไม่สร้างคำด้วยตัวอักษรจะถูกกำหนดได้ง่ายและเห็นได้ชัดว่าไม่ใช่ศูนย์ คำตอบแบบปิดแน่นอนใด ๆ จะต้องรวมโครงสร้างพจนานุกรมทั้งหมดและจะเป็นสูตรที่น่ากลัวและยาวอย่างแท้จริง1k

เหตุผลที่สองคือ MC นั้นเป็นไปได้จริง: คุณต้องทำมันให้ถูกต้อง ย่อหน้าก่อนหน้าให้เบาะแส: อย่าเพิ่งสร้างคำที่สุ่มและค้นหา แทนวิเคราะห์พจนานุกรมแรกและใช้ประโยชน์จากโครงสร้างของมัน

วิธีหนึ่งแทนคำในพจนานุกรมเป็นต้นไม้ ต้นไม้ถูกฝังที่สัญลักษณ์และกิ่งที่ว่างเปล่าบนตัวอักษรแต่ละตัวลงไปจนสุด ใบของมันเป็นคำพูดของตัวเอง อย่างไรก็ตามเราสามารถแทรกการเรียงสับเปลี่ยนที่ไม่น่าสนใจของทุกคำลงในต้นไม้ได้เช่นกัน (มากถึงของคำเหล่านั้นสำหรับแต่ละคำ) สิ่งนี้สามารถทำได้อย่างมีประสิทธิภาพเพราะไม่จำเป็นต้องเก็บเงินเรียงสับเปลี่ยนทั้งหมด ต้องเพิ่มเฉพาะขอบในทรี ใบยังคงเหมือนเดิม ในความเป็นจริงนี้สามารถทำให้ง่ายขึ้นโดยยืนยันว่าต้นไม้ที่จะปฏิบัติตามลำดับตัวอักษรk!-1

กล่าวอีกนัยหนึ่งเมื่อต้องการตรวจสอบว่าชุดอักขระตัวอยู่ในพจนานุกรมหรือไม่อันดับแรกให้จัดเรียงองค์ประกอบตามลำดับที่เรียงลำดับkจากนั้นมองหาคำว่า "เรียง" นี้ในต้นไม้ที่สร้างขึ้นจากตัวแทนที่เรียงลำดับของคำในพจนานุกรมต้นฉบับ อันนี้จริงแล้วจะเล็กกว่าต้นไม้ดั้งเดิมเพราะมันรวมชุดคำทั้งหมดที่มีการเรียงลำดับที่เทียบเท่าเช่น {stop, post, pot, opts, spot} ในความเป็นจริงในพจนานุกรมภาษาอังกฤษของคำศัพท์นี้จะไม่สามารถเข้าถึงได้เพราะ "เพื่อ" จะได้พบก่อน เรามาดูกันว่าในทางปฏิบัติ ชุดมัลติเซตที่เรียงลำดับคือ "opst"; "o" จะแยกออกเป็นทุกคำที่มีเพียงตัวอักษร {o, p, ... , z}, "p" จะแตกสาขาเป็นคำทั้งหมดที่มีเพียง {o, p, ... , z} และมากที่สุด หนึ่ง "o" และในที่สุด "s" จะแตกแขนงออกเป็นใบไม้ "งั้น"! (ฉันสันนิษฐานว่าไม่มีผู้สมัครที่น่าเชื่อถือ "o", "op", "

จำเป็นต้องมีการดัดแปลงเพื่อจัดการสัญลักษณ์แทน: ฉันจะให้โปรแกรมเมอร์ประเภทที่คุณคิดเกี่ยวกับมัน มันจะไม่เพิ่มขนาดพจนานุกรม (ควรลดลงจริง) มันจะทำให้การเคลื่อนที่ของต้นไม้ช้าลงเล็กน้อย แต่ไม่มีการเปลี่ยนแปลงในทางพื้นฐานใด ๆ ในพจนานุกรมใด ๆ ที่มีคำตัวอักษรเดียวเช่นอังกฤษ ("a", "i") ไม่มีความยุ่งยาก: การมี wildcard หมายความว่าคุณสามารถสร้างคำได้! (นี่เป็นการบอกใบ้ว่าคำถามเดิมอาจไม่น่าสนใจเท่าที่ฟัง)

ผลที่สุดคือการค้นหาพจนานุกรมเดียวต้องการ (a) การเรียงลำดับ -letter multiset และ (b) ภายในไม่เกินขอบของต้นไม้ เวลาทำงานเป็น(k)) หากคุณชาญฉลาดสร้างมัลติสุ่มเรียงลำดับ (ที่ฉันสามารถคิดวิธีที่มีประสิทธิภาพหลายประการที่จะทำเช่นนี้) เวลาทำงานลด(k) คูณด้วยจำนวนการวนซ้ำเพื่อให้ได้เวลาการทำงานทั้งหมดkkO(kเข้าสู่ระบบ(k))O(k)

ฉันพนันได้เลยว่าคุณสามารถทำการศึกษานี้ด้วยชุด Scrabble ที่แท้จริงและการวนซ้ำนับล้านครั้งในไม่กี่วินาที


@whuber ต้นไม้เป็นความคิดที่เรียบร้อย (ขึ้นอยู่กับความคิดนั้น) แต่มันจะไม่ต้องใช้หน่วยความจำมากมาย? ฉันเดาว่ามันขึ้นอยู่กับความหลากหลายของพจนานุกรม แต่ฉันเดาว่าพจนานุกรมที่มีความหลากหลายพอสมควรจะต้องใช้ต้นไม้จำนวนมากตัวอย่างเช่นต้นไม้ 'b' จะเริ่มต้นด้วยตัวอักษร 'b' แทนที่จะเป็น 'a' สำหรับคำเหล่านั้นทั้งหมด มี 'a' ในพวกเขา ในทำนองเดียวกันต้นไม้ 'c' จะเริ่มต้นด้วยตัวอักษร 'c' สำหรับคำเหล่านั้นที่ไม่มี 'a' และ 'b' แต่มี 'c' วิธีการโดยตรงที่เสนอของฉันดูเหมือนง่ายกว่าเพราะต้องใช้การข้ามผ่านครั้งเดียวของคำทั้งหมดในพจนานุกรมใช่ไหม

1
@Srikant: ต้นไม้อาจต้องการ RAM น้อยกว่าการแคชพจนานุกรมทั้งหมดเพื่อเริ่มต้น คุณกังวลเกี่ยวกับ RAM สักสองสามเมกะไบต์ใช่ไหม? BTW มีต้นไม้เพียงต้นเดียวมีไม่มากต้นไม้ทั้งหมดถูกหยั่งรากด้วยคำที่ว่างเปล่า วิธีการของคุณตามที่ฉันเข้าใจนั้นต้องใช้การค้นหาหลายครั้งของพจนานุกรม (มากถึง 7! ของพวกเขา) ในการทำซ้ำทุกครั้งทำให้ไม่สามารถทำได้เมื่อกลัว @shabbychef มันจะช่วยถ้าคุณสามารถอธิบายเกี่ยวกับอัลกอริทึมที่คุณมีในใจที่คุณเขียน "ดูว่าคุณสามารถสร้างคำ": ที่ซ่อนรายละเอียดที่สำคัญมากมาย!
whuber

@whuber: ฉันตระหนักถึงความจริงที่ว่ามีเพียงต้นไม้เดียวหลังจากฉันโพสต์ความคิดเห็น Reg แนวทางของฉัน - ฉันยอมรับว่าข้อเสนอมอนเต้คาร์โลของฉันนั้นคลุมเครือและคำตอบของคุณจะบอกได้ว่าใครจะสามารถใช้มอนเต้คาร์โลได้ในการตั้งค่านี้ จริง ๆ แล้วฉันหมายถึงว่าวิธีการโดยตรง (ดูคำตอบของฉัน) อาจง่ายกว่าเนื่องจากวิธีการนั้นต้องการการดำเนินการครั้งเดียวในพจนานุกรมซึ่งแตกต่างจาก monte carlo ซึ่งต้องใช้การซ้ำหลายพันต้นบนต้นไม้ เพียงแค่สงสัยในข้อดีของวิธีการ

@Sriantant ฉันไม่แสดงความคิดเห็นกับวิธีการโดยตรงของคุณเพราะฉันสงสัยว่าจะได้รับคำตอบที่ผิด ดูเหมือนจะไม่ได้อธิบายโครงสร้างพจนานุกรม: นั่นคือความสัมพันธ์ย่อยของคำต่างๆ ตัวอย่างเช่นสูตรของคุณจะได้คำตอบที่ถูกต้องเป็นศูนย์สำหรับพจนานุกรมทั้งหมดที่มีคำเดียวที่เป็นไปได้ทั้งหมดหรือไม่
whuber

@ โฮ่อืมจุดที่ดี บางทีฉันอาจตอบคำถามผิด!

2

วิธีมอนติคาร์โล

kม.kม.W

1-ม.Wม.

วิธีการโดยตรง

Sเสื้อssTHsTHม.a,ม.,...,ม.ZsTHม.aยังไม่มีข้อความ

ยังไม่มีข้อความ=(nk)

และ

เสื้อs=(naม.a)(nม.)...(nZม.Z)

(รวมถึงผลกระทบของไทล์แทนการ์ดนั้นค่อนข้างยุ่งยากฉันจะเลื่อนออกไปเป็นปัญหาในตอนนี้)

ดังนั้นความน่าจะเป็นที่ต้องการคือ:

1-Σsเสื้อsยังไม่มีข้อความ

วิธีการที่รวดเร็วและสกปรกอาจไม่รวดเร็วนัก! พจนานุกรมอาจมี 100,000 คำและการค้นหาการจับคู่ของไทล์ที่ระบุอาจเป็นความหายนะการเขียนโปรแกรม
shabbychef

@shabbychef นี่คือสิ่งที่ทำได้ดีเพื่อให้เหมาะกับตัวตรวจสอบการสะกด ดูตัวอย่างn3labs.com/pdf/lexicon-squeeze.pdf

@shabbychef Reg monte-carlo- หากพจนานุกรมเรียงการแข่งขันควรจะค่อนข้างเร็วไม่? ไม่ว่าในกรณีใดวิธีการโดยตรงที่ฉันระบุไว้ก่อนหน้านี้มีข้อบกพร่อง ฉันซ่อมมัน. ปัญหาในการแก้ปัญหาก่อนหน้าของฉันคือคำเดียวกันสามารถเกิดขึ้นได้หลายวิธี (เช่น 'bat', 'b * t' ฯลฯ )

1
@ shabbychef เมื่อพิจารณาเพิ่มเติมฉันเห็นด้วยกับคุณว่าวิธี monte carlo จะไม่ทำงาน ปัญหาหนึ่งคือคุณต้องคิดออกว่าคำใดที่คุณสามารถสร้างด้วยกระเบื้อง k และคำที่สองคือคุณสามารถสร้างหลายคำด้วยไพ่ k การคำนวณชุดค่าผสมเหล่านี้จากไทล์ k อาจไม่ง่ายอย่างนั้น

1
@Srikant ขอบคุณ สูตรของคุณดูเหมือนจะสมมติว่าคุณต้องใช้ตัวอักษร k ทั้งหมดเพื่อสร้างคำ แต่ฉันไม่คิดว่านั่นคือสิ่งที่ OP ขอ (นั่นไม่ใช่วิธีที่เล่น Scrabble อยู่แล้ว) ด้วยข้อสันนิษฐานนั้นคุณกำลังติดตามถูกต้อง แต่คุณต้องแก้ไขอัลกอริทึม: คุณจะต้องไม่ทำการคำนวณซ้ำสำหรับคำในพจนานุกรมที่เรียงสับเปลี่ยนกัน ตัวอย่างเช่นคุณต้องไม่ลบทั้ง t_ {stop} และ t_ {post} ในสูตรของคุณ (นี่เป็นการแก้ไขที่ง่ายต่อการติดตั้ง)
whuber
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.