Mettre en œuvre un hachage de longueur variable

10

Mon ami et moi avons ce jeu que nous jouons avec des mots. C'est un passe-temps amusant et cela implique "d'annuler" les lettres d'un mot jusqu'à ce qu'il ne reste plus rien. Je suis vraiment fatigué qu'il soit tellement plus rapide que moi, donc c'est votre travail de le mettre en œuvre et de me laisser enfin le battre. Évidemment, puisque je dois rendre le programme aussi facile à cacher que possible, il doit être aussi petit que possible.

Comment fonctionne ce jeu?

Le jeu est un algorithme assez simple. Il réduit une chaîne alphabétique jusqu'à ce qu'elle ne puisse plus être réduite, ce qui en fait une sorte de hachage. Le jeu réel que nous, les humains, sommes très difficiles à implémenter, mais il peut être simplifié dans l'algorithme suivant:

Vous commencez par plier l'alphabet en deux et aligner les deux pièces comme ceci:

a b c d e f g h i j k l m
z y x w v u t s r p q o n

Ensuite, en partant du milieu, vous affectez les entiers positifs à la moitié supérieure et les négatifs au bas:

a  b  c  d  e f g h i j k l m
13 12 11 10 9 8 7 6 5 4 3 2 1

z   y   x   w   v  u  t  s  r  p  q  o  n
-13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1

Ensuite, vous prenez votre chaîne (nous utiliserons hello world) et en ignorant tous les caractères non alphabétiques, traduisez-la:

h e l l  o w   o  r  l d
6 9 2 2 -2 -10 -2 -5 2 10

Ensuite, vous additionnez les valeurs des lettres. Ceux qui étaient alignés dans le diagramme précédent (par exemple, det w, let o) seront annulés, tandis que les autres s'additionneront.

sum(6 9 2 2 -2 -10 -2 -5 2 10 )=12

12 est le nombre pour b, donc le hachage de hello worldestb

Pour un mot qui annule complètement (par exemple love), vous sortie le « 0 caractère »: -. Notez que dans l'entrée, -sera toujours ignoré. Cela n'a d'importance que dans la sortie.

Si l'ampleur du nombre est supérieur à 13, alors vous commencez à doubler sur les a« s et z» s vous prenez essentiellement autant a« s ou zd » ajustement dans le nombre et prendre tout ce qui est à gauche dans la dernière lettre comme ceci:

code golf: 43.

Convient à 3 aet il en reste 4:

aaa 4: j
result: aaaj

Astuce: Cette partie est fondamentalement divmodsauf qu'elle arrondit vers zéro, non -infinity(par exemple -43 deviendrait 3 zet et a -4qui est painsi zzzp).

Remarque: le tiret ne vient pas si le a«ou z» s'intègre parfaitement, seulement s'il est exact 0.

Clarifications:

  • Le hachage est cas dans sensible
  • Les échappatoires standard ne sont pas autorisées
  • Les E / S peuvent être dans n'importe quel format qui n'est pas trop bizarre, stdin, stdout, arg en ligne de commande, fonction, etc.
  • Il s'agit de donc la taille la plus courte en octets l' emporte.

Exemples:

hello world  -->  b

love  -->  -

this is an example -->  aak

hello *&*(&(*&%& world  -->  b

good bye --> ae

root users --> zzs
Maltysen
la source
3
loveest vide ...
Justin

Réponses:

4

CJam, 46 octets

Essayez-le en ligne , ou essayez la suite de tests en ligne .

lel{'n-_W>+_zE<*}%:+{_De<C~e>___0>-'n+'-?o-}h;

Explication

L'algorithme fonctionne comme vous pouvez vous y attendre: lisez l'entrée, convertissez-la en minuscules, mappez chaque caractère à une valeur, additionnez les valeurs et imprimez les caractères et ajustez la somme en conséquence jusqu'à ce que la somme soit nulle. L'optimisation probablement la plus intéressante (bien qu'elle n'économise que deux octets) est que les mappages de caractères annulés sont utilisés à la place, car cela évite d'échanger les arguments de soustraction pour corriger le signe lors du calcul de la valeur mappée et évite de les échanger à nouveau lors du mappage vers une lettre en raison de la la soustraction d'une valeur négative pouvant être remplacée par l'addition.

lel             "Read a line of input and convert all letters to lowercase.";
{               "Map each character:";
  'n-_W>+         "Map each character to its negated value by subtracting 'n'
                   and incrementing if the result is nonnegative.";
  _zE<*           "If the value is out of the letter range, use 0 instead.";
}%
:+              "Compute the sum of the mapped character values.";
{               "Do...";
  _De<C~e>        "Compute the sum clamped to the letter range.";
  __              "If the clamped sum is nonzero, ...";
  _0>-'n+         "... then produce the clamped sum mapped back to a letter by
                     decrementing if it is positive and adding 'n', ...";
  '-              "... else produce '-'.";
  ?
  o               "Output the character produced above.";
  -               "Subtract the clamped sum out of the sum.";
}h              "... while the sum is nonzero.";
;               "Clean up.";
Runer112
la source
4

Pyth, 79 78 77 65 61 58

J+\-GK+0fTr13_14=ZsX@JzJKMe,pk*G/H13%H13@JxK?g\aZ>Z0_g\z_Z
orlp
la source
Vous pouvez utiliser @Jzau lieu de f}YJzIl y en a probablement plus, mais je dois dormir maintenant. Bonne chance;)
FryAmTheEggman
@FryAmTheEggman Cool, je n'étais pas au courant de l'intersection de @!
orlp
2

Extrait 10 , 87

Fr+`m[y?cAyg#Ay-v,-RRZ]0]}m.U`[Fx?x?<x0,:-/xR'z*m'm%xR!!%xR],:/xR'a*m'n%xR!!%xR]]'-[R13
Ypnypn
la source
1

R, 258 octets

function(s){a=13;r=data.frame;z=strsplit(gsub("[^a-z]","",tolower(s)),"")[[1]];d=r(l=rev(letters),h=c(-1*a:1,1:a));m=merge(r(l=z),d);n=sum(m$h);q=abs(n);v=rep(ifelse(n>0,"a","z"),q%/%a);paste0(paste(v,collapse=""),d$l[d$h==sign(n)*q%%a],ifelse(n==0,"-",""))}

Ce doit être le code R le plus grossier de tous les temps. J'ai pensé que R pourrait être un choix décent car il a un vecteur de toutes les lettres "a" à "z" comme variable globale intégrée. Mais il s'avère que le reste est un gâchis.

Non golfé + explication:

function(s) {
    a <- 13              # Store the value associated with a
    r <- data.frame      # Store the `data.frame` function

    # Split the input into a vector, ignoring case and non-letters
    z <- strsplit(gsub("[^a-z]", "", tolower(s)), "")[[1]]

    # Create a data frame where the first column is the letters
    # z through a and the second is the associated scores
    d <- data.frame(l=reverse(letters), h=c(-1*a:1, 1:a))

    # Merge the split vector with the data frame of scores
    m <- merge(data.frame(l=z), d)

    # Get the total score for the input
    n <- sum(m$h)
    q <- abs(n)

    # Pad the output with a or z as necessary
    v <- rep(ifelse(n > 0, "a", "z"), q %/% a)

    # Collapse the vector of a's or z's into a string
    out1 <- paste(v, collapse="")

    # Look up the letter associated with remainder
    out2 <- d$l[d$h == sign(n)*q%%a]

    # If n = 0, we still want a dash
    out3 <- ifelse(n == 0, "-", "")

    # Return the concatenation of all pieces of the output
    paste0(out1, out2, out3)
}

Cela crée un objet fonction sans nom qui accepte une chaîne en entrée et renvoie la valeur de hachage associée. Pour l'appeler, donnez-lui un nom, par exemplef=function(s){...} .

Exemples:

> f("this is an example")
[1] "aak"

> f("root users")
[1] "zzs"

> f("love")
[1] "-"

> f("People like grapes.")
[1] "aaag"

Essayez-le en ligne!

Des questions? Je serai ravi de fournir toute autre explication. Suggestions? Les suggestions sont les bienvenues!

Alex A.
la source
1

Haskell, 171 octets

import Data.Char
m=13
l=zip['a'..'z'][-i|i<-[-m..m],i/=0]
p 0="-"
p n|n>m='a':p(n-m)|n<(-m)='z':p(n+m)|1<2=[c|(c,i)<-l,i==n]
f n=p$sum[y|Just y<-[lookup(toLower x)l|x<-n]]

Essai:

> map f ["hello world", "love", "this is an example", "hello *&*(&(*&%& world", "good bye", "root users"]
["b","-","aak","b","ae","zzs"]

Comment ça marche: lest une table de recherche de lettres à la valeur correspondante. Recherchez tous les caractères de la chaîne d'entrée et jetez ceux qui ne sont pas trouvés. Additionnez la liste résultante. En fonction de la somme des pimpressions -ou peut-être d'abord des as ou des zs et enfin des recherches (inversées) de la lettre l.

nimi
la source
1

R - 200

function(s){l=letters
N=setNames
x=strsplit(tolower(s),'')[[1]]
n=(13:-13)[-14]
v=sum(N(n,l)[x[x%in%l]])
o=''
while(v){d=min(max(v,-13),13)
o=paste0(o,N(l,n)[as.character(d)])
v=v-d}
if(o=='')o='-'
o}
flodel
la source
+1, certainement mieux que ma réponse R. Bon travail!
Alex A.