Thực hiện Hash chiều dài thay đổi


10

Bạn tôi và tôi có trò chơi này mà chúng tôi chơi với các từ. Đây là một trò tiêu khiển thú vị và nó liên quan đến việc "hủy bỏ" các chữ cái trong một từ cho đến khi không còn gì. Tôi thực sự mệt mỏi vì anh ta nhanh hơn tôi rất nhiều, vì vậy công việc của bạn là thực hiện nó và để tôi cuối cùng đánh bại anh ta. Rõ ràng, vì tôi phải làm cho chương trình dễ dàng che giấu nhất có thể, nó phải nhỏ nhất có thể.

Trò chơi này hoạt động như thế nào?

Trò chơi là một thuật toán khá đơn giản. Nó giảm một chuỗi chữ cái cho đến khi không thể giảm thêm nữa, do đó làm cho nó trở thành một loại băm. Trò chơi thực tế mà con người chúng ta làm rất khó thực hiện, nhưng nó có thể được đơn giản hóa thành thuật toán sau:

Bạn bắt đầu bằng cách gấp bảng chữ cái làm đôi và xếp thành hai mảnh như sau:

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

Sau đó, bắt đầu từ giữa, bạn gán các số nguyên dương cho nửa trên và âm ở dưới:

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

Sau đó, bạn lấy chuỗi của mình (chúng tôi sẽ sử dụng hello world) và bỏ qua mọi ký tự không theo thứ tự chữ cái, dịch nó:

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

Sau đó, bạn tổng hợp các giá trị chữ cái. Những người xếp hàng trong biểu đồ trước đó (ví dụ dw, lo) sẽ hủy bỏ ra, trong khi những người khác sẽ thêm lên.

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

12 là số cho b, vì vậy các hash của hello worldb

Đối với một từ hoàn toàn hủy bỏ (ví dụ love), bạn xuất "0 ký tự" : -. Lưu ý rằng trong đầu vào, -vẫn sẽ bị bỏ qua. Nó chỉ quan trọng trong đầu ra.

Nếu cường độ của số lớn hơn 13, thì bạn bắt đầu nhân đôi số acủa bạn và zvề cơ bản, bạn có thể lấy bao nhiêu số ahoặc zphù hợp với số đó và lấy bất cứ thứ gì còn lại trong chữ cái cuối cùng như vậy:

code golf: 43.

Phù hợp với 3 a'và có 4 trái:

aaa 4: j
result: aaaj

Gợi ý: Phần này về cơ bản divmodngoại trừ việc nó làm tròn về 0, không -infinity(ví dụ -43 sẽ trở thành 3 zvà một -4pnhư vậy zzzp).

Lưu ý: dấu gạch ngang không đến nếu a's hoặc z' s phù hợp trong một cách hoàn hảo, chỉ khi nó là chính xác 0.

Làm rõ:

  • Băm là trường hợp trong nhạy cảm
  • Lỗ hổng tiêu chuẩn không được phép
  • I / O có thể ở bất kỳ định dạng nào không quá xa lạ, stdin, stdout, dòng lệnh arg, hàm, v.v.
  • Đây là để kích thước ngắn nhất tính bằng byte thắng.

Ví dụ:

hello world  -->  b

love  -->  -

this is an example -->  aak

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

good bye --> ae

root users --> zzs

3
lovetrống rỗng ...
Justin

Câu trả lời:


4

CJam, 46 byte

Dùng thử trực tuyến hoặc thử bộ thử nghiệm trực tuyến .

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

Giải trình

Thuật toán hoạt động như bạn mong đợi: đọc đầu vào, chuyển đổi thành chữ thường, ánh xạ từng ký tự thành một giá trị, tính tổng các giá trị và in các ký tự và điều chỉnh tổng cho phù hợp cho đến khi tổng bằng không. Có lẽ tối ưu hóa thú vị nhất (mặc dù chỉ tiết kiệm được hai byte) là ánh xạ ký tự phủ định được sử dụng thay thế, vì điều này tránh hoán đổi các đối số phép trừ để sửa dấu hiệu khi tính toán giá trị ánh xạ và tránh hoán đổi lại khi ánh xạ trở lại một chữ cái do phép trừ của một giá trị phủ định có thể thay thế bằng phép cộng.

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

Kim tự tháp, 79 78 77 65 61 58

J+\-GK+0fTr13_14=ZsX@JzJKMe,pk*G/H13%H13@JxK?g\aZ>Z0_g\z_Z

Bạn có thể sử dụng @Jzthay vì f}YJzCó lẽ nhiều hơn, nhưng tôi phải ngủ bây giờ. Chúc may mắn;)
FryAmTheEggman

@FryAmTheEggman Thật tuyệt, tôi không biết về giao lộ của @!
orlp

2

Clip 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

1

R, 258 byte

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

Đây phải là mã R thô nhất từ ​​trước đến nay. Tôi cho rằng R có thể là một lựa chọn hợp lý vì nó có một vectơ gồm tất cả các chữ cái "a" đến "z" là một biến toàn cục tích hợp. Nhưng hóa ra phần còn lại là một mớ hỗn độn.

Ungolfed + giải thích:

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

Điều này tạo ra một đối tượng hàm không tên, chấp nhận một chuỗi làm đầu vào và trả về giá trị băm liên quan. Để gọi nó, đặt tên cho nó, vd f=function(s){...}.

Ví dụ:

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

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

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

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

Hãy thử trực tuyến!

Câu hỏi? Tôi sẽ vui vẻ cung cấp bất kỳ lời giải thích thêm. Gợi ý? Đề xuất được chào đón nhiều hơn!


1

Haskell, 171 byte

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

Chạy thử nghiệm:

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

Cách thức hoạt động: llà bảng tra cứu từ các chữ cái đến giá trị tương ứng. Tra cứu tất cả các ký tự từ chuỗi đầu vào và loại bỏ những ký tự không tìm thấy. Tổng hợp danh sách kết quả. Tùy thuộc vào tổng số pin -hoặc có thể đầu tiên một số as hoặc zs và cuối cùng (đảo ngược) tìm kiếm chữ cái từ 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, chắc chắn tốt hơn câu trả lời R của tôi. Công việc tốt đẹp!
Alex A.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.