Реализуйте хэш переменной длины


10

У меня и моего друга есть эта игра, в которую мы играем словами. Это забавное времяпрепровождение, и оно включает в себя «отмену» букв в слове, пока ничего не останется. Я действительно устал от того, что он намного быстрее меня, поэтому твоя задача - реализовать это и позволить мне наконец победить его. Очевидно, что поскольку я должен сделать программу максимально простой для скрытия, она должна быть как можно меньше.

Как работает эта игра?

В игре довольно простой алгоритм. Он сокращает алфавитную строку до тех пор, пока ее нельзя будет уменьшить, что делает его своего рода хэшем. Реальную игру, которую мы, люди, делаем, очень сложно реализовать, но ее можно упростить до следующего алгоритма:

Вы начинаете с того, что складываете алфавит пополам и выстраиваете две части так:

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

Затем, начиная с середины, вы присваиваете положительные целые числа верхней половине, а отрицательные - нижней:

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

Затем вы берете свою строку (мы будем использовать hello world) и, игнорируя любые не алфавитные символы, переводим ее:

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

Затем вы суммируете значения букв. Те, которые выстроились на предыдущей диаграмме (например, dи w, lи o), отменится, а остальные добавят.

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

12 это номер b, так что хэш hello worldISb

Для слова , которые полностью уравновешивает (например love), то вывести «0 символ»: -. Обратите внимание, что при вводе -все равно будет игнорироваться. Это имеет значение только на выходе.

Если величина числа больше 13, то вы начинаете удваивать числа a«и z». Вы в основном берете столько же aили z«вписывается» в число и берете все, что осталось в последней букве, например:

code golf: 43.

Подходит 3 aи 4 осталось:

aaa 4: j
result: aaaj

Подсказка: эта часть в основном divmodза исключением того, что она округляется до нуля, а не -infinity(например, -43 станет 3 z-х, а a -4- это pтак zzzp).

Примечание: черточка не появляется, если она aили zвписывается идеально, только если это точно 0.

Разъяснения:

  • Хэш регистр в чувствительном
  • Стандартные лазейки не допускаются
  • Ввод / вывод может быть в любом не слишком странном формате: стандартный ввод, стандартный вывод, аргумент командной строки, функция и т. Д.
  • Это поэтому выигрывает самый короткий размер в байтах .

Примеры:

hello world  -->  b

love  -->  -

this is an example -->  aak

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

good bye --> ae

root users --> zzs

3
loveпусто ...
Джастин

Ответы:


4

CJam, 46 байтов

Попробуйте онлайн или попробуйте набор тестов онлайн .

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

объяснение

Алгоритм работает так, как вы могли бы ожидать: читать ввод, преобразовывать в нижний регистр, отображать каждый символ в значение, суммировать значения и печатать символы и корректировать сумму соответственно, пока сумма не станет равной нулю. Вероятно, наиболее интересная оптимизация (хотя она сохраняет только два байта) заключается в том, что вместо этого используются сопоставления с отрицательными символами, поскольку это позволяет избежать замены аргументов вычитания для исправления знака при вычислении отображенного значения и избежать замены снова при отображении обратно на букву из-за вычитание отрицательного значения, заменяемого сложением.

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

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

Вы можете использовать @Jzвместо f}YJzТам, вероятно, больше, но я должен спать сейчас. Удачи;)
FryAmTheEggman

@FryAmTheEggman Круто, я не знал о пересечении @!
2015 года


1

R, 258 байт

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,"-",""))}

Это должен быть самый грубый код R когда-либо. Я подумал, что R может быть достойным выбором, поскольку он имеет вектор всех букв от «а» до «z» в качестве встроенной глобальной переменной. Но оказывается, все остальное - беспорядок.

Ungolfed + объяснение:

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

Это создает безымянный объект функции, который принимает строку в качестве входных данных и возвращает соответствующее значение хеш-функции. Чтобы назвать его, дайте ему имя, например f=function(s){...}.

Примеры:

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

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

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

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

Попробуйте онлайн!

Вопросов? Я с радостью предоставлю дальнейшие объяснения. Предложения? Предложения более чем приветствуются!


1

Haskell, 171 байт

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

Тестовый забег:

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

Как это работает: lэто таблица поиска из букв на соответствующее значение. Найти все символы из входной строки и отбросить те, которые не найдены. Подведите итоговый список. В зависимости от суммы, которую вы pпечатаете, -или, может быть, сначала несколько as или zs и, наконец, (обратный) ищет букву l.


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}

+1, определенно лучше моего R ответа. Хорошо сделано!
Алекс А.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.