ช่วยฉันจำสัตว์ประหลาดของฉัน


35

พื้นหลัง

NetHack เป็นเกมคอมพิวเตอร์ตั้งแต่ปี 1987 ก่อนที่จะมีการใช้กราฟิกในเกมคอมพิวเตอร์ มีมอนสเตอร์จำนวนมากในเกมและอาจจำเป็นต้องมีจำนวนมากบนหน้าจอในครั้งเดียวดังนั้นมอนสเตอร์จะถูกวาดในวิธีที่น้อยมาก: มอนสเตอร์จะถูกวาดเป็นอักขระ ASCII บนหน้าจอ

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

งาน

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

Stack Snippet ต่อไปนี้เป็นอ็อบเจ็กต์ JSON ที่ให้การแม็พแบบเต็มของอินพุตที่เป็นไปได้กับเอาต์พุตที่สอดคล้องกัน:

ดังนั้นโดยทั่วไปงานที่นี่คือ "ให้คีย์ในพจนานุกรมที่แสดงโดยวัตถุ JSON ด้านบนส่งคืนค่าที่สอดคล้องกัน"

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

ชี้แจง

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

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

เงื่อนไขชัยชนะ

นี่คือดังนั้นรายการที่ชนะจะเป็นรายการที่สั้นที่สุดนับเป็นไบต์ โชคดี!


6
mail daemon> _ <
นักเทศน์

1
คำแนะนำ: บางทีคุณสามารถจัดเรียงรายการสัตว์ประหลาดตามลำดับสัญลักษณ์ ASCII ที่พวกเขาเป็นตัวแทน
Kritixi Lithos

2
เฮ้อ - ที่เกมดังกล่าวที่ดีเหล่านั้นเป็นวัน ...
GreenAsJade

2
@GreenAsJade ยังคงเป็นเกมที่ยอดเยี่ยม! ในความเป็นจริงมีการเปิดตัวเวอร์ชั่นใหม่เมื่อไม่กี่เดือนที่ผ่านมาหลังจากไม่ได้ใช้งานเป็นเวลาหลายปี
nmjcman101

1
ป่าสีน้ำตาลผุดขึ้นได้ปรากฏ !!
Magic Octopus Urn

คำตอบ:


11

Jelly , 309 ไบต์ในการเข้ารหัสของ Jelly

“Æ÷“¥s“ɲ“¡µ’;“ịƊ⁴çNṂ‘_\
OḌ;¢*5$%¥/µ“+⁷ż!¤ña¡jIȧƁfvḶg/Ọ=^ƝĠ0Ẇƭ³½N~=.Ɗ°ɗẇ⁵\ɦ*ɠPf⁾?ṾHḣ 2=⁹ƒ!©ƊĠṣƥ®Ƙ0Yƙ>!ȧtƊN0w,$ɠẎ46fẋ⁷(ṣẆm⁾ŻƓṫµsçwṣḂḲd0Ruṛ’ḃ21+\iµØW“&;:' ”;“¡3ȧ%⁾xƑ?{Ñṃ;Ċ70|#%ṭdṃḃ÷ƑĠẏþḢ÷ݳȦṖcẇọqƁe ʠ°oḲVḲ²ụċmvP[ỴẊẋ€kṢ ȯḂ;jɓỴẏeṾ⁴ḳḢ7Ẓ9ġƤṙb€xÇ4ɗ⁻>Ẉm!Ƈ)%Ḃẇ$ġ£7ȧ`ỵẈƘɗ¡Ṃ&|ƙƥ³ẏrṛbḋƙċ⁻ṁƲRṀẹṾ<ñ⁻Ṅ7j^ɓĊ’b58¤ị;0ị@
ḲÇ€t0”@;Ṫ

ลองออนไลน์!

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

อัลกอริทึมและคำอธิบาย

การจำแนกประเภทโดยใช้คำ

ฉันตัดสินใจว่าเพื่อให้ได้คะแนนดีจำเป็นต้องใช้ประโยชน์จากโครงสร้างของอินพุตมากกว่ารายการอื่น ๆ สิ่งหนึ่งที่เห็นได้ชัดเจนมากคือสัตว์ประหลาดหลายตัวมีชื่อของรูปแบบ " คำคุณศัพท์ สายพันธุ์ "; red dragonและมีทั้งสองประเภทของมังกรและทำให้ปรากฏเป็นblue dragon Dสัตว์ประหลาดอื่น ๆ บางชื่อมีรูปแบบ " งานสายพันธุ์ " เช่น; เป็นประเภทของผีนี้จะปรากฏเป็น เรื่องที่ซับซ้อนเป็นเรื่องที่ไม่ตาย ทั้งเป็นโกโบลด์และผีดิบและรัฐหลังจะมีความสำคัญในการตั้งชื่อ NetHack มอนสเตอร์ที่ทำให้เราต้องการที่จะจำแนกประเภทนี้เช่นorc shamanokobold zombieZ

ด้วยเหตุนี้ฉันจึงจำแนกคำที่ปรากฏในชื่อสัตว์ประหลาดดังต่อไปนี้: ตัวบ่งชี้เป็นคำที่บ่งบอกระดับสัตว์ประหลาดที่เหมาะสมsphereอย่างยิ่ง(เช่นแสดงให้เห็นอย่างชัดเจนว่าสัตว์ประหลาดนั้นอยู่ในชั้นเรียนe); คำกำกวมเป็นคำที่ทำให้มากน้อยของข้อเสนอแนะ (ที่lordไม่ได้บอกคุณมาก) และคำอื่น ๆ ทั้งหมดที่มีnonwordsว่าเราไม่สนใจเกี่ยวกับ แนวคิดพื้นฐานคือเราดูคำในชื่อสัตว์ประหลาดตั้งแต่ต้นจนจบและเริ่มเลือกตัวบ่งชี้แรกที่เราเห็น ดังนั้นจึงจำเป็นที่จะต้องแน่ใจว่าชื่อมอนสเตอร์แต่ละตัวมีตัวบ่งชี้อย่างน้อยหนึ่งตัวซึ่งตามด้วยคำที่คลุมเครือ เป็นข้อยกเว้นคำที่ปรากฏในชื่อของสัตว์ประหลาดที่ดูเหมือน@(กลุ่มที่ใหญ่ที่สุด) ล้วนจัดว่าคลุมเครือ สิ่งใดสามารถปรากฏขึ้นก่อนที่ตัวบ่งชี้ ตัวอย่างเช่นชื่อสี (เช่นred) จะปรากฏก่อนหน้านี้เสมอในชื่อที่ไม่ใช่ตัวบ่งชี้และถือเป็น nonwords (เนื่องจากไม่เคยตรวจสอบในขณะที่กำหนดเอกลักษณ์ของสัตว์ประหลาด)

ในท้ายที่สุดโปรแกรมนี้ลงมาที่ตารางแฮชเหมือนกับที่โปรแกรมอื่นทำ อย่างไรก็ตามตารางไม่มีรายการชื่อมอนสเตอร์ทั้งหมดหรือคำทั้งหมดที่ปรากฏในชื่อมอนสเตอร์ ค่อนข้างจะมีเพียงตัวบ่งชี้ ความยุ่งเหยิงของคำที่ไม่ชัดเจนไม่ปรากฏในตาราง แต่ต้องกำหนดให้กับช่องว่าง (การพยายามค้นหาคำที่ไม่ชัดเจนจะปรากฏขึ้นเสมอ) สำหรับ nonwords นั้นไม่สำคัญว่าคำนั้นจะปรากฏในตารางหรือไม่หรือว่า hash collides หรือไม่เพราะเราไม่เคยใช้คุณค่าของการค้นหา nonword (ตารางค่อนข้างเบาบางดังนั้น nonwords ส่วนใหญ่จะไม่ปรากฏในตาราง แต่มีบางอย่างที่fleshพบในตารางเนื่องจากการชนกันของแฮช)

นี่คือตัวอย่างบางส่วนของการทำงานของโปรแกรมนี้:

  • woodchuckมีความยาวคำเดียว (เช่นตัวบ่งชี้) และการค้นหาบนโต๊ะwoodchuckให้คำตอบที่rต้องการ
  • abbotยังเป็นคำเดียวนาน @แต่ดูเหมือนว่า เช่นabbotนี้ถือว่าเป็นคำที่คลุมเครือ การค้นหาตารางจะว่างเปล่าและเรากลับคำตอบ@ตามค่าเริ่มต้น
  • vampire lordประกอบด้วยตัวบ่งชี้ ( vampireสอดคล้องกับV) และคำที่ไม่ชัดเจน ( lordซึ่งไม่ได้อยู่ในตาราง) ซึ่งหมายความว่าเราจะตรวจสอบทั้งสองคำ (ย้อนลำดับ) Vแล้วให้คำตอบที่ถูกต้องของ
  • gelatinous cubeประกอบด้วย nonword ( gelatinousซึ่งสอดคล้องกับHเนื่องจากการชนกันของข้อมูลแฮช) และตัวบ่งชี้ ( cubeซึ่งสอดคล้องกับb) เนื่องจากเราใช้คำสุดท้ายที่พบในตารางเท่านั้นการส่งคืนนี้bจึงเป็นไปตามที่คาดไว้
  • gnome mummyประกอบด้วยสองตัวชี้วัดgnomeที่สอดคล้องกับGและสอดคล้องกับmummy Mเราใช้ตัวบ่งชี้สุดท้ายและรับMซึ่งเป็นสิ่งที่เราต้องการ

รหัสสำหรับการจัดการการจำแนกประเภทคำนั้นเป็นบรรทัดสุดท้ายของโปรแกรม Jelly นี่คือวิธีการทำงาน:

ḲÇ€t0”@;Ṫ
Ḳ          Split on spaces
 ǀ        Call function 2 (table lookup) on each entry
   t0      Remove trailing zeroes (function 2 returns 0 to mean "not found")
     ”@;   Prepend an @ character
        Ṫ  Take the last result

มีสองกรณีจริง; หากอินพุตประกอบด้วยคำที่ไม่ชัดเจนt0ทั้งหมดลบเอาต์พุตทั้งหมดของการค้นหาตารางและเราจะได้@ผลลัพธ์ตามค่าเริ่มต้น หากมีตัวบ่งชี้ในอินพุตt0จะลบสิ่งใด ๆ ทางด้านขวาของตัวบ่งชี้ขวาสุดและจะให้ผลลัพธ์ที่สอดคล้องกันสำหรับตัวบ่งชี้นั้น

การบีบอัดตาราง

แน่นอนการป้อนข้อมูลเป็นคำพูดไม่ได้แก้ปัญหาด้วยตัวเอง เรายังต้องเข้ารหัสการติดต่อระหว่างตัวชี้วัดและคลาสสัตว์ประหลาดที่เกี่ยวข้อง (และการขาดการติดต่อจากคำที่ไม่ชัดเจน) เมื่อต้องการทำสิ่งนี้ฉันสร้างตาราง sparse ด้วยรายการ 181 ที่ใช้ (ตรงกับตัวบ่งชี้ 181 นี่เป็นการปรับปรุงที่ยิ่งใหญ่เหนือสัตว์ประหลาด 378!) และรายการทั้งหมด 966 รายการ (สอดคล้องกับค่าเอาต์พุต 966 ของฟังก์ชันแฮช) ตารางถูกเข้ารหัสในโปรแกรมของเขาโดยใช้สองสาย: สตริงแรกระบุขนาดของ "ช่องว่าง" ในตาราง (ซึ่งไม่มีรายการ); และสตริงที่สองระบุคลาสมอนสเตอร์ซึ่งสอดคล้องกับแต่ละรายการ สิ่งเหล่านี้ทั้งสองแสดงออกอย่างกระชับผ่านการแปลงฐาน

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

“…’ḃ21+\iµØW“&;:' ”;“…’b58¤ị;0ị@
“…’                              Base 250 representation of the gap sizes
   ḃ21                           Convert to bijective base 21 
      +\                         Cumulative sum (converts gaps to indexes)
        i                        Find the input in this list
         µ                       Set as the new default for missing arguments

          ØW                     Uppercase + lowercase alphabets (+ junk we ignore)
            “&;:' ”;             Prepend "&;:' "
                    “…’          Base 250 representation of the table entries
                       b58       Convert to base 58
                          ¤      Parse the preceding two lines as a unit
                           i     Use the table to index into the alphabets
                            ;0   Append a zero
                              i@ Use {the value as of µ} to index into the table

Bijective base 21 เป็นเหมือนฐาน 21 ยกเว้นว่า 21 เป็นตัวเลขทางกฎหมายและ 0 ไม่ใช่ นี่เป็นการเข้ารหัสที่สะดวกกว่าสำหรับเราเพราะเรานับรายการที่อยู่ติดกันสองรายการว่ามีช่องว่าง 1 เพื่อให้เราสามารถค้นหาดัชนีที่ถูกต้องผ่านผลรวมสะสม เมื่อมาถึงส่วนของตารางที่เก็บค่าเรามี 58 ค่าที่ไม่ซ้ำกันดังนั้นเราจึงถอดรหัสเป็นจำนวนเต็ม 58 ต่อเนื่องกันแล้วถอดรหัสอีกครั้งโดยใช้ตารางการค้นหาที่แมปเหล่านี้เป็นตัวละครที่ใช้จริง (ส่วนใหญ่เป็นตัวอักษรดังนั้นเราจึงเริ่มต้นตารางการค้นหารองนี้ด้วยรายการที่ไม่ใช่ตัวอักษร&;:' จากนั้นเพียงผนวกค่าคงที่ของเยลลี่ที่เริ่มต้นด้วยตัวอักษรตัวพิมพ์ใหญ่และตัวพิมพ์เล็กมันยังมีขยะอื่น ๆ แต่เราไม่สนใจ เกี่ยวกับสิ่งนั้น.)

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

ฟังก์ชันแฮช

ส่วนที่เหลือของโปรแกรมคือฟังก์ชั่นแฮช นี้เริ่มพอเพียงกับOḌ; สิ่งนี้จะแปลงสตริงอินพุตให้เป็นรหัส ASCII ของมันแล้วคำนวณรหัสสุดท้ายบวก 10 เท่าของรหัสสุดท้ายและบวก 100 เท่าของรหัสก่อนหน้าและต่อไปเรื่อย ๆ (นี่เป็นตัวแทนที่สั้นมากในเยลลี่เพราะมันใช้บ่อยกว่า string →ฟังก์ชั่นการแปลงจำนวนเต็ม) อย่างไรก็ตามหากเราลดแฮชเพียงแค่นี้โดยตรงผ่านการทำงานของโมดูลัสเราจะต้องมีโต๊ะที่ค่อนข้างใหญ่ ดังนั้นฉันเริ่มด้วยการปฏิบัติการเพื่อลดตาราง พวกเขาแต่ละคนทำงานเช่นนี้: เรารับพลังที่ห้าของค่าแฮชปัจจุบัน; จากนั้นเราลดค่าโมดูโลค่าคงที่ (ค่าคงที่ใดขึ้นอยู่กับการดำเนินการที่เราใช้) ห่วงโซ่นี้ให้การประหยัดมากขึ้น (ในแง่ของการลดขนาดของตารางผลลัพธ์) กว่าค่าใช้จ่าย (ในแง่ของความจำเป็นในการเข้ารหัสสายโซ่ของการดำเนินงานของตัวเอง) ในสองวิธี: มันสามารถทำให้ตารางมีขนาดเล็กกว่ามาก (966 รายการมากกว่า 3529 รายการ) และการใช้หลายขั้นตอนทำให้มีโอกาสมากขึ้นในการแนะนำการชนที่เป็นประโยชน์ (สิ่งนี้ไม่ได้เกิดขึ้นมากนัก แต่มีการชนกันเช่น: ทั้งสองDeathและYeenoghuแฮชถึง 806) รายการจากตารางขณะที่พวกเขาทั้งสองไป&) ตัวดัดแปลงที่ใช้ที่นี่คือ [3529, 2163, 1999, 1739, 1523, 1378, 1246, 1223, 1145, 966] อนึ่งเหตุผลในการเพิ่มพลังที่ห้าคือถ้าคุณเพิ่งเอาค่าโดยตรงไปช่องว่างก็มักจะมีขนาดเท่าเดิมในขณะที่การยกกำลังจะย้ายช่องว่างรอบ ๆ และทำให้ตารางกระจายได้อย่างเท่าเทียมกันมากขึ้น ห่วงโซ่แทนที่จะติดอยู่ในขั้นต่ำของท้องถิ่น (ช่องว่างกระจายอย่างเท่าเทียมกันมากขึ้นช่วยให้การเข้ารหัส terser ขนาดช่องว่าง) สิ่งนี้จะต้องมีพลังแปลก ๆ เพื่อป้องกันไม่ให้ข้อเท็จจริงที่x ² = (- x ) ²แนะนำการชนและ 5 ทำงานได้ดีกว่า 3

บรรทัดแรกของโปรแกรมเข้ารหัสลำดับของโมเดลโดยใช้การเข้ารหัสเดลต้า:

“…’;“…‘_\
“…’       Compressed integer list encoding, arbitrary sized integers
   ;      Append
    “…‘   Compressed integer list encoding, small integers (≤ 249)
       _\ Take cumulative differences

ส่วนที่เหลือของโปรแกรมจุดเริ่มต้นของบรรทัดที่สองใช้ฟังก์ชันแฮช:

OḌ;¢*5$%¥/
O           Take ASCII codepoints
 Ḍ          "Convert from decimal", generalized to values outside the range 0-9
  ;¢        Append the table of moduli from the previous line
         /  Then reduce by:
    *5$       raising to the power 5 (parsing this as a group)
       %¥     and modulusing by the right argument (parsing this as a group, too).

การตรวจสอบ

นี่เป็นสคริปต์ Perl ที่ฉันใช้ในการตรวจสอบว่าโปรแกรมทำงานอย่างถูกต้อง:

use warnings;
use strict;
use utf8;
use IPC::Run qw/run/;

my %monsters = ("Aleax", "A", "Angel", "A", "Arch Priest", "@", "Archon", "A",
"Ashikaga Takauji", "@", "Asmodeus", "&", "Baalzebub", "&", "Chromatic Dragon",
"D", "Croesus", "@", "Cyclops", "H", "Dark One", "@", "Death", "&", "Demogorgon",
"&", "Dispater", "&", "Elvenking", "@", "Famine", "&", "Geryon", "&",
"Grand Master", "@", "Green-elf", "@", "Grey-elf", "@", "Hippocrates", "@",
"Ixoth", "D", "Juiblex", "&", "Keystone Kop", "K", "King Arthur", "@",
"Kop Kaptain", "K", "Kop Lieutenant", "K", "Kop Sergeant", "K", "Lord Carnarvon",
"@", "Lord Sato", "@", "Lord Surtur", "H", "Master Assassin", "@", "Master Kaen",
"@", "Master of Thieves", "@", "Medusa", "@", "Minion of Huhetotl", "&",
"Mordor orc", "o", "Nalzok", "&", "Nazgul", "W", "Neferet the Green", "@", "Norn",
"@", "Olog-hai", "T", "Oracle", "@", "Orcus", "&", "Orion", "@", "Pelias", "@",
"Pestilence", "&", "Scorpius", "s", "Shaman Karnov", "@", "Thoth Amon", "@",
"Twoflower", "@", "Uruk-hai", "o", "Vlad the Impaler", "V", "Wizard of Yendor",
"@", "Woodland-elf", "@", "Yeenoghu", "&", "abbot", "@", "acid blob", "b",
"acolyte", "@", "air elemental", "E", "aligned priest", "@", "ape", "Y",
"apprentice", "@", "arch-lich", "L", "archeologist", "@", "attendant", "@",
"baby black dragon", "D", "baby blue dragon", "D", "baby crocodile", ":",
"baby gray dragon", "D", "baby green dragon", "D", "baby long worm", "w",
"baby orange dragon", "D", "baby purple worm", "w", "baby red dragon", "D",
"baby silver dragon", "D", "baby white dragon", "D", "baby yellow dragon", "D",
"balrog", "&", "baluchitherium", "q", "barbarian", "@", "barbed devil", "&",
"barrow wight", "W", "bat", "B", "black dragon", "D", "black light", "y",
"black naga hatchling", "N", "black naga", "N", "black pudding", "P",
"black unicorn", "u", "blue dragon", "D", "blue jelly", "j", "bone devil", "&",
"brown mold", "F", "brown pudding", "P", "bugbear", "h", "captain", "@",
"carnivorous ape", "Y", "cave spider", "s", "caveman", "@", "cavewoman", "@",
"centipede", "s", "chameleon", ":", "chickatrice", "c", "chieftain", "@",
"clay golem", "'", "cobra", "S", "cockatrice", "c", "couatl", "A", "coyote", "d",
"crocodile", ":", "demilich", "L", "dingo", "d", "disenchanter", "R", "djinni",
"&", "dog", "d", "doppelganger", "@", "dust vortex", "v", "dwarf king", "h",
"dwarf lord", "h", "dwarf mummy", "M", "dwarf zombie", "Z", "dwarf", "h",
"earth elemental", "E", "electric eel", ";", "elf mummy", "M", "elf zombie", "Z",
"elf", "@", "elf-lord", "@", "energy vortex", "v", "erinys", "&", "ettin mummy",
"M", "ettin zombie", "Z", "ettin", "H", "fire ant", "a", "fire elemental", "E",
"fire giant", "H", "fire vortex", "v", "flaming sphere", "e", "flesh golem", "'",
"floating eye", "e", "fog cloud", "v", "forest centaur", "C", "fox", "d",
"freezing sphere", "e", "frost giant", "H", "gargoyle", "g", "garter snake", "S",
"gas spore", "e", "gecko", ":", "gelatinous cube", "b", "ghost", " ", "ghoul",
"Z", "giant ant", "a", "giant bat", "B", "giant beetle", "a", "giant eel", ";",
"giant mimic", "m", "giant mummy", "M", "giant rat", "r", "giant spider", "s",
"giant zombie", "Z", "giant", "H", "glass golem", "'", "glass piercer", "p",
"gnome king", "G", "gnome lord", "G", "gnome mummy", "M", "gnome zombie", "Z",
"gnome", "G", "gnomish wizard", "G", "goblin", "o", "gold golem", "'",
"golden naga hatchling", "N", "golden naga", "N", "gray dragon", "D", "gray ooze",
"P", "gray unicorn", "u", "green dragon", "D", "green mold", "F", "green slime",
"P", "gremlin", "g", "grid bug", "x", "guard", "@", "guardian naga hatchling",
"N", "guardian naga", "N", "guide", "@", "healer", "@", "hell hound pup", "d",
"hell hound", "d", "hezrou", "&", "high priest", "@", "hill giant", "H",
"hill orc", "o", "hobbit", "h", "hobgoblin", "o", "homunculus", "i",
"horned devil", "&", "horse", "u", "housecat", "f", "human mummy", "M",
"human zombie", "Z", "human", "@", "hunter", "@", "ice devil", "&", "ice troll",
"T", "ice vortex", "v", "iguana", ":", "imp", "i", "incubus", "&", "iron golem",
"'", "iron piercer", "p", "jabberwock", "J", "jackal", "d", "jaguar", "f",
"jellyfish", ";", "ki-rin", "A", "killer bee", "a", "kitten", "f", "knight", "@",
"kobold lord", "k", "kobold mummy", "M", "kobold shaman", "k", "kobold zombie",
"Z", "kobold", "k", "kraken", ";", "large cat", "f", "large dog", "d",
"large kobold", "k", "large mimic", "m", "leather golem", "'", "lemure", "i",
"leocrotta", "q", "leprechaun", "l", "lich", "L", "lichen", "F", "lieutenant",
"@", "little dog", "d", "lizard", ":", "long worm", "w", "lurker above", "t",
"lynx", "f", "mail daemon", "&", "manes", "i", "marilith", "&", "master lich",
"L", "master mind flayer", "h", "mastodon", "q", "mind flayer", "h", "minotaur",
"H", "monk", "@", "monkey", "Y", "mountain centaur", "C", "mountain nymph", "n",
"mumak", "q", "nalfeshnee", "&", "neanderthal", "@", "newt", ":", "ninja", "@",
"nurse", "@", "ochre jelly", "j", "ogre king", "O", "ogre lord", "O", "ogre", "O",
"orange dragon", "D", "orc mummy", "M", "orc shaman", "o", "orc zombie", "Z",
"orc", "o", "orc-captain", "o", "owlbear", "Y", "page", "@", "panther", "f",
"paper golem", "'", "piranha", ";", "pit fiend", "&", "pit viper", "S",
"plains centaur", "C", "pony", "u", "priest", "@", "priestess", "@", "prisoner",
"@", "purple worm", "w", "pyrolisk", "c", "python", "S", "quantum mechanic", "Q",
"quasit", "i", "queen bee", "a", "quivering blob", "b", "rabid rat", "r",
"ranger", "@", "raven", "B", "red dragon", "D", "red mold", "F",
"red naga hatchling", "N", "red naga", "N", "rock mole", "r", "rock piercer", "p",
"rock troll", "T", "rogue", "@", "rope golem", "'", "roshi", "@", "rothe", "q",
"rust monster", "R", "salamander", ":", "samurai", "@", "sandestin", "&",
"sasquatch", "Y", "scorpion", "s", "sergeant", "@", "sewer rat", "r", "shade", " ",
"shark", ";", "shocking sphere", "e", "shopkeeper", "@", "shrieker", "F",
"silver dragon", "D", "skeleton", "Z", "small mimic", "m", "snake", "S",
"soldier ant", "a", "soldier", "@", "spotted jelly", "j", "stalker", "E",
"steam vortex", "v", "stone giant", "H", "stone golem", "'", "storm giant", "H",
"straw golem", "'", "student", "@", "succubus", "&", "tengu", "i", "thug", "@",
"tiger", "f", "titan", "H", "titanothere", "q", "tourist", "@", "trapper", "t",
"troll", "T", "umber hulk", "U", "valkyrie", "@", "vampire bat", "B",
"vampire lord", "V", "vampire", "V", "violet fungus", "F", "vrock", "&", "warg",
"d", "warhorse", "u", "warrior", "@", "watch captain", "@", "watchman", "@",
"water demon", "&", "water elemental", "E", "water moccasin", "S", "water nymph",
"n", "water troll", "T", "werejackal", "d", "wererat", "r", "werewolf", "d",
"white dragon", "D", "white unicorn", "u", "winged gargoyle", "g",
"winter wolf cub", "d", "winter wolf", "d", "wizard", "@", "wolf", "d",
"wood golem", "'", "wood nymph", "n", "woodchuck", "r", "wraith", "W", "wumpus",
"q", "xan", "x", "xorn", "X", "yellow dragon", "D", "yellow light", "y",
"yellow mold", "F", "yeti", "Y", "zruty", "z");

for my $monster (sort keys %monsters) {
    run ["./jelly", "fu", "monsters.j", $monster], \ "", \my $out;
    print "$monster -> \"$out\" (",
        ($out ne $monsters{$monster} ? "in" : ""), "correct)\n";
}

10

JavaScript (ES6), 915 ... 902 890 ไบต์

w=>[..."aZM?o@;LWu&P?D@zF@W: @aT&@nCEfvQ&R&Tb'b@&p@:Srn @ahlrdpdT'TRv:HUYG@&fSfYdG&SGHL@Mh@G@gs';@CS@km@OsirA@q@njOZS@O@';HYqHE&DJavq&&aYaBmZMf;bv@EqHg@Z@;dm@M@?@rs@d@@oDAosDT@d@ZeBVrq@jFooD@VV&&BvMEDKiuiPC@&@DYrD&eD@D@@:AwccKZiF:DKLXAwdL@w&@@u'Hc@@q&;D:::WjdN@N@xD&eFh@gh@&Md?&Ye@@&h@hNN'Z&qtKEd@@HtH&@'@&@xd&dZsv@oo@FDyd@@&&@&@HS'Hw?DF@@@MPfDfi'AH&@@pkZkuMyZhFNN'P?d@u@NN&B@uo'fdi@?ke&"].find((_,i)=>!(s-=`GD4~#_@'R<1*~7C7RbZ6F'"Sa&!*1),#''3'.+B6(K$.l%9&!#0@51""~/+!gaW!/.(5'-@0'';!%C.&""!-.$16.2>(#&g!!O,#8A50O!)*(9b|Z4@7V).;*A*HWO(g1$/*-4&SL1I#K$#"3"#=e/'V~4'B(*,.3),$@D3)*76-"\\&kL7(-4#=7!!#+(B/B!-%!"_+!")+)0$1:E84!L191&)(255)!3O<,90NN6&;Q2'"bO=*h7.%1![<o!%M'G5/R.0$-J*%\\~6T?>)16""L&!X94T4"3$!2'^070Y2a"##)#"&n&(+1*&!-M""73R5%'y0~$-6<".MV?+1*ED>!B6b!)%&)8.+$&X0~Q'E%8&#%S/H.1<#>~!sU`.charCodeAt(i)-32),w=w.replace(/\W/g,1),s=parseInt((w+=w+w)[0]+w[2]+w[3]+w[6]+[...w].pop(),36)%8713)

ที่จัดรูปแบบ

ด้านล่างเป็นรุ่นที่จัดรูปแบบของรหัสพร้อมข้อมูล payload ที่ถูกตัดทอน

w => [..."aZM(…)"].find(
  (_, i) =>
    !(s -= `GD4(…)`.charCodeAt(i) - 32),
    w = w.replace(/\W/g, 1),
    s = parseInt((w += w + w)[0] + w[2] + w[3] + w[6] + [...w].pop(), 36) % 8713
)

มันทำงานอย่างไร

ขั้นตอนที่ 1

เราลดชื่อมอนสเตอร์ก่อนโดย:

  1. การแทนที่อักขระที่ไม่ใช่ตัวอักษรและตัวเลข (ช่องว่างและเครื่องหมายขีดกลาง) ด้วย1's
  2. ทำซ้ำสตริงนี้ 3 ครั้งเพื่อให้แน่ใจว่าเรามีตัวอักษรมากพอที่จะทำงานในขั้นตอนต่อไป
  3. เก็บเฉพาะอักขระที่ 1, 3, 4, 7 และตัวสุดท้าย

ตัวอย่าง:

1.34..7..L
Demogorgon -> Dmorn
^ ^^  ^  ^

             1.34..7.L
orc mummy -> orc1mummy -> oc1my
             ^ ^^  ^ ^

        1.34..7....L
xorn -> xornxornxorn -> xrnrn
        ^ ^^  ^    ^

สิ่งนี้นำไปสู่การชนกันเล็กน้อย ยกตัวอย่างเช่น"Master Assassin"และมีทั้งที่ลดลงไป"Master Kaen" "Mst1n"โชคดีที่ชื่อมอนสเตอร์ที่ชนกันทั้งหมดใช้สัญลักษณ์เดียวกัน ( @ในกรณีนี้)

ขั้นตอนที่ 2

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

ตัวอย่าง:

Dmorn --[from base 36]--> 22893539 --[MOD 8713]--> 4488
oc1my --[from base 36]--> 40872778 --[MOD 8713]--> 95
xrnrn --[from base 36]--> 56717843 --[MOD 8713]--> 4926

ขั้นตอนที่ # 3

คีย์ทั้งหมดจะเรียงลำดับจากน้อยไปมาก:

[ 39, 75, 95, 192, 255, 287, 294, 344, 372, 389, 399, 516, 551, 574, 624, ..., 8635, 8688 ]

แปลงเป็นค่าเดลต้า:

[ 39, 36, 20, 97, 63, 32, 7, 50, 28, 17, 10, 117, 35, 23, 50, ..., 83, 53 ]

และเข้ารหัสเป็นอักขระ ASCII [ 32, 126 ]ในช่วง ค่าจำลองกลางบางค่าจะถูกแทรกเมื่อความแตกต่างระหว่างสองปุ่มที่ต่อเนื่องเกินกว่าขนาดที่เข้ารหัสได้สูงสุด

ในที่สุดรายการของคีย์จะถูกแมปกับรายการของสัญลักษณ์ที่เรียงตามลำดับเดียวกัน

ทดสอบ


จากการทดสอบของคุณเองนี้จะแบ่ง 5 รายการ ฉันไม่ได้ตรวจสอบเพื่อดูว่ามีอะไรทำให้พวกเขา แต่อาจต้องแก้ไข

@ ais523 นั่นคือสิ่งที่ฉันจะได้รับเมื่อทำการทดสอบใน Firefox เท่านั้น ฉันจะพยายามแก้ไขสำหรับ Chrome (อย่างน้อย)
Arnauld

2
@ ais523 ตอนนี้ควรทำงานได้ดีกับ FF, Chrome & Edge ขอโทษสำหรับเรื่องนั้น.
Arnauld

ฉันมีความคิดที่จะแยกบิตจากชื่อที่แปลงเป็นตัวเลข แต่ฉันคิดว่ามันเล็กเกินไปอย่างเห็นได้ชัด ยินดีด้วย!
Jonas Schäfer

8

Java, 1130 ไบต์

import java.util.*;class G{public static void main(String[]u){BitSet s=BitSet.valueOf(Base64.getDecoder().decode("D94FuoCWYEIhCTEgLWwRNU/CMB1cE7XBhxBsBCusihaASRg14IJpQMOIDJdFx3BOdDcmThdhILVkCgGsEmhII8UE+SB4kDYEEJzw7Tw54oUEQZe0AUHCACH6nAdqgiZgJhASCIPAEAzJBmuMIrBCHE8IiFjgKQwrN4/90B4QFaLBQBEwTArRBMLCLHQOUQs7ZXZ8B8uGC1EbeAMJBdihUDgCIwGUEKgEAu4W2SJkIAhzB1IQSHgNiEAwABQECV5BvAB7eizABXxFLEg5iMA3whhAFXOKHXEURB7UA7PQjgUK7sji8CmIC0FJsTB4tAMFgiARB3hOJATDsBkgGKnGmWIiIWBRwkMgToQJ49G8gTR4IqcB4vJwDBHSVBLQhpwHsUFipqBcWWaEsCBoGBF0AlNAE305HAfdU1AEbELBO0EERAfkmMkgZcEXDIa4MAp4HcENmYAMBB7UBbTwBqQPSMS9kVkEBMhCudAqBAKaR1CzZggDRw8WMAh0FQPEyKAsRAxzBwn0grwDMQMyQMdADRtFUBAsBQetRRBwcUgrlsQ1IkosBc9B6iBcjAkSDDKgEAQ1wgLIMEEwMkYB42ERBCdiEJMAt1wYSIAQkdIEI0UPNhALsDnRQ1AT/HQi1AyCEwiICOICpiAPlB8MwxnBPIk6JYaIgDy8NJHDsiAqzK0JAXpQPXgPLwJuEEbMTAGBYlQbDESvAXJAAQ=="));int i,j,k,c,d,h=u[0].hashCode(),a=(h&4092)>>2|(h>>5)&1024|(h>>7)&2048|(h>>9)&4096;char r='@';for(i=k=0;i<4297;i+=14){for(c=0,j=7;j>=0;j--)c+=c+(s.get(i+j)?1:0);if((k+=c)==a){for(d=0,j=13;j>=8;j--)d+=d+(s.get(i+j)?1:0);r=d<5?" &':;".charAt(d):(char)((d<31?60:66)+d);}}System.out.println(r);}}

Ungolfed:

import java.util.*;

class G {
    public static void main(String[] u) {
        BitSet s = BitSet.valueOf(Base64.getDecoder().decode(
                "D94FuoCWYEIhCTEgLWwRNU/CMB1cE7XBhxBsBCusihaASRg14IJpQMOIDJdFx3BOdDcmThdhILVkCgGsEmhII8UE+SB4kDYEEJzw7Tw54oUEQZe0AUHCACH6nAdqgiZgJhASCIPAEAzJBmuMIrBCHE8IiFjgKQwrN4/90B4QFaLBQBEwTArRBMLCLHQOUQs7ZXZ8B8uGC1EbeAMJBdihUDgCIwGUEKgEAu4W2SJkIAhzB1IQSHgNiEAwABQECV5BvAB7eizABXxFLEg5iMA3whhAFXOKHXEURB7UA7PQjgUK7sji8CmIC0FJsTB4tAMFgiARB3hOJATDsBkgGKnGmWIiIWBRwkMgToQJ49G8gTR4IqcB4vJwDBHSVBLQhpwHsUFipqBcWWaEsCBoGBF0AlNAE305HAfdU1AEbELBO0EERAfkmMkgZcEXDIa4MAp4HcENmYAMBB7UBbTwBqQPSMS9kVkEBMhCudAqBAKaR1CzZggDRw8WMAh0FQPEyKAsRAxzBwn0grwDMQMyQMdADRtFUBAsBQetRRBwcUgrlsQ1IkosBc9B6iBcjAkSDDKgEAQ1wgLIMEEwMkYB42ERBCdiEJMAt1wYSIAQkdIEI0UPNhALsDnRQ1AT/HQi1AyCEwiICOICpiAPlB8MwxnBPIk6JYaIgDy8NJHDsiAqzK0JAXpQPXgPLwJuEEbMTAGBYlQbDESvAXJAAQ=="));

        int i, j, k, c, d, h = u[0].hashCode(), 
            a = (h & 4092) >> 2 | (h >> 5) & 1024 | (h >> 7) & 2048 | (h >> 9) & 4096;
        char r = '@';
        for (i = 0, k = 0; i < 4297; i += 14) {
            for (c = 0, j = 7; j >= 0; j--)
                c += c + (s.get(i + j) ? 1 : 0);
            if ((k += c) == a) {
                for (d = 0, j = 13; j >= 8; j--)
                    d += d + (s.get(i + j) ? 1 : 0);
                r = d < 5 ? " &':;".charAt(d) : (char) ((d < 31 ? 60 : 66) + d);
            }
        }
        System.out.println(r);
    }
}

ชื่อสัตว์ประหลาดคือ:

  • แฮชโดยใช้ Java hashcodemethod => 32 bits
  • ANDed with mask 1001001000111111111100 => 13 บิต
  • เรียงจากที่เล็กที่สุดไปหาใหญ่ที่สุด
  • จากนั้นเราจะใช้ค่า delta ของรายการที่เรียงลำดับ => 8 บิต

อักขระที่แสดงถูกเข้ารหัสบน 6 บิต

ดังนั้นแต่ละ tuple (ชื่อมอนสเตอร์, ตัวอักษร) จึงใช้ 14 บิต tuples ทั้งหมดจะถูกบันทึกใน BitSet และการเข้ารหัส 64 ฐาน

ฉันสูญเสียข้อมูลจำนวนมากด้วยการเข้ารหัส base64 และการทำงานของ BitSet :-)


()->{...}คุณสามารถลดขนาดด้วยการทำให้การแสดงออกแลมบ์ดา: คำถามพูดอย่างนั้นในส่วน "การชี้แจง"
Olivier Grégoire

5

Mathematica, 1067 ไบต์ (การเข้ารหัสอักขระ Mac OS Roman)

FromCharacterCode[Mod[Tr/@{c=ToCharacterCode@#,c^2},216,32],"MacintoshRoman"]/.Inner[Rule,";¤7«´3πœ(ú-UU=6z±'¥ÿ†tƒ|\¢KÛd§≤jSóKWÊ8‰Ñwiøì¡ÛhÓ\‡¨:–*~‚¬æº¢»‘¤Á^∫„·nLÒ¤b|$|ÇòCóÌÈS_Ñä.Ëí 5y«KΔË\Ãò™_E`J’ëΔñTV–N„'„Ÿà¥xpîH#-PP)ÈÊVQ©LrBt}∑WÉ∏dÿå„•Tz∑Âao¿rÃ^bbP¨}ëÖ◇1èÇ&d¢¤ái√,B}±BˆÍdA´íBtæÅ/m√yQ6,uãÊ≤/Î!ïøuΩÒÉ)ë“∕C$RY•ÍÍu£oÉÓå‚Ïl.·1‚40ÃÚ¨ÇÆÅccflÓ8Ï Gáç3EÑ¥fXñ¨Àìz~j÷–ñÓz0~ôWtñ}μÎ◇f||Dd\ ÙH﷿É∑Ì´|¿Ö_»RT8Ûª|Äqü‘&6Ãác›Yˆ¿ô5≈ënÚqΩåVä>∫æ∂p ¨jtöåoÌfløÏÏò§¤flÈ;À∑Ѥ·›9né∕<·ì∕ÿmŸ«Ì»j√üà‰÷“5ïä^Ûe◇kd‡“(Ïö71›iΟÁm„ÈïÒß„kÕπ°ÊÓÒçÓfˆ¨flÁ9k|¶ä∕l~Òød‹jZÏ2[kÎ√3ÛâìÓΔE]ıIÚ>{#ÁÖ‚Üâ;·?l^vàß‹‘jîÙÇÅÉú¥äärÆæ™∏Üi≈mØÂ’-%USÌâ’ı Ê›·Ëÿb‡ıÖ31nh™Δ$~%À0n-À´sflk∑p.o5vz}mè]ÎÅç©lt;Îu„ŸW„›ˆˆÍ﷿Ä*7m8‰πór,„Õш/”Ë∕ªß9±‡¶çÁ•âg˜fló)ÖÔ¡'wúæ0ñ„Kûr"~(a=StringPartition)~2,"AAA&&DH&&&&&D&KKKKH&o&WT&&soV&bEYLDD:DDwDwDDDD&q&WBDyNNPuDj&FPhYss:c'ScAd:LdR&dvhhMZhE;MZv&MZHaEHve'evCdeHgSe:b ZaBa;mMrsZH'pGGMZGGo'NNDPuDFPgxNNdd&Hohoi&ufMZ&Tv:i&'pJdf;AafkMkZk;fdkm'iqlLFd:wtf&i&LhqhHYCnq&:jOODMoZooYf';&SCuwcSQiabrBDFNNrpT'qR:&Ysr eFDZmSajEvH'H'&ifHqtTUBVVF&du&ESnTdrdDugddd'nrWqXDyFYz"~a~1,List]/.x_/;StringLength@x>1->"@"&

ฟังก์ชันที่ไม่มีชื่อการรับสตริงเป็นอินพุตและส่งคืนอักขระ ฟังก์ชั่นมีรูปแบบดังต่อไปนี้:

1  FromCharacterCode[
2    Mod[Tr/@{c=ToCharacterCode@#,c^2},216,32]
3    ,"MacintoshRoman"] /.
4  Inner[Rule,
5    GIANT_STRING_1 ~(a=StringPartition)~2,
6    GIANT_STRING_2 ~a~1,
7    List]
8  /. x_/;StringLength@x>1 -> "@" &

นี่ GIANT_STRING_1 เป็นสตริงที่มี 608 อักขระหนึ่งไบต์ในการเข้ารหัสอักขระโรมัน Mac OS (ซึ่งไม่มีอยู่ในช่วง 00-1F) ในขณะที่ GIANT_STRING_2 เป็นสตริงที่มีอักขระ ASCII 304 ตัว

บรรทัดที่ 2 เริ่มฟังก์ชั่นแฮช: มันจะแปลงสตริงอินพุตให้เป็นรายการของรหัสตัวอักษร (การเข้ารหัสที่ไม่เกี่ยวข้องเนื่องจากพวกเขาสามารถพิมพ์ ASCII ได้ทั้งหมด) จากนั้นคำนวณผลรวมของรหัสอักขระเหล่านั้นและผลรวมของสี่เหลี่ยมทั้งโมดูโล 216 และบังคับใช้ คำตอบที่จะอยู่ระหว่าง 32 และ 255 จากนั้นบรรทัดที่ 1 และ 3 แปลงคู่ของจำนวนเต็มที่ได้รับคำสั่งเหล่านั้นเป็นสายอักขระสองตัวซึ่งเป็นค่าแฮที่เราใช้ในที่สุด

บรรทัด 5 เปลี่ยน GIANT_STRING_1 เป็นรายการของสตริงสองตัวอักษร 304 บรรทัด 6 เปลี่ยน GIANT_STRING_2 เป็นรายการของสตริงหนึ่งตัวอักษร 304 จากนั้นบรรทัดที่ 4 และ 5 จะแปลงรายการทั้งสองให้เป็นชุดของกฎการแทนที่ 304: หากคุณเห็นสตริงอักขระสองตัวที่มีลักษณะเช่นนั้นให้เปลี่ยนเป็นสตริงที่มีอักขระหนึ่งตัวเช่นนั้น สุดท้ายสาย 8 จะเปิดที่เหลืออยู่สองสายตัวอักษรใด ๆ "@"ลงใน

มีสัตว์ประหลาด 71 ตัวในรายการที่มีสัญลักษณ์คือ"@"และพวกมันถูกจัดการโดยไม่ต้อง hashing (ฉันขโมยความคิดนี้จากความคิดเห็นโดย ais523 ในคำตอบอื่น) มันเกิดขึ้นเพียงว่าค่าแฮชอีก 304 ค่านั้นไม่เหมือนใครทั้งหมด! ดังนั้นจึงไม่จำเป็นต้องแก้ไขอัลกอริทึมอื่น ๆ (มันเป็นการพักผ่อนที่โชคดีที่"human"ต้องถูกแมป"@"เนื่องจากผลรวมของรหัสตัวอักษรของตัวอักษรใน"human"และตัวอักษรใน"shark"เหมือนกันเช่นเดียวกับผลรวมของสี่เหลี่ยมของรหัสเหล่านั้น - เป็นจำนวนเต็มแม้โมดูโล 216!)


3

Python 2055 ไบต์

def f(s):import re;m=re.search(s[-3:-1]+s[:2]+str(len(s))+"(.)","omgn5Gteen13vligr7glero10'akga12Sanso11aragi9rgoDe10&tiet5HleVl16Vanst11Hmpmo14nubge15brsho5uingo21Nbuin7&gobl11Dgobl12Duaja6faule10lkest7Eolic9Ttawa15EanKo14KanKo12Kviba12&gore10Dimim3iutzr5zingn10Ganhi10Herfr15emmel9Mlele13'guNa6Wkaja6dotco6docvr5&petr7tmaor10oarli6:nhpi7;moma11&icli4Linbl20Nolwa11Titwr6Wtlgi12ateru12Rbign12Zozgr9Plepa11'oufo9vingu23Norhi8onena10&tati5Hiosc8sinre18Nligo6obeki10aeaow7Yeyfl12elewo10'adsh5 anfr11Hapap3Ygrog4Obequ9ahopy6Steki6fgogr11Dgogr12Dpepi9Sngdi5dindw10hlegl11'imgr11Pbava11Bcero12phaOl8Tdoli10dcuwi15dargn14GotIx5Dinbl13Parwa4dpuhe14dtisa9&ilba14:liho9onyer6&euAs8&aupl14Cttle9qmmdw11Molbr10Fmism11mncPe10&mpwa11noror3oispy8caumo16Clest11'haUr8okekr6;bigi12ZbuBa9&gowh12Dbiko13Zbiet12Zmmgn11Molwe8dmowa11&icde8Lbiho6hdola9dleJu7&otMi18&ulum10Uenpi9&luho10ighye12ymamu5qorwh13ughbl11yylga8gKoKe12Knndj6&mmet11Magbl10Narsh5;osgh5 orxo4Xoltr5Tdoma8qopCy7Hceir12pgoba18Dorlo9wgoba16Dbidw12ZinFa6&goor13DeaAl5Aiuba14qloac9bkemo6Yniqu16QteDi8&aufo14Ckesh8Fetye4Yolro9ryema18hersh15eaggo11Nrase9ranig6:ghba12Winbr13Polwi11dgeti5fzoNa6&orga9emmko12Manfi8aorgn10Gatco6Alecl10'goye13Deabu7hinog9Oheli6Feoch9:ynly4fngte5ieeel12;rawe7ricch11caior11ocala9fguvi13Fangi9aangi5Hhepa7fdesa10:cuOr5&rswa8ubrco5Sorva12Vxaxa3xovlu12tbaba3Bilcr9:geAn5Aolwo4dviic9&tafi14Ecegl13pbugr8xorpu11wgoCh16Dicar9Laggu13Ndegi12shoAr6Aolla12kedce9sitma8&erti11qicma11Lbior10Zviho12&test12vbusu8&fofo3ddeca11srara9rolko6kmpwo10ntaea15Ellbl10jgosi13Daksn5Svibo10&tosk8Zicco10cvera5Bgoba15DatDe5&goba17Dpuwu6qkawe10dmmhu11Mdodo3dunhe10dtcsa9Yckge5:tefi11vsiqu6iloqu14bewne4:yoGe6&caho8fucwo9rorMo10oisje9;taai13Eardw5holye11Fordw10hlloc11jough5Zerfl14emila11mtedu11vthro5qteic10vtuLo11Hmmor9Mirva7Vbagi9Bolro10Tmako13kleir10'biel10Zmmgi11Mnema5ilego10'olre8Forbl13usiwa14Sroba6&agre8Nrohe6&orgr12ulefl11'ocja10JghYe8&aumi8HiuSc8sbihu12Zriki6Ayemi11horko11kolgr10Furle6ianfi10Hmigi11monpo4ullsp13jaiKo11Ktedi12Rapca15Yorog9Oylwi15geegi9;orba14worba16w");return m.group(1)if m else'@'

นี่คือชุดทดสอบของฉันในกรณีที่ช่วยคนอื่นได้

MAPPING = {
    # as given in the original question
}
def validate_solution(f):
    for k, v in MAPPING.iteritems():
        vv = f(k)
        if vv != v:
            print 'FAIL: f(%s) = %s instead of %s' % (k, vv, v)
    print 'SUCCESS!'

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

นั่นคือสิ่งที่ฉันต้องการได้รับคือ

def f(monster_name):
    small_string = f1(monster_name)
    integer_index = f2(small_string)
    symbol = "relatively_short_table"[integer_index]
    return symbol

แต่ฉันทำได้แค่ไกลถึง

def f(monster_name):
    small_string = f1(monster_name)
    symbol = {relatively_large_dict}[small_string]
    return symbol

ที่ฉันค้นหา dict {relatively_large_dict}[small_string]แสดงเป็นre.match(small_string+"(.)", "relatively_large_string")golfiness


2

JavaScript (ES6), 1178

n=>'@0uy1c8@@@@@@2cb7sj0sb5rhcm626435y6js6u651b1nj5jg85g2xj02l4wh31u2py2xl96h5fz6ys46tc7821p2e9c1o1td1cy834@2sq2c055iabn91f82vahc6ytagh5d363i@@@@@@@@@@@@@@@@@@@7hh2wf2nd1bu2d93cm0gu862@144819a6v2h44o41d4@@@@@@0c404806f3fa0z8@04c82o1vfac3@c10a3g08g@82e0lr7bf26p2dibcb11t9y19q6bbh4db7tr3592u2bof4913edawy84p1cr@bap1qzb1o033bt6@8d93v230t4240w9ahh8cy@09u0a60sd1qd@1n23ak1bt614bax0ro7sd57xagg22s1gj@@be0@74l01c28qcdi@1so83t0c068s@2jh7as7ddalq0vxag68pn6b9@0gabu71zp54m6997imb2047h@10s0zo0mv@aww6ixbqgag7@944@bza76b@1a053c2yn6101eh8en@4je6fq97t1py9f0@6co@b3k5my44p@4edb737t9@0tl@00rau75y369z5hk0ot@23d2wicb90uwb54a9l3gw9lv3z51nv@@@@@@@amy81e3kh9yc90e59d@6528z42ic@7uv6bm58t@3av0w004t05aavs3oq3040irawj0ov1n90213h89yn0vs@0mcc284fv6uyaxp@3242ok39h0jd06905v1ia@7zc9659bk@ax30ua0um0652sa65daqd@00z03d2ra1f95751xu@9x10676yz@72w33r24b63d@2d7@ats6f678u@bcg9uf6h6@1b60us2d17ygbxn72106t02g@adublf05q@8xu5wobqb1tc1c73cs7pj@87k3cj2xq6258l379y@0q42qy3vs3y70r9@06v2a9@ast4su12w0ko4y77dn@7oubr07ju1ct5qe81v@0d52kb66t4zj@93508c@af30kj@299'.replace(/@\w*/g,v=>~-v.search((100+h.toString(36)).slice(-3))%3?++i:r=String.fromCharCode(i),i=32,r='@',n.replace(/\w/g,c=>h=parseInt(c,36)^(h*3)&16383,h=0))&&r

น้อย golfed

n=>(
'@0uy1c8@@@@@@2cb7sj0sb5rhcm626435y6js6u651b1nj5jg85g2xj02l4wh31u2py2xl96h5fz6ys46tc7821p2e9c1o1td1cy834@2sq2c055iabn91f82vahc6ytagh5d363i@@@@@@@@@@@@@@@@@@@7hh2wf2nd1bu2d93cm0gu862@144819a6v2h44o41d4@@@@@@0c404806f3fa0z8@04c82o1vfac3@c10a3g08g@82e0lr7bf26p2dibcb11t9y19q6bbh4db7tr3592u2bof4913edawy84p1cr@bap1qzb1o033bt6@8d93v230t4240w9ahh8cy@09u0a60sd1qd@1n23ak1bt614bax0ro7sd57xagg22s1gj@@be0@74l01c28qcdi@1so83t0c068s@2jh7as7ddalq0vxag68pn6b9@0gabu71zp54m6997imb2047h@10s0zo0mv@aww6ixbqgag7@944@bza76b@1a053c2yn6101eh8en@4je6fq97t1py9f0@6co@b3k5my44p@4edb737t9@0tl@00rau75y369z5hk0ot@23d2wicb90uwb54a9l3gw9lv3z51nv@@@@@@@amy81e3kh9yc90e59d@6528z42ic@7uv6bm58t@3av0w004t05aavs3oq3040irawj0ov1n90213h89yn0vs@0mcc284fv6uyaxp@3242ok39h0jd06905v1ia@7zc9659bk@ax30ua0um0652sa65daqd@00z03d2ra1f95751xu@9x10676yz@72w33r24b63d@2d7@ats6f678u@bcg9uf6h6@1b60us2d17ygbxn72106t02g@adublf05q@8xu5wobqb1tc1c73cs7pj@87k3cj2xq6258l379y@0q42qy3vs3y70r9@06v2a9@ast4su12w0ko4y77dn@7oubr07ju1ct5qe81v@0d52kb66t4zj@93508c@af30kj@299'
.replace(/@\w*/g, v= > 
   (v.search((100 + h.toString(36)).slice(-3))-1) % 3  
     ? ++i : r = String.fromCharCode(i),
   i=32,
   r='@',
   n.replace(/\w/g,c => h=parseInt(c,36) ^ (h*3) & 16383,h=0)
)
&& r

ทดสอบ

F=
n=>'@0uy1c8@@@@@@2cb7sj0sb5rhcm626435y6js6u651b1nj5jg85g2xj02l4wh31u2py2xl96h5fz6ys46tc7821p2e9c1o1td1cy834@2sq2c055iabn91f82vahc6ytagh5d363i@@@@@@@@@@@@@@@@@@@7hh2wf2nd1bu2d93cm0gu862@144819a6v2h44o41d4@@@@@@0c404806f3fa0z8@04c82o1vfac3@c10a3g08g@82e0lr7bf26p2dibcb11t9y19q6bbh4db7tr3592u2bof4913edawy84p1cr@bap1qzb1o033bt6@8d93v230t4240w9ahh8cy@09u0a60sd1qd@1n23ak1bt614bax0ro7sd57xagg22s1gj@@be0@74l01c28qcdi@1so83t0c068s@2jh7as7ddalq0vxag68pn6b9@0gabu71zp54m6997imb2047h@10s0zo0mv@aww6ixbqgag7@944@bza76b@1a053c2yn6101eh8en@4je6fq97t1py9f0@6co@b3k5my44p@4edb737t9@0tl@00rau75y369z5hk0ot@23d2wicb90uwb54a9l3gw9lv3z51nv@@@@@@@amy81e3kh9yc90e59d@6528z42ic@7uv6bm58t@3av0w004t05aavs3oq3040irawj0ov1n90213h89yn0vs@0mcc284fv6uyaxp@3242ok39h0jd06905v1ia@7zc9659bk@ax30ua0um0652sa65daqd@00z03d2ra1f95751xu@9x10676yz@72w33r24b63d@2d7@ats6f678u@bcg9uf6h6@1b60us2d17ygbxn72106t02g@adublf05q@8xu5wobqb1tc1c73cs7pj@87k3cj2xq6258l379y@0q42qy3vs3y70r9@06v2a9@ast4su12w0ko4y77dn@7oubr07ju1ct5qe81v@0d52kb66t4zj@93508c@af30kj@299'.replace(/@\w*/g,v=>~-v.search((100+h.toString(36)).slice(-3))%3?++i:r=String.fromCharCode(i),i=32,r='@',n.replace(/\w/g,c=>h=parseInt(c,36)^(h*3)&16383,h=0))&&r


monsters = {
  "Aleax": "A",
  "Angel": "A",
  "Arch Priest": "@",
  "Archon": "A",
  "Ashikaga Takauji": "@",
  "Asmodeus": "&",
  "Baalzebub": "&",
  "Chromatic Dragon": "D",
  "Croesus": "@",
  "Cyclops": "H",
  "Dark One": "@",
  "Death": "&",
  "Demogorgon": "&",
  "Dispater": "&",
  "Elvenking": "@",
  "Famine": "&",
  "Geryon": "&",
  "Grand Master": "@",
  "Green-elf": "@",
  "Grey-elf": "@",
  "Hippocrates": "@",
  "Ixoth": "D",
  "Juiblex": "&",
  "Keystone Kop": "K",
  "King Arthur": "@",
  "Kop Kaptain": "K",
  "Kop Lieutenant": "K",
  "Kop Sergeant": "K",
  "Lord Carnarvon": "@",
  "Lord Sato": "@",
  "Lord Surtur": "H",
  "Master Assassin": "@",
  "Master Kaen": "@",
  "Master of Thieves": "@",
  "Medusa": "@",
  "Minion of Huhetotl": "&",
  "Mordor orc": "o",
  "Nalzok": "&",
  "Nazgul": "W",
  "Neferet the Green": "@",
  "Norn": "@",
  "Olog-hai": "T",
  "Oracle": "@",
  "Orcus": "&",
  "Orion": "@",
  "Pelias": "@",
  "Pestilence": "&",
  "Scorpius": "s",
  "Shaman Karnov": "@",
  "Thoth Amon": "@",
  "Twoflower": "@",
  "Uruk-hai": "o",
  "Vlad the Impaler": "V",
  "Wizard of Yendor": "@",
  "Woodland-elf": "@",
  "Yeenoghu": "&",
  "abbot": "@",
  "acid blob": "b",
  "acolyte": "@",
  "air elemental": "E",
  "aligned priest": "@",
  "ape": "Y",
  "apprentice": "@",
  "arch-lich": "L",
  "archeologist": "@",
  "attendant": "@",
  "baby black dragon": "D",
  "baby blue dragon": "D",
  "baby crocodile": ":",
  "baby gray dragon": "D",
  "baby green dragon": "D",
  "baby long worm": "w",
  "baby orange dragon": "D",
  "baby purple worm": "w",
  "baby red dragon": "D",
  "baby silver dragon": "D",
  "baby white dragon": "D",
  "baby yellow dragon": "D",
  "balrog": "&",
  "baluchitherium": "q",
  "barbarian": "@",
  "barbed devil": "&",
  "barrow wight": "W",
  "bat": "B",
  "black dragon": "D",
  "black light": "y",
  "black naga hatchling": "N",
  "black naga": "N",
  "black pudding": "P",
  "black unicorn": "u",
  "blue dragon": "D",
  "blue jelly": "j",
  "bone devil": "&",
  "brown mold": "F",
  "brown pudding": "P",
  "bugbear": "h",
  "captain": "@",
  "carnivorous ape": "Y",
  "cave spider": "s",
  "caveman": "@",
  "cavewoman": "@",
  "centipede": "s",
  "chameleon": ":",
  "chickatrice": "c",
  "chieftain": "@",
  "clay golem": "'",
  "cobra": "S",
  "cockatrice": "c",
  "couatl": "A",
  "coyote": "d",
  "crocodile": ":",
  "demilich": "L",
  "dingo": "d",
  "disenchanter": "R",
  "djinni": "&",
  "dog": "d",
  "doppelganger": "@",
  "dust vortex": "v",
  "dwarf king": "h",
  "dwarf lord": "h",
  "dwarf mummy": "M",
  "dwarf zombie": "Z",
  "dwarf": "h",
  "earth elemental": "E",
  "electric eel": ";",
  "elf mummy": "M",
  "elf zombie": "Z",
  "elf": "@",
  "elf-lord": "@",
  "energy vortex": "v",
  "erinys": "&",
  "ettin mummy": "M",
  "ettin zombie": "Z",
  "ettin": "H",
  "fire ant": "a",
  "fire elemental": "E",
  "fire giant": "H",
  "fire vortex": "v",
  "flaming sphere": "e",
  "flesh golem": "'",
  "floating eye": "e",
  "fog cloud": "v",
  "forest centaur": "C",
  "fox": "d",
  "freezing sphere": "e",
  "frost giant": "H",
  "gargoyle": "g",
  "garter snake": "S",
  "gas spore": "e",
  "gecko": ":",
  "gelatinous cube": "b",
  "ghost": " ",
  "ghoul": "Z",
  "giant ant": "a",
  "giant bat": "B",
  "giant beetle": "a",
  "giant eel": ";",
  "giant mimic": "m",
  "giant mummy": "M",
  "giant rat": "r",
  "giant spider": "s",
  "giant zombie": "Z",
  "giant": "H",
  "glass golem": "'",
  "glass piercer": "p",
  "gnome king": "G",
  "gnome lord": "G",
  "gnome mummy": "M",
  "gnome zombie": "Z",
  "gnome": "G",
  "gnomish wizard": "G",
  "goblin": "o",
  "gold golem": "'",
  "golden naga hatchling": "N",
  "golden naga": "N",
  "gray dragon": "D",
  "gray ooze": "P",
  "gray unicorn": "u",
  "green dragon": "D",
  "green mold": "F",
  "green slime": "P",
  "gremlin": "g",
  "grid bug": "x",
  "guard": "@",
  "guardian naga hatchling": "N",
  "guardian naga": "N",
  "guide": "@",
  "healer": "@",
  "hell hound pup": "d",
  "hell hound": "d",
  "hezrou": "&",
  "high priest": "@",
  "hill giant": "H",
  "hill orc": "o",
  "hobbit": "h",
  "hobgoblin": "o",
  "homunculus": "i",
  "horned devil": "&",
  "horse": "u",
  "housecat": "f",
  "human mummy": "M",
  "human zombie": "Z",
  "human": "@",
  "hunter": "@",
  "ice devil": "&",
  "ice troll": "T",
  "ice vortex": "v",
  "iguana": ":",
  "imp": "i",
  "incubus": "&",
  "iron golem": "'",
  "iron piercer": "p",
  "jabberwock": "J",
  "jackal": "d",
  "jaguar": "f",
  "jellyfish": ";",
  "ki-rin": "A",
  "killer bee": "a",
  "kitten": "f",
  "knight": "@",
  "kobold lord": "k",
  "kobold mummy": "M",
  "kobold shaman": "k",
  "kobold zombie": "Z",
  "kobold": "k",
  "kraken": ";",
  "large cat": "f",
  "large dog": "d",
  "large kobold": "k",
  "large mimic": "m",
  "leather golem": "'",
  "lemure": "i",
  "leocrotta": "q",
  "leprechaun": "l",
  "lich": "L",
  "lichen": "F",
  "lieutenant": "@",
  "little dog": "d",
  "lizard": ":",
  "long worm": "w",
  "lurker above": "t",
  "lynx": "f",
  "mail daemon": "&",
  "manes": "i",
  "marilith": "&",
  "master lich": "L",
  "master mind flayer": "h",
  "mastodon": "q",
  "mind flayer": "h",
  "minotaur": "H",
  "monk": "@",
  "monkey": "Y",
  "mountain centaur": "C",
  "mountain nymph": "n",
  "mumak": "q",
  "nalfeshnee": "&",
  "neanderthal": "@",
  "newt": ":",
  "ninja": "@",
  "nurse": "@",
  "ochre jelly": "j",
  "ogre king": "O",
  "ogre lord": "O",
  "ogre": "O",
  "orange dragon": "D",
  "orc mummy": "M",
  "orc shaman": "o",
  "orc zombie": "Z",
  "orc": "o",
  "orc-captain": "o",
  "owlbear": "Y",
  "page": "@",
  "panther": "f",
  "paper golem": "'",
  "piranha": ";",
  "pit fiend": "&",
  "pit viper": "S",
  "plains centaur": "C",
  "pony": "u",
  "priest": "@",
  "priestess": "@",
  "prisoner": "@",
  "purple worm": "w",
  "pyrolisk": "c",
  "python": "S",
  "quantum mechanic": "Q",
  "quasit": "i",
  "queen bee": "a",
  "quivering blob": "b",
  "rabid rat": "r",
  "ranger": "@",
  "raven": "B",
  "red dragon": "D",
  "red mold": "F",
  "red naga hatchling": "N",
  "red naga": "N",
  "rock mole": "r",
  "rock piercer": "p",
  "rock troll": "T",
  "rogue": "@",
  "rope golem": "'",
  "roshi": "@",
  "rothe": "q",
  "rust monster": "R",
  "salamander": ":",
  "samurai": "@",
  "sandestin": "&",
  "sasquatch": "Y",
  "scorpion": "s",
  "sergeant": "@",
  "sewer rat": "r",
  "shade": " ",
  "shark": ";",
  "shocking sphere": "e",
  "shopkeeper": "@",
  "shrieker": "F",
  "silver dragon": "D",
  "skeleton": "Z",
  "small mimic": "m",
  "snake": "S",
  "soldier ant": "a",
  "soldier": "@",
  "spotted jelly": "j",
  "stalker": "E",
  "steam vortex": "v",
  "stone giant": "H",
  "stone golem": "'",
  "storm giant": "H",
  "straw golem": "'",
  "student": "@",
  "succubus": "&",
  "tengu": "i",
  "thug": "@",
  "tiger": "f",
  "titan": "H",
  "titanothere": "q",
  "tourist": "@",
  "trapper": "t",
  "troll": "T",
  "umber hulk": "U",
  "valkyrie": "@",
  "vampire bat": "B",
  "vampire lord": "V",
  "vampire": "V",
  "violet fungus": "F",
  "vrock": "&",
  "warg": "d",
  "warhorse": "u",
  "warrior": "@",
  "watch captain": "@",
  "watchman": "@",
  "water demon": "&",
  "water elemental": "E",
  "water moccasin": "S",
  "water nymph": "n",
  "water troll": "T",
  "werejackal": "d",
  "wererat": "r",
  "werewolf": "d",
  "white dragon": "D",
  "white unicorn": "u",
  "winged gargoyle": "g",
  "winter wolf cub": "d",
  "winter wolf": "d",
  "wizard": "@",
  "wolf": "d",
  "wood golem": "'",
  "wood nymph": "n",
  "woodchuck": "r",
  "wraith": "W",
  "wumpus": "q",
  "xan": "x",
  "xorn": "X",
  "yellow dragon": "D",
  "yellow light": "y",
  "yellow mold": "F",
  "yeti": "Y",
  "zruty": "z"
}
err = ok = 0

for(name in monsters) {
  code = monsters[name]
  result = F(name)
  if (result != code)
    console.log('ERROR',++err, name, result, code)
  else
    ++ok
}
console.log('Errors',err,'OK', ok)


2

Javascript, 1185 ไบต์

s=>{h=0;for(i of s)h=(h<<5)-h+i.charCodeAt()|0;for(v of "Aqgh201etxitsxy0_&ctpzfekt09j36uafamqw46mz1qcxvnnoego4212nxfivutt09qyac4td1ayiotfh3dvub5fggzjqa58h37bnva3dzy_D9wlywkgkifldlp6t46v97basg905f8wadwt0w49q0gk9c8edz9e33uj6esjl_Hkkt54kr0qdlxs6hxdxxyegrdzcmz8ymvg_Ki0enu0ct1shv_o193ve2y3tpa71xu3pud405o7_We09jfsayx_Tw2gk0spoqab5c9k_s7timco3yh674rp1_Vppq2k9t1q_b3mo3tac13_E0r50a7vi5a0kgim_Y2omnjbkq59mw5njf5t_Lu9z2bj6w2128_:n0gngsocqeuh5czhyiedwd3a_w9lf1hv1rra7r_qmckg7rbhlldbvros4f44h_B32t12yzdci83_yjkb3va_Nt2cbaqd46toc29anic1qq3es_P3mkmtv2l4j8r_ukjb44lwm5vkaz5hwkh_j3oo7uj9ip_Fzuk8mh1rpfw7obl6s9fsq_hzmwz3f7kdhiaj4enlxha1_c0q0yu8tnf_'nf7c1sks8rzgxhw83vjq0s76xhrvppbgn_Slr90h5su3zokncwi2m_doi5t2p4vw6dryycyhtl6eujb1ta26752ta7hr19d9vceq_Rqk8tsy_vuxwglitt4u25zfhj5q_M4j7tjk9cryvqn8101u5h646p_Ztzwr09t8ckxx3hbsl6r7dqv7qxmnwt_;u7r3e9trqqkmdj5tlx_apoj0ngpcqy6r7t8gw9_e2wtyw9oyve8uxlf_C8tpo3hlb3_gxji2n2nl4_ kwft9p_maxcdzat5e_rcy28c360mmndp8ksxh_pegqkkuur3_Gh6f8pheo0nn2_xu6yjdx_iz538jwkbwuh4ge7ymj_f3eytt6khltgxj13itedbz_Jlgk_knskybpe8n69a_llnv_tuxgkxc_nod5ob3cft_Oij0a222q3_Q6af_Uc5x_Xzjn_z6iq".split`_`)if(~v.slice(1).match(/.../g).indexOf(h.toString(36).slice(-3)))return v[0];return"@"}

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


1
ดังนั้นเท่าที่ฉันสามารถบอกได้คุณกำลัง hashing โดย {อักขระแรกอักขระสุดท้ายความยาว} แล้วใช้ตารางค้นหาขนาดใหญ่? แต่ฉันคิดว่ามีการปรับปรุงสองสามอย่างที่คุณสามารถทำได้: มีรายการที่ซ้ำกันในตารางและคุณสามารถประหยัดพื้นที่ได้มากโดยการลบรายการสำหรับ@ออกจากตารางและเพิ่งเริ่มต้น@หากอินพุต ไม่พบ

2
cavewomanและchameleonมีอักขระตัวแรกตัวแรกตัวสุดท้ายและความยาวซึ่งอาจเป็นปัญหาหรือไม่
Arnaud

1
split("_")สามารถกลายเป็นsplit backtick _ backtick
user2428118

แก้ไข @ SuperChafouin แล้ว
SuperJedi224

1
@ SuperJedi224 มีคนอื่น ๆ มีดังนี้: CyclopsและCroesus, baluchitheriumและbaby long worm, crocodileและcentipede24 และอื่น ๆ อีกมากมาย
นาด

1

Python 3, 1915 1900 ไบต์

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

  • ทำงานกับและส่งออกโค้ด ASCII แทนตัวอักขระ (บันทึก 15 ไบต์)

ส่งชื่อมอนสเตอร์เป็นอาร์กิวเมนต์บรรทัดคำสั่งแรกรับตัวอักษรใน stdout

import sys
D=b'`"\x08\x04\x02&@Yx\xf6\x90a\x00Z\x00\x00c\x00X\x00\x00f\x00z\x00\x00hS\x12\x06\t@PSTft?z\x0fnK\nH\x87\xa2ig\t\t\x12 &;@FZkoq\x05\xfc~?\x1b\x80\xc2,z\r\xf3Y\x141\x9cS\x10\x80jU\x06\x08\t&;@BKpqr\x9f\xbe\xbb\xf9O\xcde\x03!kK\x11\x07\x07&:@WYsu\x1boDv\xc9i\x90lS$\x06\r@Sdirw\x1f\x1d\x198\xb3\xb2\x91\x0fm\xa5\x03A@mB#\x07\x07@GPWdiv\x7f;n\xb3Bk\xa5ng\x07\x0c\x16&@EHSVcdfqru\x01\xfen\x83q\xd8\xf3\x1c.\xe5\xac^\x87\t\xaaT\xd4D\x9c\xe1*Io;\x03\x05\x06@desu\x01\xf7\x95R0\x88pc \x08\n:@KMNknq\xfd\xfe\ru\xb2z\xea\\\x9b\x05qC\x08\x07\x06&@AGOfhy\xe2\xbbA\xf2ArS\x1e\x08\x08&@JVYdfi_\x1c\xd8/k\x89\xa8\xe0sw\x08\x0b\x1c&;@Kdfhijou\t\xe0[# \\\x9a\xd3F(L\xfapM\tp\xa8t\xccp\x8d\x11e+\x05\x0c\x8a\x08t+)\x04\x02@PQT\xf2\x94uG\x1c\x06\t&@Uilq\x0f\ryl\xc4`\xa5\x10\x90v\x85\r\x0e$&:@FKLNORSWYry\x9f\x97\xf8\xae\xb8\xdf\xdd\xc1\xcdl\xb2\xc9L|\xbb;\x92\xb8j\xb0\xa99\xdd\x9c\xb8\xd0\x8bh\x95\x88T\xb3;1\xb6\x0bwb\x06\x0c\x11&:;@DGHOVhkm\x02\xfe\x8fO{\xd9u\xac&\xd7\x90\x9fe\xc0\xf44GxW\x07\x07\x0bADHScdv?>\xdd<:\xb7s.\x8cI\x07yR\x07\x07\t&:@bcht;Zx\x16sO\x8d\xab\xc3ze\x0b\x08\x14&@ABCaqs\x01}\xbe=\x15\xc6\xcdL\xa1\xc8\x9e.\xf7\x02\xc1Xq4\x99\t{G\x16\x06\t@Faefg\x1f\x9bU$2P`\xa8\x80|G\x15\x06\x07&\';@Go\x1c1\\\xa7*\x0bS}s\x06\n" &@AHLYZdh\xf6\x1e\t\xb93N2\xc27\xd6\xd8\xd8*\xe5L\xa3\xa4f\x860A\xfa:7.\xdd\x9b)\xb80\x85\xc4\xb4\x83~W\x0e\x07\r&:@ERbd>\x1b\xda\x15\xd4\x92\x0eM\xacJH\x04c\x7fG\x00\x06\x08:@dghx\x1f\xbc\xf4Z\xa1%\xd3C'
R=range
N=sys.argv[1].lower()
B=0
for c in N:B|=ord(c)&0x7f;B<<=7
B%=2**62-1
P=N.split()
F=ord(P[-1][0])^(ord(P[-1][1])>>2)
while D:
 f=D[0];ik,j,h,n=D[1:5];i=ik>>4;k=ik&15;D=D[5:];c=D[:h];m=D[h:h+n];m=int.from_bytes(m,"big");s=1;C=j;b=(h-1).bit_length()
 for x in R(i-1):s<<=k;s|=1
 s<<=j;z=(B&s)>>j;x=0;u=1
 for y in R(i):x<<=1;x|=bool(z&u);u<<=k
 if f!=F:D=D[h+n:];continue
 while m:
  if m&(2**i-1)==x:m>>=i;C=c[m&(2**b-1)];break
  m>>=b+i
 break
print(C)

เมื่อฉันอ่านคำถามฉันคิดว่า "ฉันต้องบีบอัดข้อมูลนี้" ขั้นตอนแรกคือการพิมพ์เล็กทั้งหมดชื่อ

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

 'd' (37) => & @ D L R d h
 'g' (31) =>   & ' : @ G H Z g o
 's' (30) =>   & : ; @ E F H K P S Y Z e k o s
 'm' (28) => & @ F H M Q R S Y i m q r
 'c' (24) => : @ A C H S b c d f s v
 'p' (20) => & ; @ P S c d f p u
 'w' (20) => @ G W d q r u w
 'a' (19) => & @ A L Y a t
 'h' (17) => & @ N U d f h i o u
 'l' (17) => : @ F G K L O V f h i k l q y
 'n' (15) => & : @ N W n
 't' (14) => @ H T f i q t
 'b' (14) => & @ B a b h q x
 'k' (13) => ; @ A G K O f h k
 'e' (12) => & ; @ E H e
 'o' (12) => & @ O P T Y o
 'z' ( 9) => Z z
 'v' ( 9) => & @ S V v
 'r' ( 8) => @ B q r
 'j' ( 8) => & ; J d f j
 'f' ( 6) => & F d h
 'i' ( 5) => & : D V i
 'u' ( 4) => o u
 'y' ( 3) => & @ Y
 'x' ( 2) => X x
 'q' ( 1) => i

เพื่อปรับปรุงการแพร่กระจายต่อไปฉันปรับเปลี่ยนคีย์เล็กน้อยโดย XOR-ing อักขระตัวที่สองของคำสุดท้ายเปลี่ยนเป็นบิตไปทางขวาเป็นอักขระตัวแรก (ให้เราเรียกโครงสร้างนี้ first_key ):

 '}' (29) =>   & @ A H L Y Z d h
 'v' (25) => & : @ F K L N O R S W Y r y
 'x' (25) => A D H S c d v
 's' (21) => & ; @ K d f h i j o u
 'p' (21) => : @ K M N k n q
 'z' (19) => & @ A B C a q s
 'n' (19) => & @ E H S V c d f q r u
 '|' (18) => & ' ; @ G o
 'l' (17) => @ S d i r w
 '~' (16) => & : @ E R b d
 '{' (15) => @ F a e f g
 'w' (14) => & : ; @ D G H O V h k m
 'i' (14) =>   & ; @ F Z k o q
 'j' (13) => & ; @ B K p q r
 'u' (12) => & @ U i l q
 'm' (12) => @ G P W d i v
 '\x7f' (11) => : @ d g h x
 'o' (11) => @ d e s u
 'h' (11) => @ P S T f t
 'y' (10) => & : @ b c h t
 'r' ( 9) => & @ J V Y d f i
 'k' ( 9) => & : @ W Y s u
 'a' ( 8) => Z
 'q' ( 7) => & @ A G O f h
 't' ( 6) => @ P Q T
 '`' ( 4) => & @ Y x
 'c' ( 1) => X
 'f' ( 1) => z

อย่างที่คุณเห็นสิ่งนี้ทำให้เรามีเก้าชื่อซึ่งสามารถแมปกับข้อมูลนั้นได้โดยไม่ซ้ำกัน ดี!

ตอนนี้ฉันต้องการค้นหาแผนที่ที่เหลือ สำหรับสิ่งนี้ฉันเริ่มต้นด้วยการแปลงชื่อเต็ม (ตัวเล็ก) ให้เป็นจำนวนเต็ม:

def name_to_int(name):
    bits = 0
    for c in name:
        bits |= ord(c) & 0x7f
        bits <<= 7
    return bits

นี่เป็นการรวมค่า 7 บิต ASCII ของชื่อเข้าด้วยกันเป็นจำนวนเต็มขนาดใหญ่ เรารับโมดูโล่นี้4611686018427387903โล่ (2⁶²-1) สำหรับขั้นตอนถัดไป

ตอนนี้ฉันพยายามค้นหา bitmask ที่ให้จำนวนเต็มซึ่งจะแยกแยะตัวละครสัตว์ประหลาดต่าง ๆ ออกมาอย่างชัดเจน บิตมาสก์ประกอบด้วยสเปรดที่สม่ำเสมอ (เช่น101010101หรือ1000100010001) และถูกกำหนดด้วยจำนวนบิต ( i>=1) และสเปรด ( k>=1) นอกจากนี้มาสก์จะถูกเลื่อนไปทางซ้ายนานถึง32*iบิต สิ่งเหล่านี้คือ AND-ed ที่มีชื่อจำนวนเต็มและจำนวนเต็มที่ได้จะใช้เป็นคีย์ในการจับคู่ i*number_of_mapping_entriesใช้การทำแผนที่ที่ปราศจากความขัดแย้งที่ดีที่สุด

เลขที่ได้จาก AND-ing หน้ากากและชื่อ integerised จะขยับกลับjบิตและปลดออกจากศูนย์ของพวกเขา (เราเก็บi,kและjพร้อมกับการทำแผนที่เพื่อให้สามารถที่จะสร้างนั้น) ประหยัดพื้นที่มาก

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

Row = struct.Struct(
    ">"
    "B"  # first word char
    "B"  # number of bits (i) and bit spacing (k)
    "B"  # shift (j) or character to map to if i = 0
    "B"  # number of monster characters
    "B"  # map entry bytes
)

ตามด้วยตัวละครสัตว์ประหลาดและการแมประดับที่สอง

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

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

ข้อมูลทั้งหมดมีขนาด 651 ไบต์เรียงลำดับเป็นสตริงไพ ธ อนของสตริง 1426 ไบต์

โปรแกรมถอดรหัสเป็นหลักทำอีกวิธีหนึ่ง: ก่อนอื่นมันจะแยก first_keyและค้นหาข้อมูลสำหรับรายการที่เกี่ยวข้อง จากนั้นจะคำนวณแฮชของชื่อและค้นหาผ่าน hashmap สำหรับรายการที่เกี่ยวข้อง

ตัวถอดรหัสที่ไม่ทำให้รำคาญ

#!/usr/bin/python3
import sys
import math

data = b'`"\x08\x04\x02&@Yx\xf6\x90a\x00Z\x00\x00c\x00X\x00\x00f\x00z\x00\x00hS\x12\x06\t@PSTft?z\x0fnK\nH\x87\xa2ig\t\t\x12 &;@FZkoq\x05\xfc~?\x1b\x80\xc2,z\r\xf3Y\x141\x9cS\x10\x80jU\x06\x08\t&;@BKpqr\x9f\xbe\xbb\xf9O\xcde\x03!kK\x11\x07\x07&:@WYsu\x1boDv\xc9i\x90lS$\x06\r@Sdirw\x1f\x1d\x198\xb3\xb2\x91\x0fm\xa5\x03A@mB#\x07\x07@GPWdiv\x7f;n\xb3Bk\xa5ng\x07\x0c\x16&@EHSVcdfqru\x01\xfen\x83q\xd8\xf3\x1c.\xe5\xac^\x87\t\xaaT\xd4D\x9c\xe1*Io;\x03\x05\x06@desu\x01\xf7\x95R0\x88pc \x08\n:@KMNknq\xfd\xfe\ru\xb2z\xea\\\x9b\x05qC\x08\x07\x06&@AGOfhy\xe2\xbbA\xf2ArS\x1e\x08\x08&@JVYdfi_\x1c\xd8/k\x89\xa8\xe0sw\x08\x0b\x1c&;@Kdfhijou\t\xe0[# \\\x9a\xd3F(L\xfapM\tp\xa8t\xccp\x8d\x11e+\x05\x0c\x8a\x08t+)\x04\x02@PQT\xf2\x94uG\x1c\x06\t&@Uilq\x0f\ryl\xc4`\xa5\x10\x90v\x85\r\x0e$&:@FKLNORSWYry\x9f\x97\xf8\xae\xb8\xdf\xdd\xc1\xcdl\xb2\xc9L|\xbb;\x92\xb8j\xb0\xa99\xdd\x9c\xb8\xd0\x8bh\x95\x88T\xb3;1\xb6\x0bwb\x06\x0c\x11&:;@DGHOVhkm\x02\xfe\x8fO{\xd9u\xac&\xd7\x90\x9fe\xc0\xf44GxW\x07\x07\x0bADHScdv?>\xdd<:\xb7s.\x8cI\x07yR\x07\x07\t&:@bcht;Zx\x16sO\x8d\xab\xc3ze\x0b\x08\x14&@ABCaqs\x01}\xbe=\x15\xc6\xcdL\xa1\xc8\x9e.\xf7\x02\xc1Xq4\x99\t{G\x16\x06\t@Faefg\x1f\x9bU$2P`\xa8\x80|G\x15\x06\x07&\';@Go\x1c1\\\xa7*\x0bS}s\x06\n" &@AHLYZdh\xf6\x1e\t\xb93N2\xc27\xd6\xd8\xd8*\xe5L\xa3\xa4f\x860A\xfa:7.\xdd\x9b)\xb80\x85\xc4\xb4\x83~W\x0e\x07\r&:@ERbd>\x1b\xda\x15\xd4\x92\x0eM\xacJH\x04c\x7fG\x00\x06\x08:@dghx\x1f\xbc\xf4Z\xa1%\xd3C'


def name_to_int(name):
    bits = 0
    for c in name:
        bits |= ord(c) & 0x7f
        bits <<= 7
    return bits


def make_mask(nbits, k):
    mask = 1
    for i in range(nbits-1):
        mask <<= k
        mask |= 1
    return mask


def collapse_mask(value, nbits, k):
    bits = 0
    shift = 0
    for i in range(nbits):
        bits <<= 1
        bits |= bool(value & (1<<shift))
        shift += k
    return bits


name = sys.argv[1].casefold()
last_word = name.split()[-1]
last_word_char = chr(ord(last_word[0]) ^ (ord(last_word[1]) >> 2))
while data:
    first_char = chr(data[0])
    ik, j, nchars, nbytes = data[1:5]

    i = ik >> 4
    k = ik & 15

    data = data[5:]
    if first_char != last_word_char:
        # skip this entry
        data = data[nchars+nbytes:]
        continue

    chars, mapping = data[:nchars], data[nchars:nchars+nbytes]
    result = j
    if i == 0:
        break

    mapping = int.from_bytes(mapping, "big")

    name_bits = name_to_int(name) % (2**62-1)
    mask = make_mask(i, k) << j
    key = collapse_mask((name_bits & mask) >> j, i, k)
    bits_per_key = i
    key_mask = 2**(bits_per_key)-1
    bits_per_value = math.ceil(math.log(len(chars), 2))
    value_mask = 2**(bits_per_value)-1
    while mapping:
        if mapping & key_mask == key:
            mapping >>= bits_per_key
            result = chars[mapping & value_mask]
            break
        mapping >>= bits_per_value+bits_per_key

    break
print(chr(result))

เครื่องมือวิเคราะห์

นี่คือเครื่องมือที่ฉันสร้างและใช้เพื่อสร้างข้อมูล - อ่านในความเสี่ยงของคุณเอง:

#!/usr/bin/python3
import base64
import collections
import math
import json
import struct
import zlib

data = json.load(open("data.json"))

reverse_pseudomap = {}
forward_pseudomap = {}
forward_info = {}
reverse_fullmap = {}
hits = collections.Counter()
monster_char_hitmap = collections.Counter()

for name, char in data.items():
    name = name.casefold()
    parts = name.split()
    monster_char_hitmap[char] += 1

    # if len(parts) > 1:
    #     key = first_char + parts[0][0]
    # else:
    #     key = first_char + last_part[1]

    key = chr(ord(parts[-1][0]) ^ (ord(parts[-1][1]) >> 2))
    # key = parts[-1][0]

    hits[key] += 1
    reverse_pseudomap.setdefault(char, set()).add(key)
    forward_pseudomap.setdefault(key, set()).add(char)
    forward_info.setdefault(key, {})[name] = char
    reverse_fullmap.setdefault(char, set()).add(name)


for char, hit_count in sorted(hits.items(), key=lambda x: x[1], reverse=True):
    monsters = forward_pseudomap[char]
    print(" {!r} ({:2d}) => {}".format(
        char,
        hit_count,
        " ".join(sorted(monsters))
    ))


def make_mask(nbits, k):
    mask = 1
    for i in range(nbits-1):
        mask <<= k
        mask |= 1
    return mask


def collapse_mask(value, nbits, k):
    bits = 0
    shift = 0
    for i in range(nbits):
        bits <<= 1
        bits |= bool(value & (1<<shift))
        shift += k
    return bits


def expand_mask(value, nbits, k):
    bits = 0
    for i in range(nbits):
        bits <<= k
        bits |= value & 1
        value >>= 1
    return bits


assert collapse_mask(expand_mask(0b110110, 6, 3), 6, 3)
assert expand_mask(collapse_mask(0b1010101, 7, 3), 7, 3)


def name_to_int(name):
    # mapped_name = "".join({"-": "3", " ": "4"}.get(c, c) for c in name)
    # if len(mapped_name) % 8 != 0:
    #     if len(mapped_name) % 2 == 0:
    #         mapped_name += "7"
    #     mapped_name = mapped_name + "="*(8 - (len(mapped_name) % 8))
    # print(mapped_name)
    # return base64.b32decode(
    #     mapped_name,
    #     casefold=True,
    # )

    bits = 0
    for c in name:
        bits |= ord(c) & 0x7f
        bits <<= 7
    return bits


compressed_maps = {}
max_bit_size = 0
nmapentries = 0


for first_char, monsters in sorted(forward_info.items()):
    monster_chars = forward_pseudomap[first_char]
    print("trying to find classifier for {!r}".format(first_char))
    print("  {} monsters with {} symbols".format(
        len(monsters),
        len(monster_chars))
    )
    bits = math.log(len(monster_chars), 2)
    print("  {:.2f} bits of clever entropy needed".format(
        bits
    ))

    bits = math.ceil(bits)

    int_monsters = {
        name_to_int(name): char
        for name, char in monsters.items()
    }

    reverse_map = {}
    for name, char in int_monsters.items():
        reverse_map.setdefault(char, set()).add(name)

    solution = None
    solution_score = float("inf")

    if bits == 0:
        char = ord(list(int_monsters.values())[0][0])
        solution = 0, 0, char, {}

    for i in range(bits, 3*bits+1):
        print("  trying to find solution with {} bits".format(i))
        for k in [2, 3, 5, 7, 11]:
            mask = make_mask(i, k)
            for j in range(0, 32*bits):
                bucketed = {}
                for int_name, char in int_monsters.items():
                    bucket = (int_name % (2**62-1)) & mask
                    try:
                        if bucketed[bucket] != char:
                            break
                    except KeyError:
                        bucketed[bucket] = char
                else:
                    new_solution_score = i*len(bucketed)
                    if new_solution_score < solution_score:
                        print("   found mapping: i={}, k={}, j={}, mapping={}".format(
                            i, k, j, bucketed
                        ))
                        solution = i, k, j, bucketed
                        solution_score = new_solution_score
                mask <<= 1

    if solution is not None:
        print("  solution found!")

    chars = "".join(sorted(set(int_monsters.values())))
    i, k, j, mapping = solution

    # sanity check 1
    if i > 0:
        mask = make_mask(i, k) << j
        for int_name, char in int_monsters.items():
            key = (int_name % (2**62-1)) & mask
            assert mapping[key] == char

    compressed_mapping = {}
    for hash_key, char in mapping.items():
        hash_key = collapse_mask(hash_key >> j, i, k)
        max_bit_size = max(hash_key.bit_length(), max_bit_size)
        compressed_mapping[hash_key] = chars.index(char)

    nmapentries += len(compressed_mapping)
    compressed_maps[first_char] = i, k, j, chars, compressed_mapping

    print(" ", compressed_maps[first_char])

    print()

print("max_bit_size =", max_bit_size)
print("nmapentries =", nmapentries)

print("approx size =", (1+math.ceil(max_bit_size/8))*nmapentries)


# first we need to map first word chars to compressed mappings
Row = struct.Struct(
    ">"
    "B"  # first word char
    "B"  # number of bits (i) and bit spacing (k)
    "B"  # shift (j) or character to map to if i = 0
    "B"  # number of characters
    "B"  # map entry bytes
)


def map_to_bytes(i, nchars, mapping):
    bits_per_value = math.ceil(math.log(nchars, 2))
    bits_per_key = i

    bits = 0
    # ensure that the smallest value is encoded last
    for key, value in sorted(mapping.items(), reverse=True):
        assert key.bit_length() <= bits_per_key
        assert value.bit_length() <= bits_per_value

        bits <<= bits_per_value
        bits |= value
        bits <<= bits_per_key
        bits |= key

    return bits.to_bytes(math.ceil(bits.bit_length() / 8), "big")


def bytes_to_map(i, nchars, data):
    data = int.from_bytes(data, "big")

    bits_per_value = math.ceil(math.log(nchars, 2))
    bits_per_key = i
    key_mask = 2**(bits_per_key)-1
    value_mask = 2**(bits_per_value)-1

    mapping = {}
    while data:
        key = data & key_mask
        data >>= bits_per_key
        value = data & value_mask
        data >>= bits_per_value
        assert key not in mapping
        mapping[key] = value

    return mapping


parts = bytearray()
for first_char, (i, k, j, chars, mapping) in sorted(compressed_maps.items()):
    raw_data = map_to_bytes(i, len(chars), mapping)
    recovered_mapping = bytes_to_map(i, len(chars), raw_data)
    assert recovered_mapping == mapping, "{}\n{}\n{}\n{} {}".format(
        mapping,
        recovered_mapping,
        raw_data,
        i, len(chars),
    )
    assert len(raw_data) <= 255

    print(" {!r} => {} {} {} {} {}".format(
        first_char,
        i, k, j,
        len(chars),
        raw_data
    ))

    assert k <= 15
    assert i <= 15

    if i == 0:
        chars = ""

    row = Row.pack(
        ord(first_char),
        (i << 4) | k, j,
        len(chars),
        len(raw_data),
    )
    row += chars.encode("ascii")
    row += raw_data
    parts.extend(row)

parts = bytes(parts)
print(parts)
print(len(parts))
print(len(str(parts)))
print(len(str(zlib.compress(parts, 9))))

ทดสอบไดรเวอร์

#!/usr/bin/python3
import json
import subprocess
import sys

with open("data.json") as f:
    data = json.load(f)

for name, char in data.items():
    stdout = subprocess.check_output(["python3", sys.argv[1], name])
    stdout = stdout.decode().rstrip("\n")
    if char != stdout:
        print("mismatch for {!r}: {!r} != {!r}".format(
            name, char, stdout
        ))

0

awk 73 + 2060 ไบต์

s{while(!(i=index(s,$0)))sub(/.$/,"");print substr(s,i+length(),1)}{s=$0}

ข้อมูลถูกจัดทำตามสิ่งนี้:

  "Aleax": "A",            Al A     # first of alphabet truncate to len=1
  "Angel": "A",            An A
  "Arch Priest": "@",      Arch @   # this needs to come
  "Archon": "A",           Archo A  # before this
  "Ashikaga Takauji": "@", Ash @
  "Asmodeus": "&",         Asm &    

(2060 ตัวอักษร) เช่น เพื่อสตริงที่สั้นที่สุดที่ไม่ซ้ำกับอักขระมอนสเตอร์ที่ผนวกเข้ากับชื่อและในที่สุดกับแบบฟอร์มนี้:

AlAAnAArch@ArchoAAsh@Asm&

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

$ cat monster
Aleax
$ awk -f program.awk monsters_string monster
A

ฉันยังคงสามารถกำจัดบางส่วนออกจากสตริงสัตว์ประหลาดด้วยการจัดระเบียบ:

AAnArch@ArchoAsh@Asm&

พิจารณาขนาดของข้อมูลด้วยชื่อสัตว์ประหลาดที่ขึ้นต้นด้วย Aจะลดลงจาก 38 ไบต์เป็น 22 หมายถึงการลดขนาดข้อมูลจาก 2060 เป็น 1193 โดยเฉลี่ย

สิ่งนี้ยังคงอยู่ในระหว่างดำเนินการและสายอักขระประหลาดจะถูกเผยแพร่ในภายหลัง

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