Colisão de hash: "NÃO" significa "SIM"


63

Este Code Golf foi inspirado no recente artigo do Daily WTF, You Can't Handle the True! , que apresenta uma comparação de cadeias escrita como:

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

Imagine o problema que teria causado à equipe de Steve se o String.hashCodemétodo de Java fosse implementado de uma maneira assim "YES".hashCode() == "NO".hashCode(). Então, o desafio que proponho aqui é:

Escreva, no menor número de caracteres possível, uma função hash (eu a chamarei h) com um parâmetro de string e um valor de retorno inteiro, de modo que h("YES")seja igual a h("NO").

Obviamente, isso seria trivial para uma função como def h(s): return 0, que faz uma colisão de hash para cada string. Para tornar esse desafio mais interessante, você deve respeitar a seguinte regra adicional:

Dos outros 18 277 cordas possíveis constituídos por três ou menos letras maiúsculas (ASCII ^[A-Z]{0,3}$), deve haver nenhum colisões de hash.

Esclarecimento (apontado por Heiko Oberdiek): A sequência de entrada pode conter caracteres diferentes de A-Z, e seu código deve ser capaz de hash seqüências arbitrárias. (No entanto, você pode supor que a entrada seja uma cadeia de caracteres em vez de um ponteiro nulo ou um objeto de outro tipo de dados.) No entanto, não importa qual é o valor de retorno para cadeias que não coincidem ^[A-Z]{0,3}$, desde que é um número inteiro.

Além disso, ofuscar a intenção desta função:

Seu código não deve incluir nenhuma das letras 'Y', 'E', 'S', 'N' ou 'O' (em maiúsculas ou minúsculas) entre caracteres literais ou caracteres.

Claro, esta restrição não se aplica ao idioma palavras-chave, assim else, return, etc. são muito bem.


4
Isso não ajuda em nada que ainda possamos usar os valores numéricos ASCII YESNOpara verificar esta exceção específica.
Joe Z.

11
Lendo o artigo não não se lembra do "por razões de" comic: threewordphrase.com/pardonme.gif
Antonio Ragagnin

Respostas:


7

GolfScript: 19 caracteres (24 caracteres para a função nomeada)

26base.2107=59934*+

Este é o corpo da função. A atribuição a uma função nomeada hleva mais cinco caracteres:

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

(O ponto e vírgula final pode ser omitido, se você não se importa de deixar uma cópia do código na pilha.)

O núcleo da função hash é 26base, que calcula a soma (26 n - k · um k ; k = 1 .. n ), onde n é o número de caracteres na entrada e um k indica o código ASCII do k -ésimo caractere de entrada. Para entradas que consistem em letras ASCII maiúsculas, essa é uma função de hash sem colisão. O restante do código compara o resultado a 2107 (o código hash de NO) e, se forem iguais, adiciona 59934 para gerar 2701 + 59934 = 62041, o código hash de YES.

Por exemplo, saída, consulte esta demonstração online com casos de teste.


Como você testou isso? Acabei de encontrar um monte de colisões . Exemplo: h('DXP') == h('KK') == 65884.
Nneonneo

(Python equivalente ao que você escreveu, para os meus fins de teste: lambda w:sum(ord(c)*26**i for i,c in enumerate(reversed(w*9)))%102983)
nneonneo

@nneonneo: Obviamente, não o suficiente. Eu pensei que eu gerei o conjunto completo de três letras ou menos entradas, hash todos eles e verifiquei que o conjunto de hashes tinha um elemento menor do que o conjunto de entradas. Claramente, meu equipamento de teste tinha um bug em algum lugar. :-( Vou reverter para a versão original de 19 caracteres até / a menos que eu possa consertar a versão mais curta.
Ilmari Karonen

54

Python de 32 bits 2.x (19)

hash(w*9)%537105043

O RSA usa um módulo semiprime, e isso o torna seguro; portanto, usar um com meu algoritmo de hash certamente deve torná-lo ainda melhor! 1 1

Esta é uma função matemática pura, funciona para todas as strings (inferno, funciona para qualquer objeto Python hashável) e não contém condicionais ou letras especiais! 32-bit Python geralmente pode ser chamado como python-32na maioria dos sistemas que têm ambos instalados 2 .

Eu testei isso e ele retorna 18.278 valores diferentes para as 18.279 seqüências de letras maiúsculas ou menos de 3 letras. Atribuir isso a uma função leva mais 11 bytes:

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

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

Python de 64 bits 2.x (19)

hash(w*2)%105706823

O mesmo acordo que acima.


Para chegar a esses números, um pouco de matemática modular foi usada. Eu estava procurando por uma função fe um módulo ncomo esse hash(f('YES')) % n == hash(f('NO')) % n. Isso é equivalente ao teste que ndivide d = hash(f('YES')) - hash(f('NO')), ou seja, só precisamos verificar os fatores de dpara valores adequados de n.

O ideal né cerca de 20.000 ** 2 para reduzir a chance de uma colisão de paradoxos no aniversário. Encontrar um adequado nacaba por ser um pouco de tentativa e erro, jogando com todos os fatores d(geralmente não existem muitos) e diferentes opções para a função f. Observe, porém, que a tentativa e o erro são necessários apenas porque eu queria fazer no menor possível (para jogar golfe). Se isso não fosse um requisito, eu poderia apenas escolher dcomo meu módulo, que geralmente é suficientemente grande.

Observe também que você não pode fazer esse truque usando just f(s) = s(a função de identidade) porque o caractere mais à direita da string tem essencialmente um relacionamento linear (na verdade, um XORrelacionamento) com o hash final (os outros caracteres contribuem de uma maneira muito mais não-linear) ) A repetição da sequência garante, portanto, que as diferenças entre as sequências sejam amplificadas para eliminar o efeito de alterar apenas o caractere mais à direita.


1 Isso é um absurdo de patentes.
O hash de cadeia de caracteres 2 Python depende da versão principal (2 vs 3) e bitness (32 bits vs 64 bits). Não depende da plataforma AFAIK.


Você tem meu voto. : D
cjfaure

Infelizmente, isso não funciona nas versões recentes do Python devido ao novo recurso de randomização de hash.
dan04

@ dan04: Estranho, eu pensei que tinha especificado que isso era apenas para Python 2.x. Eu editei novamente.
Nneonneo

Posso saber como você encontrou esses números mágicos? Eu vejo que hash('YES'*9)tem 34876679como fator, enquanto que hash('NO'*9)tem 34876679+537105043como fator. Mas como você sabia que esse 537105043era um bom módulo? ou seja, não fez outras colisões?
Antonio Ragagnin

@AntonioRagagnin: Adicionado isso à resposta.
N

38

Perl, 53 49 40 bytes

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

Teste:

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

Os valores de hash para YESe NOsão os mesmos e existem 18279 seqüências de caracteres ^[A-Z]{0,3}$, livres de colisão, exceto a única colisão para YESe NO.

Ungolfed:

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

Versão antiga, 49 bytes

Como o novo algoritmo é um pouco diferente, eu mantenho a versão antiga.

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

Teste:

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

Ungolfed:

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

Editar% s:

  • Usar "\0"como byte de preenchimento economiza 4 bytes em comparação com $".

De onde vem 5457241e 20047vem? Como você calcula esses números? Desde já, obrigado.
AL

@ n.1: YESem hexadecimal é 594553. 0x594553 = 5850451. NOem hexadecimal é 4e4f. 0x4e4f = 20047.
nneonneo 26/04

7

Python: 63

Uma solução incrivelmente ruim:

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

Ele funciona interpretando seqüências alfanuméricas como números da base 36 e retornando 0 para todo o resto. Há um caso especial explícito para verificar o valor de retorno 852 (NO) e retornar 44596 (YES).


3
A menos que eu entenda errado: é código de golfe, você pode assumir que a entrada é precisa. Você pode abandonar try:e toda a terceira linha. Você também pode salvar algumas mordidas por ter cada linha lógica na mesma linha real, separados por ponto e vírgula ( def h(s):r=int(s,36);return(r,44596)[r==852])
undergroundmonorail

11
@undergroundmonorail: O parâmetro string para a função hash não é restrito na pergunta. Para uma determinada classe de seqüências de caracteres (até três letras maiúsculas), há uma restrição em relação aos valores de retorno da função hash. No entanto, não importa, o que é retornado para outras strings, se o valor de retorno for um número inteiro.
precisa saber é o seguinte

3
Eu gosto da indexação booleana de sua matriz lá
kratenko

6

Pure Bash, 29 bytes (corpo da função)

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

Isso simplesmente trata a sequência de entrada como um número base 36 e converte em decimal, depois lida com o NOcaso especial .

Resultado:

$ h A
10
$ h B
11
$ h CAT
15941
$ h NÃO
44596
$ h SIM
44596
$ h ZZZ
46655
$

5

Ruby, 51 bytes

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

código de teste:

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
}

resultado :

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

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

5

Javascript ( ES6 ) 54 bytes

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

Desenrolado:

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

Narrativa - para f(s) = BigInteger(s.getBytes()):

  • f("YES") xor f("NO") = 5835548
  • assim f("YES") xor 5835548 = f("NO")
  • Então f("YES") - (f("YES") xor 5835548) = f("NO") - (f("NO") xor 5835548)estou certo?

Você não pode incorporar o BigInteger?
Mafu

@mafutrct - SIM !!! Obrigado.
OldCurmudgeon

5

CJam, 15 bytes

q42b_*81991617%

Funciona como a solução GolfScript abaixo. Experimente online.


GolfScript, 17 bytes

42base.*81991617%

Essa abordagem baseia-se nas respostas de nneonneo e Ilmari Karonen .

Como funciona

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.

Escolhendo um algoritmo

Começamos com {b base}:h, ou seja, a string de entrada é considerada um número base-b. Contanto que b > 25, hseja inativo.

Temos uma colisão para as seqüências de caracteres "SIM" e "NÃO" se modificarmos hda seguinte maneira :, {x base n}:honde né um divisor de "YES" h "NO" h -.

Infelizmente, isso significa que também teremos uma colisão para, por exemplo, YETe NP. Para evitar isso, precisamos modificar o número da base-b de maneira não linear antes de executar o módulo.

A maneira mais curta de conseguir isso no GolfScript é multiplicar o número da base-b por si mesmo (por exemplo, ao quadrado). hé agora {base b .* n %}:h.

Tudo o que resta fazer é encontrar valores adequados para be n. Podemos fazer isso com força bruta:

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

Os menores valores possíveis para b nsão:

37 92176978
42 81991617

Testando

$ 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 caracteres (corpo da função de 33 caracteres)

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

Casos de teste:

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

Explicação:

Antes de mais, deixe-me apresentar-lhe NaN- "Não é um número" - em JavaScript. É um número:

typeof NaN  // number

Assim como:

typeof 42   // number

Sua propriedade especial é que nunca se iguala . Minha função retorna 1se a string for YESor NOe NaNpara qualquer outra string.

Portanto, isso não quebra as regras, porque não haveria colisão de hash para nenhuma outra string;) ( NaN !== NaNmostrada acima nos casos de teste).

E meu sonho se torna realidade: derrotar Bash, Perl e Ruby no tamanho do código!

Código Ungolfed:

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

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

Se esse valor for "WUVT"ou "Tk8=", retorne 1. Senão, voltar

+s // parseInt(s, 10)

o que seria NaN.


2
NaN pode ser um número, mas não é um "número inteiro" em nenhum sentido da palavra.
Paŭlo Ebermann

2
@ PaŭloEbermann No wiki , "Um número inteiro é um número escrito sem um componente fracionário". A questão não diz explicitamente que o número inteiro deve ser ^\d+$. E JS trata NaNcomo um número. Você pode multiplicá-lo por um número, adicionar, dividir, subtrair da mesma forma que com números. É uma propriedade especial do JavaScript. Não há mal nenhum em usá-lo. Isso é o que chamamos de flexão de regras ;)
Gaurang Tandon

11
Eu poderia usar Object.is()e alegar que ainda é uma colisão…
user2428118:

11
@ user2428118 Obrigado por trazer o Object.is ao meu conhecimento. Eu nunca soube disso. Mas gostaria que você observasse que o OP usa o operador de igualdade ( ==) para comparação, o que garantirá que não ocorra colisão de hash para nenhuma sequência além de "SIM" ou "NÃO".
Gaurang Tandon

2
Ignorando o fato de que alegando NaNnão conta como colisão parece barato, esta solução tem colisões com cordas NAatravés NPe YEQatravésYET
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

A função de hash concatena os valores ordinais dos caracteres ASCII, a instrução print garante que as duas entradas desejadas colidem.


2

ECMAScript 6 (30 bytes)

Tentei evitar a atribuição de variáveis, o retorno e a palavra-chave da função, e isso parece uma ótima maneira de evitar toda essa bobagem (também parece uma programação funcional, de certa forma). Diferente de outras soluções, ele não depende de btoaou atob, que não é o ECMAScript 6, mas o HTML5. 0+é necessário, para que ele possa analisar seqüências de caracteres arbitrárias.

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

11
Agradável! Eu não sabia que eles adicionaram outras bases para a análise. Você pode cortar muitos bytes embora. :)a=>parseInt(0+a,36)-852||43744
nderscore

@nderscore: Obrigado pela sugestão. Isso realmente melhorou muito meu script.
precisa saber é o seguinte

2

Java - 45 (ou 62?)

Não tenho ideia de como pontuar corretamente, considerando o que é necessário para executar um programa em Java, preciso incluir a definição de função? Sinta-se livre para editar e ajustar minha pontuação adequadamente. Atualmente, estou marcando da mesma maneira que a resposta @OldCurmudgeon. Adicione 17 int h(String t){}se for necessário:

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

Ungolfed with harness test:

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

E o mais frouxo é ...

Transportador, 145 caracteres

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

Basicamente, este programa faz algum tipo de base 26 nos caracteres. Depois disso, verifica se o hash é igual a 12999 (o código de hash de YES) e, se sim, imprime 404 (o código de hash de NO); caso contrário, ele apenas imprime o código de hash.

Transportador é uma linguagem feita por mim que está atualmente em estágios beta, mas um intérprete, juntamente com alguns exemplos e código fonte, pode ser encontrado aqui: https://github.com/loovjo/Conveyor


0

C # 4.5 (112 bytes)

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

Versão de trabalho (?) Da tentativa de undergroundmonorail, em C #. Concatiza os bytes na cadeia de caracteres em um número inteiro de 32 bits (funciona apenas até 4 caracteres), em seguida, ORs resulta no resultado de "YES" e "NO", respectivamente, e os ORs juntos.

Embora possa colidir em algum momento, isso não deve acontecer para nenhum ^ [AZ] {2,3} $ que não seja "SIM" e "NÃO".


Sua função hash terá muito mais colisões. Sua "função hash" está basicamente ignorando muitos bits na concatenação. Todos os pares de cadeias que diferem apenas nesses bits terão o mesmo código de hash.
Paŭlo Ebermann

0

Sem comentário - 31 (conteúdo da função: 26)

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

Solução bastante simples. ;) Funciona para toda e qualquer sequência UTF-8.

EXPLICAÇÃO: ' é, obviamente, a função. Primeiro, ele verifica se *(sua entrada) é igual a |,,|+|"#|( |NO|). Se for, ele retorna |, |+|-%3|( |YES|) - caso contrário, apenas retorna *.


2
Eu nunca trabalhei com No Comment, seria possível você explicar sua solução como costuma ser feito com respostas opacas da Golfscript, J ou APL?
Kaya

@Kaya Oh, sim, desculpe, eu vou editar o post.
Cjfaure

11
Sem desculpas necessárias, eu só estava curioso para saber como funcionava.
Kaya

0

C 54

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

Converta a string em número inteiro - "NO" e multiplique pelo mesmo valor + "NO" - "YES" para obter 0 para "NO" e "YES" e diferente de zero para qualquer outra string no intervalo especificado.

Todos os valores na máquina Windows 7, se houver alguma preocupação com endian.



-1

CoffeeScript - 36

Deve retornar 1para YESe NO, e qualquer absurdo ilusório que atobproduz para todo o resto que não seja uma string base64.

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

O equivalente a JavaScript ( não o código JS do compilador CS):

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

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

3
"A função deve ter um valor de retorno inteiro" - suponho que o seu retorne _quando a entrada não for "SIM" ou "NÃO".
Gaurang Tandon

-1

Aqui está um super manco. TÃO MANGA QUE NÃO FUNCIONA

Python 2.7 - 79 bytes

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

Primeiro, obtemos a soma de (valor ascii de cada caractere) * 100 ^ (posição desse caractere na string). Em seguida, multiplicamos (esse resultado - 7978) e (esse resultado - 836989) para obter nossa resposta final. 7978 e 836989 são os resultados para "SIM" e "NÃO" do primeiro bit, portanto, para SIM e NÃO, multiplicamos por 0.

Isso não deve ter colisões? Não me apetece testar contra 18000 possíveis contra-exemplos, mas, se houve uma colisão não intencional, posso dar outro 0 nisso 100e, na verdade , não deve haver colisão.

Desapontado por não poder usar um lambdapara isso, mas não queria fazer todo o cálculo duas vezes, então tive que salvá-lo em uma variável.

Por favor, não deixe isso vencer. É super manco e eu não mereço.


Não atende ao requisito "sem outras colisões": existem apenas 18012 hashes exclusivos do conjunto de 18277 cordas que não devem ter colisões.
dan04

@ Dan Droga, me dê um segundo
undergroundmonorail

11
@dan Eu não consigo fazê-lo funcionar. Talvez haja algo inerentemente errado com o algoritmo. Eu não quero excluí-lo porque alguém pode saber o que está errado, mas eu vou colocar uma nota
undergroundmonorail

Isso funciona para mim, h = lambda s: (haxixe (s) 997.192.582) * (de hash (s) -480644903)
Lucas

assim como definindo uma função hash semelhante ao seu mas com 99 ** i * int (C, 36)
Lucas
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.