ใช้แฮชความยาวผันแปรได้


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 worldคือb

สำหรับคำว่าสมบูรณ์ยกเลิกออก (เช่นlove), คุณเอาท์พุท "0 -ตัวละคร": โปรดทราบว่าในการป้อนข้อมูล-จะยังคงถูกมองข้าม มันเป็นเรื่องสำคัญในการส่งออกเท่านั้น

หากขนาดของตัวเลขมีขนาดใหญ่กว่า 13 คุณจะเริ่มเพิ่มจำนวนaของคุณและzของคุณโดยทั่วไปจะมีจำนวนมากaหรือzพอดีกับตัวเลขและนำสิ่งที่เหลือไว้ในจดหมายฉบับสุดท้ายดังนี้:

code golf: 43.

เหมาะกับ 3 aและมี 4 เหลือ:

aaa 4: j
result: aaaj

คำแนะนำ: ส่วนนี้จะเป็นพื้นdivmodยกเว้นว่ามันรอบไปทางศูนย์ไม่ได้-infinity(เช่น -43 จะกลายเป็น 3 z'และและ-4ซึ่งเป็นpเช่นนั้นzzzp)

หมายเหตุ: รีบไม่ได้มาถ้าa'หรือz' s พอดีอย่างสมบูรณ์แบบ 0แต่ถ้ามันเป็นสิ่ง

ชี้แจง:

  • กัญชาเป็นกรณีในความละเอียดอ่อน
  • ไม่อนุญาตช่องโหว่มาตรฐาน
  • I / O สามารถอยู่ในรูปแบบใด ๆ ที่ไม่ต่างชาติเกินไป stdin, stdout, ARG บรรทัดคำสั่งฟังก์ชัน ฯลฯ
  • นี่คือขนาดเพื่อให้สั้นที่สุดในไบต์ชนะ

ตัวอย่าง:

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;

คำอธิบาย

อัลกอริทึมทำงานตามที่คุณคาดหวัง: อ่านอินพุตแปลงเป็นตัวพิมพ์เล็กแม็พอักขระแต่ละตัวเป็นค่ารวมค่าและพิมพ์อักขระและปรับผลรวมตามลำดับจนกว่าผลรวมจะเป็นศูนย์ น่าจะเป็นการเพิ่มประสิทธิภาพที่น่าสนใจที่สุด (แม้ว่าจะประหยัดเพียงสองไบต์เท่านั้น) ก็คือการใช้การจับคู่อักขระเมื่อใช้แทนเนื่องจากการหลีกเลี่ยงการแลกเปลี่ยนการลบเพื่อแก้ไขสัญลักษณ์เมื่อคำนวณค่าที่แมปและหลีกเลี่ยงการสลับอีกครั้ง การลบค่าเมื่อตะกี้จะถูกแทนที่ด้วยนอกจาก

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 ยอดเยี่ยมฉันไม่รู้ถึงจุดตัดของ@!
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" เป็นตัวแปรทั่วโลกในตัว แต่ปรากฎว่าส่วนที่เหลือเป็นระเบียบ

คำอธิบาย 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พิมพ์-หรืออาจจะเป็นครั้งแรกบางส่วนaหรือzs และในที่สุด (รีเวอร์ส) lookups 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.