Betrachten Sie eine haben Hash - Funktion die Strings der Länge nimmt und kehrt Strings der Länge und hat die schöne Eigenschaft , dass es resistent gegen Kollisionen , dh es ist schwierig , zwei verschiedene Zeichenketten zu finden mit dem gleichen Hash - .
Sie möchten jetzt eine neue Hash-Funktion erstellen , die Zeichenfolgen beliebiger Länge auf Zeichenfolgen der Länge abbildet und dabei trotzdem kollisionssicher ist.
Zum Glück schon 1979 eine Methode, die heute als Merkle-Damgård-Konstruktion bekannt ist genau dies erreicht.
Die Aufgabe dieser Herausforderung wird es sein, diesen Algorithmus zu implementieren. Wir werden uns daher zunächst die formale Beschreibung der Merkle-Damgård-Konstruktion ansehen, bevor wir uns einem schrittweisen Beispiel zuwenden, das zeigen soll, dass der Ansatz einfacher ist als es könnte zuerst erscheinen.
Wenn eine ganze Zahl , eine Hash-Funktion wie oben beschrieben und eine Eingabezeichenfolge beliebiger Länge gegeben sind, führt die neue Hash-Funktion Folgendes aus:
- Setze , die Länge von und die Aufteilung von in Abschnitte der Länge , wobei der letzte Abschnitt bei Bedarf mit nachgestellten Nullen aufgefüllt wird. Dies ergibt viele Stücke, die mit.
- Hinzufügen eines vorderen und einen hinteren chunk und , wobei eine Zeichenfolge ist , die aus Nullen und ist , im Binär-, aufgefüllt mit führenden Nullen auf Länge .
- Wenden Sie nun iterativ auf den aktuellen Block an, der an das vorherige Ergebnis angehängt ist : , wobei . (Dieser Schritt ist möglicherweise klarer, nachdem Sie sich das folgende Beispiel angesehen haben.)
- Die Ausgabe von ist das Endergebnis .
Die Aufgabe
Schreiben Sie ein Programm oder eine Funktion, die eine positive ganze Zahl , eine Hash-Funktion als Blackbox und eine nicht leere Zeichenfolge als Eingabe verwendet und an denselben Eingängen dasselbe Ergebnis wie zurückgibt .
Das ist Code-Golf , also gewinnt die kürzeste Antwort in jeder Sprache.
Beispiel
Nehmen wir an, , also nimmt unsere gegebene Hash-Funktion Zeichenfolgen der Länge 10 und gibt Zeichenfolgen der Länge 5 zurück.
- Bei einer Eingabe von wir die folgenden Blöcke: , , und . Beachten Sie, dass mit einer nachgestellten Null auf Länge 5 aufgefüllt werden musste.
- ist nur eine Folge von fünf Nullen und ist fünf in binär ( ), aufgefüllt mit zwei führenden Nullen.
- Nun werden die Brocken mit kombiniertem :
- ist unser Output.
Lassen Sie uns einen Blick darauf werfen, wie diese Ausgabe aussehen würde, abhängig von einigen Optionen 1 für :
- Wenn , dh nur jedes zweite Zeichen zurück, erhalten wir:
So Bedürfnisse der Ausgang auf, wennsolches als BlackBoxFunktion gegeben ist. - Wenn einfach die ersten 5 Zeichen seines Eingangszurückkehrt, die Ausgabe des ist . In ähnlicher Weise ist die Ausgabe "00101", wenn die letzten 5 Zeichen .
- Wenn die Zeichencodes seiner Eingabe multipliziert und die ersten fünf Ziffern dieser Zahl zurückgibt, z. B. , dann ist .
1 Der Einfachheit halber sind diese tatsächlich nicht kollisionssicher, obwohl dies für die Prüfung Ihres Beitrags keine Rolle spielt.
omgPzzles0
. Gut gewählter Beispieleingang!Antworten:
Haskell ,
919086 BytesProbieren Sie es online!
Erläuterung
Weist einfach die Zeichenfolgen mal) zu
"00...0"
('0'
a
Die Funktionn ), n Zeichen von
?
implementiert die rekursive Anwendung vonh
:c
ist der bisher erhaltene Hash (Längez
ist der Rest des Strings. Wennz
leer ist, kehren wir einfach zurückc
, ansonsten nehmen wir die erstenz
(möglicherweise mit Nullena
aufgefüllt von ), stellen sie voranc
und wenden sie anh
. Dies ergibt den neuen Hash, und dann rufen wir?
diesen Hash und die verbleibenden Zeichen von rekursiv aufz
.Die Funktionn .
!
ist diejenige, die die Herausforderung tatsächlich löst. Es dauertn
,h
unds
(implizit) als Eingänge. Wir berechnena?s
, und alles, was wir tun müssen, ist,n
binär anzuhängen und erneut anzuwendenh
.mapM(:"1")a!!n
gibt die binäre Darstellung vonquelle
let
in einer Wache ist kürzer als mitwhere
: Probieren Sie es online!mapM(\_->"01")a
kannmapM(:"1")a
.R ,
159154 BytesProbieren Sie es online!
Yuck! Das Beantworten von String- Herausforderungen in R ist nie schön, aber das ist schrecklich. Dies ist eine lehrreiche Antwort darauf, wie man keinen "normalen" R-Code schreibt ...
Vielen Dank an nwellnhof für die Behebung eines Fehlers, zu einem Preis von 0 Bytes!
Vielen Dank an J.Doe für das Auswechseln des Operator-Aliasing, um die Priorität zu ändern. Gut für -4 Bytes.
Die folgende Erklärung gilt für die vorherige Version des Codes, die Prinzipien bleiben jedoch gleich.
quelle
0*(n-(?s)%%n)
funktioniert nicht, wenn n s gleichmäßig teilt. Sollte aber0*-((?s)%%-n)
funktionieren.seq
es standardmäßig1
alsfrom
Argument hat.C (gcc) , 251 Bytes
Probieren Sie es online!
Nicht so sauber wie die Bash-Lösung und hochgradig verbesserungsfähig.
Die Funktion
f
nimmtH
als eine Funktion, die ihre Zeichenfolgeneingabe durch den Hash dieser Zeichenfolge,n
wie in der Beschreibung, undx
die Eingabezeichenfolge und den Ausgabepuffer ersetzt.Beschreibung:
quelle
Ruby , 78 Bytes
Probieren Sie es online!
Wie es funktioniert:
quelle
Jelly , 23 Bytes
Probieren Sie es online!
AkzeptiertH an der Linie darüber, s als linkes Argument und n als das richtige Argument.
quelle
Bash , 127-ε Bytes
Probieren Sie es online!
Dies funktioniert als Programm / Funktion / Skript / Snippet. H muss in ein Programm oder eine Funktion auflösbar sein, die das Hashing ausführt. N ist das Argument. Beispielaufruf:
Beschreibung:
Dies erzeugt eine Folge von
$1
Nullen. Dies funktioniert, indem printf aufgerufen und angewiesen wird, eine Ganzzahl zu drucken, die mit einer zusätzlichen Argumentbreite aufgefüllt ist . Das zusätzliche Argument, das wir übergeben, ist$1
das Argument für das Programm / die Funktion / das Skript, in dem n gespeichert ist.Dies kopiert lediglich Z, unsere Nullzeichenfolge, nach R, unsere Ergebniszeichenfolge, um die Hashing-Schleife vorzubereiten.
Dies durchläuft alle
$1
(n) Zeichen die Eingabe und lädt die gelesenen Zeichen in c. Wenn die Eingabe endet, endet c einfach zu kurz. Dier
Option stellt sicher, dass Sonderzeichen in der Eingabe nicht vom Bash interpretiert werden. Dies ist der-ε
Titel, derr
nicht unbedingt erforderlich ist, aber die Funktion genauer an die Eingabe anpasst.Dies verkettet die von der Eingabe in R gelesenen n Zeichen mit Nullen zum Auffüllen (vorerst zu viele Nullen).
Dies verwendet einen Here-String als Eingabe für die Hash-Funktion. Der Inhalt
${R::2*$1}
ist eine etwas esoterische Bash-Parameter-Ersetzung, die lautet: R, beginnend mit 0, nur 2n Zeichen.Hier endet die Schleife und wir beenden mit:
Hier wird der gleiche Formatstringtick verwendet, um die Zahl mit 0 aufzufüllen.
bc
wird verwendet, um es in binär umzuwandeln, indem die Ausgabebasis (obase) auf 2 gesetzt wird. Das Ergebnis wird an die Hash-Funktion / das Hash-Programm übergeben, dessen Ausgabe nicht erfasst und somit dem Benutzer angezeigt wird.quelle
r
Flagge. Ich dachte, dass 1 Byte keine Rolle spielt, aber wenn es gedrückt wird, kann ich es rasieren.read
Befehl?Pyth , 24 Bytes
Da Pyth nicht zulässt, dass H für einen Funktionsnamen verwendet wird, verwende ich
y
stattdessen.Probieren Sie es online! Beispiel ist mit der "Every Second Character" -Version von H.
quelle
Perl 6 ,
7968 BytesProbieren Sie es online!
Erläuterung
quelle
Sauber , 143 Bytes
Probieren Sie es online!
quelle
Python 2 ,
126113 BytesProbieren Sie es online!
-13 dank Triggernometrie .
Ja, das ist ein Gräuel, warum kann ich nicht einfach eine eingebaute Funktion verwenden, um einen String in Stücke zu teilen ...? :-(
quelle
while
Schleife ist die beste, die ich mir erhoffen kann. 104 Bytes'0'*~-n
statt'0'*(len(s)%n)
ist kürzer (und eigentlich korrekt für kürzere Eingaben).Programming Puzz
(16 Zeichen). Ersetzen'0'*(len(s)%n)
mit'0'*~-n
behebt das und spart 7 Bytes.Python 2 ,
106102 BytesAusnahmsweise übertrifft die Funktion den Lambda. -4 Bytes für einfache Syntaxmanipulation dank Jo King.
Probieren Sie es online!
quelle
Japt , 27 Bytes
Versuch es!
Ich habe keine Möglichkeit für Japt gefunden, Funktionen direkt als Eingabe zu verwenden. Daher wird eine Zeichenfolge verwendet, die als Japt-Code interpretiert wird und eine Funktion definiert.H das braucht Zeichen bei ungeraden Indizes, während dies das Beispiel "Multipliziere Zeichencodes und nimm die 5 höchsten Ziffern" ist.
OvW
Nimmt speziell die dritte Eingabe, interpretiert sie als Japt undg
ruft sie dann auf.OxW
Wenn Sie dies durch ersetzen, wird die Eingabe stattdessen als Javascript-Funktion ermöglicht, oder wenn die Funktion (irgendwie) bereits in W gespeichert wäre, könnten Sie einfachW
2 Bytes einsparen. Der obige Link hat das funktionierende Beispiel vonAufgrund der Art und Weise Japt Eingaben nimmt,s wird sein n wird sein H wird sein
U
,V
, undW
Erläuterung:
quelle
GolfScript , 47 Bytes
Probieren Sie es online!
quelle
ok , 41 bytes
Probieren Sie es online!
quelle