ฟังก์ชันแฮชทวีตที่ท้าทาย


73

ในนี้คุณจะเขียนฟังก์ชันแฮชใน 140 ไบต์1หรือน้อยกว่าของรหัสที่มา ฟังก์ชัน hash ต้องใช้สตริง ASCII เป็นอินพุตและส่งคืนจำนวนเต็มที่ไม่ได้ลงชื่อ 24 บิต ([0, 2 24 -1]) เป็นเอาต์พุต

ฟังก์ชันแฮชของคุณจะได้รับการประเมินสำหรับทุกคำพูดในเรื่องนี้ขนาดใหญ่อังกฤษพจนานุกรมภาษาอังกฤษ 2 คะแนนของคุณคือจำนวนคำที่ใช้ค่าแฮชกับคำอื่น (การชนกัน)

คะแนนต่ำสุดที่ชนะการเชื่อมโยงโดยโปสเตอร์แรก

กรณีทดสอบ

ก่อนส่งโปรดทดสอบสคริปต์การให้คะแนนของคุณจากอินพุตต่อไปนี้:

duplicate
duplicate
duplicate
duplicate

ถ้ามันให้คะแนนใด ๆ นอกเหนือจาก 4 มันเป็นรถ


ชี้แจงกฎ:

  1. ฟังก์ชันแฮชของคุณจะต้องทำงานในสายเดียวไม่ใช่ทั้งอาเรย์ นอกจากนี้ฟังก์ชันแฮชของคุณอาจไม่ทำ I / O อื่นใดนอกจากสตริงอินพุตและเอาต์พุตจำนวนเต็ม
  2. ฟังก์ชั่นแฮชในตัวหรือฟังก์ชั่นที่คล้ายกัน (เช่นการเข้ารหัสไปยังไบต์ช่วงชิง)
  3. ฟังก์ชันแฮชของคุณจะต้องกำหนดไว้ล่วงหน้า
  4. ตรงกันข้ามกับการแข่งขันอื่น ๆ ส่วนใหญ่ปรับให้เหมาะสมโดยเฉพาะสำหรับการให้คะแนนที่ได้รับอนุญาต

1ฉันทราบว่า Twitter จำกัด ตัวอักขระแทนที่จะเป็นไบต์ แต่เพื่อความง่ายเราจะใช้จำนวนไบต์เป็นข้อ จำกัด สำหรับความท้าทายนี้
2ดัดแปลงจากwbritish-hugeของ Debian โดยลบคำที่ไม่ใช่ ASCII ออก


11
Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch's? อะไรนะ ...
Luis Mendo

8
@DonMuesli en.wikipedia.org/wiki/Llanfairpwllgwyngyll (ข้อเท็จจริงที่สนุกสนาน: คำนั้นยังอยู่ในพจนานุกรมการบีบอัดในตัวของ Jelly)
Martin Ender

8
ฉันคิดว่าคุณควรไม่อนุญาตพจนานุกรมในตัว
Dennis

4
สำหรับการอ้างอิง: Taking 24 MSB ของ SHA-512 จะบรรลุคะแนน 6816.
เดนนิส

10
การคำนวณด้านหลังซองจดหมาย: ด้วยD=340275คำและR=2^24เอาต์พุตแฮชแฮนแบบสุ่มมีD^2/(2*R) = 3450คู่การชนที่คาดไว้ซึ่งบางส่วนซ้อนทับกัน มีการD^3/(6*R^2) = 23ปะทะกันที่คาดหวังไว้จำนวนหนึ่งและการชนที่มีขนาดใหญ่กว่าเล็กน้อยซึ่งหมายความว่าอเนกประสงค์เหล่านี้มีแนวโน้มที่จะแยกกัน สิ่งนี้จะให้6829คำที่คาดหวังซึ่งแบ่งปันค่าแฮช ~ เป็น70สามเท่าและที่เหลือเป็นคู่ ค่าเบี่ยงเบนมาตรฐานอยู่ที่ประมาณ118ดังนั้นการ<6200แฮชแบบสุ่มจะเป็นเหตุการณ์ 5 ซิกม่า
xnor

คำตอบ:


11

เอาล่ะฉันจะไปเรียนภาษากอล์ฟ

CJam, 140 ไบต์, 3314 คำที่ขัดแย้งกัน

00000000: 7b5f 3162 225e d466 4a55 a05e 9f47 fc51  {_1b"^.fJU.^.G.Q
00000010: c45b 4965 3073 72dd e1b4 d887 a4ac bcbd  .[Ie0sr.........
00000020: 9c8f 70ca 2981 b2df 745a 10d0 dfca 6cff  ..p.)...tZ....l.
00000030: 7a3b 64df e730 54b4 b068 8584 5f6c 9f6b  z;d..0T..h.._l.k
00000040: b7f8 7a1f a2d3 b2b8 bcf5 cfa6 1ef7 a55c  ..z............\
00000050: dca8 795c 2492 dc32 1fb6 f449 f9ca f6b7  ..y\$..2...I....
00000060: a2cf 4772 266e ad4f d90c d236 b51d c5d5  ..Gr&n.O...6....
00000070: 5c46 3f9b 7cb4 f195 4efc fe4a ce8d 9aee  \F?.|...N..J....
00000080: 9dbc 223d 6962 3443 2329 257d            .."=ib4C#)%}

กำหนดบล็อก (ฟังก์ชั่นที่ไม่ระบุชื่อ) ในการทดสอบคุณสามารถเพิ่มqN%%N*Nรายการคำที่คั่นด้วยการขึ้นบรรทัดใหม่บน stdin และเขียนรายการแฮชที่คั่นด้วยการขึ้นบรรทัดใหม่บน stdout รหัส Python ที่เทียบเท่า:

b=lambda s,a:reduce(lambda n,c:n*a+ord(c),s,0)
f=lambda s:b(s,ord('^\xd4fJU\xa0^\x9fG\xfcQ\xc4[Ie0sr\xdd\xe1\xb4\xd8\x87\xa4\xac\xbc\xbd\x9c\x8fp\xca)\x81\xb2\xdftZ\x10\xd0\xdf\xcal\xffz;d\xdf\xe70T\xb4\xb0h\x85\x84_l\x9fk\xb7\xf8z\x1f\xa2\xd3\xb2\xb8\xbc\xf5\xcf\xa6\x1e\xf7\xa5\\\xdc\xa8y\\$\x92\xdc2\x1f\xb6\xf4I\xf9\xca\xf6\xb7\xa2\xcfGr&n\xadO\xd9\x0c\xd26\xb5\x1d\xc5\xd5\\F?\x9b|\xb4\xf1\x95N\xfc\xfeJ\xce\x8d\x9a\xee\x9d\xbc'[b(s,1)%125]))%(8**8+1)

Pyth, 140 bytes, 3535 3396 คำที่ขัดแย้งกัน

00000000: 4c25 4362 2d68 5e38 2038 2a36 3643 4022  L%Cb-h^8 8*66C@"
00000010: aa07 f29a 27a7 133a 3901 484d 3f9b 1982  ....'..:9.HM?...
00000020: d261 79ab adab 9d92 888c 3012 a280 76cf  .ay.......0...v.
00000030: a2e5 8f81 7039 acee c42e bc18 28d8 efbf  ....p9......(...
00000040: 0ebe 2910 9c90 158e 3742 71b4 bdf5 59c2  ..).....7Bq...Y.
00000050: f90b e291 8673 ea59 6975 10be e750 84c8  .....s.Yiu...P..
00000060: 0b0f e7e8 f591 f628 cefa 1ab3 2e3c 72a3  .......(.....<r.
00000070: 7f09 6190 dbd2 d54e d6d0 d391 a780 ebb6  ..a....N........
00000080: ae86 2d1e 49b0 552e 7522 4362            ..-.I.U.u"Cb

yกำหนดฟังก์ชั่นที่มีชื่อว่า ในการทดสอบคุณสามารถเพิ่มjmyd.zรายการคำที่คั่นด้วยการขึ้นบรรทัดใหม่บน stdin และเขียนรายการแฮชที่คั่นด้วยการขึ้นบรรทัดใหม่บน stdout รหัส Python ที่เทียบเท่า:

b=lambda s,a:reduce(lambda n,c:n*a+ord(c),s,0)
f=lambda s:b(s,256)%(8**8+1-66*ord("\xaa\x07\xf2\x9a'\xa7\x13:9\x01HM?\x9b\x19\x82\xd2ay\xab\xad\xab\x9d\x92\x88\x8c0\x12\xa2\x80v\xcf\xa2\xe5\x8f\x81p9\xac\xee\xc4.\xbc\x18(\xd8\xef\xbf\x0e\xbe)\x10\x9c\x90\x15\x8e7Bq\xb4\xbd\xf5Y\xc2\xf9\x0b\xe2\x91\x86s\xeaYiu\x10\xbe\xe7P\x84\xc8\x0b\x0f\xe7\xe8\xf5\x91\xf6(\xce\xfa\x1a\xb3.<r\xa3\x7f\ta\x90\xdb\xd2\xd5N\xd6\xd0\xd3\x91\xa7\x80\xeb\xb6\xae\x86-\x1eI\xb0U.u"[b(s,256)%121]))

ข้อ จำกัด ทางทฤษฎี

เราคาดหวังได้ดีแค่ไหน? นี่คือพล็อตของ x, จำนวนคำที่มีการชนกัน, กับ y, เอนโทรปีในหน่วยไบต์ที่ต้องใช้เพื่อให้ได้คำที่ x มากที่สุด ตัวอย่างเช่นจุด (2835, 140) บอกเราว่าฟังก์ชั่นแบบสุ่มได้รับมากที่สุด 2835 คำที่มีความน่าจะเป็น 1/256 ** 140 ดังนั้นจึงไม่น่าเป็นไปได้ที่เราจะทำได้ดีกว่า 140 ไบต์ของรหัส

กราฟ


การวิเคราะห์ที่ดีของข้อ จำกัด ทางทฤษฎี เพื่อที่จะเอาชนะขีด จำกัด ทางทฤษฎีที่หนึ่งอาจจะต้องใช้ภาษาที่มีฟังก์ชั่น builtin เหมาะสำหรับพจนานุกรมในคำถาม (ซึ่งจะเป็นการโกง) หากภาษามีแฮชการเข้ารหัสลับในตัวขีด จำกัด สามารถเปลี่ยนเป็นวิธีการที่สร้างสรรค์มากขึ้นหรือน้อยลงสำหรับการค้นหาโซลูชันที่ดีที่สุด พิจารณาสิ่งนี้: $ h (w || c)% 2 ^ {24} $ โดยที่ $ c $ เป็นค่าคงที่สตริงไบต์ ในแบบจำลอง oracle แบบสุ่มที่สามารถแสดงให้ใกล้เคียงกับค่าที่เหมาะสมและมีความน่าจะเป็นสูง แน่นอนว่าเดรัจฉานบังคับให้ $ c $ จะไม่เป็นไปได้
kasperd

คุณคำนวณสูตรสำหรับกราฟอย่างไร น่าสนใจจริงๆ!
NikoNyrh

@NikoNyrh การเขียนโปรแกรมแบบไดนามิก Let ( W , C , H ) เป็นตัวแทนของรัฐที่มีWคำซึ่งจะชนกับชั่วโมง hashes ที่แตกต่างกันและที่เหลือW - ทุกคนมีแฮชที่แตกต่างกัน หากเราเพิ่มคำแบบสุ่มสถานะจะกลายเป็น ( w + 1, c , h ) โดยมีความน่าจะเป็น 1 - ( h + w - c ) / 2 ^ 24 หรือ ( w + 1, c + 1, h ) ด้วยความน่าจะเป็นh / 2 ^ 24 หรือ ( w + 1, c+ 2, h + 1) ด้วยความน่าจะเป็น ( w - c ) / 2 ^ 24 แล้วเอนโทรปีสุดท้ายกับกราฟxชนคำคือบันทึกฐาน 1/256 ของผลรวมของความน่าจะเป็นที่สหรัฐฯ (340,275, C , H ) กับ ≤ x
Anders Kaseorg

ฉันไม่อยากจะเชื่อเลยว่าไม่มีใครถามว่าคุณคิดอย่างไรกับฟังก์ชั่นแฮช? ฉันอยากจะรู้มาก
Anush

22

Python 5333 4991

ฉันเชื่อว่านี่เป็นคู่แข่งรายแรกที่ทำคะแนนได้ดีกว่า oracle สุ่ม

def H(s):n=int(s.encode('hex'),16);return n%(8**8-ord('+%:5O![/5;QwrXsIf]\'k#!__u5O}nQ~{;/~{CutM;ItulA{uOk_7"ud-o?y<Cn~-`bl_Yb'[n%70]))

1
เวทมนตร์! def H(s):n=int(s.encode('hex'),16);return n%...ช่วยประหยัด 5 ไบต์ในกรณีที่คุณสามารถใช้พวกเขาอย่างใด ...
Dennis

3
@Dennis ฉันสามารถใช้ 5 ไบต์เพื่อทำให้สตริงคงที่ได้อีก 5 ไบต์ แต่ฉันจะต้องเริ่มต้นใหม่ในการสร้างค่าคงที่สตริงตั้งแต่เริ่มต้นถ้าฉันเปลี่ยนความยาว และฉันไม่แน่ใจว่า 5 ไบต์เหล่านั้นจะทำให้ฉันมีการปรับปรุงมากพอที่จะคุ้มค่าที่จะเริ่มต้นสร้างสตริง ฉันใช้เวลา CPU นานหลายชั่วโมงเพื่อปรับค่าคงที่สตริงให้เหมาะสมแล้ว
kasperd

@ เดนนิสฉันคิดว่าไบต์พิเศษอีกสองสามอันจะให้อิสระแก่ฉันในการใช้อักขระบางตัวในการหลบหนีที่ต้องการอย่างต่อเนื่อง ด้วยวิธีนี้ฉันสามารถใช้ไบต์พิเศษจำนวนไม่กี่ไบต์โดยไม่ต้องสร้างสตริงทั้งหมดอีกครั้ง
kasperd

7
ถ้าคุณต้องการไบต์อื่น, 2**24 == 8**8.
Anders Kaseorg

20

Python 2, 140 bytes, 4266 คำที่ขัดแย้งกัน

ฉันไม่ต้องการเริ่มต้นด้วยสิ่งที่ไม่สามารถพิมพ์จำนวนไบต์ได้เนื่องจากการทวีตที่ไม่ชัดเจน แต่ก็ไม่ได้เริ่มเลย :-P

00000000: efbb bf64 6566 2066 2873 293a 6e3d 696e  ...def f(s):n=in
00000010: 7428 732e 656e 636f 6465 2827 6865 7827  t(s.encode('hex'
00000020: 292c 3336 293b 7265 7475 726e 206e 2528  ),36);return n%(
00000030: 382a 2a38 2b31 2d32 3130 2a6f 7264 2827  8**8+1-210*ord('
00000040: 6f8e 474c 9f5a b49a 01ad c47f cf84 7b53  o.GL.Z........{S
00000050: 49ea c71b 29cb 929a a53b fc62 3afb e38e  I...)....;.b:...
00000060: e533 7360 982a 50a0 2a82 1f7d 768c 7877  .3s`.*P.*..}v.xw
00000070: d78a cb4f c5ef 9bdb 57b4 7745 3a07 8cb0  ...O....W.wE:...
00000080: 868f a927 5b6e 2536 375d 2929            ...'[n%67]))

Python 2 140 ไบต์ที่พิมพ์ได้4662 4471 4362 คำที่ขัดแย้งกัน

def f(s):n=int(s.encode('hex'),16);return n%(8**8+3-60*ord('4BZp%(jTvy"WTf.[Lbjk6,-[LVbSvF[Vtw2e,NsR?:VxC0h5%m}F5,%d7Kt5@SxSYX-=$N>'[n%71]))

แรงบันดาลใจจากรูปแบบการแก้ปัญหาของ kasperd ชัดเจน - แต่ด้วยการเพิ่มที่สำคัญของการแปลงเลียนแบบในพื้นที่มอดุลัสและพารามิเตอร์ที่แตกต่างกันโดยสิ้นเชิง


+1 ฉันไม่ยอมแพ้หากไม่มีการต่อสู้ แต่ฉันคิดว่าฉันต้องหยุดปรับแก้ปัญหาปัจจุบันของฉันและหาแนวทางอื่นเพราะฉันจะไม่เอาชนะคุณถ้าฉันใช้วิธีการปัจจุบันของฉันเพื่อปรับพารามิเตอร์ให้เหมาะสมที่สุด ฉันจะกลับมาพร้อมกับการแก้ไขวิธีการแก้ปัญหาของฉันเมื่อฉันเอาชนะคุณ ....
kasperd

@kasperd: ยอดเยี่ยมนำมาไว้ :-P
Anders Kaseorg

1
@AndersKaseorg คุณค้นหาสตริงได้อย่างไร
ASCII เท่านั้นเท่านั้น

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

1
@kasperd: ดีมาก เมื่อค้นหาสตริงที่ดีขึ้นn%(8**8-ord('…'[n%70]))โดยไม่มีการเปลี่ยนแปลงพารามิเตอร์อื่น ๆ ฉันมีการจัดการที่จะได้รับเพียง 4995 เท่านั้นดังนั้นดูเหมือนว่าเครื่องมือเพิ่มประสิทธิภาพใหม่ของคุณได้รับการตอบรับ ตอนนี้สิ่งนี้น่าสนใจยิ่งขึ้น!
Anders Kaseorg

16

CJam, 4125 3937 3791 3677

0000000: 7b 5f 39 62 31 31 30 25 5f 22 7d 13 25 77  {_9b110%_"}.%w
000000e: 77 5c 22 0c e1 f5 7b 83 45 85 c0 ed 08 10  w\"...{.E.....
000001c: d3 46 0c 5c 22 59 f8 da 7b f8 18 14 8e 4b  .F.\"Y..{....K
000002a: 3a c1 9e 97 f8 f2 5c 18 21 63 13 c8 d3 86  :.....\.!c....
0000038: 45 8e 64 33 61 50 96 c4 48 ea 54 3b b3 ab  E.d3aP..H.T;..
0000046: bc 90 bc 24 21 20 50 30 85 5f 7d 7d 59 2c  ...$! P0._}}Y,
0000054: 4a 67 88 c8 94 29 1a 1a 1a 0f 38 c5 8a 49  Jg...)....8..I
0000062: 9b 54 90 b3 bd 23 c6 ed 26 ad b6 79 89 6f  .T...#..&..y.o
0000070: bd 2f 44 6c f5 3f ae af 62 9b 22 3d 69 40  ./Dl.?..b."=i@
000007e: 62 31 35 32 35 31 39 25 31 31 30 2a 2b 7d  b152519%110*+}

วิธีการนี้แบ่งโดเมนและโคโดเมนเป็น 110 ชุดแยกกันและกำหนดฟังก์ชันแฮชที่แตกต่างกันเล็กน้อยสำหรับแต่ละคู่

การให้คะแนน / การยืนยัน

$ echo $LANG
en_US
$ cat gen.cjam
"qN%{_9b110%_"
[125 19 37 119 119 34 12 225 245 123 131 69 133 192 237 8 16 211 70 12 34 89 248 218 123 248 24 20 142 75 58 193 158 151 248 242 92 24 33 99 19 200 211 134 69 142 100 51 97 80 150 196 72 234 84 59 179 171 188 144 188 36 33 32 80 48 133 95 125 125 89 44 74 103 136 200 148 41 26 26 26 15 56 197 138 73 155 84 144 179 189 35 198 237 38 173 182 121 137 111 189 47 68 108 245 63 174 175 98 155]
:c`"=i@b152519%110*+}%N*N"
$ cjam gen.cjam > test.cjam
$ cjam test.cjam < british-english-huge.txt | sort -n > temp
$ head -1 temp
8
$ tail -1 temp
16776899
$ all=$(wc -l < british-english-huge.txt)
$ unique=$(uniq -u < temp | wc -l)
$ echo $[all - unique]
3677

พอร์ตต่อไปนี้สู่ Python สามารถใช้กับตัวอย่างการให้คะแนนอย่างเป็นทางการ:

h=lambda s,b:len(s)and ord(s[-1])+b*h(s[:-1],b)

def H(s):
 p=h(s,9)%110
 return h(s,ord(
  '}\x13%ww"\x0c\xe1\xf5{\x83E\x85\xc0\xed\x08\x10\xd3F\x0c"Y\xf8\xda{\xf8\x18\x14\x8eK:\xc1\x9e\x97\xf8\xf2\\\x18!c\x13\xc8\xd3\x86E\x8ed3aP\x96\xc4H\xeaT;\xb3\xab\xbc\x90\xbc$! P0\x85_}}Y,Jg\x88\xc8\x94)\x1a\x1a\x1a\x0f8\xc5\x8aI\x9bT\x90\xb3\xbd#\xc6\xed&\xad\xb6y\x89o\xbd/Dl\xf5?\xae\xafb\x9b'
  [p]))%152519*110+p

1
ฉันย้ายรหัสของฉันไปที่ Python เพื่อการตรวจสอบง่าย
Dennis

ไม่hอยู่ในท่างูหลามที่สอดคล้องกับ builtin CJam?
kasperd

ใช่. มันเป็นของ CJam b(การแปลงฐาน)
Dennis

กระบวนการให้คะแนนของคุณเป็นแบบทุบตีหรือไม่?
GamrCorps

@GamrCorps ใช่นั่นคือ Bash
Dennis

11

Python 6446 6372


วิธีการแก้ปัญหานี้ประสบความสำเร็จในการนับจำนวนการชนที่ต่ำกว่ารายการก่อนหน้าทั้งหมดและต้องการเพียง 44 จาก 140 ไบต์ที่อนุญาตให้ใช้สำหรับโค้ด:

H=lambda s:int(s.encode('hex'),16)%16727401

2
@ ส่ง mbomb007 orlp ของตัวเองทำ%(2**24-1)ดังนั้นฉันคิดว่ามันอาจจะดีสำหรับการชี้แจง
Sp3000

12
@ mbomb007 ความท้าทายบอกว่าไม่มีสิ่งนั้น มันบอกว่าฟังก์ชั่นจะต้องใช้สตริง ASCII เป็นอินพุตและเอาต์พุตจำนวนเต็มในช่วงนั้น ไม่ว่าคุณจะให้ฟังก์ชั่นของฉันอินพุทใดจะอยู่ในช่วงนั้น นิยามทางคณิตศาสตร์ของฟังก์ชัน word ไม่ต้องการให้สร้างเอาต์พุตที่อนุญาตทั้งหมด ถ้านั่นคือสิ่งที่คุณต้องการคำศัพท์ทางคณิตศาสตร์ที่คุณจะใช้เป็นฟังก์ชันที่น่าสนใจ แต่คำว่า surjective ไม่ได้ถูกใช้ในข้อกำหนด
kasperd

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

3
@ mbomb007 - ในความเป็นจริงให้มีไกลมากขึ้นค่าตัวเลขจาก[0, 2**24-1]กว่าที่มีคำในภาษาอังกฤษก็จะเป็นทางคณิตศาสตร์เป็นไปไม่ได้ที่จะทำให้กัญชาที่ทุกค่าเดียวในช่วงที่เป็นไปได้
Darrel Hoffman

7

CJam, 6273

{49f^245b16777213%}

แฮคเกอร์ตัวละครแต่ละตัวมี49ลดสตริงผลลัพธ์ผ่านx, y ↦ 245x + yและใช้มอดูโลที่เหลืออยู่16,777,213 (ไพร์ม 24 บิตที่ใหญ่ที่สุด)

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

$ cat hash.cjam
qN% {49f^245b16777213%} %N*N
$ all=$(wc -l < british-english-huge.txt)
$ unique=$(cjam hash.cjam < british-english-huge.txt | sort | uniq -u | wc -l)
$ echo $[all - unique]
6273

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

7

JavaScript (ES6), 6389

ฟังก์ชันแฮช (105 ไบต์):

s=>[...s.replace(/[A-Z]/g,a=>(b=a.toLowerCase())+b+b)].reduce((a,b)=>(a<<3)*28-a^b.charCodeAt(),0)<<8>>>8

ฟังก์ชันการให้คะแนน (NodeJS) (170 ไบต์):

h={},c=0,l=require('fs').readFileSync(process.argv[2],'utf8').split('\n').map(a=>h[b=F(a)]=-~h[b])
for(w of Object.getOwnPropertyNames(h)){c+=h[w]>1&&h[w]}
console.log(c)

เรียกใช้node hash.js dictionary.txtโดยที่hash.jsสคริปต์อยู่ที่ไหนคือdictionary.txtไฟล์ข้อความพจนานุกรม (โดยไม่ขึ้นบรรทัดใหม่สุดท้าย) และFถูกกำหนดเป็นฟังก์ชันการแฮช

ขอบคุณ Neil สำหรับการโกน 9 ไบต์จากฟังก์ชั่นคร่ำครวญ!


ทำไมการมอบหมายให้? นอกจากนี้((...)>>>0)%(1<<24)คุณอาจใช้(...)<<8>>>8แทน
Neil

@Neil เพราะตัวอักษรและฉันก็น่าเบื่อ = P เช่นกันการคิดเลขคณิตที่ดี! ที่บันทึกไว้ 7 ไบต์ =)
Mwr247

สิ่งที่ดีนี่ไม่ใช่โค้ดกอล์ฟมิฉะนั้นฉันจะต้องขอตัวแปรที่ไม่ได้ใช้iเช่นกัน
Neil

@ Neil Crap> _ <ฉันใช้มันในขณะที่ทดสอบความคิดที่เลือกใช้และลืมลบ XD ใช่สิ่งที่ดีนี่ไม่ใช่กอล์ฟแม้ว่าจะเหมือนกันทั้งหมดฉันชอบที่จะบีบอัดแฮชและคะแนน เป็น 140 ไบต์เดียวกันดังนั้นทุก ๆ บิตช่วย;)
Mwr247

1
@ Sp3000 Gah ฉันเห็นว่าคุณหมายถึงอะไร ฉันไม่นับคนที่อยู่ในนั้นตั้งแต่แรกเมื่อพบการชน ฉันจะแก้ไขมัน
Mwr247

5

Mathematica, 6473

ขั้นตอนต่อไปขึ้นมาแทน ... ข้อสรุปรหัสอักขระที่เรารักษาพวกเขาเป็นตัวเลขของจำนวนฐาน 151 ก่อนที่จะพาพวกเขาแบบโมดูโล 2 24

hash[word_] := Mod[FromDigits[ToCharacterCode @ word, 151], 2^24]

นี่เป็นสคริปต์สั้น ๆ เพื่อพิจารณาจำนวนการชน:

Total[Last /@ DeleteCases[Tally[hash /@ words], {_, 1}]]

ฉันเพิ่งลองทุกฐานอย่างเป็นระบบตั้งแต่1เป็นต้นไปและจนถึงตอนนี้ฐาน 151 ได้ชนกันน้อยที่สุด ฉันจะลองอีกสองสามครั้งเพื่อให้คะแนนลดลงอีกเล็กน้อย แต่การทดสอบช้าลงเล็กน้อย


5

Javascript (ES5), 6765

นี่คือ CRC24 ที่ลดลงเหลือ 140 Bytes สามารถตีกอล์ฟได้มากกว่านี้ แต่ต้องการรับคำตอบจากฉัน :)

function(s){c=0xb704ce;i=0;while(s[i]){c^=(s.charCodeAt(i++)&255)<<16;for(j=0;j++<8;){c<<=1;if(c&0x1000000)c^=0x1864cfb}}return c&0xffffff}

validator ใน node.js:

var col = new Array(16777215);
var n = 0;

var crc24_140 = 
function(s){c=0xb704ce;i=0;while(s[i]){c^=(s.charCodeAt(i++)&255)<<16;for(j=0;j++<8;){c<<=1;if(c&0x1000000)c^=0x1864cfb}}return c&0xffffff}

require('fs').readFileSync('./dict.txt','utf8').split('\n').map(function(s){ 
    var h = crc24_140(s);
    if (col[h]===1) {
        col[h]=2;
        n+=2;
    } else if (col[h]===2) {
        n++;
    } else {
        col[h]=1;
    }
});

console.log(n);

ยินดีต้อนรับสู่การเขียนโปรแกรมปริศนา & รหัสกอล์ฟ!
Alex A.

... และขอขอบคุณสำหรับการต้อนรับอย่างอบอุ่น @AlexA.!
binarymax

5

Python 340053

คะแนนแย่มากจากอัลกอริธึมที่แย่คำตอบนี้มีมากขึ้นเพื่อให้สคริปต์ Python ขนาดเล็กที่แสดงการให้คะแนน

H=lambda s:sum(map(ord, s))%(2**24)

ที่จะทำคะแนน:

hashes = []
with open("british-english-huge.txt") as f:
    for line in f:
        word = line.rstrip("\n")
        hashes.append(H(word))

from collections import Counter
print(sum(v for k, v in Counter(hashes).items() if v > 1))

1
มันอาจมีประโยชน์ที่จะมีรหัสการให้คะแนนยืนยันว่าค่าส่งคืนจากฟังก์ชันแฮชเป็นจำนวนเต็มในช่วงที่อนุญาต
kasperd

4

Python, 6390 6376 6359

H=lambda s:reduce(lambda a,x:a*178+ord(x),s,0)%(2**24-48)

อาจมีการพิจารณาการปรับเปลี่ยนเล็กน้อยเพื่อคำตอบที่มาร์ตินBüttnerของ


3
@ mbomb007 นั่นไม่เป็นความจริง หากฟังก์ชั่นของคุณมักจะออกผลลัพธ์ 4 [0, 2**24-1]ก็ยังคงแสดงผลในช่วง สิ่งเดียวที่ไม่ได้รับอนุญาตเป็นจำนวนการแสดงผลใด ๆ ที่ไม่ได้อยู่ในช่วงที่เช่นหรือ-1 2**24
orlp

3

Python 9310


ใช่ไม่ใช่สิ่งที่ดีที่สุด แต่อย่างน้อยมันก็เป็นอะไรบางอย่าง ในฐานะที่เราพูดในการเข้ารหัสลับ, ไม่เคยเขียนฟังก์ชันแฮชของคุณเอง

นี่คือความยาว 140 ไบต์เช่นกัน

F=lambda x,o=ord,m=map:int((int(''.join(m(lambda z:str(o(z)^o(x[-x.find(z)])^o(x[o(z)%len(x)])),x)))^(sum(m(int,m(o,x))))^o(x[-1]))%(2**24))

2

Matlab, 30828 8620 6848

มันสร้างความยุ่งเหยิงโดยการกำหนดหมายเลขเฉพาะให้กับตัวละคร / ตำแหน่งคำสั่งผสม ASCII แต่ละตัวและคำนวณผลิตภัณฑ์ของพวกเขาสำหรับแต่ละคำโมดูโลที่สำคัญที่สุดที่เล็กกว่า 2 ^ 24 โปรดทราบว่าสำหรับการทดสอบฉันย้ายการโทรไปยังช่วงเวลาที่อยู่ด้านนอกของผู้ทดสอบโดยตรงก่อนหน้าลูปและส่งผ่านไปยังฟังก์ชันแฮชเพราะมันเร่งความเร็วขึ้นประมาณ 1,000 เท่า แต่เวอร์ชันนี้ใช้งานได้ มันอาจมีปัญหากับคำยาวเกิน 40 ตัวอักษร

function h = H(s)
p = primes(1e6);
h = 1;
for i=1:length(s)
    h = mod(h*p(double(s(i))*i),16777213);
end
end

Tester:

clc
clear variables
close all

file = fopen('british-english-huge.txt');
hashes = containers.Map('KeyType','uint64','ValueType','uint64');

words = 0;
p = primes(1e6);
while ~feof(file)
    words = words + 1;
    word = fgetl(file);
    hash = H(word,p);
    if hashes.isKey(hash)
        hashes(hash) = hashes(hash) + 1;
    else
        hashes(hash) = 1;
    end
end

collisions = 0;
for key=keys(hashes)

    if hashes(key{1})>1
        collisions = collisions + hashes(key{1});
    end
end

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

1

Ruby 9309 ชน 107 ไบต์

def hash(s);require'prime';p=Prime.first(70);(0...s.size).reduce(0){|a,i|a+=p[i]**(s[i].ord)}%(2**24-1);end 

ไม่ใช่คู่แข่งที่ดี แต่ฉันต้องการสำรวจความคิดที่แตกต่างจากรายการอื่น ๆ

กำหนด n primes ครั้งแรกให้กับตำแหน่ง n แรกของสตริงจากนั้นรวมนายกทั้งหมด [i] ** (รหัส ascii ของสตริง [i]), จากนั้น mod 2 ** 24-1


1

Java 8, 7054 6467

สิ่งนี้ได้รับแรงบันดาลใจจาก (แต่ไม่ได้คัดลอกมาจาก) ฟังก์ชัน builtin java.lang.String.hashCode ดังนั้นอย่าลังเลที่จะไม่อนุญาตตามกฎ # 2

w -> { return w.chars().reduce(53, (acc, c) -> Math.abs(acc * 79 + c)) % 16777216; };

ที่จะทำคะแนน:

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

public class TweetableHash {
    public static void main(String[] args) throws Exception {
        List<String> words = Files.readAllLines(Paths.get("british-english-huge.txt"));

        Function<String, Integer> hashFunc = w -> { return w.chars().reduce(53, (acc, c) -> Math.abs(acc * 79 + c)) % 16777216; };

        Map<Integer, Integer> hashes = new HashMap<>();
        for (String word : words) {
            int hash = hashFunc.apply(word);
            if (hash < 0 || hash >= 16777216) {
                throw new Exception("hash too long for word: " + word + " hash: " + hash);
            }

            Integer numOccurences = hashes.get(hash);
            if (numOccurences == null) {
                numOccurences = 0;
            }
            numOccurences++;

            hashes.put(hash, numOccurences);
        }

        int numCollisions = hashes.values().stream().filter(i -> i > 1).reduce(Integer::sum).get();
        System.out.println("num collisions: " + numCollisions);
    }
}

@muddyfish คุณช่วยตรวจสอบเวอร์ชั่นปัจจุบันได้ไหม? ฉันคิดว่า ive คิดเป็น 3-way-collision และฉันยังคงได้ผลลัพธ์เดียวกัน
Bewusstsein

สิ่งนี้ไม่ได้หมายถึงการชนสามทาง หากคุณแทนที่hashesด้วยMap<Integer, Integer> hashes = new HashMap<>()แล้วนับจำนวนคำสำหรับแฮชแต่ละรายการคุณสามารถอธิบายได้อย่างถูกต้อง
Peter Taylor

คะแนนของคุณยังไม่ถูกต้อง ฉันคิดว่าการคำนวณคะแนนที่ถูกต้องคุณต้องส่งออก numHashes + numCollisions (ซึ่งผมคิดว่าจะทำให้คุณใกล้ชิดกับ 6832 ประมาณการของฉันสำหรับ oracle สุ่ม.)
kasperd

ปรับเปลี่ยนส่วนการจัดลำดับเป็น: pastebin.com/nLeg4qut
TheNumberOne

ใช่แก้ไขการให้เกรดแล้วและดูเหมือนว่าจะมีราคาที่สมเหตุสมผลมากกว่านี้ตอนนี้
Bewusstsein

1

Python, 6995 6862 6732

เพียงแค่ฟังก์ชั่น RSA ที่เรียบง่าย ง่อยสวย แต่เต้นบางคำตอบ

M=0x5437b3a3b1
P=0x65204c34d
def H(s):
    n=0
    for i in range(len(s)):
        n+=pow(ord(s[i]),P,M)<<i
    return n%(8**8)

1

C ++: 7112 6694 6483 6479 6412 6339 การชน 90 ไบต์

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

int h(const char*s){uint32_t t=0,p=0;while(*s)t="cJ~Z]q"[p++%6]*t+*s++;return t%16777213;}

ฟังก์ชั่นการทดสอบ:

int main(void)
{
    std::map<int, int> shared;

    std::string s;
    while (std::cin >> s) {
        shared[h(s.c_str())]++;
    }

    int count = 0;
    for (auto c : shared) {
        if ((c.first & 0xFFFFFF) != c.first) { std::cerr << "invalid hash: " << c.first << std::endl; }
        if (c.second > 1) { count += c.second; }
    }

    std::cout << count << std::endl;
    return 0;
}

1

C #, 6251 6335

int H(String s){int h = 733;foreach (char c in s){h = (h * 533 + c);}return h & 0xFFFFFF;}

ค่าคงที่ 533 และ 733 889 และ 155ให้คะแนนที่ดีที่สุดจากค่าทั้งหมดที่ฉันเคยค้นหามา


1

TCL

88 ไบต์การชน 6448/3233

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

# 88 bytes, 6448 collisions, 3233 words in nonempty buckets

puts "[string length {proc H w {incr h;lmap c [split $w {}] {set h [expr (2551*$h+[scan $c %c])%2**24]};set h}}] bytes"

proc H w {incr h;lmap c [split $w {}] {set h [expr (2551*$h+[scan $c %c])%2**24]};set h}

# change 2551 above to:
#   7: 85 bytes, 25839 colliding words, 13876 words in nonempty buckets
#   97: 86 bytes, 6541 colliding words, 3283 words in nonempty buckets
#   829: 87 bytes, 6471 colliding words, 3251 words in nonempty buckets


# validation program

set f [open ~/Downloads/british-english-huge.txt r]
set words [split [read $f] \n]
close $f

set have {};                        # dictionary whose keys are hash codes seen
foreach w $words {
    if {$w eq {}} continue
    set h [H $w]
    dict incr have $h
}
set coll 0
dict for {- count} $have {
    if {$count > 1} {
        incr coll $count
    }
}
puts "found $coll collisions"

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

1
เท่าที่ฉันจะบอกได้รหัสของคุณคือproc H w {incr h;lmap c [split $w {}] {set h [expr (2551*$h+[scan $c %c])%2**24]};set h}... ใช่มั้ย
Erik the Outgolfer

@EriktheOutgolfer: ใช่แล้ว
sergiol

1
ฉันที่สอง @kasperd: คุณช่วยชี้ให้เห็นว่าคำตอบใดที่ไม่ใช่การบันทึกการชนตามข้อมูลจำเพาะของคำถาม คุณพยายามใช้มันจริง ๆ เหรอ?
sergiol

1

Python 3, 89 bytes, 6534 hash collision

def H(x):
 v=846811
 for y in x:
  v=(972023*v+330032^ord(y))%2**24
 return v%2**24

ตัวเลขเวทย์มนตร์ขนาดใหญ่ทั้งหมดที่คุณเห็นที่นี่เป็นค่าคงที่เหลวไหล


1

JavaScript, 121 ไบต์, 3268 3250 3244 6354 (3185) การชน

s=>{v=i=0;[...s].map(z=>{v=((((v*13)+(s.length-i)*7809064+i*380886)/2)^(z.charCodeAt(0)*266324))&16777215;i++});return v}

พารามิเตอร์ (13, 7809064, 380886, 2, 266324) เป็นการทดลองและข้อผิดพลาด

ฉันยังคงปรับให้เหมาะสมฉันคิดว่าและยังมีห้องพักสำหรับการเพิ่มพารามิเตอร์เพิ่มเติมทำงานเพื่อเพิ่มประสิทธิภาพเพิ่มเติม ...

การตรวจสอบ

hashlist = [];
conflictlist = [];
for (x = 0; x < britain.length; x++) {
    hash = h(britain[x]);                      //britain is the 340725-entry array
    hashlist.push(hash);
}

conflict = 0; now_result = -1;
(sortedlist = sort(hashlist)).map(v => {
    if (v == now_result) {
        conflict++;
        conflictlist.push(v);
    }
    else
        now_result = v;
});

console.log(conflictlist);

var k = 0;
while (k < conflictlist.length) {
    if (k < conflictlist.length - 1 && conflictlist[k] == conflictlist[k+1])
        conflictlist.splice(k,1);
    else
        k++;
}

console.log(conflict + " " + (conflict+conflictlist.length));

3268> 3250 - เปลี่ยนพารามิเตอร์ที่ 3 จาก 380713 เป็น 380560

3250> 3244 - เปลี่ยนพารามิเตอร์ที่ 3 จาก 380560 เป็น 380886

3244> 6354 - เปลี่ยนพารามิเตอร์ที่ 2 จาก 7809143 เป็น 7809064 และพบว่าฉันใช้วิธีคำนวณผิด


1

ต่อไปนี้เป็นโครงสร้างที่คล้ายกันสองสามประการซึ่งค่อนข้าง "เป็นค่าเริ่มต้น" และทำให้การเพิ่มประสิทธิภาพพารามิเตอร์เพิ่มขึ้นเป็นไปได้ ประณามมันเป็นเรื่องยากที่จะได้รับต่ำกว่า 6k! สมมติว่าคะแนนมีค่าเฉลี่ยของ 6829 และ std จาก 118 ฉันยังคำนวณความน่าจะเป็นของการได้รับคะแนนต่ำโดยการสุ่ม

Clojure A, 6019, Pr = 1: 299.5e9

 #(reduce(fn[r i](mod(+(* r 811)i)16777213))(map *(cycle(map int"~:XrBaXYOt3'tH-x^W?-5r:c+l*#*-dtR7WYxr(CZ,R6J7=~vk"))(map int %)))

Clojure B, 6021, Pr = 1: 266.0e9

#(reduce(fn[r i](mod(+(* r 263)i)16777213))(map *(cycle(map int"i@%(J|IXt3&R5K'XOoa+Qk})w<!w[|3MJyZ!=HGzowQlN"))(map int %)(rest(range))))

Clojure C, 6148, Pr = 1: 254.0e6

#(reduce(fn[r i](mod(+(* r 23)i)16777213))(map *(cycle(map int"ZtabAR%H|-KrykQn{]u9f:F}v#OI^so3$x54z2&gwX<S~"))(for[c %](bit-xor(int c)3))))

Clojure, 6431, Pr = 1: 2.69e3 (บางอย่างแตกต่างกัน)

#(mod(reduce bit-xor(map(fn[i[a b c]](bit-shift-left(* a b)(mod(+ i b c)19)))(range)(partition 3 1(map int(str"w"%"m")))))16776869)

นี่เป็นฟังก์ชั่นแฮชเฉพาะกิจแบบเดิมของฉันมันมีสี่พารามิเตอร์ที่ปรับค่าได้


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

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

บางทีการเพิ่มค่า ASCII อาจทำให้เอนโทรปีของเกมไม่พอ f(n) % (8^8 - g(n))หลายขั้นตอนวิธีการที่ดีคะแนนดูเหมือนจะมีแบบฟอร์ม
NikoNyrh

มีคำตอบหนึ่งข้อซึ่งอธิบายว่ามันต่ำแค่ไหนได้ 3677 คำตอบที่ให้คะแนนต่ำกว่าคำอธิบายเล็กน้อย
kasperd

0

Ruby, 6473 การชน, 129 ไบต์

h=->(w){@p=@p||(2..999).select{|i|(2..i**0.5).select{|j|i%j==0}==[]};c=w.chars.reduce(1){|a,s|(a*@p[s.ord%92]+179)%((1<<24)-3)}}

ตัวแปร @p เต็มไปด้วยจำนวนทั้งหมดต่ำกว่า 999

สิ่งนี้จะแปลงค่า ascii เป็นตัวเลขช่วงเวลาและนำโมดูโลของผลิตภัณฑ์ไปสู่ไพรม์ขนาดใหญ่ ปัจจัยเหลวไหลของ 179 เกี่ยวข้องกับความจริงที่ว่าอัลกอริทึมเดิมมีไว้สำหรับใช้ในการค้นหา anagrams ที่ทุกคำที่มีการเรียงลำดับใหม่ของตัวอักษรเดียวกันได้รับแฮชเดียวกัน โดยการเพิ่มตัวประกอบในลูปทำให้แอนนาแกรมมีรหัสที่แตกต่างกัน

ฉันสามารถลบ ** 0.5 (การทดสอบ sqrt สำหรับ Prime) ด้วยค่าใช้จ่ายของประสิทธิภาพที่ต่ำกว่าเพื่อทำให้รหัสสั้นลง ฉันสามารถทำให้ตัวค้นหาหมายเลขเฉพาะทำงานในลูปเพื่อลบอักขระอีกเก้าตัวโดยเหลือ 115 ไบต์

ในการทดสอบต่อไปนี้จะพยายามหาค่าที่ดีที่สุดสำหรับปัจจัยเหลวไหลในช่วง 1 ถึง 300 โดยจะถือว่าไฟล์คำนั้นในไดเรกทอรี / tmp:

h=->(w,y){
  @p=@p||(2..999).
    select{|i|(2..i**0.5). 
    select{|j|i%j==0}==[]};
  c=w.chars.reduce(1){|a,s|(a*@p[s.ord%92]+y)%((1<<24)-3)}
}

american_dictionary = "/usr/share/dict/words"
british_dictionary = "/tmp/british-english-huge.txt"
words = (IO.readlines british_dictionary).map{|word| word.chomp}.uniq
wordcount = words.size

fewest_collisions = 9999
(1..300).each do |y|
  whash = Hash.new(0)
  words.each do |w|
    code=h.call(w,y)
    whash[code] += 1
  end
  hashcount = whash.size
  collisions = whash.values.select{|count| count > 1}.inject(:+)
  if (collisions < fewest_collisions)
    puts "y = #{y}. #{collisions} Collisions. #{wordcount} Unique words. #{hashcount} Unique hash values"
    fewest_collisions = collisions
  end
end

1
คะแนนดูน่าสงสัย คุณแน่ใจหรือว่าคุณกำลังนับคำที่มีการชนกันทั้งหมด? คำตอบก่อนหน้าจำนวนมากนับผิดพลาดเพียงคำเดียวสำหรับค่าแฮชแต่ละครั้ง
kasperd

คุณอาจจะถูก ฉันต้องพิจารณาวิธีการนับและดูว่ามันเป็นคำนิยามของคุณหรือไม่ ฉันกำลังนับจำนวนคำที่มีและลบจำนวน hashcodes ที่ไม่ซ้ำกันที่ถูกสร้างขึ้น ถ้าคำ A และ B ได้รับแฮชโค้ดเดียวกันนั่นคือหนึ่งชนหรือสองครั้ง? ฉันนับมันเป็นหนึ่งเดียว
Paul Chernoch

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

1
ใช่ฉันทำผิดพลาดเหมือนกัน ฉันจะแก้ไขคำตอบของฉันในภายหลัง ต้องขึ้นรถบัส
Paul Chernoch

แก้ไขการให้คะแนน
Paul Chernoch

0

TCL

# 91 ไบต์, 6508 การชน

91 ไบต์, 6502 การชน

proc H s {lmap c [split $s ""] {incr h [expr [scan $c %c]*875**[incr i]]};expr $h&0xFFFFFF}

คอมพิวเตอร์ยังคงทำการค้นหาเพื่อประเมินว่ามีค่าที่ทำให้เกิดการชนน้อยกว่า147 875 ฐานซึ่งยังเป็นนักบันทึก

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