मनमानी लंबाई हाशिंग


16

पर विचार करें यदि आप एक है हैश फंक्शन H जो लंबाई के तार लेता है 2n और रिटर्न लंबाई के तार n और अच्छा गुण है कि यह है टक्कर प्रतिरोधी , यानी इसे खोजने के लिए कठिन है दो अलग अलग तार ss एक ही हैश के साथ H(s)=H(s)

अब आप एक नया हैश फंक्शन बनाना चाहेंगें H जो के तार लेता है मनमाने ढंग से लंबाई और उन्हें लंबाई के तार करने के लिए नक्शे n , जबकि अभी भी टक्कर प्रतिरोधी जा रहा है।

आपके लिए भाग्यशाली, पहले से ही 1979 में अब एक विधि जिसे मर्कले-डैमगार्ड निर्माण के रूप में जाना जाता है, प्रकाशित हुई थी जो वास्तव में इसे प्राप्त करती है।

इस चुनौती का कार्य इस एल्गोरिथ्म को लागू करना होगा, इसलिए हम पहले चरण-दर-चरण उदाहरण के माध्यम से जाने से पहले, मर्कले-दामगार्ड निर्माण के एक औपचारिक विवरण पर एक नज़र डालेंगे, जो यह दिखाना चाहिए कि दृष्टिकोण की तुलना में सरल है यह पहली बार में दिखाई दे सकता है।

यह देखते हुए कुछ पूर्णांक n>0 , एक हैश समारोह H ऊपर वर्णित और एक इनपुट स्ट्रिंग के रूप में s मनमाना लंबाई की, नए हैश फंक्शन H निम्नलिखित है:

  • सेट l=|s|, की लंबाई s , और विभाजन s लंबाई की मात्रा में n , के साथ पिछले हिस्सा भरने अनुगामी यदि आवश्यक हो तो शून्य। यह पैदावार m=lnकईचूजेजिन्हेंc1,c2,,cmलेबल किया जाता है।
  • एक अग्रणी और पीछे हिस्सा जोड़े c0 और cm+1 , जहां c0 से मिलकर एक स्ट्रिंग है n शून्य और cm+1 है n बाइनरी में, साथ गद्देदार प्रमुख लंबाई करने के लिए शून्य n
  • अब iteratively H को वर्तमान chunk ci लागू करते हैं, जो पिछले परिणाम ri1 : ri=H(ri1ci) जुड़ा है , जहाँ r0=c0(यह कदम नीचे दिए गए उदाहरण को देखने के बाद अधिक स्पष्ट हो सकता है।)
  • H का आउटपुट अंतिम परिणाम rm+1

काम

एक प्रोग्राम या फ़ंक्शन लिखें जो इनपुट के रूप में पॉजिटिव पूर्णांक n , एक हैश फ़ंक्शन H को ब्लैक बॉक्स और एक गैर-रिक्त स्ट्रिंग s रूप में H है और उसी इनपुट पर H के समान परिणाम देता है।

यह , इसलिए प्रत्येक भाषा में सबसे कम उत्तर जीतता है।

उदाहरण

मान लें कि n=5 , इसलिए हमारा दिया गया हैश फंक्शन H लंबाई 10 का तार लेता है और लंबाई 5 का तार देता है।

  • s="Programming Puzzles"पज़ल्स" के इनपुट को देखते हुए , हमें निम्नलिखित चंक्स मिलते हैं : s1="Progr" , s2="ammin" , s3="g Puz" और s4="zles0" । ध्यान दें कि s4 को एक अनुगामी शून्य के साथ लंबाई 5 तक गद्देदार करने की आवश्यकता है।
  • c0="00000" सिर्फ पांच शून्य के एक स्ट्रिंग और हैc5="00101" है पाँच बाइनरी में (101 ) , दो प्रमुख शून्य के साथ गद्देदार है।
  • अब मात्रा के साथ संयुक्त कर रहे हैं H :
    r0=c0="00000"
    r1=H(r0c1)=H("00000Progr")
    r2=H(r1c2)=H(H("00000Progr")"ammin") r3=H(r2c3)=H(H(H("00000Progr")"ammin")"g Puz")
    r4=H(r3c4)=H(H(H(H("00000Progr")"ammin")"g Puz")"zles0")
    r5=H(r4c5)=H(H(H(H(H("00000Progr")"ammin")"g Puz")"zles0")"00101")
  • r5 हमारा आउटपुट है।

चलो इस उत्पादन कुछ विकल्प के आधार पर इस तरह दिखाई देंगे एक नजर है 1 के लिए H :

  • यदि H("0123456789")="13579" , यानी H बस हर दूसरे चरित्र देता है, हम पाते हैं:
    r1=H("00000Progr")="00Por"
    r2=H("00Porammin")="0oamn"
    r3=H("0oamng Puz")="omgPz"
    r4=H("omgPzzles0")="mPze0"
    r5=H("mPze000101")="Pe011"
    So "Pe011" needs to be the output if such a H is given as black box function.
  • If H simply returns the first 5 chars of its input, the output of H is "00000". Similarly if H returns the last 5 chars, the output is "00101".
  • यदि H अपने इनपुट के वर्ण कोड को गुणा करता है और इस संख्या के पहले पाँच अंक लौटाता है, जैसे H("PPCG123456")="56613" , तो H("Programming Puzzles")="91579"

1 सादगी के लिए, उन H वास्तव में टकराव प्रतिरोधी नहीं हैं, हालांकि यह आपके प्रस्तुत करने के परीक्षण के लिए कोई फर्क नहीं पड़ता।



I must say it's fun that the example given has the last 'full' hash be of "OMG Puzzles!" effectively omgPzzles0. Well chosen example input!
LambdaBeta

Can we assume some flexibility on the input format for H (e.g. it takes two strings of length n, or a longer string of which it only considers the first 2n characters)?
Delfad0r

Are space characters, e.g., between "g P" valid output?
guest271314

@guest271314 If the space is part of the resulting hash, it needs to be outputted. If the hash is actually "gP", you may not output a space inbetween.
Laikoni

जवाबों:


7

Haskell, 91 90 86 bytes

n!h|let a='0'<$[1..n];c?""=c;c?z=h(c++take n(z++a))?drop n z=h.(++mapM(:"1")a!!n).(a?)

Try it online!

Explanation

a='0'<$[1..n]

Just assigns the string "00...0" ('0' n times) to a


c?""=c
c?z=h(c++take n(z++a))?drop n z

The function ? implements the recursive application of h: c is the hash we have obtained so far (length n), z is the rest of the string. If z is empty then we simply return c, otherwise we take the first n characters of z (possibly padding with zeros from a), prepend c and apply h. This gives the new hash, and then we call ? recursively on this hash and the remaining characters of z.


n!h=h.(++mapM(:"1")a!!n).(a?)

The function ! is the one actually solving the challenge. It takes n, h and s (implicit) as inputs. We compute a?s, and all we have to do is append n in binary and apply h once more. mapM(:"1")a!!n returns the binary representation of n.


1
let in a guard is shorter than using where: Try it online!
Laikoni

2
ऐसा लग रहा है कि mapM(\_->"01")aहो सकता है mapM(:"1")a
xnor

7

आर , 159 154 बाइट्स

function(n,H,s,`?`=paste0,`*`=strrep,`/`=Reduce,`+`=nchar,S=0*n?s?0*-(+s%%-n)?"?"/n%/%2^(n:1-1)%%2)(function(x,y)H(x?y))/substring(S,s<-seq(,+S,n),s--n-1)

इसे ऑनलाइन आज़माएं!

नीरस R में चुनौतियों का उत्तर देना कभी भी सुंदर नहीं होता है, लेकिन यह भयानक है। यह "सामान्य" R कोड नहीं लिखने के बारे में एक शिक्षाप्रद उत्तर है ...

0 बाइट की कीमत पर बग को ठीक करने के लिए nwellnhof का धन्यवाद !

4 बाइट्स के लिए अच्छा है, पूर्वता को बदलने के लिए ऑपरेटर को स्वैप करने के लिए J.Doe का धन्यवाद ।

नीचे दिया गया स्पष्टीकरण कोड के पिछले संस्करण के लिए है, लेकिन सिद्धांत समान हैं।

function(n,H,s,               # harmless-looking function arguments with horrible default arguments 
                              # to prevent the use of {} and save two bytes
                              # then come the default arguments,
                              # replacing operators as aliases for commonly used functions:
 `+`=paste0,                  # paste0 with binary +
 `*`=strrep,                  # strrep for binary *
 `/`=Reduce,                  # Reduce with binary /
 `?`=nchar,                   # nchar with unary ?
 S=                           # final default argument S, the padded string:
  0*n+                        # rep 0 n times
  s+                          # the original string
  0*-((?s)%%-n)+              # 0 padding as a multiple of n
  "+"/n%/%2^(n:1-1)%%2)       # n as an n-bit number
                              # finally, the function body:
 (function(x,y)H(x+y)) /      # Reduce/Fold (/) by H operating on x + y
  substring(S,seq(1,?S,n),seq(n,?S,n))  # operating on the n-length substrings of S

मुझे लगता 0*(n-(?s)%%n)है कि अगर एन समान रूप से विभाजित होता है तो काम नहीं करता है। लेकिन 0*-((?s)%%-n)काम करना चाहिए।
nwellnhof

@nwellnhof आह, निश्चित रूप से, धन्यवाद, निश्चित।
ग्यूसेप

मामूली परिवर्तन, 155 बाइट्स
जे। डी। ओ।

1
@ जे। अच्छा! मैं एक बाइट बचाया के बाद से seqहै 1इसकी के रूप में fromडिफ़ॉल्ट रूप से तर्क।
ग्यूसेप

3

सी (जीसीसी) , 251 बाइट्स

#define P sprintf(R,
b(_){_=_>1?10*b(_/2)+_%2:_;}f(H,n,x)void(*H)(char*);char*x;{char R[2*n+1],c[n+1],*X=x;P"%0*d",n,0);while(strlen(x)>n){strncpy(c,x,n);x+=n;strcat(R,c);H(R);}P"%s%s%0*d",R,x,n-strlen(x),0);H(R);P"%s%0*d",R,n,b(n));H(R);strcpy(X,R);}

इसे ऑनलाइन आज़माएं!

बैश समाधान के रूप में साफ नहीं है, और अत्यधिक कामचलाऊ है।

फ़ंक्शन एक फ़ंक्शन के रूप में fले रहा है Hजो कि स्ट्रिंग के हैश के साथ उसके स्ट्रिंग इनपुट को बदलता है, nजैसा कि विवरण में है, और xइनपुट स्ट्रिंग और आउटपुट बफर।

विवरण:

#define P sprintf(R,     // Replace P with sprintf(R, leading to unbalanced parenthesis
                         // This is replaced and expanded for the rest of the description
b(_){                    // Define b(x). It will return the integer binary expansion of _
                         // e.g. 5 -> 101 (still as integer)
  _=_>1?                 // If _ is greater than 1
    10*b(_/2)+_%2        // return 10*binary expansion of _/2 + last binary digit
    :_;}                 // otherwise just _
f(H,n,x)                 // Define f(H,n,x)
  void(*H)(char*);       // H is a function taking a string
  char*x; {              // x is a string
  char R[2*n+1],c[n+1],  // Declare R as a 2n-length string and c as a n-length string
  *X=x;                  // save x so we can overwrite it later
  sprintf(R,"%0*d",n,0); // print 'n' 0's into R
  while(strlen(x)>n){    // while x has at least n characters
    strncpy(c,x,n);x+=n; // 'move' the first n characters of x into c
    strcat(R,c);         // concatenate c and R
    H(R);}               // Hash R
  sprintf(R,"%s%s%0*d"   // set R to two strings concatenated followed by some zeroes
    R,x,                 // the two strings being R and (what's left of) x
    n-strlen(x),0);      // and n-len(x) zeroes
  H(R);                  // Hash R
  sprintf(R,"%s%*d",R,n, // append to R the decimal number, 0 padded to width n
    b(n));               // The binary expansion of n as a decimal number
  H(R);strcpy(X,R);}     // Hash R and copy it into where x used to be


मुझे लगता है: 227 बाइट्स (सीलिंगकैट की टिप्पणी से दूर जाना)
ज़ाचारि

3

रूबी , 78 बाइट्स

->n,s,g{(([?0*n]*2*s).chop.scan(/.{#{n}}/)+["%0#{n}b"%n]).reduce{|s,x|g[s+x]}}

इसे ऑनलाइन आज़माएं!

यह काम किस प्रकार करता है:

([?0*n]*2*s).chop    # Padding: add leading and trailing 
                     # zeros, then remove the last one
.scan(/.{#{n}}/)     # Split the string into chunks
                     # of length n
+["%0#{n}b"%n]       # Add the trailing block
.reduce{|s,x|g[s+x]} # Apply the hashing function
                     # repeatedly


2

बैश , 127-tes बाइट्स

Z=`printf %0*d $1` R=$Z
while IFS= read -rn$1 c;do R=$R$c$Z;R=`H<<<${R::2*$1}`;done
H< <(printf $R%0*d $1 `bc <<<"obase=2;$1"`)

इसे ऑनलाइन आज़माएं!

यह एक प्रोग्राम / फंक्शन / स्क्रिप्ट / स्निपेट के रूप में काम करता है। H को किसी प्रोग्राम या फ़ंक्शन के लिए फिर से शुरू करना चाहिए जो हैशिंग प्रदर्शन करेगा। एन तर्क है। उदाहरण कॉल:

$ H() {
>   sed 's/.\(.\)/\1/g'
> }
$ ./wherever_you_put_the_script.sh 5 <<< "Programming Puzzles"  # if you add a shebang
Pe011

विवरण:

Z=`printf %0*d $1`

यह $1शून्य की एक स्ट्रिंग बनाता है । यह प्रिंटफ को कॉल करके और अतिरिक्त तर्क चौड़ाई में पूर्णांक पेडर्ड प्रिंट करने के लिए कहता है । वह अतिरिक्त तर्क जो हम पास करते हैं $1, वह प्रोग्राम / फ़ंक्शन / स्क्रिप्ट का तर्क है जो n को संग्रहीत करता है।

R=$Z

यह केवल हैशिंग लूप की तैयारी में Z, हमारे शून्य स्ट्रिंग को R, हमारे परिणाम स्ट्रिंग को कॉपी करता है।

while IFS= read -rn$1 c; do

यह प्रत्येक इनपुट इनपुट $1(n) पर लूप्स को रीड कैरेक्टर्स को c में लोड करता है। यदि इनपुट समाप्त हो जाता है तो c केवल बहुत कम समाप्त होता है। rविकल्प सुनिश्चित करता है कि इनपुट में कोई विशेष वर्ण नहीं मिलता बैश-व्याख्या की। यह शीर्षक में है - rयह कड़ाई से आवश्यक नहीं है, लेकिन फ़ंक्शन को इनपुट से अधिक सटीक रूप से मेल खाता है।

R=$R$c$Z

यह इनपुट से R तक के n अक्षर को पैडिंग के लिए जीरो के साथ पढ़ता है (अभी के लिए बहुत सारे जीरो)।

R=`H<<<${R::2*$1}`;done

यह यहाँ हैश फ़ंक्शन के इनपुट के रूप में स्ट्रिंग का उपयोग करता है। विषय सूचि${R::2*$1} कुछ गूढ़ बाश पैरामीटर प्रतिस्थापन हैं जो पढ़ता है: आर, 0 से शुरू, केवल 2n वर्ण।

यहाँ लूप समाप्त होता है और हम इसके साथ समाप्त होते हैं:

H< <(printf $R%0*d $1 `bc <<<"obase=2;$1"`)

यहां समान प्रारूप स्ट्रिंग ट्रिक का उपयोग नंबर को पैड करने के लिए किया जाता है। bcइसका उपयोग आउटपुट बेस (ओबेस) को 2 में सेट करके बाइनरी में परिवर्तित करने के लिए किया जाता है। परिणाम हैश फ़ंक्शन / प्रोग्राम को दिया जाता है जिसका आउटपुट कैप्चर नहीं किया गया है और इस प्रकार उपयोगकर्ता को दिखाया गया है।


"127-" "क्यों? सिर्फ "127" ही क्यों?
Solomon Ucko

I don't know. I was on the fence about the necessity of the r flag. I figured 1 byte doesn't really matter, but if pushed I could shave it.
LambdaBeta

के लिए readआदेश?
सोलोमन उको

क्योंकि इसके बिना इनपुट में `` को अनदेखा करने के बजाय व्याख्या की जाएगी, इसलिए उन्हें बचना होगा।
लैंबडाटा

हो सकता है कि इसके बारे में एक नोट जोड़ें?
सोलोमन उको

2

पायथ , 24 बाइट्स

चूंकि पायथ एच को एक फ़ंक्शन नाम के लिए उपयोग करने की अनुमति नहीं देता है, इसलिए मैं yइसके बजाय उपयोग करता हूं ।

uy+GH+c.[E=`ZQQ.[ZQ.BQ*Z

इसे ऑनलाइन आज़माएं! उदाहरण एच के "हर दूसरे चरित्र" संस्करण के साथ है।


2

पर्ल 6 , 79 68 बाइट्स

{reduce &^h o&[~],comb 0 x$^n~$^s~$n.fmt("%.{$n-$s.comb%-$n}b"): $n}

इसे ऑनलाइन आज़माएं!

व्याख्या

{
  reduce         # Reduce with
    &^h o&[~],   # composition of string concat and hash function
    comb         # Split string
      0 x$^n     # Zero repeated n times
      ~$^s       # Append input string s
      ~$n.fmt("  # Append n formatted
        %.       # with leading zeroes,
        {$n             # field width n for final chunk
         -$s.comb%-$n}  # -(len(s)%-n) for padding,
        b")      # as binary number
      :          # Method call with colon syntax
      $n         # Split into substrings of length n
}


1

पायथन 2 , 126 113 बाइट्स

lambda n,H,s:reduce(lambda x,y:H(x+y),re.findall('.'*n,'0'*n+s+'0'*(n-len(s)%n))+[bin(n)[2:].zfill(n)])
import re

इसे ऑनलाइन आज़माएं!

-13 त्रिगुणमिति के लिए धन्यवाद

हाँ, यह एक घृणित बात है, क्यों मैं सिर्फ एक निर्मित का उपयोग करने के लिए एक स्ट्रिंग विखंडू में विभाजित नहीं कर सकता ...? :-(


codegolf.stackexchange.com/a/173952/55696 एक whileलूप सबसे अच्छा बिल्टिन है जिसकी मैं उम्मीद कर सकता था। 104 बाइट्स
स्टीवन एच।

@StevenH। हाँ, खासकर यदि आप वास्तव में गोल्फ पर ही ध्यान केंद्रित कर रहे हैं। > _>
आउटगॉल्फ

'0'*~-nके बजाय '0'*(len(s)%n)कम है (और वास्तव में कम आदानों के लिए सही है)।
nwellnhof

@nwellnhof हाँ, लेकिन यह निश्चित रूप से एक ही बात नहीं है।
आउटगॉल्फ

शायद मैं पर्याप्त स्पष्ट नहीं था। आपका समाधान स्ट्रिंग्स के लिए गलत उत्तर देता है जैसे Programming Puzz(16 वर्ण)। 7 बाइट्स '0'*(len(s)%n)को '0'*~-nठीक करने और सहेजने के साथ प्रतिस्थापित करना ।
nwellnhof

1

पायथन 2 , 106 102 बाइट्स

एक बार के लिए, फंक्शन लैम्ब्डा से बाहर निकल जाता है। -4 सरल वाक्यविन्यास हेरफेर के लिए बाइट्स, जो किंग के लिए धन्यवाद।

def f(n,H,s):
 x='0'*n;s+='0'*(n-len(s)%n)+bin(n)[2:].zfill(n)
 while s:x=H(x+s[:n]);s=s[n:]
 return x

इसे ऑनलाइन आज़माएं!


क्या परिणाम 'Pe011' नहीं होना चाहिए, 'e011' नहीं?
त्रिगुटर्नोमेट्री

कि यह चाहिए। फिक्स्ड!
स्टीवन एच।

न्यूलाइन्स के बजाय सेमी-कॉलन्स का उपयोग करें। -4 निवाले
जो किंग

मुझे पता ही नहीं चला कि काम करते हुए, साथ ही साथ, धन्यवाद!
स्टीवन एच।

1

जाप , 27 बाइट्स

òV ú'0 pV¤ùTV)rÈ+Y gOvW}VçT

कोशिश करो!

मुझे Japt के लिए सीधे इनपुट के रूप में कार्य करने की कोई क्षमता नहीं मिली है, इसलिए यह एक स्ट्रिंग लेता है जिसे Japt कोड के रूप में व्याख्या किया गया है और यह अपेक्षा करता है कि यह एक फ़ंक्शन को परिभाषित करे। विशेष रूप से, OvWतीसरा इनपुट लेता है और इसे Japt के रूप में व्याख्या करता है, फिर gइसे कॉल करता है। प्रतिस्थापित करने के साथ OxWएक जावास्क्रिप्ट फ़ंक्शन के बजाय इनपुट की अनुमति देता है, या यदि फ़ंक्शन (किसी तरह) पहले से ही डब्ल्यू में संग्रहीत किया गया था तो यह सिर्फ W2 बाइट्स बचा सकता है । ऊपर दिए गए लिंक में काम किया गया उदाहरण हैएचयह विषम अनुक्रम में वर्ण लेता है, जबकि यह "चार-कोड गुणा करें और 5 उच्चतम अंक" उदाहरण लें।

जिस तरह से जाप इनपुट लेता है, रोंहोगा U,nहोगा V, औरएच होगा W

स्पष्टीकरण:

òV                             Split U into segments of length V
   ú'0                         Right-pad the short segment with "0" to the same length as the others
       p     )                 Add an extra element:
        V¤                       V as a base-2 string
          ùTV                    Left-pad with "0" until it is V digits long
              r                Reduce...
                        VçT          ...Starting with "0" repeated V times...
               È       }                                                  ...By applying:
                +Y               Combine with the previous result
                   gOvW          And run W as Japt code



0

ओ.के. , 41 बाइट्स

{(x#48)(y@,)/(0N,x)#z,,/$((x+x!-#z)#2)\x}

इसे ऑनलाइन आज़माएं!

{                                       } /x is n, y is H, z is s.
                          (x+x!-#z)       /number of padding 0's needed + x
                         (         #2)\x  /binary(x) with this length
                      ,/$                 /to string
                    z,                    /append to z
             (0N,x)#                      /split into groups of length x
       (y@,)/                             /foldl of y(concat(left, right))...
 (x#48)                                   /...with "0"*x as the first left string
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.