Tabrakan hash: "TIDAK" berarti "YA"

63

Golf Kode ini terinspirasi oleh artikel Harian WTF, You Can't Handle the True! , yang menampilkan perbandingan string yang ditulis sebagai:

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

Bayangkan masalah yang akan ditimbulkan tim Steve jika String.hashCodemetode Java kebetulan diterapkan dengan cara seperti itu "YES".hashCode() == "NO".hashCode(). Jadi, tantangan yang saya usulkan di sini adalah:

Tulis, sesedikit mungkin karakter, fungsi hash (saya akan menyebutnya h) dengan parameter string dan nilai pengembalian integer, sehingga h("YES")sama dengan h("NO").

Tentu saja, ini akan sepele untuk dilakukan dengan fungsi seperti def h(s): return 0, yang membuat tabrakan hash untuk setiap string. Untuk membuat tantangan ini lebih menarik, Anda harus mematuhi aturan tambahan berikut:

Dari lain 18 277 string mungkin terdiri dari tiga atau lebih sedikit huruf ASCII huruf besar ( ^[A-Z]{0,3}$), harus ada ada tabrakan hash.

Klarifikasi (ditunjukkan oleh Heiko Oberdiek): String input dapat berisi karakter selain A-Z, dan kode Anda harus dapat hash string sewenang-wenang. (Anda dapat, bagaimanapun, menganggap bahwa input adalah string karakter daripada pointer nol atau objek dari beberapa tipe data lainnya.) Namun, tidak masalah apa nilai pengembalian untuk string yang tidak cocok ^[A-Z]{0,3}$, selama itu adalah bilangan bulat.

Selanjutnya, untuk mengaburkan maksud fungsi ini:

Kode Anda tidak boleh menyertakan huruf 'Y', 'E', 'S', 'N', atau 'O' (dalam huruf besar atau kecil) dalam karakter atau string literal.

Tentu saja, pembatasan ini tidak berlaku untuk kata kunci bahasa, sehingga else, return, dll baik-baik saja.

dan04
sumber
4
Agak tidak membantu bahwa kita masih dapat menggunakan nilai ASCII numerik YESNOuntuk memeriksa pengecualian khusus ini.
Joe Z.
1
Membaca artikel yang tidak dapat mengingat komik "karena alasan": threewordphrase.com/pardonme.gif
Antonio Ragagnin

Jawaban:

7

GolfScript: 19 karakter (24 karakter untuk fungsi bernama)

26base.2107=59934*+

Ini adalah fungsi tubuh. Menugaskannya ke fungsi bernama hmembutuhkan lima karakter lagi:

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

(Tanda titik koma terakhir dapat dihilangkan, jika Anda tidak keberatan meninggalkan salinan kode di tumpukan.)

Inti dari fungsi hash adalah 26base, yang menghitung jumlah (26 n - k · a k ; k = 1 .. n ), di mana n adalah jumlah karakter dalam input dan sebuah k menunjukkan kode ASCII dari k th karakter input. Untuk input yang terdiri dari huruf ASCII huruf besar, ini adalah fungsi hash bebas tabrakan. Sisa kode membandingkan hasilnya dengan 2107 (kode hash NO) dan, jika sama, menambah 59934 untuk menghasilkan 2701 + 59934 = 62041, kode hash YES.

Sebagai contoh keluaran, lihat demo online ini dengan test case.

Ilmari Karonen
sumber
Bagaimana Anda menguji ini? Saya baru saja menemukan banyak tabrakan . Contoh: h('DXP') == h('KK') == 65884.
nneonneo
(Python setara dengan apa yang Anda tulis, untuk tujuan pengujian saya: lambda w:sum(ord(c)*26**i for i,c in enumerate(reversed(w*9)))%102983)
nneonneo
@nneonneo: Jelas, tidak cukup baik. Saya pikir saya menghasilkan set lengkap input tiga huruf atau kurang, hash semua dan memeriksa bahwa set hash memiliki satu elemen kurang dari set input. Jelas, test harness saya memiliki bug di suatu tempat. :-( Saya akan kembali ke versi 19-char asli sampai / kecuali saya dapat memperbaiki yang lebih pendek.
Ilmari Karonen
54

32-bit Python 2.x (19)

hash(w*9)%537105043

RSA menggunakan modulus semiprime, dan itu membuatnya aman, jadi menggunakan satu dengan algoritma hash saya pasti akan membuatnya lebih baik! 1

Ini adalah fungsi matematika murni, bekerja untuk semua string (neraka, bekerja untuk objek Python hashable), dan tidak mengandung persyaratan atau casing khusus! 32-bit Python biasanya dapat disebut sebagai python-32pada kebanyakan sistem yang keduanya menginstal 2 .

Saya telah menguji ini, dan mengembalikan 18.278 nilai yang berbeda untuk string huruf besar 18.279 atau kurang. Menugaskan ini ke suatu fungsi membutuhkan 11 byte lebih:

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

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

64-bit Python 2.x (19)

hash(w*2)%105706823

Kesepakatan yang sama seperti di atas.


Untuk menghasilkan angka-angka ini, sedikit matematika modular digunakan. Saya sedang mencari fungsi fdan modulus nsedemikian rupa hash(f('YES')) % n == hash(f('NO')) % n. Ini setara dengan pengujian yang nmembagi d = hash(f('YES')) - hash(f('NO')), yaitu kita hanya perlu memeriksa faktor duntuk nilai yang sesuai n.

Yang ideal nada di sekitar 20000 ** 2 untuk mengurangi kemungkinan tabrakan paradoks ulang tahun. Menemukan yang cocok nternyata sedikit trial and error, bermain dengan semua faktor d(biasanya tidak banyak) dan pilihan yang berbeda untuk fungsi tersebut f. Perhatikan bahwa coba-coba hanya diperlukan karena saya ingin membuat nsekecil mungkin (untuk bermain golf). Jika itu bukan persyaratan, saya hanya bisa memilih dmodulus saya, yang biasanya cukup besar.

Perhatikan juga bahwa Anda tidak dapat melakukan trik ini hanya dengan menggunakan f(s) = s(fungsi identitas) karena karakter paling kanan dari string pada dasarnya memiliki hubungan linier (sebenarnya XORhubungan) dengan hash terakhir (karakter lain berkontribusi dalam cara yang jauh lebih nonlinear ). Oleh karena itu, pengulangan string memastikan bahwa perbedaan antara string diperkuat untuk menghilangkan efek mengubah hanya karakter paling kanan.


1 Ini omong kosong paten.
2 hashing string Python tergantung pada versi utama (2 vs 3) dan bitness (32-bit vs 64-bit). Itu tidak tergantung pada platform AFAIK.

nneonneo
sumber
Anda mendapat suara saya. : D
cjfaure
Sayangnya, ini tidak berfungsi pada versi terbaru Python karena fitur pengacakan hash baru.
dan04
@ dan04: Aneh, saya pikir saya telah menentukan bahwa ini hanya untuk Python 2.x. Saya sudah mengeditnya lagi.
nneonneo
Boleh saya tahu bagaimana Anda menemukan angka ajaib ini? Saya melihat hash('YES'*9)memiliki 34876679sebagai faktor, sementara hash('NO'*9)memiliki 34876679+537105043sebagai faktor. Tapi bagaimana Anda tahu 537105043itu modulus yang bagus? yaitu tidak membuat tabrakan lainnya?
Antonio Ragagnin
@AntonioRagagnin: Menambahkan itu ke jawabannya.
nneonneo
38

Perl, 53 49 40 byte

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

Uji:

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

Nilai hash untuk YESdan NOsama dan ada 18279 string ^[A-Z]{0,3}$, yang bebas benturan kecuali untuk satu-satunya tabrakan untuk YESdan NO.

Tidak Disatukan:

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";

Versi yang lebih lama, 49 byte

Karena algoritma baru sedikit berbeda, saya tetap menggunakan versi yang lama.

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

Uji:

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

Tidak Disatukan:

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".
}

Suntingan:

  • Menggunakan "\0"sebagai byte mengisi menghemat 4 byte dibandingkan dengan $".
Heiko Oberdiek
sumber
Di mana 5457241dan 20047berasal? Bagaimana Anda menghitung angka-angka ini? Terima kasih sebelumnya.
AL
@ n.1: YESdalam hex adalah 594553. 0x594553 = 5850451. NOdalam hex adalah 4e4f. 0x4e4f = 20047.
nneonneo
7

Python: 63

Solusi yang sangat timpang:

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

Ini bekerja dengan mengartikan string alfanumerik sebagai angka base-36, dan mengembalikan 0 untuk yang lainnya. Ada kasus khusus yang eksplisit untuk memeriksa nilai kembali 852 (TIDAK), dan mengembalikan 44596 (YA) sebagai gantinya.

dan04
sumber
3
Kecuali saya salah paham: Ini kode golf, Anda boleh berasumsi inputnya akurat. Anda dapat parit try:dan seluruh baris ketiga. Anda juga dapat menyimpan beberapa gigitan dengan membuat setiap baris logis pada baris aktual yang sama, dipisahkan oleh tanda titik koma ( def h(s):r=int(s,36);return(r,44596)[r==852])
undergroundmonorail
1
@undergroundmonorail: Parameter string untuk fungsi hash tidak dibatasi dalam pertanyaan. Untuk kelas string tertentu (hingga tiga huruf besar) ada batasan mengenai nilai kembali fungsi hash. Namun tidak masalah, apa yang dikembalikan untuk string lain, jika nilai kembali adalah bilangan bulat.
Heiko Oberdiek
3
Saya suka boolean-pengindeksan array Anda di sana
kratenko
6

Pure Bash, 29 byte (badan fungsi)

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

Ini hanya memperlakukan string input sebagai nomor basis 36 dan mengubahnya menjadi desimal, kemudian berurusan dengan NOcase khusus .

Keluaran:

$ h A
10
$ h B
11
$ h CAT
15941
$ h TIDAK
44596
$ h YA
44596
$ h ZZZ
46655
$
Trauma Digital
sumber
5

Ruby, 51 byte

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

kode pengujian:

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
}

keluaran:

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

tested 17576
duplicate : "YES" = "NO" (0)
onionpsy
sumber
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
nderscore
sumber
5

Jawa - 94 77

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

Belum dibuka:

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

Narasi - untuk f(s) = BigInteger(s.getBytes()):

  • f("YES") xor f("NO") = 5835548
  • Begitu f("YES") xor 5835548 = f("NO")
  • Jadi f("YES") - (f("YES") xor 5835548) = f("NO") - (f("NO") xor 5835548)saya benar?
OldCurmudgeon
sumber
Tidak bisakah Anda sebaris dengan BigInteger?
mafu
@mafutrct - YA !!! Terima kasih.
OldCurmudgeon
5

CJam, 15 byte

q42b_*81991617%

Berfungsi sebagai solusi GolfScript di bawah ini. Cobalah online.


GolfScript, 17 byte

42base.*81991617%

Pendekatan ini dibangun berdasarkan jawaban nneonneo dan Ilmari Karonen .

Bagaimana itu bekerja

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.

Memilih algoritma

Kita mulai dengan {b base}:h, yaitu, string input dianggap sebagai nomor basis-b. Selama b > 25, hadalah inyective.

Kami mendapatkan tabrakan untuk string "YA" dan "TIDAK" jika kami memodifikasi hdengan cara berikut:, di {x base n}:hmana nadalah pembagi "YES" h "NO" h -.

Sayangnya, ini berarti kami juga akan mendapatkan tabrakan untuk, misalnya, YETdan NP. Untuk mencegah hal ini, kita harus memodifikasi basa basis-b secara non-linear sebelum mengambil modulus.

Cara terpendek untuk mencapai hal ini dalam GolfScript adalah mengalikan nomor basis-b dengan dirinya sendiri (yaitu, mengkuadratkannya). hsekarang {base b .* n %}:h.

Yang harus dilakukan hanyalah menemukan nilai yang sesuai untuk bdan n. Kita bisa mencapai ini dengan kekerasan:

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
    }
}

Nilai terpendek yang mungkin untuk b nadalah:

37 92176978
42 81991617

Pengujian

$ 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
Dennis
sumber
3

JavaScript (ES6) - 38 karakter (33 fungsi char)

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

Kasus uji:

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

Penjelasan:

Pertama-tama, izinkan saya memperkenalkan Anda kepada NaN- "Bukan Angka" - dalam JavaScript. Ini nomor:

typeof NaN  // number

Seperti:

typeof 42   // number

Properti khususnya adalah bahwa ia tidak pernah sama dengan dirinya sendiri . Fungsi saya kembali 1jika string adalah YESatau NO, danNaN untuk string lainnya.

Jadi, ini tidak melanggar aturan, karena tidak akan ada tabrakan hash untuk string lain;) ( NaN !== NaN ditunjukkan di atas dalam kasus uji).

Dan impian saya menjadi kenyataan: mengalahkan Bash, Perl dan Ruby dalam kode panjangnya!

Kode Tidak Terkunci:

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

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

Jika nilai itu "WUVT"atau "Tk8=", kembali 1. Lain, kembali

+s // parseInt(s, 10)

yang akan menjadi NaN.

Gaurang Tandon
sumber
2
NaN mungkin angka, tetapi itu bukan "bilangan bulat" dalam arti kata.
Paŭlo Ebermann
2
@ PaŭloEbermann Dari wiki , "Integer adalah angka yang ditulis tanpa komponen fraksional". Pertanyaannya tidak secara eksplisit mengatakan bahwa bilangan bulat harus ^\d+$. Dan JS memperlakukan NaNsebagai angka. Anda dapat mengalikannya dengan angka, menambah, membagi, mengurangi seperti halnya dengan angka. Ini adalah properti khusus JavaScript. Tidak ada salahnya menggunakannya. Itulah yang kami sebut pelengkungan aturan ;)
Gaurang Tandon
1
Saya bisa menggunakan Object.is()dan mengklaim itu masih tabrakan ...
user2428118
1
@ user2428118 Terima kasih telah membawa Object.is sepengetahuan saya. Saya tidak pernah tahu itu. Tetapi saya ingin Anda perhatikan bahwa OP menggunakan operator kesetaraan ( ==) untuk perbandingan, yang akan menjamin tidak ada tabrakan hash untuk string apa pun selain "YA" atau "TIDAK".
Gaurang Tandon
2
Mengabaikan fakta bahwa klaim NaNtidak dianggap sebagai tabrakan tampaknya murah, solusi ini memiliki tabrakan dengan string NAmelalui NPdan YEQmelaluiYET
nderscore
2

Python 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

Fungsi hashing menyatukan nilai-nilai ordinal karakter ASCII, pernyataan cetak memastikan bahwa dua input yang diinginkan bertabrakan.

Kaya
sumber
2

ECMAScript 6 (30 byte)

Saya sudah mencoba menghindari penugasan variabel, pengembalian, dan kata kunci fungsi, dan ini terlihat seperti cara yang bagus untuk menghindari semua omong kosong itu (ini juga terlihat seperti pemrograman fungsional, dengan cara). Tidak seperti solusi lain, itu tidak bergantung pada btoaatau atob, yang bukan ECMAScript 6, tetapi HTML5. 0+diperlukan, sehingga bisa mengurai string sewenang-wenang.

a=>parseInt(0+a,36)-852||43744
Konrad Borowski
sumber
1
Bagus! Saya tidak tahu mereka menambahkan basis lain untuk parseInt. Anda dapat memotong banyak byte. :)a=>parseInt(0+a,36)-852||43744
nderscore
@nderscore: Terima kasih atas sarannya. Ini benar-benar meningkatkan skrip saya.
Konrad Borowski
2

Java - 45 (atau 62?)

Saya tidak tahu bagaimana cara menilai secara adil mengingat apa yang dibutuhkan seseorang untuk menjalankan suatu program di Jawa, apakah saya perlu memasukkan definisi fungsi? Merasa bebas untuk mengedit dan menyesuaikan skor saya dengan tepat. Saat ini saya mencetak dengan cara yang sama dengan jawaban @OldCurmudgeon. Tambahkan 17 int h(String t){}jika diperlukan:

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

Tidak diikat dengan test harness:

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;
  }
}
durron597
sumber
1

Dan yang lebih longgar adalah ...

Conveyor, 145 karakter

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

Pada dasarnya program ini melakukan beberapa hal berbasis 26 pada karakter. Setelah itu memeriksa apakah hash sama dengan 12999 (Kode hash YA) dan jika demikian cetak 404 (kode hash TIDAK), kalau tidak hash hanya akan mencetak kode hash.

Conveyor adalah bahasa yang dibuat oleh saya yang saat ini masih dalam tahap beta tetapi seorang juru bahasa beserta beberapa contoh dan kode sumber dapat ditemukan di sini: https://github.com/loovjo/Conveyor

Loovjo
sumber
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);}

Bekerja (?) Versi upayamonmon bawah tanah, dalam C #. Concats byte dalam string menjadi integer 32-bit (hanya bekerja hingga 4 karakter), lalu ATAU hasilnya terhadap hasil untuk "YA" dan "TIDAK" masing-masing, lalu ATAU yang bersama-sama.

Meskipun mungkin bertabrakan di beberapa titik, itu tidak boleh terjadi untuk ^ ^ [AZ] $ 2,2 selain $ "YA" dan "TIDAK".

Garandy
sumber
Fungsi hash Anda akan memiliki lebih banyak tabrakan. "Fungsi hash" Anda pada dasarnya mengabaikan banyak bit dalam rangkaian. Semua pasangan string yang hanya berbeda dalam bit tersebut akan memiliki kode hash yang sama.
Paŭlo Ebermann
0

Tidak Ada Komentar - 31 (konten fungsi: 26)

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

Solusi yang cukup sederhana. ;) Bekerja untuk semua dan semua string UTF-8.

PENJELASAN: ' jelas, fungsinya. Pertama, ia memeriksa apakah *(inputnya) sama dengan |,,|+|"#|( |NO|). Jika ya, ia mengembalikan |, |+|-%3|( |YES|) - jika tidak, ia hanya mengembalikan *.

cjfaure
sumber
2
Saya tidak pernah bekerja dengan No Comment, apakah mungkin bagi Anda untuk menjelaskan solusi Anda seperti yang sering dilakukan dengan jawaban Golfscript, J, atau APL yang buram?
Kaya
@Kaya Oh, ya, maaf, saya akan mengedit posting.
cjfaure
1
Tidak perlu minta maaf, saya hanya ingin tahu bagaimana cara kerjanya.
Kaya
0

C 54

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

Konversikan string ke integer - "TIDAK" dan kalikan dengan nilai yang sama + "TIDAK" - "YA" untuk mendapatkan 0 untuk "TIDAK" dan "YA" dan bukan-nol untuk string lain dalam rentang yang ditentukan.

Semua nilai pada mesin Windows 7 jika ada masalah endian.

Ahli alkimia
sumber
-1

CoffeeScript - 36

Harus kembali 1untuk YESdan NO, dan omong kosong kacau apa pun atobmenghasilkan untuk segala sesuatu yang bukan string base64.

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

Setara dengan JavaScript ( bukan kode JS dari kompiler CS):

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

    if( _ === "`D" || _ === "4" )
        return 1;
    else
        return _;
}
Tony Ellis
sumber
3
"Fungsi harus memiliki nilai pengembalian integer" - Saya kira Anda mengembalikan nilai _ketika input bukan "YA" atau "TIDAK".
Gaurang Tandon
-1

Ini yang super lumpuh. BEGITU LAME ITU TIDAK BEKERJA

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)

Pertama kita mendapatkan jumlah (nilai ascii masing-masing karakter) * 100 ^ (posisi karakter dalam string). Kemudian kita mengalikan (hasil itu - 7978) dan (hasil itu - 836989) untuk mendapatkan jawaban akhir kita. 7978 dan 836989 adalah hasil untuk "YA" dan "TIDAK" dari bit pertama, jadi untuk YA dan TIDAK kita mengalikan dengan 0.

Ini seharusnya tidak memiliki tabrakan? Saya tidak merasa ingin menguji terhadap 18000 contoh tandingan yang mungkin, tetapi jika ada tabrakan yang tidak disengaja saya bisa melempar 0 lagi pada itu 100dan kemudian benar-benar ada - tidak boleh ada tabrakan.

Kecewa karena saya tidak bisa menggunakan a lambda untuk ini, tetapi saya tidak ingin melakukan seluruh perhitungan dua kali jadi saya harus menyimpannya ke variabel.

Tolong jangan biarkan ini menang. Itu sangat timpang dan aku tidak pantas mendapatkannya.

monmon bawah tanah
sumber
Tidak memenuhi persyaratan "tidak ada tabrakan lainnya": Hanya ada 1.812 hash unik dari rangkaian 18277-string yang seharusnya tidak memiliki tabrakan.
dan04
@dan Damn, beri aku sebentar
undergroundmonorail
1
@dan aku tidak bisa membuatnya bekerja. Mungkin ada sesuatu yang salah dengan algoritma. Saya tidak ingin menghapusnya karena orang lain mungkin tahu apa yang salah, tetapi saya akan membuat catatan
undergroundmonorail
Ini bekerja untuk saya, h = lambda s: (hash (s) +997192582) * (hash (s) -480644903)
Lucas
seperti halnya mendefinisikan fungsi hash mirip dengan Anda tetapi dengan 99 ** i * int (c, 36)
Lucas