가변 길이 해시 구현


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

그런 다음 글자 값을 합산합니다. 이전 다이어그램에서 정렬 된 항목 (예 : dw, lo)은 취소되고 다른 다이어그램 은 추가됩니다.

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

의 수는 12 b이므로 해시 hello worldb

완전히 취소 된 단어 (예 :)의 love경우 "0 character"를 출력합니다 -. 입력에서 -여전히 무시됩니다. 출력에서만 중요합니다.

숫자의 크기가 13보다 크면 a의 및에서 두 배로 증가하기 시작합니다. z기본적으로 숫자에 많은 수 a또는 z적합을 취하고 마지막 글자에 남은 모든 것을 다음과 같이 취합니다.

code golf: 43.

3에 맞고 a4 남음 :

aaa 4: j
result: aaaj

힌트 :이 부분은 기본적 divmod으로 0이 아닌 반올림을 제외하고 는 예외입니다 -infinity(예 : -43은 3이되고 za -4p그렇습니다 zzzp).

참고 : a의 또는 z이 완벽하게 맞으면 대시가 오지 않습니다 0.

설명 :

  • 해시는 대소 문자 구분합니다
  • 표준 허점 은 허용되지 않습니다
  • I / O는 너무 외설적이지 않고 stdin, stdout, 명령 줄 인수, 함수 등이 아닌 형식 일 수 있습니다.
  • 이것은 이므로 바이트 단위의 최단 크기가 이깁니다.

예 :

hello world  -->  b

love  -->  -

this is an example -->  aak

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

good bye --> ae

root users --> zzs

3
love비어 있습니다.
Justin

답변:


4

CJam, 46 바이트

온라인으로 시도 하거나 온라인 테스트 스위트를 사용해보십시오 .

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

설명

이 알고리즘은 예상대로 작동합니다. 입력을 읽고, 소문자로 변환하고, 각 문자를 값에 매핑하고, 값을 합한 후, 문자를 인쇄하고 합이 0이 될 때까지 합을 조정하십시오. 아마도 가장 흥미로운 최적화는 (두 바이트 만 절약하지만) 무시 된 문자 매핑이 대신 사용된다는 것입니다. 이는 매핑 된 값을 계산할 때 빼기 인수를 바꾸어 부호를 수정하고 문자로 다시 매핑 할 때 다시 스왑을 피하기 때문에 빼기 인수를 대신 사용한다는 것입니다. 부정 된 값의 뺄셈은 덧셈으로 대체 가능합니다.

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

피스, 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 Cool, 나는 교차로를 몰랐다 @!
orlp


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은 내장 전역 변수로 모든 문자 "a"부터 "z"까지의 벡터를 가지고 있기 때문에 적절한 선택이 될 수 있다고 생각했습니다. 그러나 나머지는 엉망입니다.

언 골프 + 설명 :

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

하스켈, 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인쇄 -또는 어쩌면 첫번째 일부 a의 또는 z마지막 s와 (리버스)에서 편지를 조회 l.


1

제 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 답변보다 확실히 낫습니다. 잘 했어!
Alex A.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.