可変長ハッシュを実装する


10

私の友人と私は言葉で遊ぶこのゲームを持っています。それは楽しい娯楽であり、言葉がなくなるまで文字を「キャンセル」することを含みます。私は彼が私よりもはるかに速いことに本当にうんざりしているので、それを実装して私が最終的に彼を倒すのはあなたの仕事です。明らかに、プログラムをできるだけ簡単に隠す必要があるので、できるだけ小さくする必要があります。

このゲームはどのように機能しますか?

ゲームはかなり単純なアルゴリズムです。アルファベット文字列は、それ以上削減できなくなるまで削減され、一種のハッシュになります。私たち人間が行う実際のゲームは実装が非常に困難ですが、次のアルゴリズムに簡略化できます。

まず、アルファベットを半分に折りたたみ、次のように2つの部分を並べます。

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

次に、文字の値を合計します。前の図で並んでいたもの(例:dwlo)はキャンセルされますが、その他は合計されます。

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

12 bはの数値なので、のハッシュhello worldb

完全に相殺される単語(たとえばlove)の場合、「0文字」を出力します-。なお、入力で-は無視されます。これは出力でのみ重要です。

数値の絶対値が13より大きい場合は、a'と'を2倍にしzます。基本的には、数値に 's a'またはz''がいくつあっても、最後の文字に残っているものはすべて次のようにします。

code golf: 43.

3に適合しa、4が残っています。

aaa 4: j
result: aaaj

ヒント:この部分は基本的にはdivmodゼロに向かって丸めることを除いて-infinity(たとえば、-43は3にzなり、a -4pそうなりますzzzp)。

注:a's z' または's'が完全に適合する場合、ダッシュは表示されません0。正確に適合する場合のみです。

明確化:

  • ハッシュは大文字小文字を区別します
  • 標準の抜け穴は許可されていません
  • I / Oは、風変わりではない、stdin、stdout、コマンドライン引数、関数などの任意の形式にすることができます。
  • これはので、バイト単位の最短サイズが優先されます

例:

hello world  -->  b

love  -->  -

this is an example -->  aak

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

good bye --> ae

root users --> zzs

3
loveis empty ...
Justin

回答:


4

CJam、46バイト

オンライン試す、テストスイートをオンラインで試してください

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

説明

アルゴリズムは期待どおりに機能します。入力を読み取り、小文字に変換し、各文字を値にマップし、値を合計し、文字を出力し、それに応じて合計がゼロになるまで合計を調整します。おそらく最も興味深い最適化(2バイトしか節約しない)は、代わりに否定文字マッピングが使用されることです。これにより、マップされた値を計算するときに減算引数をスワップして符号を修正することが回避され、否定値の減算は加算で置き換え可能です。

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クール、私は交差点を知りませんでした@
orlp 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には組み込みのグローバル変数として「a」から「z」までのすべての文字のベクトルがあるので、Rはまともな選択かもしれないと考えました。しかし、残りは混乱していることがわかりました。

非ゴルフ+説明:

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の回答よりも優れています。よくやった!
Alex A.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.