Va chạm băm: Số ít có nghĩa là


63

Code Golf này được lấy cảm hứng từ bài báo WTF hàng ngày gần đây mà bạn không thể xử lý đúng! , có tính năng so sánh chuỗi được viết là:

String yes = "YES";
if ((delay.hashCode()) == yes.hashCode())

Hãy tưởng tượng những rắc rối mà nó đã gây ra cho nhóm của Steve nếu String.hashCodephương pháp của Java tình cờ được thực hiện theo cách đó "YES".hashCode() == "NO".hashCode(). Vì vậy, thách thức tôi đề xuất ở đây là:

Viết, càng ít ký tự càng tốt, hàm băm (tôi sẽ gọi nó h) với tham số chuỗi và giá trị trả về số nguyên, sao cho h("YES")bằng h("NO").

Tất nhiên, điều này sẽ không quan trọng đối với một hàm như def h(s): return 0, điều này tạo ra xung đột băm cho mỗi chuỗi. Để làm cho thử thách này thú vị hơn, bạn phải tuân thủ quy tắc bổ sung sau:

Trong số khác 18 277 chuỗi có thể gồm ba hoặc ít chữ ASCII chữ hoa ( ^[A-Z]{0,3}$) thì phải có không va chạm băm.

Làm rõ (được chỉ ra bởi Heiko Oberdiek): Chuỗi đầu vào có thể chứa các ký tự khác A-Zvà mã của bạn phải có thể băm các chuỗi tùy ý. (Tuy nhiên, bạn có thể giả sử rằng đầu vào một chuỗi ký tự chứ không phải là một con trỏ null hoặc một đối tượng của một số loại dữ liệu khác.) Tuy nhiên, giá trị trả về là gì đối với các chuỗi không khớp ^[A-Z]{0,3}$, miễn là không quan trọng nó là một số nguyên.

Hơn nữa, để làm xáo trộn ý định của chức năng này:

Mã của bạn không được bao gồm bất kỳ chữ cái 'Y', 'E', 'S', 'N' hoặc 'O' (bằng chữ hoa hoặc chữ thường) trong ký tự hoặc ký tự chuỗi.

Tất nhiên, hạn chế này không áp dụng cho từ khóa ngôn ngữ, vì vậy else, returnvv cũng tốt.


4
Việc này vẫn không giúp chúng ta vẫn có thể sử dụng các giá trị ASCII số YESNOđể kiểm tra ngoại lệ cụ thể này.
Joe Z.

1
Đọc bài viết người ta không thể không nhớ "vì những lý do" hài hước: threewordphrase.com/pardonme.gif
Antonio Ragagnin

Câu trả lời:


7

GolfScript: 19 ký tự (24 ký tự cho chức năng được đặt tên)

26base.2107=59934*+

Đây là cơ thể của chức năng. Việc gán nó cho một hàm được đặt tên hsẽ mất thêm năm ký tự:

{26base.2107=59934*+}:h;

(Dấu chấm phẩy cuối cùng có thể được bỏ qua, nếu bạn không để lại một bản sao của mã nằm trên ngăn xếp.)

Cốt lõi của hàm băm là 26base, mà tính toán sum (26 n - k · một k ; k = 1 .. n ), trong đó n là số ký tự trong các đầu vào và một k biểu thị mã ASCII của k -thứ ký tự đầu vào. Đối với các đầu vào bao gồm các chữ cái ASCII viết hoa, đây là hàm băm không va chạm. Phần còn lại của mã so sánh kết quả với 2107 (mã băm của NO) và, nếu chúng bằng nhau, thêm 59934 để mang lại 2701 + 59934 = 62041, mã băm của YES.

Ví dụ đầu ra, xem bản demo trực tuyến này với các trường hợp thử nghiệm.


Làm thế nào bạn kiểm tra điều này? Tôi chỉ tìm thấy một loạt các va chạm . Ví dụ : h('DXP') == h('KK') == 65884.
nneonneo

(Python tương đương với những gì bạn đã viết, cho mục đích thử nghiệm của tôi lambda w:sum(ord(c)*26**i for i,c in enumerate(reversed(w*9)))%102983:)
nneonneo

@nneonneo: Rõ ràng, không đủ tốt. Tôi nghĩ rằng tôi đã tạo ra một bộ đầy đủ các đầu vào ba chữ cái hoặc ít hơn, băm tất cả chúng và kiểm tra xem bộ băm có ít hơn một phần tử so với bộ đầu vào. Rõ ràng, khai thác thử nghiệm của tôi có một lỗi ở đâu đó. :-( Tôi sẽ trở lại phiên bản 19 char ban đầu cho đến khi / trừ khi tôi có thể sửa phiên bản ngắn hơn.
Ilmari Karonen

54

Python 32 bit 2.x (19)

hash(w*9)%537105043

RSA sử dụng mô đun bán thời gian và điều đó làm cho nó an toàn, do đó, sử dụng một mô đun với thuật toán băm của tôi chắc chắn sẽ làm cho nó thậm chí còn tốt hơn! 1

Đây là một hàm toán học thuần túy, hoạt động cho tất cả các chuỗi (địa ngục, hoạt động cho bất kỳ đối tượng Python có thể băm nào) và không chứa bất kỳ điều kiện hoặc vỏ đặc biệt nào! Python 32 bit thường có thể được gọi như python-32trên hầu hết các hệ thống đã cài đặt cả 2 .

Tôi đã thử nghiệm điều này và nó trả về 18.278 giá trị khác nhau cho 18.279 chuỗi ký tự viết hoa hoặc ít hơn 3 chữ cái. Việc gán hàm này cho hàm mất thêm 11 byte:

h=lambda w:hash(w*9)%537105043

h('YES') == h('NO') == 188338253.

Python 64 bit 2.x (19)

hash(w*2)%105706823

Thỏa thuận tương tự như trên.


Để đưa ra những con số này, một chút toán học mô-đun đã được sử dụng. Tôi đã tìm kiếm một chức năng fvà một mô-đun nnhư vậy hash(f('YES')) % n == hash(f('NO')) % n. Điều này tương đương với thử nghiệm nphân chia d = hash(f('YES')) - hash(f('NO')), tức là chúng ta chỉ phải kiểm tra các yếu tố của dcác giá trị phù hợp n.

Lý tưởng nlà trong khu phố 20000 ** 2 để giảm nguy cơ va chạm nghịch lý sinh nhật. Tìm một cái phù hợp nhóa ra là một chút thử nghiệm và sai sót, chơi với tất cả các yếu tố d(thường không có nhiều) và các lựa chọn khác nhau cho chức năng f. Mặc dù lưu ý rằng bản dùng thử và lỗi chỉ cần thiết vì tôi muốn làm nnhỏ nhất có thể (để chơi gôn). Nếu đó không phải là một yêu cầu, tôi chỉ có thể chọn dlàm mô đun của mình, thường là đủ lớn.

Cũng lưu ý rằng bạn không thể thực hiện thủ thuật này bằng cách sử dụng chỉ f(s) = s(hàm nhận dạng) vì ký tự ngoài cùng bên phải của chuỗi có mối quan hệ tuyến tính (thực sự là XORmối quan hệ) với hàm băm cuối cùng (các ký tự khác đóng góp theo cách phi tuyến tính hơn nhiều ). Do đó, sự lặp lại của chuỗi đảm bảo rằng sự khác biệt giữa các chuỗi được khuếch đại để loại bỏ hiệu ứng chỉ thay đổi ký tự ngoài cùng bên phải.


1 Đây là bằng sáng chế vô nghĩa.
2 băm chuỗi Python phụ thuộc vào phiên bản chính (2 so với 3) và độ bit (32 bit so với 64 bit). Nó không phụ thuộc vào nền tảng AFAIK.


Bạn đã có phiếu bầu của tôi. : D
cjfaure

Thật không may, điều này không hoạt động trên các phiên bản gần đây của Python do tính năng ngẫu nhiên băm mới.
dan04

@ dan04: Lạ, tôi nghĩ tôi đã chỉ định rằng đây chỉ dành cho Python 2.x. Tôi đã chỉnh sửa nó một lần nữa.
nneonneo

Tôi có thể biết làm thế nào bạn tìm thấy những con số ma thuật? Tôi thấy hash('YES'*9)34876679một yếu tố, trong khi hash('NO'*9)34876679+537105043một yếu tố. Nhưng làm thế nào để bạn biết rằng đó 537105043là một mô-đun tốt? tức là nó không tạo ra va chạm khác?
Antonio Ragagnin

@AntonioRagagnin: Đã thêm câu trả lời.
nneonneo

38

Perl, 53 49 40 byte

sub h{hex(unpack H6,pop)-20047||5830404}

Kiểm tra:

h('YES') = 5830404
h('NO')  = 5830404
Keys:   18279
Values: 18278

Các giá trị băm cho YESNOgiống nhau và có 18279 chuỗi ^[A-Z]{0,3}$, không có xung đột ngoại trừ xung đột duy nhất cho YESNO.

Ung dung:

sub h {
    hex(unpack("H6", pop())) - 20047 || 5830404;
    # The argument is the first and only element in the argument array @_.
    # "pop" gets the argument from array @_ (from the end).
    # The first three bytes of the argument or less, if the argument
    # is shorter, are converted to a hex string, examples:
    #   "YES" -> "594553"
    #   "NO"  -> "4e4f"
    # Then the hex string is converted to a number by function "hex":
    #   0x594553 = 5850451
    #   0x4e4f   =   20047
    # The value for "NO" is subtracted, examples:
    #   case "YES": 5850451 - 20047 = 5830404
    #   case "NO":    20047 - 20047 =       0
    # If the argument is "NO", the subtraction is zero, therefore
    # 5830404 is returned, the result of "YES".
}

# Test
my %cache;
sub addcache ($) {$cache{$_[0]} = h($_[0])}

# Check entries 'YES' and 'NO'
addcache 'YES';
addcache 'NO';
print "h('YES') = $cache{'YES'}\n";
print "h('NO')  = $cache{'NO'}\n";

# Fill cache with all strings /^[A-Z]{0-3}$/
addcache '';
for my $one (A..Z) {
    addcache $one;
    for (A..Z) {
        my $two = "$one$_";
        addcache $two;
        for (A..Z) {
            my $three = "$two$_";
            addcache $three;
        }
    }
}
# Compare number of keys with number of unique values
my $keys = keys %cache;
my %hash;
@hash{values %cache} = 1 x $keys;
$values = keys %hash;
print "Keys:   $keys\n";
print "Values: $values\n";

Phiên bản cũ hơn, 49 byte

Vì thuật toán mới hơi khác một chút, tôi giữ phiên bản cũ.

sub h{($_=unpack V,pop."\0"x4)==20302?5457241:$_}

Kiểm tra:

h('YES') = 5457241
h('NO')  = 5457241
Keys:   18279
Values: 18278

Ung dung:

sub h {
    $_ = unpack('V', pop() . ($" x 4);
        # pop():  gets the argument (we have only one).
        # $" x 4: generates the string "    " (four spaces);
        #   adding the four spaces ensures that the string is long
        #   enough for unpack's template "V".
        # unpack('V', ...): takes the first four bytes as
        #   unsigned long 32-bit integer in little-endian ("VAX") order.
    $_ == 20302 ? 5457241 : $_;
        # If the hash code would be "NO", return the value for "YES".
}

Chỉnh sửa:

  • Sử dụng "\0"như điền byte tiết kiệm 4 byte so với $".

Nơi làm 545724120047đến từ đâu? Làm thế nào để bạn tính toán những con số này? Cảm ơn trước.
AL

@ n.1: YEStrong hex là 594553. 0x594553 = 5850451. NOtrong hex là 4e4f. 0x4e4f = 20047.
nneonneo

7

Con trăn: 63

Một giải pháp cực kỳ khập khiễng:

def h(s):
 try:r=int(s,36)
 except:r=0
 return(r,44596)[r==852]

Nó hoạt động bằng cách giải thích các chuỗi ký tự chữ và số là 36 số cơ bản và trả về 0 cho mọi thứ khác. Có một trường hợp đặc biệt rõ ràng để kiểm tra giá trị trả về là 852 (NO) và thay vào đó trả về 44596 (CÓ).


3
Trừ khi tôi hiểu nhầm: Đó là mã golf, bạn được phép cho rằng đầu vào là chính xác. Bạn có thể bỏ mương try:và toàn bộ dòng thứ ba. Bạn cũng có thể tiết kiệm một vài miếng bằng cách mỗi dòng logic trên dòng thực tế tương tự, cách nhau bằng dấu chấm phẩy ( def h(s):r=int(s,36);return(r,44596)[r==852])
undergroundmonorail

1
@undergroundmonorail: Tham số chuỗi cho hàm băm không bị hạn chế trong câu hỏi. Đối với một loại chuỗi nhất định (tối đa ba chữ cái viết hoa), có một hạn chế liên quan đến các giá trị trả về của hàm băm. Tuy nhiên, điều đó không quan trọng, những gì được trả về cho các chuỗi khác, nếu giá trị trả về là một số nguyên.
Heiko Oberdiek

3
Tôi thích lập chỉ mục boolean của mảng của bạn ở đó
kratenko

6

Pure Bash, 29 byte (thân hàm)

h()(echo $[n=36#$1,n-852?n:44596])

Điều này chỉ đơn giản coi chuỗi đầu vào là số 36 cơ sở và chuyển thành số thập phân, sau đó xử lý NOtrường hợp đặc biệt .

Đầu ra:

$ h A
10
$ h B
11
$ h CAT
15941
$ h KHÔNG
44596
$ h CÓ
44596
$ h
46655
$

5

Ruby, 51 byte

h=->s{d=s.unpack('C*').join;d=~/896983|^7879$/?0:d}

mã kiểm tra:

h=->s{d=s.unpack('C*').join;d=~/896983|^7879$/?0:d}

puts 'YES : '+h.call('YES').to_s # 0
puts 'NO : '+h.call('NO').to_s # 0
puts 'NOX : '+h.call('NOX').to_s # 787988
puts 'FNO : '+h.call('FNO').to_s # 707879
puts ''

values = Hash[]
n = 0
('A'..'Z').each{|c|
    values[c] = h.call(c)
    ('A'..'Z').each{|c2|
        values[c+c2] = h.call(c+c2)
        ('A'..'Z').each{|c3|
            values[c+c2+c3] = h.call(c+c2+c3)
            n += 1
        }
    }
}
puts 'tested '+n.to_s
duplicate = Hash.new()

values.each{|k, e|
    if duplicate.has_key?(e)
        puts 'duplicate : "'+k+'" = "'+duplicate[e].to_s+'" ('+e.to_s+')'
    else
        duplicate[e] = k
    end
}

đầu ra:

YES : 0
NO : 0
NOX : 787988
FNO : 707879

tested 17576
duplicate : "YES" = "NO" (0)

5

Javascript ( ES6 ) 54 byte

f=s=>[x.charCodeAt()for(x of s)].join('')^7879||897296
f('YES'); // 897296
f('NO'); // 897296
f('MAYBE'); // -824036582

5

Java - 94 77

int h=new BigInteger(s.getBytes()).intValue();return Math.abs(h-(h^5835548));

Chưa được kiểm soát:

int hashCode(String s) {
    int h = new BigInteger(s.getBytes()).intValue();
    return Math.abs(h - (h ^ 5835548));
}

Tường thuật - cho f(s) = BigInteger(s.getBytes()):

  • f("YES") xor f("NO") = 5835548
  • Vì thế f("YES") xor 5835548 = f("NO")
  • Vậy f("YES") - (f("YES") xor 5835548) = f("NO") - (f("NO") xor 5835548)tôi có đúng không?

Bạn không thể nội tuyến BigInteger?
mafu

@mafutrct - CÓ !!! Cảm ơn bạn.
OldCurmudgeon

5

CJam, 15 byte

q42b_*81991617%

Hoạt động như giải pháp GolfScript dưới đây. Hãy thử trực tuyến.


GolfScript, 17 byte

42base.*81991617%

Cách tiếp cận này dựa trên câu trả lời của nneonneoIlmari Karonen .

Làm thế nào nó hoạt động

42base    # Interpret the input string as a base 42 number.
          # "YES" is [ 89 69 83 ] in ASCII, so it becomes 42 * (42 * 89 + 69) + 83 = 159977.
          # "NO" is [ 78 79 ] in ASCII, so it becomes 42 * 78 + 79 = 3355.
          #
.*        # Square. "YES" becomes 25592640529, "NO" becomes 11256025.
          #
81991617% # "YES" becomes 11256025.

Chọn một thuật toán

Chúng tôi bắt đầu với {b base}:h, tức là, chuỗi đầu vào được coi là số b cơ sở. Miễn là b > 25, hlà vô dụng.

Chúng ta có một xung đột cho các chuỗi "CÓ" và "KHÔNG" nếu chúng ta sửa đổi htheo cách sau : {x base n}:h, nơi nlà ước số của "YES" h "NO" h -.

Thật không may, điều này có nghĩa là chúng ta cũng sẽ có một vụ va chạm, ví dụ, YETNP. Để ngăn chặn điều này, chúng ta phải sửa đổi số b-b theo kiểu phi tuyến tính trước khi lấy mô-đun.

Cách ngắn nhất để thực hiện điều này trong GolfScript là nhân số b cơ sở với chính nó (nghĩa là bình phương nó). htại là {base b .* n %}:h.

Tất cả những gì còn lại phải làm là tìm các giá trị phù hợp cho bn. Chúng ta có thể thực hiện điều này bằng vũ lực:

for((b=26;b<100;b++)){
    P=($(golfscript <<< "['YES' 'NO']{$b base.*}/-" | factor | cut -d\  -f 2-))

    for n in $(for((i=0;i<2**${#P[@]};i++)){
        for((n=1,j=0;j<${#P[@]};n*=${P[j]}**((i>>j)&1),j++)){ :;};echo $n;} | sort -nu);{
            [[ $n -ge 18277 && $(echo -n '' {A..Z}{,{A..Z}{,{A..Z}}} |
                golfscript <(echo "' '/[{$b base.*$n%}/].&,")) = 18278 ]] &&
            echo $b $n && break
    }
}

Các giá trị ngắn nhất có thể b nlà:

37 92176978
42 81991617

Kiểm tra

$ echo -n '' {A..Z}{,{A..Z}{,{A..Z}}} |
     golfscript <(echo '{42base.*81991617%}:h;" "/{.`"\t"+\h+puts}/') |
     sort -k 2n |
     uniq -Df 1
"NO"    11256025
"YES"   11256025

3

JavaScript (ES6) - 38 ký tự (thân hàm 33 char)

h=s=>(a=btoa(s))=="WUVT"|a=="Tk8="||+s

Các trường hợp thử nghiệm:

var l = console.log;
l(  h("YES")  );                // 1
l(  h("NO")  );                 // 1
l(  h("ABC")  );                // NaN     
l(  h("WIN")  );                // NaN
l(  h("YES") === h("NO")  );    // true
l(  h("ABC") === h("WIN")  );   // false
l(  h("WIN") === h("YES")  );   // false

l(  NaN === NaN  );             // false

Giải trình:

Trước hết, hãy để tôi giới thiệu cho bạn NaN- "Không phải là số" - bằng JavaScript. Nó là một con số:

typeof NaN  // number

Giống như:

typeof 42   // number

Tài sản đặc biệt của nó là nó không bao giờ bằng chính nó . Hàm của tôi trả về 1nếu chuỗi là YEShoặc NONaNcho bất kỳ chuỗi nào khác.

Vì vậy, điều này không phá vỡ các quy tắc, bởi vì sẽ không có xung đột băm cho bất kỳ chuỗi nào khác;) ( NaN !== NaNhiển thị ở trên trong các trường hợp thử nghiệm).

Và giấc mơ của tôi trở thành sự thật: đánh bại Bash, Perl và Ruby theo chiều dài mã!

Mã bị hủy bỏ:

h =  // h is a function 
s => // s = string argument

( ( a = btoa(s) )  ==  "WUVT" | a == "Tk8=" )
        ^-- returns some value stored in `a`

Nếu giá trị đó là "WUVT"hoặc "Tk8=", trả lại 1. Khác, trở về

+s // parseInt(s, 10)

đó sẽ là NaN.


2
NaN có thể là một số, nhưng nó không phải là "số nguyên" theo bất kỳ nghĩa nào của từ này.
Paŭlo Ebermann

2
@ PaŭloEbermann Từ wiki , "Số nguyên là một số được viết mà không có thành phần phân số". Câu hỏi không nói rõ rằng số nguyên phải có ^\d+$. Và JS không coi NaNlà một con số. Bạn có thể nhân nó với một số, thêm, chia, trừ giống như với số. Nó là một thuộc tính đặc biệt của JavaScript. Không có hại trong việc sử dụng nó. Đó là những gì chúng ta gọi là bẻ cong các quy tắc ;)
Gaurang Tandon

1
Tôi có thể sử dụng Object.is()và khẳng định đó vẫn là một vụ va chạm
user2428118

1
@ user2428118 Cảm ơn bạn đã mang Object.is đến với kiến ​​thức của tôi. Tôi không bao giờ biết điều đó. Nhưng tôi muốn bạn lưu ý rằng OP sử dụng toán tử đẳng thức ( ==) để so sánh, điều này sẽ đảm bảo không xảy ra xung đột băm cho bất kỳ chuỗi nào ngoài "CÓ" hoặc "KHÔNG".
Gaurang Tandon

2
Bỏ qua thực tế là khẳng định NaNkhông được tính là va chạm dường như giá rẻ, giải pháp này có va chạm với chuỗi NAthông qua NPYEQthông quaYET
nderscore

2

Con trăn 92

n=int("".join(map(str,map(ord,raw_input()))))    # hashing function
print n if 1+(n**2-904862*n)/7067329057 else-1   # input validation

Hàm băm kết hợp các giá trị thứ tự của các ký tự ASCII, câu lệnh in đảm bảo rằng hai đầu vào mong muốn va chạm.


2

ECMAScript 6 (30 byte)

Tôi đã cố gắng tránh việc gán biến, trả về và từ khóa hàm, và đây có vẻ là một cách tuyệt vời để tránh tất cả những điều vô nghĩa đó (theo cách nào đó cũng giống như lập trình chức năng). Không giống như các giải pháp khác, nó không phụ thuộc vào btoahoặc atob, không phải ECMAScript 6, mà là HTML5. 0+là cần thiết, vì vậy nó có thể phân tích các chuỗi tùy ý.

a=>parseInt(0+a,36)-852||43744

1
Đẹp! Tôi không biết họ đã thêm các căn cứ khác cho parseInt. Bạn có thể cắt rất nhiều byte mặc dù. :)a=>parseInt(0+a,36)-852||43744
nderscore

@nderscore: Cảm ơn bạn đã gợi ý. Nó thực sự cải thiện kịch bản của tôi rất nhiều.
Konrad Borowski

2

Java - 45 (hoặc 62?)

Tôi không biết làm thế nào để ghi điểm một cách công bằng với những gì người ta cần để chạy một chương trình trong Java, tôi có cần bao gồm định nghĩa hàm không? Hãy chỉnh sửa và điều chỉnh điểm số của tôi một cách thích hợp. Hiện tại tôi đang chấm điểm giống như câu trả lời @OldCurmudgeon. Thêm 17 int h(String t){}nếu cần thiết:

int h=t.hashCode();return h*h*3%1607172496;

Ungolfed với khai thác thử nghiệm:

import static org.junit.Assert.*;

import java.util.*;

import org.junit.Test;

public class YesNo {
  @Test
  public void testHashValue() {
    YesNo yesNo = new YesNo();
    Set<Integer> set = new HashSet<>();

    assertEquals(yesNo.hash("YES"), yesNo.hash("NO"));

    set.add(yesNo.hash(""));
    for(char i = 'A'; i <= 'Z'; i++) {
      set.add(yesNo.hash("" + i));
      for(char j = 'A'; j <= 'Z'; j++) {
        set.add(yesNo.hash("" + i + j));
        for(char k = 'A'; k <= 'Z'; k++) {
          set.add(yesNo.hash("" + i + j + k));
        }
      }
    }
    assertEquals(18278, set.size());
  }

  int hash(String toHash) {
    int hashValue=toHash.hashCode();
    return hashValue*hashValue*3%1607172496;
  }
}

1

Và người lỏng lẻo là ...

Băng tải, 145 ký tự

 I
>#<
 26*)2**\88
 >========*
 ^    \ \+-
 ^=====#==<
5**222P:
5======<
5***26*)*(\P\:@e25*:*)4*,F
>==============#=========
             P,F

Về cơ bản chương trình này thực hiện một số loại cơ sở 26 điều trên ký tự. Sau đó, nó kiểm tra xem hàm băm có bằng 12999 (Mã băm của CÓ) không và nếu có in 404 (mã băm của NO), thì nó sẽ chỉ in mã băm.

Băng tải là ngôn ngữ do tôi tạo ra hiện đang ở giai đoạn beta nhưng một trình thông dịch cùng với một số ví dụ và mã nguồn có thể được tìm thấy ở đây: https://github.com/loovjo/Conveyor


0

C # 4,5 (112 byte)

int h(string s){int code=s.Select((v,i)=>((int)v)<<(2*(i-1))).Sum();return(code|1073742225)|(code|-2147483569);}

Phiên bản làm việc (?) Của nỗ lực của ngầm, trong C #. Kết hợp các byte trong chuỗi thành một số nguyên 32 bit (chỉ hoạt động tối đa 4 ký tự), sau đó OR kết quả so với kết quả tương ứng là "CÓ" và "KHÔNG", sau đó OR kết hợp chúng lại với nhau.

Mặc dù có thể va chạm vào một lúc nào đó, nhưng điều đó không xảy ra đối với bất kỳ ^ [AZ] {2,3} $ nào ngoài "CÓ" và "KHÔNG".


Hàm băm của bạn sẽ có nhiều va chạm hơn. "Hàm băm" của bạn về cơ bản là bỏ qua nhiều bit trong phần ghép. Tất cả các cặp chuỗi chỉ khác nhau trong các bit đó sẽ có cùng mã băm.
Paŭlo Ebermann

0

Không có bình luận - 31 (nội dung chức năng: 26)

'=|*==|,,|+|"#|[|,  |+|-%3|]*|:

Giải pháp khá đơn giản. ;) Hoạt động cho bất kỳ và tất cả các chuỗi UTF-8.

GIẢI THÍCH: ' rõ ràng là chức năng. Đầu tiên, nó kiểm tra xem *(đầu vào của nó) có bằng |,,|+|"#|( |NO|) không. Nếu có, nó trả về |, |+|-%3|( |YES|) - nếu không, nó chỉ trả về *.


2
Tôi chưa bao giờ làm việc với Không có Nhận xét, bạn có thể giải thích giải pháp của mình như thường được thực hiện với các câu trả lời Golfscript, J hoặc APL không?
Kaya

@Kaya Ồ, vâng, xin lỗi, tôi sẽ chỉnh sửa bài viết.
cjfaure

1
Không có lời xin lỗi cần thiết, tôi chỉ tò mò làm thế nào nó hoạt động.
Kaya

0

C 54

h(char *c){int d=*(int*)c-20302;return d*(d-5436939);}

Chuyển đổi chuỗi thành số nguyên - "KHÔNG" và nhân số đó với cùng một giá trị + "KHÔNG" - "CÓ" để lấy 0 cho "KHÔNG" và "CÓ" và khác không cho bất kỳ chuỗi nào khác trong phạm vi được chỉ định.

Tất cả các giá trị trên máy Windows 7 nếu có bất kỳ mối quan tâm cuối cùng nào.



-1

Cà phê - 36

Phải trả lại 1cho YESNO, và bất cứ điều gì vô nghĩa bị cắt xén atobsản xuất cho tất cả mọi thứ khác mà không phải là một chuỗi base64.

h=(s)->_=atob s;_ in["`D","4"]&&1||_

Tương đương JavaScript ( không phải mã JS từ trình biên dịch CS):

function h( s ) {
    var _ = atob( s );

    if( _ === "`D" || _ === "4" )
        return 1;
    else
        return _;
}

3
"Hàm nên có giá trị trả về số nguyên" - Tôi cho rằng hàm của bạn trả về _khi đầu vào không phải là "CÓ" hoặc "KHÔNG".
Gaurang Tandon

-1

Đây là một siêu khập khiễng. VÌ VẬY NÓ KHÔNG LÀM VIỆC

Python 2.7 - 79 byte

def h(s):n=sum(100**i*ord(c)for i,c in enumerate(s));return (n-7978)*(n-836989)

Đầu tiên chúng ta nhận được tổng (giá trị ascii của mỗi ký tự) * 100 ^ (vị trí của ký tự đó trong chuỗi). Sau đó, chúng tôi nhân (kết quả đó - 7978) và (kết quả đó - 836989) để có câu trả lời cuối cùng. 7978 và 836989 là kết quả cho "CÓ" và "KHÔNG" của bit đầu tiên, vì vậy, với CÓ và KHÔNG, chúng tôi nhân với 0.

Điều này không nên có bất kỳ va chạm? Tôi không cảm thấy muốn thử nghiệm với 18000 mẫu phản ứng có thể xảy ra, nhưng nếu có một vụ va chạm ngoài ý muốn, tôi có thể ném thêm 0 vào đó 100và sau đó thực sự không nên có bất kỳ va chạm nào.

Thất vọng vì tôi không thể sử dụng một lambdacho việc này, nhưng tôi không muốn thực hiện toàn bộ phép tính hai lần nên tôi phải lưu nó vào một biến.

Xin đừng để chiến thắng này. Đó là siêu khập khiễng và tôi không xứng đáng.


Không đáp ứng yêu cầu "không có va chạm khác": Chỉ có 18012 băm duy nhất trong số chuỗi 18277 không nên có va chạm.
dan04

@ Dan Chết tiệt, cho tôi một giây
undergroundmonorail

1
@dan Tôi không thể làm cho nó hoạt động. Có lẽ có một cái gì đó vốn đã sai với thuật toán. Tôi không muốn xóa nó vì có người khác có thể biết có gì sai, nhưng tôi sẽ đưa ra một lưu ý
undergroundmonorail

Điều này hoạt động với tôi, h = lambda s: (hash (s) +997192582) * (hash (s) -480644903)
Lucas

như đã xác định hàm băm tương tự như hàm của bạn nhưng với 99 ** i * int (c, 36)
Lucas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.