เขียน Moby Dick ประมาณ


297

นี่คือไฟล์ข้อความ ASCII 1.2Mbที่มีข้อความของMoby-Dickของ Herman Melville หรือปลาวาฬ งานของคุณคือการเขียนโปรแกรมหรือฟังก์ชั่น (หรือคลาส ฯลฯ - ดูด้านล่าง) ซึ่งจะให้ไฟล์นี้ทีละตัวอักษรและในแต่ละขั้นตอนจะต้องเดาตัวละครต่อไป

นี่คือรหัสที่ท้าทายคะแนนของคุณจะเป็น

2*L + E

โดยที่Lขนาดของการส่งของคุณเป็นไบต์และEเป็นจำนวนอักขระที่คาดเดาไม่ถูกต้อง คะแนนต่ำสุดชนะ

รายละเอียดเพิ่มเติม

การส่งของคุณจะเป็นโปรแกรมหรือฟังก์ชั่น (ฯลฯ ) ที่จะถูกเรียกหรือเรียกใช้หรือส่งข้อมูลหลายครั้ง (1215235 ครั้งเป็นที่แน่นอน.) เมื่อมีการเรียกร้องให้n วันเวลาที่มันจะได้รับn THตัวละครwhale.txtหรือwhale2.txtและจะต้องส่งออกคาดเดาสำหรับ ( 1 + n ) THตัวอักษร Eส่วนประกอบของคะแนนของมันจะเป็นจำนวนรวมของตัวละครว่ามันคาดเดาไม่ถูกต้อง

การส่งส่วนใหญ่จะต้องเก็บสถานะบางอย่างในระหว่างการร้องขอเพื่อให้พวกเขาสามารถติดตามจำนวนครั้งที่พวกเขาได้รับการเรียกและสิ่งที่อินพุตก่อนหน้านี้ คุณสามารถทำได้โดยการเขียนไปยังไฟล์ภายนอกโดยใช้staticหรือตัวแปรทั่วโลกโดยการส่งชั้นเรียนมากกว่าฟังก์ชั่นการใช้รัฐ monad หรือสิ่งอื่นที่ทำงานให้กับภาษาของคุณ การส่งของคุณจะต้องมีรหัสใด ๆ ที่จำเป็นในการเริ่มต้นสถานะของมันก่อนการขอร้องครั้งแรก

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

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

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

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

Lส่วนประกอบของคะแนนของคุณจะได้รับการคำนวณตามกฎปกติสำหรับความท้าทายรหัสกอล์ฟ หากการส่งของคุณจะมีหลายไฟล์โปรดทราบกฎในการให้คะแนนและโครงสร้างไดเรกทอรีในกรณีนั้น ข้อมูลใด ๆ ที่รหัสของคุณใช้จะต้องรวมอยู่ในLคะแนนของคุณ

คุณอาจนำเข้าห้องสมุดที่มีอยู่ แต่ไม่สามารถโหลดไฟล์ภายนอกอื่น ๆ และรหัสของคุณอาจไม่สามารถเข้าถึงwhale.txtหรือwhale2.txtไฟล์ในลักษณะอื่นใดนอกเหนือจากที่อธิบายไว้ข้างต้น คุณไม่สามารถโหลดเครือข่ายประสาทเทียมที่ผ่านการฝึกอบรมมาแล้วหรือแหล่งข้อมูลทางสถิติอื่น ๆ (มันดีที่จะใช้เครือข่ายประสาท แต่คุณต้องรวมข้อมูลน้ำหนักในการส่งของคุณและนับเป็นจำนวนไบต์) ถ้าด้วยเหตุผลบางอย่างภาษาหรือไลบรารีของคุณมีคุณสมบัติที่มีข้อความของ Moby Dick บางส่วนหรือทั้งหมด คุณไม่สามารถใช้คุณสมบัตินั้นได้ นอกเหนือจากนั้นคุณสามารถใช้คุณสมบัติในตัวหรือไลบรารีอื่น ๆ ที่คุณต้องการรวมถึงคุณลักษณะที่เกี่ยวข้องกับการประมวลผลข้อความการทำนายหรือการบีบอัดตราบใดที่คุณลักษณะเหล่านี้เป็นส่วนหนึ่งของภาษาหรือไลบรารีมาตรฐานของคุณ สำหรับกิจวัตรพิเศษที่แปลกใหม่ซึ่งรวมถึงแหล่งข้อมูลทางสถิติคุณต้องดำเนินการด้วยตนเองและรวมไว้ในจำนวนไบต์ของคุณ

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

ด้วยเหตุผลทางประวัติศาสตร์ไฟล์มีสองเวอร์ชันและคุณสามารถใช้ไฟล์ใดไฟล์หนึ่งในคำตอบ ในwhale2.txt(ลิงก์ด้านบน) ข้อความจะไม่ถูกห่อดังนั้นการขึ้นบรรทัดใหม่จะปรากฏเฉพาะในตอนท้ายของย่อหน้า ในต้นฉบับwhale.txtข้อความจะถูกห่อด้วยความกว้าง 74 ตัวอักษรดังนั้นคุณต้องคาดเดาจุดสิ้นสุดของแต่ละบรรทัดรวมถึงการทำนายข้อความ สิ่งนี้ทำให้ความท้าทายมากขึ้นเที่ยวยุ่งยิ่งดังนั้นจึงwhale2.txtขอแนะนำสำหรับคำตอบใหม่ ไฟล์ทั้งสองมีขนาดเท่ากันคือ 1215236 ไบต์


เพื่อสรุปคำตอบทั้งหมดควรรวมถึงสิ่งต่อไปนี้:

  • การส่งของคุณเอง (รหัสรวมถึงไฟล์ข้อมูลใด ๆ ที่ใช้ - อาจเป็นลิงก์หากมีขนาดใหญ่)
  • คำอธิบายวิธีการทำงานของรหัสของคุณ โปรดอธิบายวิธี I / O เช่นเดียวกับวิธีที่มันทำนายตัวละครถัดไป คำอธิบายอัลกอริทึมของคุณมีความสำคัญและคำอธิบายที่ดีจะได้รับรางวัลจากฉัน
  • รหัสที่คุณใช้ประเมินคะแนนของคุณ (หากเป็นเช่นเดียวกันกับคำตอบก่อนหน้านี้คุณสามารถลิงก์ไปได้เลย)
  • รหัสใด ๆ ที่คุณใช้สร้างการส่งของคุณพร้อมด้วยคำอธิบายของรหัสนั้น ซึ่งรวมถึงรหัสที่คุณใช้ในการปรับพารามิเตอร์ให้เหมาะสมสร้างไฟล์ข้อมูลเป็นต้น (นี่ไม่นับรวมกับจำนวนไบต์ของคุณ แต่ควรรวมอยู่ในคำตอบของคุณ)

ลีดเดอร์บอร์ด

โปรดปราน

บางครั้งฉันจะเสนอเงินรางวัลเพื่อส่งเสริมแนวทางที่แตกต่างกัน

คะแนนแรกคือ 50 คะแนนจาก A. Rex สำหรับคำตอบที่ได้คะแนนดีที่สุดในขณะนั้น

คะแนนที่สองคือ 100 คะแนนสำหรับ A. Rex สำหรับคำตอบเดียวกันเพราะพวกเขาเพิ่มคำอธิบายที่ดีมากให้กับคำตอบที่มีอยู่

เงินรางวัลถัดไป200 คะแนนจะมอบให้เช่นกัน

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

หรือ:

  • ใครก็ตามที่ชนะคะแนนสูงสุดของ A. Rex (ปัจจุบันคือ 444444) โดยใช้วิธีการใดก็ได้

เมื่อได้รับค่าหัว 200 คะแนนฉันจะเสนอ 400 คะแนนให้ปรับปรุงข้อกำหนดตามนั้น


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
Dennis

9
xkcd.com/1960ดูเหมือนจะอ้างอิงถึงความท้าทายนี้!
A. Rex

ฉันคิดว่าจะบีบอัดข้อมูลนี้ ... แต่มันก็นานไปหน่อยที่คอมพิวเตอร์ของฉันจะพังยัก
Naruyoko

คำตอบ:


135

/// , 2 * 1 + 1020874 = 1020876

 

พิมพ์ช่องว่าง


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
Dennis

นั่นคือการแฮ็กรางวัลที่ยอดเยี่ยมมาก! คุณต้องเป็น AGI;)
อเล็กซ์

97

Node.js, 2 * 224 + 524279 = 524727

โปรดดูบันทึกการเปลี่ยนแปลงในตอนท้ายของโพสต์นี้สำหรับการปรับปรุงคะแนน

ฟังก์ชั่นการรับและส่งคืนไบต์

a=[...l='14210100'],m={},s={},b={}
f=c=>a.some((t,n)=>x=s[y=l.slice(n)]>t|/^[A-Z '"(]/.test(y)&&b[y],l+=String.fromCharCode(c),a.map((_,n)=>(m[x=l.slice(n)]=-~m[x])<s[y=l.slice(n,8)]||(s[y]=m[x],b[y]=c)),l=l.slice(1))&&x||32

ประกอบด้วยโมเดล PPM แบบง่ายที่ดูอักขระ 8 ตัวสุดท้ายเพื่อทำนายตัวต่อไป

เราเชื่อว่ารูปแบบของความยาวLเมื่อเราได้พบอย่างน้อยT [L]ครั้งที่Tเป็นอาร์เรย์ของเกณฑ์พล: [1,1,2,1,2,3,5,2] [A-Z '"(]นอกจากนี้เรามักจะให้ความไว้วางใจที่มีรูปแบบตัวอักษรตรงกับครั้งแรก

เราเลือกรูปแบบที่เชื่อถือได้ยาวนานที่สุดและกลับมาทำนายผลด้วยคะแนนสูงสุดที่เกี่ยวข้องกับรูปแบบนี้ในเวลาที่โทร

หมายเหตุ

  • เห็นได้ชัดว่านี่ไม่ได้ปรับให้เหมาะกับความเร็ว แต่มันใช้เวลาประมาณ 15 วินาทีในแล็ปท็อปของฉัน

  • หากเราได้รับอนุญาตให้ทำซ้ำกระบวนการหลายครั้งติดต่อกันโดยไม่ต้องรีเซ็ตแบบจำลองจำนวนข้อผิดพลาดจะรวมกันเป็น ~ 268000 หลังจากการทำซ้ำ 5 ครั้ง

  • อัตราความสำเร็จในปัจจุบันของฟังก์ชั่นการทำนายคือ ~ 56.8% ดังที่สังเกตได้จาก @immibis ในความคิดเห็นหากการเดาที่ไม่ถูกต้องและถูกผสมเข้าด้วยกันผลลัพธ์จะไม่สามารถอ่านได้แม้แต่น้อย

    ตัวอย่างเช่นตัวอย่างนี้ใกล้ถึงจุดสิ้นสุดของหนังสือ:

    Here be it said, that this pertinacious pursuit of one particular whale,[LF]
    continued through day into night, and through night into day, is a thing[LF]
    by no means unprecedented in the South sea fishery.
    

    กลายเป็น:

    "e e be it said, that thes woacangtyous sarsuet of tie oort cular thale[LF][LF]
     orsinued toeough tir on e togh   and sheough toght an o ters af t shin[LF][LF]
    be to means insrocedented tn hhe sputh Sevsaonh ry,
    

    ด้วยการแทนที่การคาดเดาที่ไม่ดีด้วยการขีดล่างเรามีความคิดที่ดีขึ้นเกี่ยวกับสิ่งที่ฟังก์ชันมี

    _e_e be it said, that th_s _____n___ous __rsu_t of __e __rt_cular _hale_[LF]
    _o__inued t__ough ___ _n__ __gh__ and _h_ough __ght _n_o ____ __ _ _hin_[LF]
    b_ _o means _n_r_cedented _n _he __uth _e_____h_ry_
    

    หมายเหตุ : ตัวอย่างข้างต้นถูกสร้างขึ้นด้วยรหัสรุ่นก่อนหน้าซึ่งทำงานกับไฟล์อินพุตรุ่นแรก

รหัสทดสอบ

/**
  The prediction function f() and its variables.
*/
a=[...l='14210100'],m={},s={},b={}
f=c=>a.some((t,n)=>x=s[y=l.slice(n)]>t|/^[A-Z '"(]/.test(y)&&b[y],l+=String.fromCharCode(c),a.map((_,n)=>(m[x=l.slice(n)]=-~m[x])<s[y=l.slice(n,8)]||(s[y]=m[x],b[y]=c)),l=l.slice(1))&&x||32

/**
  A closure containing the test code and computing E.
  It takes f as input.
  (f can't see any of the variables defined in this scope.)
*/
;
(f => {
  const fs = require('fs');

  let data = fs.readFileSync('whale2.txt'),
      len = data.length,
      err = 0;

  console.time('ElapsedTime');

  data.forEach((c, i) => {
    i % 100000 || console.log((i * 100 / len).toFixed(1) + '%');

    if(i < len - 1 && f(c) != data[i + 1]) {
      err++;
    }
  })

  console.log('E = ' + err);
  console.timeEnd('ElapsedTime');
})(f)

เปลี่ยนบันทึก

  • 524727 - บันทึก 19644 คะแนนโดยเปลี่ยนเป็นwhale2.txt (อัปเดตการท้าทาย)
  • 544371 - บันทึก 327 คะแนนโดยบังคับใช้รูปแบบที่ขึ้นต้นด้วยตัวพิมพ์ใหญ่, คำพูด, เครื่องหมายคำพูดคู่หรือวงเล็บเปิดเพื่อให้เชื่อถือได้เสมอ
  • 544698 - บันทึก 2119 คะแนนโดยบังคับให้ใช้รูปแบบที่ขึ้นต้นด้วยช่องว่างที่จะเชื่อถือได้เสมอ
  • 546817 - บันทึก 47 คะแนนโดยการปรับระดับเสียงและฟังก์ชั่นการทำนาย
  • 546864 - บันทึก 1496 คะแนนโดยขยายความยาวสูงสุดของรูปแบบเป็น 8 อักขระ
  • 548360 - บันทึก 6239 คะแนนโดยแนะนำแนวคิดของรูปแบบที่เชื่อถือได้โดยมีขีด จำกัด ตามความยาว
  • 554599 - บันทึก 1,030 คะแนนโดยการปรับปรุงการทำนายการป้อนบรรทัด
  • 555629 - บันทึก 22 คะแนนโดยการฟังก์ชั่นการทำนาย
  • 555651 - บันทึก 40 คะแนนด้วยการเล่นฟังก์ชั่นการทำนาย
  • 555691 - คะแนนเริ่มต้น

44
สำหรับสิ่งที่อยากรู้อยากเห็นไม่สิ่งนี้ไม่ได้ผลิตอะไรอย่าง Moby Dick sidg tlanses,oeth to, shuld hottut tild aoersors Ch, th! Sa, yr! Sheu arinning whales aut ihe e sl he traaty of rrsf tg homn Bho dla tiasot a shab sor ty, af etoors tnd hocket sh bts ait mtubb tiddin tis aeewnrs, dnhost maundy cnd sner aiwt d boelh cheugh -aaieiyns aasiyns taaeiins! th, tlaมันเป็นจำนวนมากทั้งจาก บางครั้งคำบางคำก็สามารถทำได้สำเร็จ กดwhalesไลค์
immibis

23
@immibis ชื่อของการท้าทายถูกเลือกอย่างชาญฉลาด นี่คือ Moby Dick, ประมาณ :-)
Arnauld

3
@ นาธาเนียลมีการอัปเดตมากมายดังนั้นจึงแทบอ่านไม่ได้และไม่มีข้อมูลจริงๆ ฉันได้เพิ่มบันทึกการเปลี่ยนแปลงแทนพร้อมคำอธิบายสั้น ๆ เกี่ยวกับการปรับปรุง
Arnauld

45
ฉันคิดว่าโปรแกรมของคุณกำลังแปลภาษาเกลิคอย่างสมบูรณ์แบบ
Beska

1
@ Draco18s มันยากที่จะบอกว่าเครื่องหมายจุลภาคนี้ดีหรือไม่ดี ถ้ามันเป็นที่คาดเดาไม่ดีฟังก์ชั่นการคาดการณ์อาจมีความพยายามที่ถูกต้องตามกฎหมายที่จะนำตัวอักษรหลังจากที่สิ่งอื่น ๆ ตัวอักษรที่-เป็น-จริง-มีแทน-of-จุลภาคเมื่อมันได้รับมัน
Arnauld

91

Perl, 2 · 70525 + 326508 = 467558

ทำนาย

$m=($u=1<<32)-1;open B,B;@e=unpack"C*",join"",<B>;$e=2903392593;sub u{int($_[0]+($_[1]-$_[0])*pop)}sub o{$m&(pop()<<8)+pop}sub g{($h,%m,@b,$s,$E)=@_;if($d eq$h){($l,$u)=(u($l,$u,$L),u($l,$u,$U));$u=o(256,$u-1),$l=o($l),$e=o(shift@e,$e)until($l^($u-1))>>24}$M{"@c"}{$h}++-++$C{"@c"}-pop@c for@p=($h,@c=@p);@p=@p[0..19]if@p>20;@c=@p;for(@p,$L=0){$c="@c";last if" "ne pop@c and@c<2 and$E>99;$m{$_}+=$M{$c}{$_}/$C{$c}for sort keys%{$M{$c}};$E+=$C{$c}}$s>5.393*$m{$_}or($s+=$m{$_},push@b,$_)for sort{$m{$b}<=>$m{$a}}sort keys%m;$e>=u($l,$u,$U=$L+$m{$_}/$s)?$L=$U:return$d=$_ for sort@b}

เพื่อเรียกใช้โปรแกรมนี้คุณจะต้องไฟล์นี้ที่นี่Bซึ่งจะต้องมีชื่อ (คุณสามารถเปลี่ยนชื่อไฟล์นี้ในอินสแตนซ์ที่สองของตัวละครBด้านบน) ดูวิธีสร้างไฟล์นี้ที่ด้านล่าง

โปรแกรมใช้การรวมกันของรุ่นมาร์คอฟเป็นหลักเช่นเดียวกับในคำตอบนี้โดยผู้ใช้ 2699แต่มีการปรับเปลี่ยนเล็กน้อย สิ่งนี้จะสร้างการกระจายสำหรับตัวละครต่อไป เราใช้ทฤษฎีข้อมูลเพื่อตัดสินใจว่าจะยอมรับข้อผิดพลาดหรือใช้บิตของพื้นที่จัดเก็บในการBเข้ารหัสคำแนะนำ (และถ้าเป็นเช่นนั้นอย่างไร) เราใช้การเข้ารหัสทางเลขคณิตในการจัดเก็บบิตเศษส่วนอย่างเหมาะสมจากโมเดล

โปรแกรมมีความยาว 582 ไบต์ (รวมถึงบรรทัดใหม่สุดท้ายที่ไม่จำเป็น) และไฟล์ไบนารีBมีความยาว 69942 ไบต์ดังนั้นภายใต้กฎสำหรับการให้คะแนนหลายไฟล์เราให้คะแนนLเป็น 582 + 69942 + 1 = 70525

โปรแกรมเกือบจะแน่นอนต้องใช้สถาปัตยกรรม 64 บิต (little-endian?) ใช้เวลาประมาณ 2.5 นาทีในการรันบนm5.largeอินสแตนซ์ของ Amazon EC2

รหัสทดสอบ

# Golfed submission
require "submission.pl";

use strict; use warnings; use autodie;

# Scoring length of multiple files adds 1 penalty
my $length = (-s "submission.pl") + (-s "B") + 1;

# Read input
open my $IN, "<", "whale2.txt";
my $input = do { local $/; <$IN> };

# Run test harness
my $errors = 0;
for my $i ( 0 .. length($input)-2 ) {
    my $current = substr $input, $i, 1;
    my $decoded = g( $current );

    my $correct = substr $input, $i+1, 1;
    my $error_here = 0 + ($correct ne $decoded);
    $errors += $error_here;
}

# Output score
my $score = 2 * $length + $errors;
print <<EOF;
length $length
errors $errors
score  $score
EOF

ชุดทดสอบจะถือว่าการส่งอยู่ในไฟล์submission.plแต่สามารถเปลี่ยนได้อย่างง่ายดายในบรรทัดที่สอง

การเปรียบเทียบข้อความ

"And did none of ye see it before?" cried Ahab, hailing the perched men all around him.\\"I saw him almost that same instant, sir, that Captain 
"And wid note of te fee bt seaore   cried Ahab, aasling the turshed aen inl atound him. \"' daw him wsoost thot some instant, wer, that Saptain 
"And _id no_e of _e _ee _t _e_ore__ cried Ahab, _a_ling the __r_hed _en __l a_ound him._\"_ _aw him ___ost th_t s_me instant, __r, that _aptain 

Ahab did, and I cried out," said Tashtego.\\"Not the same instant; not the same--no, the doubloon is mine, Fate reserved the doubloon for me. I 
Ahab aid  ind I woued tut,  said tashtego, \"No, the same instant, tot the same -tow nhe woubloon ws mane. alte ieserved the seubloon ior te, I 
Ahab _id_ _nd I ___ed _ut,_ said _ashtego__\"No_ the same instant_ _ot the same_-_o_ _he _oubloon _s m_ne_ __te _eserved the __ubloon _or _e_ I 

only; none of ye could have raised the White Whale first. There she blows!--there she blows!--there she blows! There again!--there again!" he cr
gnly  towe of ye sould have tersed the shite Whale aisst  Ihere ihe blows! -there she blows! -there she blows! Ahere arains -mhere again!  ce cr
_nly_ _o_e of ye _ould have ___sed the _hite Whale _i_st_ _here _he blows!_-there she blows!_-there she blows! _here a_ain__-_here again!_ _e cr

ตัวอย่างนี้ (เลือกในคำตอบอื่น ) เกิดขึ้นค่อนข้างช้าในข้อความดังนั้นโมเดลนี้จึงได้รับการพัฒนาโดยจุดนี้ โปรดจำไว้ว่าแบบจำลองนี้มีการเพิ่ม "คำใบ้" 70 กิโลไบต์ที่ช่วยให้เดาอักขระได้โดยตรง มันไม่ได้ขับเคลื่อนโดยตัวอย่างสั้น ๆ ของรหัสข้างต้น

สร้างคำแนะนำ

โปรแกรมต่อไปนี้ยอมรับรหัสการส่งที่ถูกต้องด้านบน (ในอินพุตมาตรฐาน) และสร้างBไฟล์ที่แน่นอนด้านบน (บนเอาต์พุตมาตรฐาน):

@S=split"",join"",<>;eval join"",@S[0..15,64..122],'open W,"whale2.txt";($n,@W)=split"",join"",<W>;for$X(0..@W){($h,$n,%m,@b,$s,$E)=($n,$W[$X]);',@S[256..338],'U=0)',@S[343..522],'for(sort@b){$U=($L=$U)+$m{$_}/$s;if($_ eq$n)',@S[160..195],'X<128||print(pack C,$l>>24),',@S[195..217,235..255],'}}'

ใช้เวลาในการประมวลผลเท่ากันโดยประมาณ

คำอธิบาย

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

แบบ

ส่วนประกอบพื้นฐานของการแก้ปัญหาคือรูปแบบภาษา สำหรับวัตถุประสงค์ของเราแบบจำลองเป็นสิ่งที่ใช้ข้อความภาษาอังกฤษจำนวนหนึ่งและส่งกลับค่าการแจกแจงความน่าจะเป็นในตัวละครถัดไป เมื่อเราใช้โมเดลข้อความภาษาอังกฤษจะเป็นส่วนนำหน้า (ที่ถูกต้อง) ของ Moby Dick โปรดทราบว่าผลลัพธ์ที่ต้องการเป็นการกระจายและไม่ใช่เพียงการเดาเพียงครั้งเดียวสำหรับตัวละครที่เป็นไปได้มากที่สุด

ในกรณีที่เราเป็นหลักใช้รูปแบบในคำตอบนี้โดย user2699 เราไม่ได้ใช้แบบจำลองจากคำตอบที่ให้คะแนนสูงสุด (นอกเหนือจากของเราเอง) โดย Anders Kaseorgอย่างแม่นยำเพราะเราไม่สามารถแยกการกระจายได้มากกว่าการเดาที่ดีที่สุดเพียงครั้งเดียว ในทางทฤษฎีคำตอบนั้นคำนวณค่าเฉลี่ยถ่วงน้ำหนักทางเรขาคณิต แต่เราได้ผลลัพธ์ที่ไม่ดีพอเมื่อเราตีความเช่นนั้นอย่างแท้จริง เรา "ขโมย" แบบจำลองจากคำตอบอื่นเพราะ "ซีเคร็ทซอส" ของเราไม่ใช่แบบจำลอง แต่เป็นแนวทางโดยรวม หากใครบางคนมีรูปแบบ "ดีกว่า" พวกเขาควรจะได้รับผลลัพธ์ที่ดีขึ้นโดยใช้เทคนิคที่เหลือของเรา

เป็นข้อสังเกตวิธีการบีบอัดส่วนใหญ่เช่น Lempel-Ziv นั้นถูกมองว่าเป็น "แบบจำลองภาษา" ด้วยวิธีนี้ถึงแม้ว่าวิธีการหนึ่งอาจต้องเหลื่อมกันเล็กน้อย (โดยเฉพาะอย่างยิ่งเป็นเรื่องยากสำหรับบางสิ่งที่ทำ Burrows-Wheeler transform!) นอกจากนี้โปรดทราบว่าโมเดลโดยผู้ใช้ 2699 เป็นการดัดแปลงโมเดลของมาร์คอฟ เป็นหลักไม่มีอะไรอื่นที่สามารถแข่งขันกับความท้าทายนี้หรือแม้กระทั่งการสร้างแบบจำลองข้อความทั่วไป

สถาปัตยกรรมโดยรวม

เพื่อวัตถุประสงค์ในการทำความเข้าใจมันเป็นเรื่องดีที่จะแยกสถาปัตยกรรมโดยรวมออกเป็นหลาย ๆ ส่วน จากมุมมองระดับสูงสุดจำเป็นต้องมีรหัสการจัดการสถานะเล็กน้อย สิ่งนี้ไม่น่าสนใจเป็นพิเศษ แต่เพื่อความสมบูรณ์เราต้องการเน้นว่าในทุก ๆ จุดโปรแกรมถูกถามถึงการคาดเดาครั้งต่อไปมันมีคำนำหน้าที่ถูกต้องของ Moby Dick เราไม่ใช้การคาดเดาที่ผิดพลาดในอดีต แต่อย่างใด เพื่อประสิทธิภาพของมันรูปแบบภาษาอาจจะสามารถนำสถานะของมันกลับมาใช้ใหม่จากตัวอักษร N ตัวแรกเพื่อคำนวณสถานะของตัวละครตัวแรก (N + 1) แต่โดยหลักการแล้วมันสามารถคำนวณสิ่งต่าง ๆ ได้ตั้งแต่เริ่มต้นทุกครั้ง

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

หากใครใช้วิธีการบีบอัดมาตรฐานเช่นbzip2 เช่นเดียวกับในคำตอบนี้ไฟล์ "คำแนะนำ" จะสอดคล้องกับไฟล์บีบอัด "ล่าม" สอดคล้องกับตัวขยายการบีบอัดในขณะที่ "รูปแบบภาษา" เป็นบิตโดยนัย (ดังกล่าวข้างต้น)

เหตุใดจึงต้องใช้ไฟล์คำใบ้

ลองเลือกตัวอย่างง่าย ๆ เพื่อวิเคราะห์เพิ่มเติม สมมติว่าข้อความเป็นNตัวอักษรที่มีความยาวและประมาณตัวอักษรได้ดีโดยที่ตัวละครทุกตัว (เป็นอิสระ) ตัวอักษรที่Eมีความน่าจะเป็นน้อยกว่าครึ่งTเล็กน้อยคล้ายกับความน่าจะเป็นที่น้อยกว่าครึ่งหนึ่งและAมีความน่าจะเป็น 1/1000 = 0.1% สมมติว่าไม่มีตัวละครอื่น ๆ ที่เป็นไปได้ ไม่ว่าในกรณีใดAลักษณะคล้ายกับกรณีของอักขระที่มองไม่เห็นก่อนหน้านี้จากสีน้ำเงิน

หากเราดำเนินการในระบอบการปกครอง L 0 (ส่วนใหญ่ แต่ไม่ใช่ทั้งหมดของคำตอบอื่น ๆ สำหรับคำถามนี้) ไม่มีวิธีใดที่ดีไปกว่าล่ามEและTเลือก โดยเฉลี่ยแล้วจะมีตัวละครประมาณครึ่งตัวที่ถูกต้อง ดังนั้น E ≈ N / 2 และคะแนน≈ N / 2 ด้วย อย่างไรก็ตามถ้าเราใช้กลยุทธ์การบีบอัดเราสามารถบีบอัดได้มากกว่าหนึ่งบิตต่อตัวอักษร เนื่องจาก L นับเป็นไบต์เราจะได้รับ L ≈ N / 8 ดังนั้นจึงให้คะแนน≈ N / 4 สองครั้งดีเท่ากับกลยุทธ์ก่อนหน้านี้

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

การเข้ารหัสทางเลขคณิต

การเข้ารหัสเป็นวิธีการแทนข้อมูลบางอย่างโดยใช้บิต / ไบต์ ตัวอย่างเช่น ASCII เป็นการเข้ารหัส 7 บิต / ตัวอักษรของข้อความภาษาอังกฤษและตัวอักษรที่เกี่ยวข้องและเป็นการเข้ารหัสของไฟล์ Moby Dick ดั้งเดิมภายใต้การพิจารณา หากตัวอักษรบางตัวพบได้บ่อยกว่าตัวอักษรอื่นการเข้ารหัสแบบความกว้างคงที่เช่น ASCII จะไม่เหมาะสม ในสถานการณ์ดังกล่าวหลายคนเข้าถึงสำหรับHuffman การเข้ารหัส สิ่งนี้จะเหมาะสมที่สุดหากคุณต้องการรหัสคงที่ (ไม่มีคำนำหน้า) ที่มีจำนวนบิตเป็นบิตต่ออักขระ

อย่างไรก็ตามการเข้ารหัสทางคณิตศาสตร์ดียิ่งขึ้น การพูดโดยประมาณสามารถใช้บิต "เศษส่วน" เพื่อเข้ารหัสข้อมูลได้ มีคำแนะนำมากมายเกี่ยวกับการเข้ารหัสทางคณิตศาสตร์ที่พร้อมใช้งานออนไลน์ เราจะข้ามรายละเอียดที่นี่ (โดยเฉพาะอย่างยิ่งการใช้งานจริงซึ่งอาจเป็นเรื่องยุ่งยากเล็กน้อยจากมุมมองการเขียนโปรแกรม) เนื่องจากแหล่งข้อมูลอื่น ๆ ที่พร้อมใช้งานออนไลน์ แต่ถ้ามีคนบ่น

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

ในการเข้ารหัสเป็นหลักที่ดีที่สุดนี้เราสิ้นสุดการใช้จ่าย -log_2 (P) บิตสำหรับตัวอักษรที่มีความน่าจะเป็นพีและอัตราบิตโดยรวมของการเข้ารหัสเป็นเอนโทรปีนอนส์ ซึ่งหมายความว่าอักขระที่มีความน่าจะเป็นใกล้ 1/2 ใช้เวลาประมาณหนึ่งบิตในการเข้ารหัสในขณะที่อักขระที่มีความน่าจะเป็น 1/1000 นั้นใช้เวลาประมาณ 10 บิต (เนื่องจาก 2 ^ 10 มีค่าประมาณ 1,000)

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

ทำผิดพลาดทำไม

มาวิเคราะห์ตัวอย่างก่อนหน้านี้เพื่อกระตุ้นสาเหตุที่เราอาจต้องการทำข้อผิดพลาด "จงใจ" ถ้าเราใช้คณิตศาสตร์การเข้ารหัสการเข้ารหัสตัวอักษรที่ถูกต้องเราจะใช้เวลาประมาณหนึ่งบิตในกรณีของนั้นEหรือแต่ประมาณสิบบิตในกรณีนั้นTA

โดยรวมแล้วนี่เป็นการเข้ารหัสที่ดีทีเดียวใช้เวลามากกว่าตัวละครเล็กน้อยต่อตัวแม้ว่าจะมีความเป็นไปได้สามอย่างก็ตาม โดยพื้นฐานแล้วAมันไม่น่าเป็นไปได้และเราไม่ได้ใช้จ่ายสิบบิตที่สอดคล้องกันบ่อยเกินไป อย่างไรก็ตามมันจะไม่ดีถ้าเราสามารถทำผิดพลาดแทนในกรณีของA? ท้ายที่สุดตัวชี้วัดของปัญหาจะพิจารณาความยาว 1 ไบต์ = 8 บิตซึ่งเท่ากับ 2 ข้อผิดพลาด ดังนั้นดูเหมือนว่าเราควรชอบข้อผิดพลาดแทนที่จะใช้มากกว่า 8/2 = 4 บิตกับตัวละคร การใช้จ่ายมากกว่าไบต์เพื่อบันทึกข้อผิดพลาดหนึ่งข้อจะส่งผลให้ไม่ได้ผลแน่นอน!

กลไก "กรอกลับ"

ส่วนนี้อธิบายถึงมุมมองที่ฉลาดหลักของโซลูชันนี้ซึ่งเป็นวิธีจัดการกับการเดาที่ไม่ถูกต้องโดยไม่มีค่าใช้จ่าย

สำหรับตัวอย่างง่ายๆที่เราวิเคราะห์อยู่นั้นกลไกการกรอกลับนั้นเรียบง่ายมาก ล่ามจะอ่านหนึ่งบิตจากไฟล์คำแนะนำ ถ้าเป็น 0 Eมันคาดเดา ถ้าเป็น 1 Tก็คาดเดา ครั้งต่อไปที่มันถูกเรียกมันจะเห็นตัวละครที่ถูกต้อง หากไฟล์คำใบ้ตั้งค่าได้ดีเราสามารถมั่นใจได้ว่าในกรณีของEหรือTล่ามคาดเดาได้อย่างถูกต้อง แต่เกี่ยวกับAอะไร ความคิดของกลไกการย้อนกลับไปก็คือการไม่ได้รหัสAที่ทั้งหมด หากล่ามรู้ในภายหลังว่าตัวอักษรที่ถูกต้องเป็นตัวอักษรนั้นAมันจะเปรียบเทียบ " ย้อนกลับเทป": มันส่งคืนบิตที่อ่านก่อนหน้านี้ บิตที่อ่านนั้นตั้งใจจะให้รหัสEหรือT, แต่ไม่ใช่ตอนนี้; มันจะถูกใช้ในภายหลัง ในตัวอย่างง่ายๆนี้โดยทั่วไปหมายความว่ามันยังคงคาดเดาอักขระเดิม ( EหรือT) จนกว่าจะทำให้ถูกต้อง จากนั้นมันจะอ่านอีกบิตและดำเนินต่อไป

การเข้ารหัสสำหรับไฟล์คำแนะนำนี้ง่ายมาก: เปลี่ยนEs ทั้งหมดเป็น 0 บิตและTs เป็น 1 บิตทั้งหมดโดยไม่สนใจAs ทั้งหมด โดยการวิเคราะห์ในตอนท้ายของส่วนก่อนหน้านี้ที่โครงการนี้จะทำให้ข้อผิดพลาดบางอย่าง แต่ลดคะแนนโดยรวมไม่ได้เข้ารหัสใด ๆ ของAs ในฐานะที่เป็นเอฟเฟกต์ขนาดเล็กจริง ๆ แล้วมันจะบันทึกตามความยาวของไฟล์คำแนะนำเช่นกันเพราะเราจะใช้หนึ่งบิตสำหรับแต่ละบิตEและTแทนที่จะเป็นบิตมากกว่าเล็กน้อย

ทฤษฎีบทเล็กน้อย

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

แต่เราควรเลือกการกระจายแบบไหน ไม่ยากเกินไปที่จะเห็นว่าอักขระที่มีรหัสควรมีความน่าจะเป็นสูงกว่า (ใน P) มากกว่าอักขระที่ไม่ได้เข้ารหัส นอกจากนี้การกระจาย Q ควรมีเฉพาะอักขระที่มีรหัสเท่านั้น ท้ายที่สุดเราไม่ได้เข้ารหัสรหัสอื่นดังนั้นเราไม่ควร "ใช้" เอนโทรปีของพวกเขา มันค่อนข้างยากที่จะเห็นว่าการแจกแจงความน่าจะเป็น Q ควรเป็นสัดส่วนกับ P ในตัวอักษรที่เขียนโค้ด การรวมการสังเกตเหล่านี้เข้าด้วยกันหมายความว่าเราควรเขียนรหัสตัวละครที่มีโอกาสมากที่สุด แต่อาจไม่ใช่ตัวละครที่มีโอกาสน้อยกว่าและ Q นั้นได้รับการปรับ P บนตัวละครที่เขียนโค้ด

มันกลับกลายเป็นว่ามีทฤษฎีบทเจ๋ง ๆ เกี่ยวกับสิ่งที่ "cutoff" ควรเลือกสำหรับตัวอักษรการเข้ารหัส: คุณควรเขียนรหัสตัวอักษรตราบเท่าที่มันมีอย่างน้อย 1 / 5.393 ที่น่าจะเป็นไปได้ สิ่งนี้ "อธิบาย" ลักษณะที่ปรากฏของค่าคงที่แบบสุ่มที่ดูเหมือนจะ5.393ใกล้เคียงกับจุดสิ้นสุดของโปรแกรมด้านบน จำนวน 1 / 5.393 ≈ 0.18542 เป็นวิธีการแก้สมการ-p เข้าสู่ระบบ (16) p - บันทึก + p (1 + P) เข้าสู่ระบบ (1 + P) = 0

อาจเป็นความคิดที่สมเหตุสมผลที่จะเขียนโพรซีเดอร์นี้เป็นโค้ด ตัวอย่างนี้อยู่ใน C ++:

// Assume the model is computed elsewhere.
unordered_map<char, double> model;

// Transform p to q
unordered_map<char, double> code;
priority_queue<pair<double,char>> pq;
for( char c : CHARS )
    pq.push( make_pair(model[c], c) );
double s = 0, p;
while( 1 ) {
    char c = pq.top().second;
    pq.pop();
    p = model[c];
    if( s > 5.393*p )
        break;
    code[c] = p;
    s += p;
}
for( auto& kv : code ) {
    char c = kv.first;
    code[c] /= s;
}

วางมันทั้งหมดเข้าด้วยกัน

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

  1. เพิ่มอักขระที่ถูกต้องให้กับส่วนนำหน้าที่ถูกต้องของ Moby Dick
  2. อัปเดตข้อความ (Markov) รุ่น
  3. ซอสลับ : ถ้าเดาก่อนหน้านี้ไม่ถูกต้องย้อนกลับสถานะของการถอดรหัสคณิตศาสตร์ให้กับรัฐก่อนที่จะคาดเดาก่อนหน้านี้!
  4. ขอให้โมเดลของมาร์คอฟทำนายการกระจายตัวของความน่าจะเป็น P สำหรับตัวละครต่อไป
  5. แปลง P เป็น Q โดยใช้รูทีนย่อยจากส่วนก่อนหน้า
  6. ขอให้ตัวถอดรหัสเลขคณิตถอดรหัสตัวอักษรจากส่วนที่เหลือของไฟล์คำใบ้ตามการแจกแจง Q
  7. เดาตัวละครที่เกิด

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

หากคุณเข้าใจภูมิหลังทางทฤษฎีข้อมูลเช่นการแจกแจงความน่าจะเป็น, เอนโทรปี, การบีบอัดและการเข้ารหัสทางคณิตศาสตร์ แต่พยายามและล้มเหลวที่จะเข้าใจโพสต์นี้ (ยกเว้นว่าทำไมทฤษฎีบทเป็นจริง) ให้เรารู้ ขอบคุณที่อ่าน!


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

8
ยอดเยี่ยม! คำตอบแรก (และเท่าที่ผ่านมาเท่านั้น) คำตอบที่จะทำลายอุปสรรคคะแนน 500k
ShreevatsaR

5
"แทนที่ปลาวาฬ shite" omg ฉันร้องไห้
Phill

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

2
@Nathaniel: ฉันเพิ่มคำอธิบายลงในโพสต์นี้ แจ้งให้เราทราบหากคุณคิดว่ารายละเอียดเพียงพอที่จะสร้างโซลูชันขึ้นมาใหม่
A. Rex

77

Python 3, 2 · 267 + 510193 = 510727

ทำนาย

def p():
 d={};s=b''
 while 1:
  p={0:1};r=range(len(s)+1)
  for i in r:
   for c,n in d.setdefault(s[:i],{}).items():p[c]=p.get(c,1)*n**b'\1\6\f\36AcWuvY_v`\270~\333~'[i]
  c=yield max(sorted(p),key=p.get)
  for i in r:e=d[s[:i]];e[c]=e.get(c,1)+1
  s=b'%c'%c+s[:15]

สิ่งนี้ใช้การผสมแบบเบย์แบบถ่วงน้ำหนักของลำดับ 0, …, 16 รุ่นมาร์คอฟที่มีน้ำหนัก [1, 6, 12, 30, 65, 99, 87, 117, 118, 89, 95, 118, 96, 184, 126, 219, 126]

ผลลัพธ์ไม่ไวต่อการเลือกน้ำหนักเหล่านี้มากนัก แต่ฉันปรับให้เหมาะสมเพราะฉันทำได้โดยใช้อัลกอริทึมการปีนเขาที่ได้รับการยอมรับปลายเดียวกับที่ฉันใช้ในคำตอบของฉันในการ เพียงแค่เพิ่มค่า± 1 ถึงน้ำหนักเดียว

รหัสทดสอบ

with open('whale2.txt', 'rb') as f:
    g = p()
    wrong = 0
    a = next(g)
    for b in f.read():
        wrong += a != b
        a = g.send(b)
    print(wrong)

2
เครื่องมือที่เหมาะสมสำหรับงาน คะแนนดีมาก ทำได้ดีนี่.
ว่าจะ

1
การชี้แจงที่b"\0\3\6\r\34'&-20'\22!P\n[\26"เป็นไปได้: เป็นการแสดงถึงน้ำหนักของ ascii ซึ่งค่าที่ไม่สามารถพิมพ์ได้ขนาดเล็กจะถูกหลบหนีในฐานแปด
Cœur

ฉันได้อัปเดตคำถามด้วยไฟล์เวอร์ชันที่ข้อความไม่ถูกห่อ - คุณอาจลองเรียกใช้โค้ดของคุณอีกครั้ง (อาจจะดีขึ้นเล็กน้อย)
นาธาเนียล

3
ขอบคุณสำหรับคำอธิบายนั้น - ถ้าคุณสามารถแก้ไขเรื่องย่อในคำถามมันจะดีมาก (ประสบการณ์กับความท้าทายที่ผ่านมาPaint Starry Nightของฉันคือขั้นตอนการเพิ่มประสิทธิภาพเหล่านี้เป็นส่วนที่น่าสนใจที่สุดของคำตอบดังนั้นมันจะดีกว่ามากถ้าคำตอบมีรหัสที่ใช้ในการทำเช่นนั้นและคำอธิบายของฉันด้วย ความท้าทายที่บอกว่าควรทำ)
นาธาเนียล

1
@Christoph การรวมแบบของฉันจริง ๆ แล้วเป็นค่าเฉลี่ยทางเรขาคณิตถ่วงน้ำหนัก แต่ค่าเฉลี่ยของ PAQ ในโดเมนโลจิสติกนั้นแตกต่างกันเล็กน้อย - ฉันต้องดูว่าดีกว่านี้หรือไม่
Anders Kaseorg

55

Python 3 , 2 * 279 + 592920 = 593478 2 * 250 + 592467 = 592967 2 * 271 + 592084 = 592626 2 * 278 + 592059 = 592615 2 * 285 + 586660 2 58 320 + 585161 2 5 = 585728

d=m={}
s=1
w,v='',0
def f(c):
 global w,m,v,s,d
 if w not in m:m[w]={}
 u=m[w];u[c]=c in u and 1+u[c]or 1;v+=1;q=n=' ';w=w*s+c;s=c!=n
 if w in m:_,n=max((m[w][k],k)for k in m[w])
 elif s-1:n=d in'nedtfo'and't'or'a'
 elif'-'==c:n=c
 elif"'"==c:n='s'
 elif'/'<c<':':n='.'
 if v>4*(n!=q)+66:n='\n'
 if s:d=c
 if c<q:w=w[:-1]+q;v=s=0
 return n

ลองออนไลน์!

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

ตัวอย่างเช่น:

  • หากสิ่งที่เห็นจนถึงตอนนี้คือ 'Captai' มันจะทำนายคำว่า "n"
  • ถ้าเป็น "กัปตัน" มันจะทำนายพื้นที่
  • ถ้ามันเป็นจุดเริ่มต้นของคำและคำสุดท้ายคือ "กัปตัน" มันทำนายว่า 'A'
  • หากคำว่า "A" เป็นคำที่คาดการณ์ว่า 'h' (และ 'a' และ 'b'; ในทำนองเดียวกันสำหรับ 'C')

ในตอนแรกมันไม่ค่อยดีนัก แต่ในตอนท้ายมีคำพูดออกมามากมาย ตัวเลือกทางเลือกคือช่องว่างและหลังจากเว้นวรรคหนึ่งเป็น "a" ยกเว้นว่าตัวอักษรก่อนหน้าคือหนึ่งใน "nedtfo" ตัวเลขหรือไฮเฟ่นหรือเครื่องหมายอัญประกาศ นอกจากนี้ยังคาดการณ์การแบ่งบรรทัดอย่างจริงจังหลังจากที่มีอักขระ 71 ตัวหรือหากคาดว่าจะมีช่องว่างหลังจาก 66 ทั้งคู่ถูกปรับไปยังข้อมูล ("t" เป็นเรื่องธรรมดามากหลังจากเว้นวรรค แต่มีการคาดการณ์ไว้บ่อยกว่าดังนั้น " a "เป็นการเดาที่ดีกว่ากรณีพิเศษทั้งหกกรณี)

เรียนรู้ว่าคู่คำใดประกอบกันและคาดเดาการทำแผนที่กลายเป็นไม่คุ้มค่า


ลงท้ายด้วยข้อความเช่นนี้

nl tneund his    I woi tis tnlost ahet toie tn tant  wod, ihet taptain Ahab ses
 snd t
oeed Sft   aoid thshtego    Io, fhe soie tn tant  tot the soie      ahe sewbtoon
swn tagd  aoths eatmved fhe sewbtoon wor ta  I sfey  aote of totsonld nive betse
d ahe
hate Whale iorst  Ihe e ioi beaos! -there soi beaos! -there soi beaos!

ซึ่งสอดคล้องกับส่วนนี้ของอินพุต:

รอบตัวเขา

“ ฉันเห็นเขาเกือบจะในทันทีนั้นครับท่านกัปตันอาแฮบทำและฉันก็ร้องออกมา” ทาชต์โกกล่าว

"ไม่เหมือนกันในทันที; ไม่เหมือนกัน - ไม่, doubloon เป็นของฉัน, โชคชะตาสงวน doubloon สำหรับฉันฉันเท่านั้นไม่มีใครที่สามารถยกปลาวาฬสีขาวขึ้นมาก่อนเธอเป่า! - ที่นั่นเธอเป่า! - - มีเธอพัด!

คุณสามารถดูว่าคำนามใดที่เหมาะสมโดยเฉพาะออกมาได้ดี แต่จุดสิ้นสุดของคำส่วนใหญ่ก็ถูกต้องเช่นกัน เมื่อเห็น "dou" จะคาดหวัง "สงสัย" แต่เมื่อ "l" ปรากฏขึ้นจะได้รับ "doubloon"

หากคุณเรียกใช้ครั้งที่สองด้วยรุ่นเดียวกันมันเพิ่งสร้างขึ้นมาใหม่จะได้รับการแก้ไขทันที 92k (51.7% -> 59.3%) แต่จะต่ำกว่า 60% จากการทำซ้ำครั้งที่สองเสมอ


รหัสการวัดอยู่ในลิงค์ TIO หรือนี่เป็นเวอร์ชั่นที่ดีกว่าเล็กน้อย:

total = 0
right = 0
with open('whale.txt') as fp:
    with open('guess.txt', 'w') as dest:
        for l in fp.readlines():
            for c in l:
                last = c
                if p == c: right += 1
                n = f(c)
                p = n
                total += 1
                dest.write(n)
                if total % 10000 == 0:
                    print('{} / {} E={}\r'.format(right, total, total-right), end='')
print('{} / {}: E={}'.format(right, total, total - right))

guess.txt มีผลลัพธ์ที่เดาได้ในตอนท้าย


3
นี่เป็นวิธีการที่ยอดเยี่ยม!
Skyler

2
<s> </s> มากเกินไป)
FantaC

1
+1 เพราะวิธีนี้ทำให้ฉันนึกถึงอัลกอริทึมการบีบอัด LZW
มาร์กอส

25

C ++, คะแนน: 2 * 132 + 865821 = 866085

ขอบคุณ @Quentin สำหรับการบันทึก 217 ไบต์!

int f(int c){return c-10?"t \n 2  sS \n  -  08........       huaoRooe oioaoheu thpih eEA \n   neo    enueee neue hteht e"[c-32]:10;}

ทางออกที่ง่ายมากที่ให้ตัวละครเพียงแค่ส่งออกตัวละครที่ปรากฏบ่อยที่สุดหลังจากที่ตัวละครอินพุต

ตรวจสอบคะแนนด้วย:

#include <iostream>
#include <fstream>

int f(int c);

int main()
{
    std::ifstream file;
    file.open("whale2.txt");

    if (!file.is_open())
        return 1;

    char p_ch, ch;
    file >> std::noskipws >> p_ch;
    int incorrect = 0;
    while (file >> std::noskipws >> ch)
    {
        if (f(p_ch) != ch)
            ++incorrect;
        p_ch = ch;
    }

    file.close();

    std::cout << incorrect;
}

แก้ไข:การใช้whale2.txtให้คะแนนดีกว่า


5
คุณสามารถแปลอาร์เรย์นี้เป็นสตริงตัวอักษรและ inline โดยตรงในสถานที่Lที่จะบันทึกพวงของตัวละคร :)
เควนติน

@Quentin ขอบคุณ! ตอนนี้ฉันสงสัยว่าทำไมฉันไม่คิดอย่างนั้นในตอนแรก ...
Steadybox

20

Python 2 * 516 + 521122 = 522154

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

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

from collections import Counter as C, defaultdict as D
R,l=range,10
s,n='',[D(C) for _ in R(l+1)]
def A(c):
 global s;s+=c;
 if len(s)<=l:return ' '
 P=D(lambda:0)
 for L in R(1,l+1):
  w=''.join(s[-L-1:-1]);n[L][w].update([c]);w=''.join(s[-L:])
  try:
   q,z=n[L][w].most_common(1)[0];x=sum(list(n[L][w].values()))
  except IndexError:continue
  p=z/x
  if x<3:p*=1/(3-x)
  P[q]+=p
 if not P:return ' '
 return max(P.items(),key=lambda i:i[1])[0]
import this, codecs as d
[A(c) for c in d.decode(this.s, 'rot-13')]

ผล:

ส่วนใหญ่พูดพล่อยๆแม้ว่าคุณจะเห็นมันหยิบขึ้นมาในวลีเป็นครั้งคราวเช่น "พ่อ Mapple"

errors: 521122
TRAINING:
result:  tetlsnowleof the won -opes  aIther Mapple,woneltnsinkeap hsd   lnd the  thth a shoey,aeidorsbine ao
actual: ntal knobs of the man-ropes, Father Mapple cast a look upwards, and then with a truly sailor-like bu
FINAL:
result: mnd wnd round  ahe   ind tveryaonsracting th ards the sol ens-ike aeock tolblescn the sgis of thet t
actual: und and round, then, and ever contracting towards the button-like black bubble at the axis of that s

รหัสทดสอบ:

ค่อนข้างง่ายเอาท์พุทตัวอย่างของข้อความที่จุดต่าง ๆ ใช้ whale2.txt เนื่องจากจะเป็นการหลีกเลี่ยงตรรกะพิเศษบางอย่างในการคำนวณบรรทัดใหม่

from minified import A

def score(predict, text):
    errors = 0
    newtext = []
    for i, (actual, current) in  enumerate(zip(text[1:], text[:-1])):
        next = predict(current)
        errors += (actual != next)
        newtext.append(next)
        if (i % (len(text) // 100) == 0):
            print ('.', end='', flush=True)
    return errors, ''.join(newtext)

t = open('whale2.txt')
text = t.read()
err2, text2 = score(A, text)
print('errors:', err2)
print("TRAINING:")
print(text2[100000:100100].replace('\n', '\\n'))
print(text1[100001:100101].replace('\n', '\\n'))
print("FINAL:")
print(text2[121400:1215500].replace('\n', '\\n'))
print(text[121401:1215501].replace('\n', '\\n'))

3
ยินดีต้อนรับสู่เว็บไซต์! นี่คือการส่งครั้งแรกที่ยอดเยี่ยม :)
DJMcMayhem

@DJMcMayhem ขอขอบคุณสำหรับการต้อนรับ ฉันสนุกกับการดูสักครู่ตอนนี้นี่เป็นการประกวดครั้งแรกที่ดึงดูดความสนใจของฉันสำหรับรายการ
user2699

19

C (gcc) , 679787 652892

84 76 ไบต์679619 652740 เดาไม่ถูกต้อง

p[128][128][128][128];a,b,c,d;g(h){p[a][b][c][d]=h;h=p[a=b][b=c][c=d][d=h];}

ลองออนไลน์!

อัปเดต: ~ 27,000 คะแนนปิดด้วยไฟล์ที่อัปเดต, 16 คะแนน (8 ไบต์) พร้อมฟังก์ชั่นการตีกอล์ฟที่ดีขึ้น

คำอธิบาย

วิธีการทำงานของมันคือเมื่อโค้ดวิ่งผ่านข้อความมันจะจดจำตัวอักษรตัวสุดท้ายที่ยกเลิกลำดับ 4 ตัวใด ๆ ที่กำหนดและส่งกลับค่านั้น ค่อนข้างคล้ายกับแนวทางของ Arnauld ด้านบน แต่ขึ้นอยู่กับความน่าจะเป็นโดยธรรมชาติของสองลำดับที่ได้รับ 4 ตัวอักษรซึ่งสิ้นสุดในลักษณะเดียวกัน

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

p[128][128][128][128];
a,b,c,d;
g(h){
    p[a][b][c][d]=h; // Memorize the last character.
    h=p[a=b][b=c][c=d][d=h]; // Read the guess. We save several
                             // bytes with the assignments inside indices.
}

... ลิงค์ TIO ไร้ประโยชน์ ดังนั้นฟังก์ชั่นจะคืนค่าของการบ้านครั้งสุดท้ายหรือไม่?
user202729

ให้ฉันแก้ไขคำตอบด้วยคำอธิบายแล้ว :)

1
@Rogem ฉันได้เพิ่มเวอร์ชัน de-golfed (ซึ่งฉันทำเพราะฉันไม่สามารถทำตามได้) - หวังว่านี่จะไม่รบกวนคุณ แต่โปรดย้อนกลับหากต้องการ
อดัมเดวิส

@AdamDavis สำหรับการใช้งานส่วนใหญ่ของ C ตัวแปรทั่วโลกทั้งหมดเริ่มต้นที่ศูนย์ มันเป็นพฤติกรรมที่ไม่ได้กำหนดดังนั้นจึงใช้ในการเขียนโค้ดเท่านั้น
NieDzejkob

1
@NieDzejkob อ่าใช่แล้วขอบคุณ! "ANSI-C กำหนดให้ตัวแปรแบบคงที่ / โกลบอลที่ไม่ได้กำหนดค่าเริ่มต้นทั้งหมดต้องมีค่าเริ่มต้นเป็น 0"
Adam Davis

16

sh + bzip2, 2 * 364106 = 728212

2 * 381249 + 0 = 762498

dd if=$0 bs=1 skip=49|bunzip2&exec cat>/dev/null

ตามด้วย bzip2- บีบอัด whale2.txt โดยที่ไบต์แรกหายไป

ละเว้นอินพุต ส่งออกคำตอบที่ถูกต้อง นี่เป็นพื้นฐานในปลายด้านหนึ่ง; daniero ให้พื้นฐานในปลายอื่น ๆ

สคริปต์ตัวสร้าง:

#!/bin/sh
if [ $# -ne 3 ]
then
    echo "Usage $0 gen.sh datafile output.sh"
    exit 1
fi

cat $1 > $3
dd ibs=1 if=$2 skip=1 | bzip2 -9 >> $3
chmod +x $3

I / O ชุดทดสอบ (tcc; ตัดบรรทัดแรกสำหรับ gcc) ทุกคนสามารถใช้ชุดทดสอบนี้ได้บนแพลตฟอร์มที่เหมาะสมซึ่งส่งโปรแกรมที่สมบูรณ์ซึ่งคาดว่าจะอ่าน / เขียน I / O จะใช้ I / O byte-at-a-time เพื่อหลีกเลี่ยงการโกง โปรแกรมลูกจะต้องล้างออกหลังจากทุกไบต์เพื่อหลีกเลี่ยงการปิดกั้น

#!/usr/bin/tcc -run
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, char **argv)
{
    volatile int result;
    int readfd[2];
    int writefd[2];
    int cppid;
    int bytecount;
    char c1, c2, c3;
    if (argc != 2) {
        printf("write X approximately -- service host\n");
        printf("Usage: %s serviceprocessbinary < source.txt\n", argv[0]);
        return 1;
    }
    /* Start service process */
    if (pipe(readfd)) {
        perror("pipe()");
        return 3;
    }
    if (pipe(writefd)) {
        perror("pipe()");
        return 3;
    }
    result = 0;
    if (!(cppid = vfork())) {
        char *argtable[3];
        argtable[0] = argv[1];
        argtable[1] = NULL;
        dup2(readfd[0], 0);
        dup2(writefd[1], 1);
        close(readfd[1]);
        close(writefd[0]);
        close(readfd[0]);
        close(writefd[1]);
        execvp(argv[1], argtable);
        if (errno == ENOEXEC) {
            argtable[0] = "/bin/sh";
            argtable[1] = argv[1];
            argtable[2] = NULL;
            /* old standard -- what isn't an executable
             * can be exec'd as a /bin/sh script */
            execvp("/bin/sh", argtable);
            result = ENOEXEC;
        } else {
            result = errno;
        }
        _exit(3);
    } else if (cppid < 0) {
        perror("vfork()");
        return 3;
    }
    if (result) {
        errno = result;
        perror("execvp()");
        return 3;
    }
    close(readfd[0]);
    close(writefd[1]);
    /* check results */
    read(0, &c2, 1);
    bytecount = 1;
    errno = 0;
    while (read(0, &c1, 1) > 0) {
        write(readfd[1], &c2, 1);
        if (read(writefd[0], &c3, 1) <= 0) {
            printf("%d errors (%d bytes)\n", result, bytecount);
            if (errno == 0)
                fprintf(stderr, "pipe: unexpected EOF\n");
            else
                perror("pipe");
            return 3;
        }
        if (c3 != c1)
            ++result;
        c2 = c1;
        ++bytecount;
    }
    printf("%d errors (%d bytes)\n", result, bytecount);
    return 0;
}

6
ฉันคิดว่าสิ่งที่เขาถามคือ: วิธีนี้ไม่ละเมิดbut may not load any other external files, and your code may not access the whale.txt file in any way other than described above.ข้อ?

8
@Rogem ข้อมูลที่ถูกบีบอัดจะถูกวางหลังจากสิ่งที่แสดงไว้ที่นี่และการเข้าถึงโค้ดเอง
user202729

4
คำถามกล่าวว่า: "การส่งของคุณจะเป็นโปรแกรมหรือฟังก์ชั่น (ฯลฯ ) ที่จะถูกเรียกหรือเรียกใช้หลายครั้งเมื่อมีการเรียกใช้ในnthช่วงเวลานั้นจะได้รับอักขระที่ n ของwhale.txtหรือwhale2.txtและจะต้องส่งออกเดาสำหรับ(n+1)thตัวละคร." - ข้อกำหนดนี้สำเร็จได้อย่างไร รหัสจะแสดงข้อความทั้งหมดของwhale.txtทุกครั้งที่มีการดำเนินการ
axiac

1
@axiac "มีอะไรดีตราบใดที่โปรแกรมของคุณให้หนึ่งไบต์ของเอาต์พุตก่อนที่จะรับไบต์ถัดไปของอินพุต"
user202729

5
@axiac ได้รับชุดทดสอบทดสอบฉันยินดีที่จะพิจารณาส่งโปรแกรมหนึ่งไบต์จาก STDIN ว่า "การโทรหรือเรียกใช้" สิ่งที่นำเข้าคือโปรแกรมส่งคืนหนึ่งไบต์ของเอาต์พุตหลังจากแต่ละไบต์ของอินพุตซึ่งอันนี้ทำจริงเมื่อรันผ่านชุดทดสอบ ตามที่คำถามบอกว่า "มีอะไรดีตราบใดที่โปรแกรมของคุณให้หนึ่งไบต์ของเอาต์พุตก่อนที่จะรับไบต์ถัดไปของอินพุต"
นาธาเนียล

13

Python 3 , 879766

F=[[0]*123for _ in range(123)]
P=32
def f(C):global P;C=ord(C);F[P][C]+=1;P=C;return chr(max(enumerate(F[C]),key=lambda x:x[1])[0])

ลองออนไลน์!


... ///คำตอบที่พิมพ์ช่องว่างรับ 10 upvotes ในขณะที่รหัสของฉันสามารถรับ 3 ...

คำอธิบาย:

สำหรับตัวละครแต่ละตัวโปรแกรม:

  • เพิ่มขึ้น frequency[prev][char]
  • ค้นหาตัวละครที่มีเวลามากที่สุด frequency[char]
  • และเอาท์พุทมัน

  • โค้ดที่ไม่ดีในลิงค์ TIO แสดงความคิดเห็น
  • รหัสคือ 131 ไบต์
  • รหัสทำงานในรายงานเครื่องของฉัน:
879504 / 1215235
Time: 62.01348257784468

ซึ่งมีคะแนนรวม

2*131 + 879504 = 879766

เนื่องจากไม่มีวิธีอัปโหลดไฟล์ขนาดใหญ่ไปยัง TIO (ยกเว้นขอให้เดนนิส) ตัวอย่างการรันในลิงค์ TIO จะรันโปรแกรมสำหรับข้อความเพียงส่วนเล็ก ๆ เท่านั้น

เมื่อเปรียบเทียบกับคำตอบที่เก่ากว่าอันนี้มีอักขระที่ไม่ถูกต้องอีก 362 ตัว แต่รหัสนั้นสั้นกว่า 255 ไบต์ ตัวคูณทำให้การส่งของฉันมีคะแนนต่ำกว่า


13

C #, 378 * 2 + 569279 = 570035

using System.Collections.Generic;using System.Linq;class P{Dictionary<string,Dictionary<char,int>>m=new
Dictionary<string,Dictionary<char,int>>();string b="";public char N(char
c){if(!m.ContainsKey(b))m[b]=new Dictionary<char,int>();if(!m[b].ContainsKey(c))m[b][c]=0;m[b][c]++;b+=c;if(b.Length>4)b=b.Remove(0,1);return
m.ContainsKey(b)?m[b].OrderBy(k=>k.Value).Last().Key:' ';}}

วิธีการนี้ใช้ตารางค้นหาเพื่อเรียนรู้อักขระที่พบบ่อยที่สุดที่ตามหลังสตริงที่กำหนด ปุ่มของตารางการค้นหามีความยาวสูงสุด 4 อักขระดังนั้นฟังก์ชันจะอัปเดตตารางการค้นหาด้วยอักขระปัจจุบันก่อนจากนั้นเพียงตรวจสอบว่าอักขระตัวใดที่น่าจะเกิดขึ้นมากที่สุดหลังจาก 4 ตัวก่อนหน้ารวมถึงตัวปัจจุบัน . หากไม่พบอักขระทั้ง 4 ตัวในตารางค้นหาจะพิมพ์เว้นวรรค

รุ่นนี้ใช้whale2.txtไฟล์เนื่องจากมันช่วยเพิ่มจำนวนการคาดเดาที่ประสบความสำเร็จอย่างมาก

ต่อไปนี้เป็นรหัสที่ใช้ในการทดสอบระดับ:

using System;
using System.IO;
using System.Text;

public class Program
{
    public static void Main(string[] args)
    {
        var contents = File.OpenText("whale2.txt").ReadToEnd();
        var predictor = new P();

        var errors = 0;
        var generated = new StringBuilder();
        var guessed = new StringBuilder();
        for (var i = 0; i < contents.Length - 1; i++)
        {
            var predicted = predictor.N(contents[i]);
            generated.Append(predicted);
            if (contents[i + 1] == predicted)
                guessed.Append(predicted);
            else
            {
                guessed.Append('_');
                errors++;
            }
        }

        Console.WriteLine("Errors/total: {0}/{1}", errors, contents.Length);
        File.WriteAllText("predicted-whale.txt", generated.ToString());
        File.WriteAllText("guessed-whale.txt", guessed.ToString());

        Console.ReadKey();
    }
}

รหัสทำงานใน 2 นาทีแทบ สำหรับบันทึกนี่คือสิ่งที่ฉันได้รับเมื่อฉันแก้ไขขนาดของคีย์ของตารางค้นหา (รวมถึงผลลัพธ์ของการรันครั้งที่สองโดยไม่รีเซ็ตโมเดล):

Size   Errors   Errors(2)
-------------------------
1      866162   865850
2      734762   731533
3      621019   604613
4      569279   515744
5      579446   454052
6      629829   396855
7      696912   335034
8      765346   271275
9      826821   210552
10     876471   158263

มันน่าสนใจที่จะรู้ว่าทำไมขนาดตัวอักษร 4 ตัวจึงเป็นตัวเลือกที่ดีที่สุดในอัลกอริทึมนี้

การเปรียบเทียบข้อความ

เดิม:

"And did none of ye see it before?" cried Ahab, hailing the perched men all around him.

"I saw him almost that same instant, sir, that Captain Ahab did, and I cried out," said Tashtego.

"Not the same instant; not the same--no, the doubloon is mine, Fate reserved the doubloon for me. I only; none of ye could have raised the White Whale first. There she blows!--there she blows!--there she blows! There again!--there again!"

บิ๊ก:

"Tnd tes note of to seamtn we ore  
sried thab  wedleng the srriead te  a l tneund tes  
"T day tim t lost shet toie tn tand  aor, ahet taptain thab sid  tnd t waued tnt   said teshtego  
"To, ahe shme tn tand  aot the shme whot nhe sewbteodsan tagd  althsteatnved the sewbteodsaor te, I hncy  aote of to sanld bave beised the shate Whale iorst  Bhe e ati boaos  -the   ati boaos  -the   ati boaos  the e anains -ahe   anains 

คาดเดา:

"_nd ___ no_e of __ se____ _e_ore____ried _hab_ ___l_ng the __r___d _e_ a_l ___und _____
"_ _a_ _im ___ost _h_t ___e _n_tan__ __r, _h_t _aptain _hab _id_ _nd _ ___ed __t__ said __shtego__
"_o_ _he s_me _n_tan__ _ot the s_me___o_ _he ___b__o____ _____ __t___e___ved the ___b__o___or _e_ I _n_y_ _o_e of __ ___ld _ave __ised the _h_te Whale __rst_ _he_e ___ b___s__-the__ ___ b___s__-the__ ___ b___s_ _he_e a_ain__-_he__ a_ain__

เปลี่ยนบันทึก

  • 569279 - เปลี่ยนเป็นwhale2.txtดังนั้นจึงเป็นการเพิ่มประสิทธิภาพออก
  • 577366 - ปรับให้เหมาะสมกับโค้ดที่พยายามเดาว่าเมื่อใดที่จะส่งคืนบรรทัดฟีด
  • 590354 - รุ่นดั้งเดิม

4
ขอขอบคุณที่แสดงความแปรปรวนในขณะที่คุณเปลี่ยนขนาดคีย์และเกณฑ์คอลัมน์!
Jeremy Weirich

ฉันได้อัปเดตคำถามด้วยไฟล์เวอร์ชันที่ข้อความไม่ถูกห่อ - คุณอาจบันทึกบางจุดโดยใช้สิ่งนั้น
Nathaniel

@ นาธาเนียลมันทำแน่นอน ฉันได้อัพเดตคำตอบแล้ว
Charlie

คุณสามารถบันทึกไบต์โดยใช้ var แทนการประกาศประเภท
Ed T

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

11

Java 7, 1995 ตัวอักษร, (1995 * 2 + 525158) 529148

Java ดูดสำหรับโปรแกรมขนาดเล็ก อย่างไรก็ตามฉันพยายามหลายวิธีที่ซับซ้อนและยุ่งยากมากซึ่งให้ผลลัพธ์ที่น่าประหลาดใจ ฉันกลับไปและทำวิธีง่ายๆง่ายๆซึ่งทำให้โปรแกรมมีขนาดเล็กลงและให้ผลลัพธ์ที่ดีขึ้น

วิธีนี้ง่ายมากจริง ๆ มันดึงข้อมูลอักขระ x ก่อนหน้า (สุ่มนอกเหนือจากสตริงย่อยทั้งหมดของอักขระเหล่านั้น) เข้าไปใน hashtable ซึ่งแมปกับอักขระปัจจุบัน จากนั้นติดตามว่าลวดลายใดทำนายตัวละครปัจจุบันได้อย่างแม่นยำที่สุด หากรูปแบบที่นำหน้าอักขระบางตัวพบหลายครั้งจะประสบความสำเร็จในการทำนายอักขระ มันให้ความสำคัญกับสตริงที่ยาวขึ้นและให้ความสำคัญกับอักขระที่มักตามหลังสตริงที่กำหนด อัลกอริทึมนี้ไม่รู้อะไรเกี่ยวกับประเภทของเอกสารหรือภาษาอังกฤษ

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

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

  • (1950 * 2 + 532919) 536819
  • (2406 * 2 + 526233) 531045ตรวจสอบเครื่องหมายวรรคตอนเพื่อคาดเดาได้ดีขึ้น
  • (1995 * 2 + 525158) 529,148 tweaking เพิ่มเติมgolfedไป verbiage บางอย่าง

package mobydick; import java.util.HashMap; public class BlindRankedPatternMatcher { String previousChars = ""; int FRAGLENGTH = 9; HashMap > patternPredictor = new HashMap<>(); void addWordInfo(String key, String prediction) { HashMap predictions = patternPredictor.get(key); if (predictions == null) { predictions = new HashMap(); patternPredictor.put(key, predictions); } WordInfo info = predictions.get(prediction); if (info == null) { info = new WordInfo(prediction); predictions.put(prediction, info); } info.freq++; } String getTopGuess (String pattern) { if (patternPredictor.get(pattern) != null) { java.util.List predictions = new java.util.ArrayList<>(); predictions.addAll(patternPredictor.get(pattern).values()); java.util.Collections.sort(predictions); return predictions.get(0).word; } return null; 
} String mainGuess() { 
if (trimGuess(",") != null) return trimGuess(","); if (trimGuess(";") != null) return trimGuess(";"); 
if (trimGuess(":") != null) return trimGuess(":"); 
if (trimGuess(".") != null) return trimGuess("."); if (trimGuess("!") != null) return trimGuess("!"); if (trimGuess("?") != null) return trimGuess("?"); if (trimGuess(" ") != null) return trimGuess(" "); for (int x = 0;x< previousChars.length();x++) { String tg = getTopGuess(previousChars.substring(x)); if (tg != null) { return tg; } } return "\n"; } String trimGuess(String c) { if (previousChars.contains(c)) { 
String test = previousChars.substring(previousChars.indexOf(c)); return getTopGuess(test); } return null; } public String predictNext(String newChar) { if (previousChars.length() < FRAGLENGTH) { previousChars+= newChar; } else { for (int x = 0; x addWordInfo(previousChars.substring(x), newChar); } previousChars = previousChars.substring(1) + newChar; } return mainGuess(); 
} class WordInfo implements Comparable { public WordInfo (String text) { this.word = text; } 
String word; int freq = 0; @Override public int compareTo(WordInfo arg0) { return Integer.compare(arg0.freq, this.freq); }

นั่นเป็นคะแนนที่ดีมากสำหรับภาษา verbose
DJMcMayhem

1
ฉันคิดว่ามันคุ้มค่าที่จะถ่ายเพราะขนาดของไฟล์ให้พื้นที่มากมายสำหรับการปรับปรุงเมื่อเทียบกับขนาดของโปรแกรม
Jim W

3
สิ่งนี้ไม่สามารถคอมไพล์ได้ใน Java 7 (หรือ Java เวอร์ชันใด ๆ สำหรับสิ่งที่คุ้มค่า) คุณช่วยแก้ไขรหัสของคุณได้ไหม เมื่อเสร็จแล้วฉันยินดีที่จะเล่นกอล์ฟเพื่อให้คะแนนของคุณดีขึ้น
Olivier Grégoire

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

อึฉันทำสิ่งนี้ในขณะที่เบื่องานเก่าของฉันและไม่ได้ใช้รหัสกับฉัน ฉันจะต้องดูมันเพื่อดูว่าพิมพ์ผิดอยู่ที่ไหน
จิม W

10

Python 3, 2 × 497 + 619608 = 620602 2 × 496 + 619608 = 620600

import operator as o
l=''
w=''
d={}
p={}
s=0
def z(x,y):
 return sorted([(k,v) for k,v in x.items() if k.startswith(y)],key=o.itemgetter(1))
def f(c):
 global l,w,d,p,s
 r=' '
 if c in' \n':
  s+=1
  if w in d:d[w]+=1
  else:d[w]=1
  if w:
   if l:
    t=l+' '+w
    if t in p:p[t]+=1
    else:p[t]=1
   n=z(p,w+' ')
   if n:g=n[-1];l=w;w='';r=g[0][len(l)+1]
   else:l=w;w='';r='t'
 else:
  w=w+c;m=z(p,w)
  if m:
   g=m[-1]
   if g[0]==w:
    if s>12:s=0;r='\n'
   else:r=g[0][len(w)]
 return r

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

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

นอกจากนี้ยังสร้างพจนานุกรมคำศัพท์คู่ที่ไม่มีประสิทธิภาพอย่างน่ารังเกียจ เมื่อกดปุ่มขอบเขตของคำมันจะเดาได้ว่าตัวอักษรตัวต่อไปคือตัวอักษรตัวแรกของคำที่สองในคู่คำที่ตรงกันมากที่สุดหรือtหากไม่มีการจับคู่ แม้ว่ามันจะไม่ฉลาดเท่าไหร่นัก ต่อไปนี้Mobyโปรแกรมคาดเดาได้อย่างถูกต้องว่าตัวละครต่อไปคือDแต่แล้วก็ลืมทุกอย่างเกี่ยวกับบริบทและมักจะจบลงด้วยการเรียกวาฬ "Moby Duck" (เพราะคำว่า "ดัตช์" ดูเหมือนจะบ่อยขึ้นในช่วงครึ่งแรกของข้อความ ) มันจะง่ายต่อการแก้ไขโดยการจัดลำดับความสำคัญของคู่คำมากกว่าคำแต่ละคำ แต่ฉันคาดหวังว่าผลกำไรจะเล็กน้อย (เนื่องจากโดยปกติแล้วจะถูกต้องจากอักขระที่สามบนและคู่คำนั้นไม่เป็นประโยชน์ในตอนแรก)

ฉันสามารถปรับแต่งนี้ให้ตรงกับข้อความที่ให้ไว้ได้ดีกว่า แต่ฉันไม่คิดว่าการปรับอัลกอริทึมด้วยตนเองตามความรู้ก่อนหน้าของอินพุตเป็นจริงในจิตวิญญาณของเกมดังนั้นนอกเหนือจากการเลือก t เป็นตัวเลือกสำรองหลังช่องว่าง และฉันก็ไม่ควรทำอย่างนั้น) ฉันหลีกเลี่ยงสิ่งนั้น ฉันเพิกเฉยต่อความยาวบรรทัดที่รู้จักของไฟล์อินพุตและแทนที่\nหลังจากเว้นวรรค 13 ทุกครั้ง - นี่เป็นการจับคู่ที่ไม่ดีอย่างแน่นอนความตั้งใจหลักคือการรักษาความยาวบรรทัดให้เหมาะสมแทนที่จะจับคู่อินพุต

รหัสไม่เร็วอย่างแน่นอน (ประมาณ 2 ชั่วโมงในเครื่องของฉัน) แต่โดยรวมแล้วมีตัวละครประมาณครึ่งตัว (49%) ฉันคาดหวังว่าคะแนนจะดีขึ้นเล็กน้อยหากทำงานต่อwhale2.txtแต่ฉันก็ไม่ได้ทำเช่นนั้น

จุดเริ่มต้นของเอาต์พุตมีลักษณะดังนี้:

T t t t t t t t t L t t t tsher t t t ty t to t t te t t t t t tem t t t d b ta tnL te t tv tath a to tr t tl t l toe g to tf ahe gi te we th austitam ofd laammars, tn te to t tis nf tim oic t t th tn cindkth ae tf t d bh ao toe tr ai tat tnLiat tn to ay to tn hf to tex tfr toe tn toe kex te tia t l t l ti toe ke tf hhe kirl tou tu the tiach an taw th t t Wh tc t d t te the tnd tn tate tl te tf teu tl tn oan. HeAL. tn nn tf r t-H ta t WhALE.... S tn nort ts tlom rhe ka tnd Dr t t tALL th teuli th tis t-H taCTIONARY " t r t o t a t A t . t eALT t I t HLW t I t e t w t AO t t t AOLE, I T t t t ALE t w t t R t EK t T t R tSupplied by wnLw t t iit ty cce thet whe to tal ty tnd

แต่ในตอนท้ายมันดูเหมือน ... บางสิ่งบางอย่างมากขึ้น ตอนที่ฉันชอบที่สุดตอนปลายเล่ม

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

ออกมาเป็น

I dhrnery oyay ooom the woc Ihal iiw chshtego -tit my ti ddohe bidmer Hh, ho sheee opdeprendera toetis of tygd ahesgapdo tnep tnd tf y arosl tinl ahesgaorsltoak, and tidlhty ai p, cnd telas taep toip syst ho she tachlhe tnd tith ut ay Rnet hor bf toom the wist tord oaeve of ty nsst toip recked,hontain th, tingly toadh af tingly tike 'h, tot a hoet ty oh ost sreat ess iik in ty oh ost sremf Hew hiw"aoom tnl tou oolthert tyand . taoneoo sot an ao syad tytlows of ty oii e oor hoi tike and th ohes if oaped uoueid tf ty ooadh Ih ards the t houle lhesganl p tyt tpdomsuera tiile ah the wist t hrenelidtith the Ioom ti p s di dd o hoinbtn the Ior tid toie o hoetefy oist tyoakh on the Opr tnl toufin and tnl ti dd .mh tf ooueon gaor tnd todce tovther lon by tygd ait my the th aih tapce ciice toill moaneng she thesgh thmd th the thesgaoy d jiile YhE t hrve tpothe woerk "

นั่นจะทำให้The Wrath of Khanสับสนมากขึ้น และ "เหงา" → "tingly" เป็นการทดแทนที่น่าพอใจเป็นพิเศษ

แก้ไข:บันทึกหนึ่งไบต์ด้วยการลบช่องว่างที่ไม่เกี่ยวข้อง

เกณฑ์การให้คะแนน

#! /usr/bin/env python3
import sys
import os
import mobydick as moby


def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)

total = 0
right = 0
real_char = ''
guess_char = 'T'
print('T',end='')
with open("whale.txt") as whale:
    while True:
        if real_char == guess_char:
            right += 1
        real_char = whale.read(1)
        if not real_char:
            eprint(str(right) + " / " + str(total) + " (" +
                str(right/total*100) + "%)")
            size = os.path.getsize("mobydick.py")
            eprint("Source size: " + str(size) + "B")
            eprint("Score: " + str(2*size + total - right))
            sys.exit(0)
        guess_char = moby.f(real_char)
        print(guess_char,end='')
        total += 1

สิ่งนี้จะรันโปรแกรมสำหรับข้อความของ Moby Dick และส่งออกข้อความ "ทำนาย" เป็น stdout และใช้ stderr ในทางที่ผิดเพื่อเขียนคะแนน ฉันขอแนะนำให้เปลี่ยนเส้นทางไปยังไฟล์


2
ยินดีต้อนรับสู่ PPCG!
Martin Ender

1
จะไม่lambda i:i[1]ถูกกว่าการจัดการกับoperator?
Draconis

@ Draconis เกือบจะแน่นอน
georgewatson

9

C ++, 2 · 62829 + 318786 = 444444

เพื่อเรียกใช้โปรแกรมนี้คุณจะต้องไฟล์นี้ที่นี่Cซึ่งจะต้องมีชื่อ

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

เมื่อเห็นว่าคำตอบนี้ใช้รูปแบบที่แน่นอนเหมือนก่อนหน้านี้การปรับปรุงเป็นกลไกข้อมูลเชิงทฤษฎีที่ดีกว่ากลไก "ย้อนกลับ" ที่อธิบายไว้ก่อนหน้านี้ สิ่งนี้ทำให้เกิดข้อผิดพลาดน้อยลงในขณะที่มีความยาวรวมกันน้อย ตัวโปรแกรมเองไม่ได้ตีกอล์ฟมากนักเพราะไม่ใช่ผู้มีส่วนร่วมสำคัญในการให้คะแนน

โปรแกรมยาว 2167 ไบต์ (รวมถึงแท็บทั้งหมดสำหรับการย่อหน้าและอักขระที่ไม่จำเป็นอื่น ๆ อีกมากมาย แต่ก่อนรหัสทดสอบ) และไฟล์ไบนารีCมีความยาว 60661 ไบต์ดังนั้นภายใต้กฎการให้คะแนนหลายไฟล์เราให้คะแนนL2167 + 60661 + 1 = 62829

โปรแกรมใช้เวลาประมาณ 8 นาทีในการรันบนm5.4xlargeอินสแตนซ์บน Amazon EC2 และใช้หน่วยความจำน้อยกว่า 16 GB (ไม่จำเป็นต้องใช้หน่วยความจำมากเกินไป - เราไม่ได้ปรับให้เหมาะสมเช่นกัน)

#include <map>
#include <queue>
#include <vector>
using namespace std;

FILE *in;
unsigned int a, b = -1, c, d;
string s, t;
double l, h = 1, x[128][129], y[129], m[128];
map<string, int> N;
map<string, double[128]> M;
int G, S;

int f(int C)
{
    int i, j;
    for (i = 0; i <= 20 && i <= S; i++) {
        t = s.substr(S - i);
        N[t]++;
        M[t][C]++;
    }
    s += C;
    S++;

    for (i = 0; i < 128; i++)
        m[i] = 0;

    int E = 0;
    for (i = 20; i >= 0; i--) {
        if (i > S)
            continue;
        t = s.substr(S - i);
        if (i <= 2 && E >= 100 && (i == 0 || t[0] != ' '))
            break;
        if (M.find(t) == M.end())
            continue;
        for (j = 0; j < 128; j++) {
            m[j] += M[t][j] / N[t];
        }
        E += N[t];
    }

    double r = 0;
    for (i = 0; i < 128; i++)
        r += m[i];
    for (i = 0; i < 128; i++)
        m[i] = m[i] / r;

    if (!in) {
        in = fopen("C", "r");
        for (i = 0; i < 4; i++)
            c = c << 8 | getc(in);
    } else {
        l = x[C][G]
            + (l - y[G]) * (x[C][G + 1] - x[C][G]) / (y[G + 1] - y[G]);
        h = x[C][G]
            + (h - y[G]) * (x[C][G + 1] - x[C][G]) / (y[G + 1] - y[G]);
    }

    priority_queue<pair<double, int>> q;
    for (i = 0; i < 128; i++) {
        q.push(make_pair(m[i], i));
    }

    int n = 0;
    double s = 0;
    while (q.size()) {
        i = q.top().second;
        q.pop();
        if (m[i] < s / (n + 15))
            break;
        s += m[i];
        n++;
    }

    r = 0;
    for (i = 0; i < 128; i++) {
        y[i + 1] = m[i] - s / (n + 15);
        if (y[i + 1] < 0)
            y[i + 1] = 0;
        r += y[i + 1];
    }
    for (i = 0; i < 128; i++)
        y[i + 1] /= r;

    for (i = 0; i < 128; i++) {
        r = 0;
        for (j = 0; j < 128; j++) {
            x[i][j + 1] = y[j + 1];
            if (i == j)
                x[i][j + 1] *= 16;
            r += x[i][j + 1];
        }
        for (j = 0; j < 128; j++)
            x[i][j + 1] /= r;
        x[i][0] = 0;
        for (j = 0; j < 128; j++)
            x[i][j + 1] += x[i][j];
    }

    y[0] = 0;
    for (i = 0; i < 128; i++)
        y[i + 1] += y[i];

    for (G = 0; G < 128; G++) {
        if (y[G + 1] <= l)
            continue;
        if (y[G + 1] < h) {
            d = a + (b - a) * ((h - y[G + 1]) / (h - l));
            if (c <= d) {
                b = d;
                l = y[G + 1];
            } else {
                a = d + 1;
                h = y[G + 1];
            }
            while ((a ^ b) < (1 << 24)) {
                a = a << 8;
                b = b << 8 | 255;
                c = c << 8 | getc(in);
            }
        }
        if (h <= y[G + 1])
            return G;
    }
}
// End submission here.  Test code follows.
int main()
{
    FILE *moby = fopen("whale2.txt", "r");

    int E = 0;
    int c = getc(moby);
    while (c != EOF) {
        int guess = f(c);
        c = getc(moby);
        if (c != guess)
            E++;
    }

    printf("E=\t%d\n", E);

    return 0;
}

7

Python 3, 526640

274 ไบต์ข้อผิดพลาด 526092 (โดยใช้whale2.txt) นี่คือความสามารถในการปรับปรุงเพิ่มเติมอย่างแน่นอน แต่ได้มาถึงขั้นตอน "ดีพอที่จะโพสต์" แล้ว

from collections import*
D=defaultdict
M=[D(lambda:D(int))for i in range(10)]
X=""
def f(c):
 global X;G=D(int)
 for L in range(10):
  M[L][X[:L]][c]+=1;N=M[L][(c+X)[:L]]
  if N:g=max(N,key=lambda k:(N[k],k));G[g]+=N[g]*L**8
 X=(c+X)[:10]
 return max(G,key=lambda k:(G[k],k))

แนวคิดคือเพื่อเก็บความถี่ของการวิ่งทั้งหมด 2, 3, 4, ... , 10 ตัวอักษร สำหรับความยาวแต่ละ L เหล่านี้เราตรวจสอบว่าอักขระ L-1 ล่าสุดตรงกับรูปแบบที่เก็บไว้หรือไม่ ถ้าเป็นเช่นนั้นเราเดาว่า G Lเป็นตัวละครต่อไปที่พบบ่อยที่สุดตามรูปแบบนั้น เรารวบรวมการเดาได้ถึงเก้าครั้งด้วยวิธีนี้ ในการตัดสินใจว่าจะเดาว่าจะใช้แบบใดเราจะกำหนดความถี่ของแต่ละรูปแบบตามความยาวของมันไปจนถึงกำลังที่ 8 เลือกการคาดเดาด้วยผลรวมความถี่ถ่วงน้ำหนักที่ใหญ่ที่สุด หากไม่มีรูปแบบที่ตรงกับที่เราคาดเดาพื้นที่

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

นี่คือเวอร์ชันที่อยู่ระหว่างดำเนินการที่ยังไม่ได้ดำเนินการของฉัน:

from collections import defaultdict

PATTERN_MAX_LEN = 10
prev_chars = ""
patterns = [defaultdict(lambda:defaultdict(int))
            for i in range(PATTERN_MAX_LEN)]
# A pattern dictionary has entries like {" wh": {"i": 5, "a": 9}}

def next_char(c):
    global prev_chars
    guesses = defaultdict(int)
    for pattern_len in range(PATTERN_MAX_LEN):
        # Update patterns dictionary based on pattern and c
        pattern = prev_chars[:pattern_len]
        patterns[pattern_len][pattern][c] += 1
        # Make a guess at the next letter based on pattern (including c)
        pattern = (c + prev_chars)[:pattern_len]
        if pattern in patterns[pattern_len]:
            potential_next_chars = patterns[pattern_len][pattern]
            guess = max(potential_next_chars,
                        key=lambda k:(potential_next_chars[k], k))
            frequency = potential_next_chars[guess]
            # Exact formula TBD--long patterns need to be heavily
            # advantaged, but not too heavily
            weight = frequency * pattern_len ** 8
            guesses[guess] += weight
    # Update prev_chars with the current character
    prev_chars = (c + prev_chars)[:PATTERN_MAX_LEN]
    # Return the highest-weighted guess
    return max(guesses, key=lambda k:(guesses[k], k))

และสายรัดทดสอบ:

from textPredictorGolfed import f as next_char
# OR:
# from textPredictor import next_char

total = 0
correct = 0
incorrect = 0

with open("whale2.txt") as file:
    character = file.read(1)
    while character != "":
        guess = next_char(character)
        character = file.read(1)
        if guess == character:
            correct += 1
        else:
            incorrect += 1
        total += 1

print("Errors:", incorrect, "({:.2f}%)".format(100 * incorrect / total))

นี่คือตัวอย่างผลลัพธ์บางส่วนจากใกล้จุดเริ่มต้นของข้อความ แล้วเราจะเริ่มเห็นความสามารถในการที่จะเสร็จสิ้นคำทั่วไปหลังจากที่ได้เห็นตัวอักษรตัวแรกของพวกเขา ( in, to, and, by; ยังเห็นได้ชัดschool)

 you take in hand to school others, and to teach them by what name a whale-fish
xU wshhlnrwn cindkgo dooool)tfhe -; wnd bo so rhoaoe ioy aienisotmhwnqiatl t n 

ใกล้ถึงจุดสิ้นสุดยังมีข้อผิดพลาดมากมาย แต่ยังมีลำดับที่ดีมาก ( shmage seashawksเช่น)

savage sea-hawks sailed with sheathed beaks. On the second day, a sail drew near
shmage seashawks wtidod oith tua dh   tyfr.  Tn the shaond tay, wnltiloloaa niar

เป็นที่น่าสนใจที่จะดูข้อผิดพลาดบางอย่างและคาดเดาว่าอัลกอริทึม "คำที่คาดหวัง" คืออะไร ตัวอย่างเช่นหลังจาก sailโปรแกรมทั้งสองครั้งคาดการณ์o- สำหรับsailorฉันเข้าใจ หรืออีกครั้งหลังจากที่, aคาดว่าn--possibly , andเพราะการเกิดขึ้นร่วมกันของ


การเปลี่ยนแปลง:

  • 274 * 2 + 526092 = 526640ค้นพบอัลกอริทึมด้วยค่าใช้จ่ายของข้อผิดพลาดพิเศษเล็กน้อย
  • 306 * 2 + 526089 = 526701รุ่นดั้งเดิม

6

Python 2 คะแนน: 2 * (407 + 56574) + 562262 = 676224

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

รหัส:

import zlib
f=open("d","rb")
l=zlib.decompress(f.read()).split()
w=""
def f(c):
 global w
 if c.isalpha():
  w+=c
  try:n=next(x for x in l if x.startswith(w))
  except StopIteration:return" "
  if len(n)>len(w):
   return list(n)[len(w)]
  return" "
 w="";
 n=ord(c)
 if n>31:
  return list("t \n 2  sS \n  -  08........       huaoRooe oioaoheu thpih eEA \n   neo    enueee neue hteht e")[n-32]
 return"\n"

ข้อมูล: https://www.dropbox.com/s/etmzi6i26lso8xj/d?dl=0

ชุดทดสอบ:

incorrect = 0

with open("whale2.txt") as file:
    p_ch = ch = file.read(1)
    while True:
        ch = file.read(1)
        if not ch:
            break
        f_ch = f(p_ch)
        if f_ch != ch:
            incorrect += 1
        p_ch = ch

print incorrect

แก้ไข:การใช้whale2.txtให้คะแนนดีกว่า


5

C ++ (GCC), 725 × 2 + 527076 = 528526

อีกหนึ่งการส่งคำนำหน้าความถี่ วิ่งต่อwhale2.txtไปและได้คะแนนคล้ายกัน (แย่กว่าเล็กน้อย) กว่าคนอื่น ๆ

#import<bits/stdc++.h>
char*T="\n !\"$&'()*,-.0123456789:;?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]_abcdefghijklmnopqrstuvwxyz";
int I[124];std::string P(7,0);struct D{int V=0;std::array<int,81>X{{0}};};std::vector<D>L(1);D
init(){for(int i=81;i--;)I[T[i]]=i;}int
f(int c){P=P.substr(1)+(char)I[c];for(int i=7;i--;){int D=0;for(char
c:P.substr(i)){if(!L[D].X[c]){L[D].X[c]=L.size();L.push_back({});}D=L[D].X[c];}++L[D].V;}std::vector<int>C(81);for(int
i=81;i--;)C[i]=i;for(int
i=0;i<7;++i){int D=0;for(char c:P.substr(i)){D=L[D].X[c];if(!D)break;}if(!D)continue;int M=0;for(int
x:C)M=std::max(M,L[L[D].X[x]].V);C.erase(std::remove_if(C.begin(),C.end(),[&](int
x){return L[L[D].X[x]].V!=M;}),C.end());if(C.size()<2)break;}return T[C[0]];}

อันนี้ละโมบหาสตริงที่ยาวที่สุดที่ขึ้นต้นด้วยคำต่อท้ายของประวัติและหากมีผู้สมัครหลายคนให้ทำการเบรคด้วยสตริงที่สั้นกว่า

ตัวอย่างเช่นหากที่ผ่านมา 7 ตัวอักษรabcdefghและสตริงabcdefghiและabcdefghjปรากฏขึ้นพร้อมกับความถี่ที่ใหญ่ที่สุดในสตริงทั้งหมดของรูปแบบabcdefgh*การส่งออกจะเป็นอย่างใดอย่างหนึ่งiหรือj, เบรคมีคำต่อท้ายสั้น ( bcdefgh, cdefgh, ... )

ด้วยเหตุผลที่ไม่รู้จักมีอะไรมากกว่า 7 และคอมพิวเตอร์ของฉันมี RAM ไม่เพียงพอที่จะเรียกใช้ แม้ว่าจะมี 7 ฉันก็ต้องปิดเว็บเบราว์เซอร์ทั้งหมดเพื่อให้ทำงานได้


รหัสการทดสอบ:

int main() {
    init(); 

    std::cout << "Start ---\n";
    std::time_t start = std::clock();

    std::ifstream file {"whale2.txt"};
    // std::ofstream file_guess {"whale_guess.txt"};
    std::ofstream file_diff {"whale_diff.txt"};
    if (!file.is_open()) {
        std::cout << "File doesn't exist\n";
        return 0;
    }

    char p_ch, ch;
    file >> std::noskipws >> p_ch;
    int incorrect = 0, total = 0;
    // file_diff << p_ch;

    int constexpr line_len = 80;
    std::string correct, guess_diff;
    correct += p_ch;
    guess_diff += '~';

    while (file >> ch) {
        char guess = f(p_ch);

        // file_guess << guess;
/*        if (guess != ch) {
            if (ch == '\n') {
                file_diff << "$";
            } else if (ch == ' ') {
                file_diff << '_';
            } else {
                file_diff << '~';
            }
        } else {
            file_diff << ch;
        }*/
        incorrect += (guess != ch);
        total += 1;
        p_ch = ch;

        if (guess == '\n') guess = '/';
        if (ch == '\n') ch = '/';
        correct += ch; guess_diff += (ch == guess ? ch == ' ' ? ' ' : '~' : guess);
        if (correct.length() == line_len) {
            file_diff << guess_diff << '\n' << correct << "\n\n";
            guess_diff.clear();
            correct.clear();
        }
    }

    file_diff << guess_diff << '\n' << correct << "\n\n";

    file.close();
    file_diff.close();

    std::cout << (std::clock() - start) 
    / double(CLOCKS_PER_SEC) << " seconds, "
    "score = " << incorrect << " / " << total << '\n';
}

Ungolfed:

size_t constexpr N = 7;

int constexpr NCHAR = 81;

std::array<int, NCHAR> const charset = {{
'\n', ' ', '!', '"', '$', '&', '\'', '(', ')', '*', ',', '-', '.', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '?', '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', '[', ']', '_', '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'
}}; // this actually contains a lot of information, may want to golf it
// (may take the idea of using AndersKaseorg's algorithm, late acceptance hill climbing)

std::array<int, 'z' + 1> const char_index = [](){
    std::array<int, 'z' + 1> char_index;
    for (size_t i = NCHAR; i --> 0;) 
        char_index[charset[i]] = i;
    return char_index;
}(); // IIFE ?

std::string past (N, 0); 
// modifying this may improve the score by a few units

struct node {
    int value = 0;
    std::array<size_t, NCHAR> child_index {{0}};
};
std::vector<node> node_pool (1); // root

int f(int c) {
    past = past.substr(1) + (char) char_index[c];

    for (size_t i = 0; i < N; ++i) {
        // add past.substr(i) to the string
        size_t node = 0;
        for (char c : past.substr(i)) {
            if (node_pool[node].child_index[c] == 0) {
                node_pool[node].child_index[c] = node_pool.size();
                node_pool.emplace_back();
            }
            node = node_pool[node].child_index[c];
        }
        assert(node != 0); // the substring is non-empty
        ++node_pool[node].value;
    }

    std::vector<size_t> candidates (NCHAR);
    std::iota(candidates.begin(), candidates.end(), 0);
    for (size_t i = 0; i < N; ++i) {
        size_t node = 0;
        for (char c : past.substr(i)) {
            node = node_pool[node].child_index[c];
            if (node == 0) break;
        }
        if (node == 0) continue;

        assert(node_pool[0].value == 0);
        int max_value = 0;
        for (size_t x : candidates)
            max_value = std::max(max_value, node_pool[node_pool[node].child_index[x]].value);

        candidates.erase(
            std::remove_if(candidates.begin(), candidates.end(), [&](size_t x){
                return node_pool[node_pool[node].child_index[x]].value != max_value;
            }), candidates.end()
        );

        if (candidates.size() == 1) 
            break;
    }

    return charset[candidates[0]];
}

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

~ ~s  ta~ hard ts tt~~~~~~~ ~doam ~~ ar~ ~ i~~~ ~~~ ~he~~~~,a~ t~~~~ t~ ho~si~  
n--as his wont at intervals--stepped forth from the scuttle in which he leaned, 

~~~ thr~ ~~ t~~ crp~~~~~~~~ a~ wap~~~~~ a~eo~~ h~~ o~~ s~~~ or~~y~ ~  boog~e~~ t
and went to his pivot-hole, he suddenly thrust out his face fiercely, snuffing u

~ a~~ ~h~ ~n~ onitn~oi~~~~~~ ~~a~ ~ cewsoat~  a~ tae~~~~ ~e~~t~~ te~~ ouc~s~i~~ 
p the sea air as a sagacious ship's dog will, in drawing nigh to some barbarous 

ct as I~ iisk~~~~ ~~e~ tls~~~~ i~~~ ~~ soe~e Ae ~ ~~e~ tar~~~~~ trd~  ot ~ h~~~ 
isle. He declared that a whale must be near. Soon that peculiar odor, sometimes 

อันนี้ใกล้ถึงจุดสิ้นสุดของข้อความ คำยาวส่วนใหญ่จะคาดการณ์ค่อนข้างแม่นยำ ( intervals, pivot-hole, distance)

 au t  tf weu~i~ aor~ mre~g~~~ m~t~~ ~~~  ~"NC~X~t~ti~  ~~n~ SNsh A FNECnSERTR O
 on as it rolled five thousand years ago./////Epilogue//"AND I ONLY AM ESCAPED A

NL~~,S~ ~HR~ yO~ -/s~n "~A~~ laeu~ta Vew~, S~e s~~  s~ ~ ain~ t~d ~t~ oirept~~ ~
LONE TO TELL THEE" Job.//The drama's done. Why then here does any one step forth

ตัวพิมพ์ใหญ่ดูไม่ดี


Trie ดูเหมือนจะใช้หน่วยความจำมากกว่าที่ฉันคาดไว้ ...
user202729

... และยังยากที่จะนำมาใช้
user202729

4

Python 2, 756837

ใช้บางสิ่งที่อาจเป็นลูกโซ่มาร์คอฟหรือไม่

import zlib
a=eval(zlib.decompress('x\x9cM\x9cis\xda\xcc\xd2\x86\xff\x8a2\xf5\xd4\x81\xb8,\x977l\'\xf9\x90\x12 \x02f\x11G\x02c||*%@,a\x11a1\xe0S\xef\x7f\x7fC\x13\xf75\xdf\xda\xaaa4\xd3\xcb\xddw\xf7\x8c\xfc\xbf\xcc\x8f\xd7E\xe6\xab\x93if\xce\x9d\xcc\x8f\xefG\xd1\x11\xf1\x1b\xa2At\x8e\xa2\'\xe2\xc5Q\xfc,\xa2{\x14+"\x9e3\xf63b\x87\x9f\xb5\x8fb$b\xeb(\x96E\x8c\x18\x1b2\xb6{\x14/D\xfcq\x14\x03\x11}\xc6zG\xb1.b\xc0\xd3\x06\xcb\xa9\xf1\xb3\xcaQl\x88X>\x8a-\x11\xb7G1\x11q\x85\x98\x1c\xc5\x95\x88\xf1Q\xec\x89\x98\x1e\xc5\x81\x88\xa2\xb3X\xc4\x19\xe2\xe4(\xbe\x898\xd6\xc9F\xa8\xe4E\x16\x19\x8a\xc8r^|U\xc9\x8b\xc7\xd8\xfcQ\xf4\x8f\xe2\xbf\x1c\x06\xbc\xa8v6\xef\xba\xb2\x17V\xf6\x92\xe8r6\x07\x9d\xcc\x95EN\xe4\xe9FW\xb6\xd9\xea6M\xa2K\xdf\xact\x86\xf9\xc976Gy\xf2\xce\xef\x96G1\x15q\xf1\xf1\xd4\xcc3\xe6\x8f\xb8\x96\xdf}\xd27\xcf\x1d\x9da\x8e\x1f\xcd\xc5c\\\x11Q\xcf\xfc\x02Q\x9c\xe7\\\xd6\xbe;\x8acY\xe5\x8c\x17\xcfu9F\xc4\x83\xfc\x0c\x076\x0b\x1d;\xc7\x97\xe7_U\x9c\xacT\xfc\xc2\x1a\xbe\xb0\x06\x83\r7b\xd9\x85<\x9d\xe8\x86\xbe|Q\xff\xfc\xf2\xa0\xe2d\xa7?\xfbr\xc5\xbc\x97\x8c\xbd\xd1\xbd}\xb9f@\x8e\x01\xb7\x88\xf7\x88w*\xce\x13v1\xc1ZCv\x1c\xebz\xe7=]\xce\x1c\x9d\xcdg\xe8,U/\x98/\x18`\xed\xf8\x8d\xa7\xe21\'\x1bo\xd4,sk\x80\xb8\xc6L\xc45Oq\xa9M\xac\x9e8\xc7?k\xb8\x9fY\xe9\x80\x9a\x8c\x9d\x8a\x98\xea\xde\x8c\xcc\xbb\x94\xa7\x13\x06\xc8\xca\xfa"\x1e\x98\xa1\xa4\xe1R\xfb\xa1\xb1W+\xf2b\xc0\xa4\x96W\xac\xa8\x15\x10=\x8d\xd3ZC#\xb2F \xd7j\xccP\xd78\xadU\x8fbWD"\xbd\xd6Q\xb7\xaf\xb5\x98\x0cH\xac\x85\xfc\x0cH\xac5\x15(k\xdd\x8f\xa7\xa6&\xf1v\xfa\x19\x00Q\xc3\x7fkxuM\xe2\xad(\xa2D\xd6\xabX\xb6&\xfeyy\x14\x1d\xdc\xa4v\x8azY\xdbU\xa4P\xf9\xc4\xcc?\x0fj\x8d\x9f\x135\xf8O\xde\xf7\xd3Q?Ym\xf4\xe9\n\xefY\xe12\xab\x9d:\xc7\n`Y\xfd>\x8a[\x11\xf1\x88\xd5\x9a\xc9\xf6\xcc\x80#\xad\xde\xd5+W\x03\x9e\x12/\xab!\xf3\x8e\x98\x81xY\xf5\x18\xd0g2\xe2e5g\xb2\x05+\x13\x07\x9d\x8b8fCD\xd1j\xca\xcf,X]\x81X+\xb0i\xa5\x88\xf5\'\x1c\x14VW`\xe9\n\x84]\x19u\xaa\x15\x16X\x81\xb0+\x0c\xb7"\'\xbf.N\xab0\xa7?n\xd5\x13^\x179\xb5\xf9\xebB<\xe4\xe1$_[c\x04\xc3\x06\'\x99W\xbd.\xb2\x1ap\xaf\x8b\xb3\x8fy\xcc\x9fW\x19\xe6t\xacE\x18\x1d\xffoR\xf1\xeb\xa2k\xc9/\x96\xfc\x1fk\xfa\x96Z\xe7u\xd1VLx]<\xa9Q^\x17\x1dkL\xd3\x9a\xe7\xdfj\xe4\xd7Eh\x8d\x8fT\xc3\xaf\x8b\x9a5\xben\xc9\ru\xd2\xd7E\xa0\xf6}]\x94\xad1\x15k\x8b\x8f\xd6\xf8\xaa\xf5\xae\xa25\xde\xb7\xe6)Y\xe3\x7fX\xb2g\x8d\xc9[\xeb/(:\xfc[\xd4P9=>X?}\xb7\xe4\x8d\xa5\x92\xad5\xe5\x9b\xb5\x9c\x9d5Fbru\x92\x7f[\xaf]Y\xe3\xd7\x96\xdaf\xd6\x16\xe7\x1a\t\xaf\x8b\x85\xb5\x06\t\x96\xe1I\x1e[\xf3L\xac\xf5\xfc\xb2~;\xb5\x9e\x0f\xac\xf1\x12\xd7\xfb\x93<\xb4\xe6\x1fYk\x8e\xad\xdf\xf6\xac\xdf\xf6u\xfc\x80\x00\x19\x10A\x03\xdcz\xa0ac\x06\x84\xe3\x00>3 2\x07D\xe6\x80\xd8\x1e\x10\xdb\x03\xd8\xc8\xc0\x02\x82\x01\xb9w \xea\xd9\x89\x08\xee\x0c\xe6\xaa\xd8\x01\xba\x19L\xf9\x19\x9a\x1c\xa0\xc8\x01\x807\x00\xf0\x06hq\x00\xd9\x1d\xf4\xd0\x89\xa5\x9e\x985\x80\xb4\x837\xd6\x00\x82\x0f\xf0\xae\x01\x19y\x80\xaf\x0c@\xf0\xc1\xf2cCf\x87Vw\xe8o\x87Vw\x98h\x87]vXk\x07a\xdc\xa1\xf6\x1d\xba\xdea\x81K\x012aR\x977\x88\x97\no\x97W<\x85u]\n\x17;e\xceK(\xda%\xc4\xed\x12\x16x\t7\xdcYV\xbe\x94-I\xba\xbcd\xa3\x97\xec\xee\xf2\\W\xb1\xc3r;l\xb4\xc3r\xbb\xbe\xea}\xd7C\x14s\x9dt\t\xb5\xdb-\xd0\x04>\xb5#)\xed\xe0\xb5;\x12\xd8\x0e\x84\xd8Q8\xec0\xe2\x8e\xe4\xbc[2\x00?\xb9\xc4#\nl\xb3\x80\xe5\n\xa2\x12![\x05\x81G!\x1e\x05AP)\xed\n\x02\xac\x02\xfa\x85\x80\xa75\xc5\xba\x02t\xad  )\xc5l\x01jW\xe8"\x86\xbcB\xd0RrR\xa1\xc5+\x08\x9d\xc2X\xd5W \xbd\x17f\xba\xcd\x82\xa8Z\xd2N!Q\xf5\x15\xdeU}\x85\x83\xc6@a\xa5\x01U\x10\xa5\x9e\xd8\xee@\x9fN 4\x06,3#\xd5\xaf\x01\xc9\x0c$\xc5\x10\xa8\x13\xe0y\xb2\xd4\x1dO0\x96I\xd5\x16\x93\xadnh\x82\x85\xcc/f \x1f\x18\x06L\xc6\xba\x9c\t\xc8c\xc8\x17\x13j\x8c\xc9L}}\x92\xea\xd2\'\xe2\x88#\x11\xd9\xd0\x04\xaa5\xe9\xf1\xb3D]\xd9\x90\xce&#\xc6\x0e\xd9[\x11\x9d\xf9\xe8\x97dj\xc8\xa5\xc6\xd3\x080dRSP\xbb\x99\x1ac\xeb<%\xf3\x9b\x00\x9d\x91\xf7\ri\xdf<2/I\xdf\xc0Y\x0c\x94\xc5<1\x03\x84\xc5\xc0W\x0ct\xc5\x84,\x07\xb2b\xe0KO\xb2\xb7\x9ah\x07\xf43\xaf\x19uv\x039\x7f\x12MI\x1d\xf3$k/\xc8\x80\x0b\xc5.s\x06\xe6=\xc9\x9e\xa58\x99\xb8\xea\xd7\x13"yr\x81\xed\x01\xb7\x89\xbcN\xb2\xd9\xc4\xe8l\x7f\xcah\x85|\xc3:\x9fp\x89\'0\xefi\xa2\xa29\x81\xe9\xdf\x15\xa5j\xc7\xc9\xe9\xb9\xbc&Gc)\x87\xeb\xe6@\xe4\x1c8\x9d\xcb)\xde\xe6\xc0\xf4\x1cew\x8e\x04\x90#-\xe4.u\xc99RHN\x12\x8b$\xa1\x1cj\xc9\x01{9\xf8w\x19L*\xd3\xf2*S\xf5\x95\x9fxJ\xff\xac\xdcb\x00uc\xb9\x82\xd8`\x00Uj\xb9\xce\x0c@d\x19\x88,\x1f\xd4ve\xca\xb4\xf2\x04\x11RR\x8e\xd5\x1ce*\xab\xb2m\x992&-\x7fV\xfd\x94/\xac\x11(\xa8\xec\xaac\x95\xb5\x92\xfd\x13VZ\xdf\xfeG\xb4\xd2\x16Q;d&\xf3\xcd\xe8l\xaf\x19\xcb\xb52\xce\x87k\x99\x8c{\x14]\x11\xcf\xcd\xc7\x0b\x17$8\x8br.\x00\xbf\x05yqA\xb6\xb4\xe8\xec\x02\xb6v"\xb3\x12\x86\'\xaey\x12\xa1R\'\xa6y\x1aKM\xba@s\'\xea*\x00qb\xae\xa7\xa7{\x9e\x92N\x17$\x97/\x04\x96E\xd2-\x8enQ\xf4\x05I`AA\xbe \tX\xf4\x7f\xa1t\xcedv\xe6o\xf8\x98\xcc\x9b\xf9;\xc0d\xb6\xe6\xef6Mf\xf3\xa1T\x93Y#\xae\x18\xfb\xdb\xfc]\x8e\xc9,\x8d\xce{`\xc0\x88\xa7C\xf3Wg&\x93\x98\xbf+3\x7fx\xb6\xce\xdb?\x8a3\x11{\xcc\x1b36\xe5\xe9\xe2\x8fh2\xe6(\xce\x99a\xc6\x0c\x13\xf3\xd7\xf2&3f9\x1dv\xfc\xc4\xd3\x16O#\xdc\x08&\xba\xb8\xc0-\x9bFm\x01\x81]\x00\x88\x0b\xc3\xd8\xae\xbe\xe2T!\x9f\x94\xea\x1f\xc5\xbd\x88E\xb4S@\xcc\xb3M\xcf\xa8{~g\xde\x80\xf56\xf8Y\xfdc\xac\xc9\xd4\xcc_\xe72\x99\n\xda)\x7f\x8c\xcd|eo_\x1du\xb9\xaf\xf4\x1a\xbeZ\xe1\xfe\'Gj\xac\xd6\x8f\x1b\x15\xbdg\xea\x8e\xe6\x9c:\xd3\xd5\t\xfc:\xc8X\x07%\xea\xf0\xf7\xfa\xe9%\x1d\x91\xe9l\xd7\xc9\x12u\x89>\xe9\x82\xd7\x01\xab:\xb5G}\xc3\xc4+D"\xaa\x0e\x08\xd6i\xf6\xd5\x0b\x9a\x0e\xeb4\x06\xeb\x02\xa3\xc2\x1e\xeb5\x05\xad:8[o(\xce\xd6+\xec\xbe\xcd\xcf\x9a\ne\xf5\x88\xe5\x90\x0c\xce_9[X[\x95\xc3\x1aD]S\xca\xac\xd1\xd59f:G\xdb\xe7g\x0c \xf9\x9c\xd3\xeeYgu\x99k\xcc\xb1f\x865\xf6ZS\xf1\xae\xf1\xe7\xb5z\xb9Yg48\xce\x1f\xf4\x15\xdfu2\xf3\x9d\x01\xdfA\xec\xccwG\xcd\xbc\xc62k@kM\x07y\r\xc0\xad\xa98\xd6t\xdd\xd7\x18\x7f\r\xd6\xad\xa1\xab\xeb_\x8a\xcdk\xe0\x7f\r\xb5]\xc3\xf6\xd7\x00\xfd\x1a\xf8_\x93\x14\xd6}\x85\xdeu\x8f\xa7\xb4\xb9\xd7#\xd6\x0b\xd0\xaf\x81\xff55@H\xb9\x15&\xba\x86P&\x93f[\xc8\xca\xc2\xb1\xbe-\x94]\x08\xa7\x0e\xe1\x07!\xdd\xa0\xf0\tQ\xb8\x84\x90\xa3\xb0\xa9\x8e\x1dBAB(H\x88[\x86\xf4\xccC\x02&\xfc\xa1\x8e\x1dz\x1a0a^}<\xa49\x15R\xb0\x85\xb0\x91P\x02F\x90#\xa4\xb8\x0b\xe9\x99\x87\xd4\x84!\xce\x1e\x12\x02!\xbd\xd2\x10\x18\n\xc5\xa3\xaeD\xc4\x81C\xf1\xc4\xbc\x888{\x08\xf6\x84\xa7\x88\x93pH(e\x12J\x99$Us&\xd4\xd4\t\x0c5\xa1\r\x93L\x15\x91\x12|.I\xd4\xc8\t| !\xf3\'\x94\x7f\tT+\xe9+\x16$\x90\x8b\x84pI\xf6\x0c\xe0\xb0.\x81\xcd%DC\xb2C$\xf3\'\x84VB\x01\x99\x10\x86\tgf\xc9\xcf\xa3(\\7\x01,\x12t\x9d\xa0\xe0\x84\xfeY\x02\xedO\x80\x90\x84\x92$!\xc5$\xd8;\x01\xfd\x12L\x7fA\xa1\x92\x9c\x0c\'S\xec\xa1w\xfb\x89jjO3dO\t\xbf\'\xa8\xf7\xf0\xb4}\xac\x10\xb2O4\xf8\xf6\xa2\xebO"\x82<{\x94\xb6\xa7E\xb2\xdf\xaa\xc7\\\xd1\x1d\xdd\xa3\x93=\x9a\xda\x8b\xfe$\x87\xedE\x11R\xaf\xecU=f\x8f\xd2\xf6\xec~om\xf9\xeaR\xadqE=rE\xa3\xeb\x8a:\xe7\x8a:\xe7J\xea\x9c{\x11\xa9s\xae\xa8\x94\xae\x04\xc5\xafE$\xbf\\\xd1l\xbb\xa2_u\xc5\xe6\x8a\x12\xca\x82\xe7\xc5\x9a\xc6z\xb1\xae\xb8P$\xc0\x8b`H\xb1\xa8\x10Q\xf4\x15N\x8ad\xe5"\x80T\xa4<*\xb6\x15\xc7\x8a\x1c\xa0\x15#\x85\x93"\xed\x87\xe2D-[\x84P\x14c\x05\xd0"\xa7\x87\xc5\xad\x1a\xaeH\xfe)\x9e\xd4.(S\xb4\xb6\xac\xf64\xc5\x8cr\xb2"\x14\xa8\x88\xbb\x17\xf1\xe6\x8e\xaf\x88\xd4\xa1r\xefp\x9b\xa1C=\xd7\x81rt\xd0_\x87\xf6X\x87\xc2\xb7#\xbb\xff&"-\xafN\x131Q\x07\xed\xd01\xec\x80n\x1d\x1a\x82\x1d\x02\xaa\xa3\x8a0\x1d\xd0\xb6\xe3\xb02\xee\x85t\xb8\x17\xd2\xb1N\x1d;\xec~\xcb\x81\xdf/p\xeaZ\xbc2\'O\'\x1a\x1a\xbf\x12\xb5\xdc/Y\xb0T>\xbfR5\xd7\x1d\xfc\xe6\x8e\xe0\xba\xc3Dw\x04\xc9\x1d\xa5\xfc\x1dArG\xe8\xdc\x11$w9\x8d\x81;\t\x129\x0e\xbb\x93EJ\x82\xb9\xa3\x9dp\xf7E\xc3\xa1\xc5\xed\x8a;\xab\x81F\xeb\xbeb\xc5o\x05\x9dT@\xbd\n\xc0ZaG\x15vT\xc1\xa7*\n\xa1\xa6\x92\xf9(r2\x95g\xf4^\xe1\xeeH\xa5\xc9\xefH\xf7\x95\x10\xb1\xad\xc1S\xc1\xa9*O\xea>\x95\x8a\xee\xb9R\xd7\xf0\xabp\xdf\xa6\x12\xa8\x87V\xc4\x85\x7f\x88\xc8\x8d\x9dJ\x81\xc9\xf2\xea(\x15\xc8E\xa5\xc8\x80\x1f\xac\xa1\xc4S*\xe4\n9\xaaB\xa3\xb5B\xc2\xab\x08\xceK\xbb\xadB2\xaf\x88\xf7\x08\xa2WH\xe6\x15\x12Ae\xa4\xc8Q\xa1\xd7\x98\xa5\xb0\xce\xaeu\rY\x8a\xf0,\r\xd1,\xb6\xf7\xb0a\x16\x92\x90\x85\x82f9O\xce\x92\xad\xb2\x9c\xa8e\xa1$Y\xc8f\x96s\x80,\xa1\x9c\x85E\\\x8b\x01\xe4\xf8?\x0b\xad\xcc\x82\x0b\xd9H\x8d\x95m\xf26i;\n^g\xe9@e\xf1\x87lU\xed\x96-3\x96.h\x96r(+\xfe \x80\x9e\xad\xf1b\n\xaa,\x9d\xd8l\x81\x9fy\n\xb6\xd9\x92:W\x96\xcb\x1c\xd9"/\xf6\xd9\x85\xc4\xf71\xb1\x99\xe3!\xb3\xc6@jUT\x0b\xfbv\x13\xa7*\x9eL\xf8$\xa3\x89\xb4\x94PL1c\n\xb1I\xc9\xd1)Q\x99\xd2\x01H\x89\xeb\x94hO\xc9\xe7\xdf\xa8\xae\xbei\xae5\xdf\xa8\x98\xbeQ\xcb}\xb3\x96#\x9e"\x97`R|8\xc5SR\xf1\x1fa0)EP\xfa\x0b\x11\x0fL\xc7\x1a\x10)\xa7\x85)\xae\x9f\xd2\x92O!\xafi\x9f5\xd0\xbeOi\x87y\xa1z`\n7M\x0f\xea\xb8\xe9\x9e\xc9\xe0\xa6\xdf\xacb8%\x1b\xa7\xc4u\xca-\xa3\x14r\x9a\xc2\xc9R\x98Z\x83}6\xe8f6h&4\x92\x8f\xa7\xa6Erk\xf0\xe2\x06i\xb7\x81\xef7\xa08\r*\x9b\x06\xd7\x85\x1a\xa4\xf3\x06d\xa6Am\xd4\xa0\xbaj\xf8\xfc\xec\x07O\x9f\x11\xe1@\r\x9a\t\r\x88O\x03Do\xb4\x18@\x0f\xa2\x01\x8c7:\xec\xc2J\xd1\r\\\xbcA\xc9\xd4\xb0\xda\xb7\x0b\x92m\x03\x8e\xd3\x80\xb36,\x05\xe2\xee\x0bk\xe2\x93me\xff16\x88\x01\xdf\x18W\x8aa+1n\x17\xe3\xa2\xf1P\x8d\x14c\xe6x\xccX\\?\xc6\xf5c\xc2$&-\xc4\x80o\xbc\xd0\xe0\x89q\xaax\xc9\xdb\xc8<\xf1\x8a\xb1\xb0\x99\x18g\x8d9(\x8f\xa9\xbabJ\xb8\x983\xc0\x980\xb9\x82\xac,\x80\x8b\x05Zm\x9dTy#\xbf\x03|b(A\x0c:\xc5\x90\xf7\x98c\x9c\x18\xc3\xc4\xa0^\xcc;b\xe0+\xb6\x88\x8b\xebk`\xbb\x9c\xc0\xb9\x9c\xb5\xb9\x82\xda\x92O\\\xf1}I\x85.G\xb6n\x9e\xb1u\xc4\x1a?\xe3\xac\xcd%\xa6\\\xb2\x8c[\xe6gD\xa5\xfb\xc8+\xda\xea\x11.\'p.gm.w\x86\\\xce\xda\xdc&\xf3r\xd6\xe6\x86\xfa\xd4!\xc5\xba\x9c\xc09\xdc>q)\xf5]2\x8ck\r\xa0#\xe4\x12\x03.g\xba.\xa5\xbeK\xa9\xba\xd9\xf1\x94\xbb4.Wl\\b`\x83\x83\xba\xdc\xa3q9\xecp\xc5W\x85\x1a\xb9\x90\x95\r5\xb2\x8b\xaf\xba\xc4\x80\x0bww\xd7h\x12\xf6\xb5\xe1\xfe\xc2\x86\x1do\xe8vm8\xe1s9~\xdap\x14\xecr\xd8\xe1\xda\xa7K\x1b+s;\xd6\xd5f\x1a\xe0\xaev\xd33\x1bBf\x83;\xbbV\xf7\xd1u1.a\xe0f\x99\x98\x88\xd80`\xe3\xa2,x\xc0\x86H\xdb\x90\xd07\xf0\x80\r\x01\xea\xa0\xee\x11\x17\\G4\x17#\x16\x1c\xb1\x8d\x88P\x8ch]E\x16:G\xb24\xc92\x11\x0b\x8e\xe4\xcdB\x1a"\xbd\xc8o"\x80::\xe9\xb5$\xf2A\x8d\x13a\xf4\x88l\x1a\x01f\x11\x1d\xd7h\xc3\xd8\xa9*0\xa2=\x16QKF)K#\xcfG@r\x84\x0fF\x84D$\x81"\x146J\x18\x10)4DT\xb9Q\x07Q@@\xca\xeb\x88\xcb\xb7\x11\x17u#\x92{TV\x18\x89\xe8JF\xa0OTg\x00\xd9?\x82\xb7Fy\xe6\xf5\x18Ku3\xc4\x9eC\xac<\x14\xd3\xca\x9d\xcc!.3\xc4e\x86\xda\x1e3C<mH6\x1eb\xef!$q\x88\x07\x8f\xf0\x9e\xa1\x15GC\x02w\x08b\x0c\xe9h\r\xe9h\ri\xb6\x0fi\x97\x0ci\x9a\r\xb1\xcb\x10\xee8\x04\x94\x86\xdc\xe4\x1f\x02kC\xcd\xbbf\xc4\xe6\x1c\xa9\xb4\xa5\xfe>\xb0\xcf\x03\x9b;\xb0\xe5\x03\xfb<\xa0\xb4\x03\xaa<\xa0\xbf\x03\xaf8`\x81\x03v9\xa0\xa9\x11o\xbb\xa63p\xcd\xd5\xafk\xdag\x07K\xab\xd7\\\xfb\xbf&\x8b_\xd3r\xb8\xa6\xe5pM\x1b\xe1\x9a\x0e\xdc\xb5\xac]: \xd7\xec\xf3\xda\xda\'Z=PU\x1e\xe6\xfa\xb3\x03\x08y\xa0\xbds\xe0`\xe3@\xf7\xeb\x00\xf8\x1e\xc8<\x07\x0e+\x0e\xc0\xf7\x81\xabI\x07\xa0\xfe\xb0d\x06\xfc\xe8@\xff\xec\x00\xe8\x1d(\x93}\x0bz|\xd0\xcbg\xcb\xbe\x85o\xbe\xc2\x9e\xf1\x81/\x1f\x8b\xfb\xdc\x88\xf7Aa\x1f\x83\xfaX\xdc\xa7\x7f\xe1\x13\xcb~\xa0p\xe1K\xdcK\xe9\xea\x83\x11~Y\xd1\xc0\x87u\xf8\x12\xe1/"B\xea}>_\xf2\xa9b}j\x01\xbf\xc0\x0cy\x96\x0e\xd5\xf7\xa5\x00\x10\x92\xed\xbf\xf0bN{\xfc\x0e?\x83\xdf\xfb\x94\xf0>=\x1f\x9f\n\xc1\xa7\xe7\xe3\xd3"\xf1q\x19\x9f\xfbZ>\xc7L>W\xe3|\xf1\x08a\xbd\xbex\x84d.\x9fF\x84Oq\xe8\xe3S\xfe\x9e\xb7Au}\x9af>\xd0\xe3C@|r\x91\xbfd\x91\xe2i\xbfE\xa47\xf3|\xf2)1\xe73\x01\xf3\x8co<\x8b9\x9fE\xa4_\xf5La\xf6\x0c\xbd}~V\x13\xfd#\x88$\x14\xfa\x1f.\xc5?\x8b1\xa4)\xf1\x0c\xb3\x99Zh0\xe5lc\x8a\xafN9?\x9d\x02ISh\xfa\x94\xb5O\xc1\xa1)\xa11\xc5\x99\xa7\xc0\xd7\x14o\xbfg\x86{\x1a\xf6\xf7\xf4Y\xef\xef\xf4m\xf79]\xef=Pw\x0fN\xdd\x83^\xf7|\xe0t\x0f\xd2\xdd\x0bzIk\xf4\x1eL\x9bb\xfb)\x1f\xd5Ma\x86\xd3\xa1b\xc4\x14\xc0\x99\x02oS\xe0mJG\x7f\n\xeb\x9d\x92J\xa6P\x87)04\xe5\xb6\xea\x14\xef\x99\xc2d\xa6$\xb9)e\xd9c\xa0\x0e\xf1\xe8+L=J\xf8J[\xf3\x99\xf3\xd5GV\xf6(K\x17\xa2\xf2\x88C<ri\xf4\x11k>b\xa1,*1\x0c\xf8\xafM\x80?c\xf0\xcf\x18\xfc3\xa3?\xe3\x1c\x9f/x\xca\x8d\xa1\xcf\xa0\xe2\x92\x88Y\xa2\xaa%Lo\x89~\x96\x1bDBu\x89\xaa\x96\\D^\xd2\x96\xfcl/~I\xd5\xb4D-K\xd8\xe2\x12;/\xb1\xfe\x92\x84\xb5D\xc7K>\xbf\\b\xfd\x1b\xf2\xe7\xd2\x8a\xbf%j[\x12\x1cK\xd8\xc1\x92\xfe\xc5\x92P\\\xc2:\x96\x98i\x89\x8a\x97(\xfe\x86\xa7\x01c\x03W!\'\xb0\x06h\x88\x9b\x80,\x16\x80\x0c\x01\x9d\x95\xe0\xb4\r\xf1\xb6\x806_@\x9a\x0fh\xf3\x05c\x8d\xe6\x00\xfa\x15\xd0Y\t\xf8\x10"\xe0\x849\x80\xd6\x05 n@\xfb+ u\x07DR@\xc6\x0f$P\xaa"rn\x15\xd4\x11\xb9\x04\x10Ty\xca\xf5\xc5\xa0\xac0\x1cH\xd2\x14\n\x1d\x94\x18\xcb\xd7\xb2\x01\x07\x04A\x01M\xf1\xe1l\xe0\xf1TR\xa9\xa4\x82\xa0\xc3+\xc8\x94\x01\xb7\xc1\x03:\xdc\x01UE\x10\xaaO\x05Z`\x98\x1en\xd2\xe3\x10\xbb\x87\r{\xd8\xbb\x87\x9b\xf4\xf0\x8d\x1e\xde\xd5\x83\xfd\xf7\xbe2\x16\xaf\xed\xbd\x02v\xbd\x81Z\xa0\x07\\\xf6F\x0c\x80\x8f\xf7z\x0c\x00\x18{TZ=\x82\xab\x97j\x18\xf5\xc6LF \xf6h\x9f\xf56\n\x97=\xdc\xa4\xf7\xc6\xcap\xa9\x1e\x05F\x8f\xa6m\x0f\xe8\xb8\xb0Ab{\xfaC\xc0\xd3\xa13ra5)\xb7\x84\xf0\x05J\xbe@\xc9[\x14wA$]X7E/2\x1c\rl\xad\x1f2\xdd\x96\x8b}[\x8e\xd5\xb6\xd8w\x0b\xa6n\x7f\xf2\xbe\xba:\xcbE\x11\xd1G,!\xfe\x97=]p\'\xec\xa2\xa3\xe2\x16%m\x856\t\xff\xd9\nmz\x17\x91\x8b\x9c[\xda\x8d[\x94\xbf\xc5$\x17\t\xf3\x02\xf7[\x92\xc0\x16\x1e\xb8\x05S\xb6|c\xbe\xa5\'\xba\xe5\x90xK\x83uK\xf9\xb7\xa5\xed\xb5\xe5\xde\xfeVPI\x9aV\xdbX]hK\xf1\xb1\xed)\xae\xb5\x0e\xba\x9c\x16m/\xcf\xeaA\xb6V\xaa\x93{\x0b\xed[\xb4\x17Zd\x94\x16I\xb9ES\xb9\x05]\xf5\x08\xe3\x960\xedc\xef\xdbx\x1c\xc3\xb4\xba\x8a\t-\xb1\x91\x90\xf9\x96\x80\x86\xd4\x0b-\x81\x12\xa9\x17<q*\xb9l\xdd\x82t{\xe2T\xc2*[\xfc\xb3\x82\x16\xa7\x04-N\xc8Z\x94\x19\xad\no\xa3\xa0hq\x87\xbf\x05qm\t\xf4\xc9)\x96WPP\xf6\xf2\xac\xc1\xfa\x19q\xe2q\x19\xc3\x13\x0f\x15\xa6\xe3Uto\x1e\xb7\r<\xaa\x1e\x0f\x84\xf7X\xba\xc7\xb1c\xcb*\xde\xbc\xa6\xc6\xa2\x17\xb1`\xce\x19<\xa0\xd8\xa3\xc0\xf1:<}\xd2\xdd{\x94H\xde3O_P\x8f\xa3\x9e\xdf"j\xbd\xbeb\xa3\x07/\xf5\x06\n}\xde\x08\x91\xa3\x05\x0f\x14\xf4\xe8cyP\x97\x16\xf7\xe8<\xd0\xd5\xe3h\xc1#v<J\x19\x8f\xa3c\x8f\x98\xf4V,\x92\xf3\x04\x8f\x00\xf7 f\x1e\x9f\xe3y\xf4R=>\xfc\x1c1\xd6\xa1\x976\x82\xef\x8e\xacf$k\x18\x81\x0b\x0e\xa1\xec\xf0\xbd\xbeC#\xd9\xa1\xbd\xecp\x99\xd2Ag\x0e\xd9\xcb\xa1m=\x02\xdd\x1c(\xdc\x88\xb3\x9d\xd1P\xb53"\xd3\x8d\xe8D8\xb0\x15\x87\x96\xc2\x88;\x98\x0e-n\xc7R\t\xc7\xed#\x8c\xe5\xf0\xa5\xd1\x88\xa5\x8f\xc6\xea\x04\x0e\x07\xd5\x0e\x9f\x0c9\x1cn8|t\xe4p\x10\xe2p<\xe2\xf0\xb9\xaf\xc3\xd7\xc1\x0e\xdf\t9|S\xe4p\xce\xe1\xf0\xfd\x91\xc3\x99\x88\xc3\xb7J\x0e\xe7\'\x0e\xdf\t9\x9c]8|S\xe4p\xce\xe1p\xfa\xe1p&\xe2pR\xe2\xf0\xad\x92\xf3\xc2+\x9e\x99\x8c\xd3\x8f\x11\xe1\xe4H>\x94v\x80c\x14+\x1c>\xffv\xfe\xf5!\x1a\'ct\xb2\x7f\x8eO\xa5\xdf\xe7\xc8\x89\xb7\x90=\'\x8b\xc8\xb5\xbf\x11\xd5\x8fC\xfev\xa4B\x95km\x0eu\xab\xc3\xb7\xec\x8e\x94\xbbR\x04\x8f(\x84\x1c)w\x856;R\x04Ki<\x82\xaa9R\xcd~\x11\x91\nc\x04\x81\x1bY\xe9\xe7\x1d\xa2\xf5N\xbd\xf2N&z\xc7\xbb\xde\xb9d\xf8\x0e\x1f\x7f\x87\xa5\xbf\x13#\xef\xef\x1a\xb2\xef\x94`74\x9b\x1cB\xf6f\xa0;z\x87\xd3\xbc\xbb\xbc\xcd\xda\xdcZ\r\xf7\x0ef\xbe\x83\x99m\x0e|\x1c\xf0\xea\x86\n\xff\x06]\xdf\xd0#\xb8\xa1\xefyC\x8f\xe0\x86/\xacnh\x9d\xde\xd0P\xbd\xa1\xf7pC+\xe4\x86\xf5>nu\x17\x0eHZ\x12\xbf\x17\xe4/\xd1\xe5/\xd1\xfb/q\x03\xa9D7\xbeTR\xff,q\xd7\xa8D]R\xa23X\xe2\xba\x7f\tU\x97\xb0E\x89{\x0f%\x0c[\xe2\xf3\x84\x12Ek\x89\xa3\xe6\x92u ^\x82\xaf\x96\xc4\x02R\x14\x948\xed)\xb9\xcc\xc6\x8d\xbb.\xed\xc9.]\xcd\xae,X\x9a\x80]z\x16]v\xdf\xa5\x90\xea\xc2R\xba\xa2\xbfS\xce\xee\xd28\xee\xe2\xa0].\x83t\xed\xcfA\xce!K)\xd0|N\xa4u\t\x99\xae\xab\xf6\xe8\xe2\xa2]\x8b/t\xf5\x03a\xd3\xa5L\xeeBZ\xba\x14\x02c\x9e\xce\xa8|g\xe4\x92\x19\xb7\x07f\xe4\x92\x19]\x8bY_w:\xa3\xee\x98Q\x1f\xcd\xb8:2\x9b1\xc3\\\x83c\xcd\xe6f\x84\xf8\x0cE\xccH\xc53\x92\xf9\x0c\x7f\x9e\xe1V3R\xf1\x8c+\xd93:\xa63\x90\xe1\x9c/\xd8g\x00\x91\x99Q\xa2\xce0\xc1\x8c\xae\xc7\x8c\x18\x9f\x11_3\xac1\x03Zg\xd6\xe6P\xfb\x0c\x18\x9ea\x81\x07&{`\xb2\x07y\xb1$\x93\x87\x07\x9erq\xf2\xe1Zq\xfa\xe1F\x01\xf7\x81\xcd=\\\xf1\x14\xecx\x00Q\x1e\x04;$\x83<\x08\xa2H/\xb2\xea|\xc4\xb8\xa9\xe2GUb\xaaj9]\x95\x05W\xd9Q\xf5\xa4V\x89\xaaj\xacJ\xa9R\xefT\xb1x\x15\x86X%\xca\xab\x90\x8e*uK\xd5\xd7x\xaf\x12\xc3\xd5\x9a\x06n\x95\xb8\xac\x86\x8aUU\xae\xe5U\xb9\xb1Y\x85\x13\x9f\x91\xc4\xcf:\xfa\xe2\xb3\xa6\xae\xec\x0c\x1ap\x161\x00\xd2q\xc6\xbf$;\xcb\xeb\x80\xefv\xad~\x86{\x9cQ\r\x9f\xd9C.\xf1\x95\xdfh\xb6\x85\xf8\x9b\xff\xfe\xd2\xa4Q\xd0\xdc \xc2T\x9b\x07u\xdd&`\xd4\x14#\xc8\x19@\x13\xf6\xd9\x9c\xa8\xb75Sf\x00\x80\x9b\xdc\x82lF\xaa\xcd\xa6hH0\xbe\xd9A$\xa34\xf9\xf8\xb6\xd9U\xfcmr\xa2\xd3\xa4\xbejr7\xb2)\x8a\x95z\xb0I\x1ai\xd2\x15kr\x81\xac\xe9\xf06"\xa9\x89\xce\x9a\x94LM\xeb\xf8\xac\xcf\xc7\xab\xfd\x89j\xb5\xcfU\xa8>t\xa4\x0fI\xe9S\x15\xf4\xa9\xc9\xfb\x16HR\xe6\xf4\xb9\x98\xd1\x07\x7f\xfa`U\x1f\x04\xeb\x93\x9c\xfb\xd8\xb0\xbfa26\xd7\'\xab\xf5\xd9g\x1f|\xeaS\x9c\xf7\t\xcb>\xf0\xd3\xc7\xd1\xfaV\x8b\xe0\x8d\x1d\xbd\xd1s~#X\xdf\xf8\x94\xfc\x8d\xb5\xbf\xb1\xe07\xdd\xa7y\xcb\x18\xfd\x19k\xcfc\xf0<\xdfB\xe5\xa9\xb8\xf3T\xc6\xf9@a$O\xb8\xe7\xdb\xcc\x00\x8d\xc9\x13\xf9y\x02;O\xea\xcd\xd3\xe7\xcb\xe3\xd7y6\x94\xe7\x7ft\xe5\xe9\xd2\xe5\xe9\xe0\xe6\xb1\xe1F\x9b&&\x0fH\xe692\xcbc\x97\xbc\x85\x97yL\xd0fD\x1b\xf5\xb4\x15}3#,\xd7\xde\xe8z\\\x98q\x9b\xfbDm\xc9\xab\xc2\xfd\xda3\x1d\xdb\x06D7\xd6\xcf\xba\n\xa2m)S\xe4\x18\xb6M7\xb7\xcd1M\x9bo\xdf\xda(\xb8\r\x18\xb4\xeb\x1a\xa9m1\x9c\xb0\xc7\xb6\x18NZ\x1am\xba\x1bmxb\x9b\xeb\x9b\xed\xa2\x86r\xfb\x87"@\xdbS#\xb7i\xcc\xb4\xf3\x1a\xcac4\xf9\x89\x1c\xfd\xc9\xba\xaf4\xe6\x9e\xd3\'\x98\xd6\'2\xf3\'\xeb\xbf6|\x02\x9c\xc7\xf0\xe81\x86\x19c\xae\xb15\x96W\x8f9\x14\x19C%>\xd9\xf0>\xb6\x0fY\x80\xe41~5\x06\xd4\xc7\xc0\xc4\x98\x92b\x0cL\x8c\xe1Gc\xf8\xd1\x98o#\xc7\xf4\xa5\xc7\xb0\xea1\x1cm\x0c]\x1ds\x9bjLwaL\x95:\x86\xad\x8f\xb9\xc60\x16\xca(g\xdd\xe3\x01\x1b\x02\r7P\xc6[J\xa0[\xa11\xc2<n\xa1&\xb7P\x93[\xbe\xbc\xbd\xcd\xa99n\xf9\xc7\x11\xb7\x14Q\xb7\xfc\x93\x89[\x8a\xa8[Lw\xcbY\xee\x85e\xf2[<~\x04t\x8e\xfeZ\xf4\xff\xfe\x1f\xfa\xddI\x97'))
global t
t=' '
def f(k):
 global t
 r=a[t+k]if t+k in a else'e';t=k
 return r

1
คำอธิบายอย่างรวดเร็ว: การzlib.decompress('...')ประเมินผล{'G?':' ', 'G;':' ','G"':' ',.......}และaเป็นพจนานุกรมที่แมปจาก 2 ตัวอักษรถึง 1 ตัวอักษร โดยทั่วไปตัวแปร 2 ตัวอักษรของ Steadybox ของคำตอบ
user202729

1
อย่างที่ฉันเห็นตัวอักษรคือ 17780 ไบต์ คุณสามารถลดเหลือ 11619 ตัวอักษรโดยการลบช่องว่างในเนื้อหาที่คลายการบีบอัดซึ่งจะบันทึก 12322 ไบต์ (ถ้าฉันนับอย่างถูกต้อง) นอกจากนี้ ... การแปลงรหัสยกเว้นฐานสิบหกเป็นอักขระดิบจริงอาจบันทึกไบต์ได้มากขึ้น
user202729

ฉันจะโพสต์สิ่งที่นี่ได้อย่างไรถ้ามันเป็นไบต์ดิบ
Skyler

1
xxd, hexdump, uuencodeหรือที่คล้ายกัน
ปีเตอร์เทย์เลอร์

@ user202729 เพิ่งทราบว่ารหัส Python ไม่สามารถมีไบต์ NUL ดิบจริง
mbomb007

4

Haskell, (1904 + 1621 + 208548 + 25646) * 2 + 371705 = 847143

{-# LANGUAGE FlexibleInstances, DeriveGeneric #-}

import Control.Arrow
import Control.Monad
import Control.Monad.Trans.State
import Data.List

import System.IO
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BSL
import qualified Data.ByteString.Char8 as BC8
import Data.Ord
import Data.Char
import Data.Monoid
import Data.Maybe (fromJust, catMaybes)
import Data.Function
import qualified Data.Map as Map

import Codec.Compression.Lzma

import Data.Flat

import GHC.Word

maxWordLen :: Integral n => n
maxWordLen = 20

wordSeqDictSize :: Integral n => n
wordSeqDictSize = 255

predict :: [Trie] -> Char -> State ([Either Char Int], String) Char
predict statDict c = do
   (nextChar:future, begunWord) <- get
   case nextChar of
     Left p -> do
       put (future, [])
       return p
     Right lw -> do
       let wpre = begunWord++[c]
       put (future, wpre)
       return $ trieLook (tail wpre) (case drop lw statDict of{(t:_)->t;_->Trie[]})

newtype Trie = Trie [(Char,Trie)] deriving (Show, Generic)
instance Flat Trie

trieLook :: String -> Trie -> Char
trieLook [] (Trie ((p,_):_)) = p
trieLook (c:cs) (Trie m)
 | Just t' <- lookup c m  = trieLook cs t'
trieLook _ _ = ' '

moby :: IO (String -> String)
moby = do
    approxWSeq <- BSL.unpack . decompress <$> BSL.readFile "wordsseq"
    Right fallbackTries <- unflat <$> BS.readFile "dicttries"
    seqWords <- read <$> readFile "seqwords"
    let rdict = Map.fromList $ zip [maxWordLen..wordSeqDictSize] seqWords
    return $ \orig ->
      let reconstructed = approxWSeq >>= \i
             -> if i<maxWordLen then let l = fromIntegral i+1
                                     in replicate l $ Right l
                                else Left <$> rdict Map.! i
      in (`evalState`(reconstructed, ""))
              $ mapM (predict fallbackTries) (' ':orig)

ตัวอย่าง:

Call me Ishmael. Some years ago--never mind how long precisely--having
 ap  me ,nhmael.  Hme ?ears |ce--never  usd how long .aacesely--|ubing
little or no money in my purse, and nothing particular to interest me on
little or no ?ivey in my ?efse, and ,uwhing .hrticular to Bdaenest me on
shore, I thought I would sail about a little and see the watery part of
?neae, I thought I would  cfl about a little and see the |rkers part of
the world. It is a way I have of driving off the spleen and regulating
the world. It is a way I have of ,uiving off the |kli   and .ia       
the circulation. Whenever I find myself growing grim about the mouth;
the Ca         . B        I  rtd |yself ,haoing  eom about the ?ivlh;
whenever it is a damp, drizzly November in my soul; whenever I find
Baieever it is a  'mp, ,uiv    Bar      in my  cfl; Baieever I  rtd

ใช้ไฟล์เสริมที่คำนวณล่วงหน้าสามไฟล์:

  • seqwords มีคำที่พบบ่อยที่สุด 236 คำ
  • wordsseq มีคำที่บีบอัด LZMA สำหรับคำเหล่านี้และสำหรับคำทั้งหมดที่ไม่ได้อยู่ในกลุ่ม 236 ความยาว
  • dicttriesมีต้นไม้การตัดสินใจแต่ละคำที่มีคำที่เหลือทั้งหมดสำหรับแต่ละคำที่มีความยาว จากความพยายามเหล่านี้รายการจะถูกเลือกตามที่เราไป

ด้วยวิธีนี้เราได้รับอัตราความผิดพลาดต่ำกว่าแผนการสูญเสียอื่นทั้งหมด น่าเสียดายที่wordsseqไฟล์นี้ยังใหญ่เกินกว่าจะแข่งขันได้

นี่เป็นเวอร์ชั่นสมบูรณ์ที่สร้างไฟล์และทำการวิเคราะห์:

depunct :: String -> [String]
depunct (p:l) = (p:take lm1 wordr) : depunct (drop lm1 wordr ++ srcr)
 where lm1 = maxWordLen-1
       (wordr, srcr) = (`span`l) $ if isAlpha p
                 then \c -> isLetter c || c=='\''
                 else not . isAlpha
depunct []=[]

mhead :: Monoid a => [a] -> a
mhead (h:_) = h
mhead [] = mempty

limit :: [Int] -> [Int]
limit = go 0
 where go z (n:l) | z<100 = n : go (z+n) l
       go _ l = take 1 l

packStr :: String -> Integer
packStr = go 0
 where go n [] = n
       go n (c:cs)
        | c>='a' && c<='z'  = go (28*n + fromIntegral
                                   (1 + fromEnum c - fromEnum 'a')) cs
        | otherwise         = go (28*n) cs


mkTrie :: [String] -> Trie
mkTrie [] = Trie []
mkTrie strs = Trie [ (c, mkTrie . filter (not . null) $ tail<$>l)
                   | l@((c:_):_) <- sortBy (comparing length)
                                  . groupBy ((==)`on`head)
                                  $ sortBy (comparing head) strs ]

mkTries :: [String] -> [Trie]
mkTries rsrc = [ mkTrie $ filter ((==l) . length) rsrc
               | l <- [0..maximum (length<$>rsrc)] ]

main :: IO ()
main = do
    orig <- readFile "whale.txt"
    let wordchopped = depunct orig
        dictRes
          = take 5000
          . map mhead
          . sortBy (comparing $ negate . length)
          . group . sort
          $ wordchopped
        dict = Map.fromList $ zip dictRes [maxWordLen..wordSeqDictSize]
        rdict = Map.fromList $ zip [maxWordLen..wordSeqDictSize] dictRes
        approxWSeq = [ case Map.lookup w dict of
                        Just i -> i
                        Nothing -> fromIntegral (length w - 1) :: Word8
                     | w <- wordchopped ]
        fallbackTries = mkTries . drop (wordSeqDictSize-maxWordLen) $ dictRes
        reconstructed = approxWSeq >>= \i
             -> if i<maxWordLen then let l = fromIntegral i+1
                                     in replicate l $ Right l
                                else Left <$> rdict Map.! i
        predicted = (`evalState`(reconstructed, ""))
              $ mapM (predict fallbackTries) (' ':orig)
        incorrects = length . filter id $ zipWith (/=) orig predicted
    putStrLn $ "longest word: "++show(maximum $ length<$>wordchopped)
    putStrLn $ show incorrects++" errors / "++show (length orig)++" chars"
    BSL.writeFile "wordsseq" . compress $ BSL.pack approxWSeq
    BS.writeFile "dicttries" $ flat fallbackTries
    writeFile "seqwords" . show $ take (256-maxWordLen) dictRes
    writeFile "whale-approx.txt" . unlines $ coLines orig predicted

coLines :: String -> String -> [String]
coLines [] _ = [[],[]]
coLines ('\n':l) (_:m) = []:[]:coLines l m
coLines l ('\n':m) = coLines l ('|':m)
coLines (c:l) (d:m) = case coLines l m of
   (lt:mt:r) -> (c:lt):(d:mt):r

3

C ++ (WIP), 1923 * 2 + 1017344 = 1021190

#include <map>
#include <random>
#include <string>
#include <type_traits>
#include <vector>

using namespace std;

constexpr minstd_rand::result_type seed = 10087702;

template<typename T>
class discrete_mapped_distribution {
private:
    discrete_distribution<size_t> distr;
    vector<T> values;

public:
    discrete_mapped_distribution() :
            distr(), values() {
    }
    template<typename I, typename = typename enable_if<is_arithmetic<I>::value,
            I>::type>
    discrete_mapped_distribution(map<T, I> distribution) :
            values() {
        vector<I> counts;

        values.reserve(distribution.size());
        counts.reserve(distribution.size());

        for (typename map<T, I>::const_reference count : distribution) {
            values.push_back(count.first);
            counts.push_back(count.second);
        }

        distr = discrete_distribution<size_t>(counts.cbegin(), counts.cend());
    }

    discrete_mapped_distribution(const discrete_mapped_distribution&) = default;
    discrete_mapped_distribution& operator=(const discrete_mapped_distribution&) = default;

    template<typename URNG>
    T operator()(URNG& urng) {
        return values.at(distr(urng));
    }
};

class generator2 {
private:
    static map<char, discrete_mapped_distribution<char>> letters;

    minstd_rand rng;

public:
    static void initDistribution(const string& text) {
        map<char, map<char, uint64_t>> letterDistribution;

        string::const_iterator it = text.cbegin();
        char oldLetter = *it++;

        for (; it != text.cend();) {
            ++(letterDistribution[oldLetter][*it]);
            oldLetter = *it++;
        }

        generator2::letters = map<char, discrete_mapped_distribution<char>>();

        for (map<char, map<char, uint64_t>>::const_reference letter : letterDistribution) {
            generator2::letters[letter.first] = discrete_mapped_distribution<char>(letter.second);
        }
    }

    generator2() :
            rng(seed) {
    }

    char getNextChar(char in) {
        return letters.at(in)(rng);
    }
};

map<char, discrete_mapped_distribution<char>> generator2::letters;

วิธีแก้ปัญหานี้ก็คือ WIP นอกจากนี้การพิจารณาว่าขนาดรหัสจริงแทบจะไม่ส่งผลกระทบต่อคะแนนฉันคิดว่าฉันโพสต์คำตอบของฉันก่อนที่จะเริ่มปรับขนาดไมโครให้เหมาะสม
(รหัสเต็มมีอยู่ที่นี่: https://github.com/BrainStone/MobyDickRNG - รวมโปรแกรมเต็มรูปแบบและการค้นหาเมล็ดพันธุ์)

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

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

หากใครต้องการค้นหาเมล็ดพันธุ์เองหรือใช้ RNG ที่แตกต่างกันคุณสามารถแยกซื้อคืนได้

วิธีที่ใช้ในการคำนวณคะแนน: https://github.com/BrainStone/MobyDickRNG/blob/master/src/search.cpp#L15

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

การเปลี่ยนแปลง

  • 2018/01/24 : โพสต์คำตอบครั้งแรก
    ตรวจสอบเมล็ด: 0-50000 คะแนน: 2305 * 2 + 1017754 = 1022364
  • 2018/01/24 : เล่นกอล์ฟได้เล็กน้อย เพิ่มลิงก์ไปยังวิธีการคำนวณคะแนน
    ตรวจสอบเมล็ด: 0-80000 คะแนน: 1920 * 2 + 1017754 = 1021594 (-770)
  • 2018/02/02 : เมล็ดพันธุ์ใหม่ (10087702) (ไม่พบเวลาในการแก้ไขการส่ง)
    เมล็ดพันธุ์ที่ถูกตรวจสอบ: 0-32000000 คะแนน: 1923 * 2 + 1017344 = 1021190 (-404)

คุณสามารถรวมชุดทดสอบในคำตอบของคุณเพื่อประเมินคะแนนได้หรือไม่?
นาธาเนียล

@ นาธาเนียลฉันเชื่อมโยงรหัสคะแนนโดยตรง นอกจากพื้นที่เก็บข้อมูลแล้วคุณจะพิจารณาเรื่องนี้มากพอไหม?
BrainStone

เมื่อตรวจสอบกฎฉันพบว่าฉันละเมิดกฎบางข้อ ฉันจะอัปเดตคำตอบตามปกติเมื่อแก้ไขปัญหาแล้ว
BrainStone

จากนั้นคุณจะได้รับการเข้ารหัสข้อความลงในเมล็ดพันธุ์แบบสุ่ม ดูSeedภาษาการเขียนโปรแกรมที่ลึกลับและคุณอาจต้องการทำวิศวกรรมโปรแกรม MT19937 และเอาชนะคำตอบนี้ (ถ้าทำได้)
user202729

เป็นความคิดที่ดี แต่จะไม่ช่วยให้ได้คะแนนดี +1 อยู่ดี
user202729

3

ทับทิม, 1164418 (อุ๊ปส์)

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

x="\"ect,htabsdd,in,\\nodniwlrfydbulkm;f?ckgwvi0,.*pr;\\\"uz17klI\\n-c'WSpA\\nTwqu8.77!-BeWO5.4.CoP\\n\\\"UHEFu2.?-9.jo6.NI3.MaLYDOGoOAR'QUECziJoxp(\\nYa:\\nVI);K\\nUS*IZEX\\n&\\n$\\n_y[S\""
f=->n{(x.include? n)? x[x.index(n)+1] : ' '}

ฉันสร้างอย่างไร x

ก่อนอื่นฉันสร้างa.txtสิ่งต่อไปนี้:

grep -o ".." whale2.txt | sort | uniq -c|sort -bn>a.txt

จากนั้นฉันก็สร้างa.csv:

cat a.txt | awk '{ print $1","$2 }'|sort -n|tac>a.csv

จากนั้นฉันก็แยกวิเคราะห์xด้วยสคริปต์ Ruby ต่อไปนี้:

f={}
File.open('./a.csv').each{|l|x=l.partition(',')
f[x.last[0..1]]=x.first}
n={}
r={}
f.each{|k,v|if((r.include? k[0]and v>n[k[0]])or not r.include? k[0])and not k[1].nil?
r[k[0]]=k[1]
n[k[0]]=v
end}
s=''
r.each{|k,v|s+=k+v}
puts s.inspect

ฉันทำคะแนนได้อย่างไร

w=File.read('whale2.txt')
x="ect,htabsdd,in,\nodniwlrfydbulkm;f?ckgwvi0,.*pr;\"uz17klI\n-c'WSpA\nTwqu8.77!-BeWO5.4.CoP\n\"UHEFu2.?-9.jo6.NI3.MaLYDOGoOAR'QUECziJoxp(\nYa:\nVI);K\nUS*IZEX\n&\n$\n_y[S"
f=->n{(x.include? n)? x[x.index(n)+1] : ' '}

score = 235
w.each_line{|l|v=l[0];l[0..-3].each_char{|n|v+=f[n]};v.split(//).each_with_index{|c,i|if l[i]==c
print c
else
print '_'
score+=1

end}}

puts "FINAL SCORE: #{score}"

ฉันแน่ใจว่าได้รับอนุญาต; ถ้าคุณวิเคราะห์ไฟล์ก็ทำได้ดี! เฉพาะในกรณีที่โปรแกรมทำเช่นนี้จะไม่ถูกต้อง
Erik the Outgolfer

@EriktheOutgolfer> _> (สไลด์เงียบ ๆ "(ไม่ใช่การแข่งขัน)" ลงในชื่อ)
NO_BOOT_DEVICE

ทำไม? หากสิ่งนี้ถูกต้องมันเป็นการแข่งขันแม้ว่ามันจะไม่ชนะมากนัก หากไม่ถูกต้อง (นั่นคือวิธีการแก้ปัญหาของคุณอ่านจากไฟล์และไม่เพียง แต่มีตัวอักษร) มันควรจะถูกลบ
Erik the Outgolfer

อืมม ฉันคิดว่าคุณหมายถึงถ้าโปรแกรมใด ๆ วิเคราะห์ไฟล์และไม่ใช่แค่วิธีแก้ปัญหา
NO_BOOT_DEVICE

1
ฉันอ่าน Ruby ไม่ได้ แต่ฉันคิดว่ามันถูกต้อง การมีตัวอักษรในโปรแกรมนั้นสมบูรณ์ดีไม่มีปัญหาเลย
นาธาเนียล

2

Python 3 , (146 * 2 + 879757) 880049 ไบต์

def f(c):return"\n                     t \n 2  sS \n  -  08........       huaoRooe oioaohue thpih eEA \n   neo    enueee neue hteht e"[ord(c)-10]

ลองออนไลน์!

ตารางความถี่ตรงไปตรงมาสวย แต่ละตำแหน่งในสตริงสอดคล้องกับรหัส ascii ของอักขระปัจจุบัน (ลบ 10 = 0x0a = '\ n', อักขระต่ำสุดในไฟล์) และอักขระในแต่ละดัชนีเป็นอักขระถัดไปที่พบบ่อยที่สุด สมมติว่าฉันคำนวณความถี่ที่ถูกต้อง ...

ทดสอบด้วยรหัสจากการทดสอบของ user202729


คุณสามารถบันทึกไบต์บางอย่างโดยใช้def f(c):return(" ">c)*c or"t ... e"[ord(c)-32]?
Neil

0

[Python 3] (644449 * 2 + 0) 1288898 คะแนน

ความแม่นยำสมบูรณ์แบบในเพียง 644449 ไบต์

import zlib,base64 as s
t=enumerate(zlib.decompress(s.b64decode(b'###')).decode());a=lambda c:next(t)[1]

รหัสเต็มไม่พอดีกับคำตอบดังนั้นฉันวางมันไว้ที่นี่และแทนที่สตริงตัวอักษรไบนารีขนาดใหญ่ด้วย b '###' ในข้อความตอบรับ

สิ่งนี้สร้างขึ้นด้วยรหัสต่อไปนี้โดยที่ "modified.py" เป็นไฟล์ที่สร้างขึ้นและ "cheatsheet.txt" เป็นไฟล์ whale2.txt ที่เริ่มต้นที่อักขระที่สอง

import zlib, base64
with open("modified.py","w") as writer:
    writer.write("import zlib,base64 as s\nt=enumerate(zlib.decompress(s.b64decode(")
    with open("cheatsheet.txt","rb") as source:
        text = source.read()
        writer.write(str(base64.b64encode(zlib.compress(text,9))))
    writer.write(')).decode());a=lambda c:next(t)[1]')

รหัสสามารถดำเนินการได้โดยการเพิ่มรายการต่อไปนี้ในตอนท้ายของ "modified.py" "whale2.txt" ต้องอยู่ในไดเรกทอรีเดียวกับ "modified.py" และเอาต์พุตจะถูกเขียนไปที่ "out.txt"

with open("out.txt","w") as writer:
    with open("whale2.txt","r") as reader:
        text = reader.read()
        for b in text:
            c = a(b)
            writer.write(c)

คำตอบนี้ไม่สามารถเข้าถึง whale.txt หรือ whale2.txt โดยตรง มันใช้ไลบรารีการบีบอัดมาตรฐานที่มีอยู่ตามที่อนุญาตไว้อย่างชัดเจนในกฎ


อาจจะมี "\ r \ n" ในการมีที่ฉันไม่สามารถกำจัดของใน Windows เมื่อฉันถูกนับพวกเขา
Legorhin

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