So finden Sie die digitale Härte einer ganzen Zahl, nehmen seine binäre Darstellung und zählen die Anzahl der Zeiten sowohl eine führende und nachlauf
1
kann entfernt werden , bis sie entweder mit einem Start oder Enden0
. Die Gesamtzahl der entfernten Bits ist die digitale Härte.
Das ist eine ziemlich wortreiche Erklärung - also lasst es uns mit einem ausgearbeiteten Beispiel aufschlüsseln.
In diesem Beispiel verwenden wir die Nummer 3167. In der Binärdatei ist dies:
110001011111
(Beachten Sie, dass Sie bei der Konvertierung in eine Binärdatei sicherstellen sollten, dass führende Nullen entfernt werden.)
Es beginnt oder endet nicht mit 0
, also entfernen wir 1 Paar Bits:
1 1000101111 1
Und ein anderer:
11 00010111 11
Aber jetzt gibt es eine 0 am Anfang, so dass wir keine 1
Paare mehr entfernen können . Insgesamt haben wir 4 Bits entfernt, also 4 die digitale Härte von 3167.
Für Zahlen, die als 2 n -1 für positives n geschrieben werden können (dh nur enthalten)1
in binärer Darstellung enthalten), wird 0 jedoch niemals erreicht, und so können alle Bits entfernt werden. Dies bedeutet, dass die Härte einfach die Bitlänge der ganzen Zahl ist.
Die Herausforderung
Ihre Aufgabe ist es, ein Programm oder eine Funktion zu schreiben, die eine nicht negative ganze Zahl enthält n >= 0
die digitale Härte bestimmt.
Sie können ein vollständiges Programm einreichen, das E / A ausführt, oder eine Funktion, die das Ergebnis zurückgibt. Ihre Eingabe sollte für Werte von "" funktionierenn
innerhalb des ganzzahligen Standardbereichs Ihrer Sprache .
Testfälle
Bitte benachrichtigen Sie mich, wenn eine dieser Angaben nicht korrekt ist oder wenn Sie Randfälle vorschlagen möchten, die hinzugefügt werden sollen.
0 -> 0
1 -> 1
8 -> 0
23 -> 2
31 -> 5
103 -> 4
127 -> 7
1877 -> 2
2015 -> 10
Hier ist die ungolfed Python-Lösung, mit der ich diese Testfälle generiert habe (ohne Gewähr, dass sie fehlerfrei sind):
def hardness(num) -> int:
binary = bin(num)[2:]
if binary.count('0') == 0:
return num.bit_length()
revbin = binary[::-1]
return min(revbin.find('0'), binary.find('0')) * 2
1
1 zurückgegeben, wenn überhaupt nichts enthalten ist0
? Ich meine, Sie können unmöglich genug Einsen aus der Zeichenkette entfernen, um den Anfang oder das Ende zu haben0
.Antworten:
Gelee ,
11 bis10 BytesProbieren Sie es online!
Wie es funktioniert
quelle
Python ,
76696863626057 BytesProbieren Sie es online!
Wie es funktioniert
Dies ist eine rekursive Lösung, die eine Eingabe n annimmt und k - beginnend bei 0 - weiter inkrementiert, während sowohl das LSB k (n) (Bit bei Index k von rechts) als auch das MSB k (n) (Bit bei Index k von links) eingestellt sind. Sobald dies beendet ist, wird k zurückgegeben, wenn alle Bits von n gesetzt sind und 2k sind wenn dies nicht der ist.
Beginnen wir damit, das Lambda f als benannte Funktion F mit einer Hilfsvariablen t umzuschreiben .
Bei jedem Aufruf von F verschieben wir zuerst n insgesamt k bitweise Einheiten nach rechts bitverschoben und das Ergebnis in t gespeichert . Auf diese Weise ist LSB 0 (t) = LSB k (n) , so dass t genau dann ungerade ist, wenn LSB k (n) gesetzt ist.
Bestimmen, ob MSB k (n) gesetzt ist, ist etwas schwieriger; das ist es, was
n & t > t >> 1
erreicht wird. Betrachten wir zur Veranschaulichung der Funktionsweiseeine ganze Zahl n = 1αβγδεζη 2 mit der Bitlänge 8 und analysieren Sie den Funktionsaufruf F (n, 3) , dh k = 3 .Wir versuchen festzustellen, ob MSB 3 (n) = γ gesetzt ist, indem den Wahrheitswert des Vergleichs untersuchen (n & t> t >> 1) = (1αβγδεζη 2 & 1αβγδ 2 > 1αβγ 2 ) . Untersuchen wir die beteiligten ganzen Zahlen.
Wir behaupten, dass genau dann γ = 1 ist, wenn n & t> t >> 1 ist .
Ob γ = 1 ist , hat n & t die Bitlänge 5, während t >> 1 die Bitlänge 4 hat , also ist n & t> t >> 1 .
Dies beweist, dass γ = 1 n & t> t >> 1 impliziert .
Wenn n & t> t >> 1 ist , gibt es zwei Möglichkeiten: entweder γ = 1 oder γ = 0 . Im ersten Fall gibt es nichts mehr zu beweisen.
Im zweiten Fall gilt αβγδ 2 ≥ n & t> t >> 1 = 1αβγ 2 .
Da αβγδ 2 > 1αβγ 2 ist , müssen wir MSB 0 (αβγδ 2 haben ) ≥ MSB 0 (1αβγ 2 ) haben , was bedeutet, dass α = 1 ist .
Auf diese Weise ist 1βγδ 2 > 11βγ 2 , also müssen wir MSB 1 haben (1βγδ 2 ) ≥ MSB 1 (11βγ 2 ) haben , was bedeutet, dass β = 1 ist .
Dies impliziert wiederum, dass 11γδ 2 > 111γ 2 ist . Wenn wir uns daran erinnern, dass im zweiten Fall γ = 0 ist, erhalten wir die Ungleichung 110δ 2 > 1110 2 , die falsch ist, da MSB 2 (110δ 2 ) = 0 <1 = MSB 2 (1110 2 ) .
Somit ist nur der erste Fall möglich und n & t> t >> 1 impliziert γ = 1 .
Zusammenfassend ist, wenn sowohl LSB k (n) als auch MSB k (n) gesetzt sind, t ungerade und n & t> t >> 1 ist wahr , so dass t & (n & t> t >> 1) ist Ausbeute 1 . Wenn jedoch LSB k (n) oder MSB k (n) nicht gesetzt ist (oder wenn beide gesetzt sind), wird t gerade sein oder n & t> t >> 1 wird falsch sein , so dass t & (n & t> t> > 1) ergibt 0 .
Wenn Sie F mit einem einzelnen Argument aufrufen, wird k = 0 initialisiert . Während die oben beschriebene Bedingung zutrifft, wird der Code after
and
ausgeführt, der (unter anderem) rekursiv F mit inkrementiertem k aufruft .Sobald LSB k (n) oder MSB k (n) nicht gesetzt ist, schlägt die Bedingung fehl und F (n, k) gibt 0 zurück . Jeder der vorhergehenden k Funktionsaufrufe addiert (n & (n + 1)> 0) + 1 zu F (n, k) = 0 , so dass F (n) ((n & (n + 1)> 0) + zurückgibt 1) k .
Wenn nun alle Bits von n gleich sind (dh wenn n entweder 0 ist oder alle seine Bits gesetzt sind), hat n + 1 keine Bits gemeinsam mit n , so dass n & (n + 1) = 0 und F (n) gibt k zurück . Wenn jedoch n beide Satz und ungesetzt Bits, n & amp ; (n + 1)> 0 und F (n) liefert 2k .
quelle
input()
,while
Undprint
sind bereits 17 Bytes ...MATL ,
13 -12 BytesProbieren Sie es online!Oder überprüfen Sie alle Testfälle .
Erläuterung
Der Code wiederholt jede Binärziffer und zählt, wie oft es möglich ist, zwei äußere zu entfernen.
quelle
Python, 82 Bytes
Ich habe das Gefühl, es kann immer noch Golf gespielt werden, aber ich habe eine Weile damit verbracht, verschiedene Methoden auszuprobieren, und dies war die kürzeste.
Probieren Sie es online aus
Obwohl dies ähnlich wie das Python-Programm des OP funktioniert, habe ich dies vor dem Posten der Frage erstellt, nachdem ich die Frage in der Sandbox angezeigt hatte, die kein solches Programm enthielt.
quelle
Python 2, 66 Bytes
Teilt die binäre Darstellung der Eingabe in Blöcke von 1 auf. Zählt die Anzahl der Einsen im kleineren des ersten und letzten Blocks und verdoppelt sie dann, es sei denn, es gibt einen einzelnen Block, der doppelt gezählt wird.
quelle
PowerShell ,
109106 BytesProbieren Sie es online!
Nimmt die Eingabe
$args[0]
, verwendet den .NET Aufrufconvert
estoString
mit Base2
(dh es binär), dann-split
S, die Zeichenfolge auf0
s, speichert , die in$a
. Wichtig zu beachten: Der .NET-Aufruf gibt keine führenden Nullen zurück, daher ist die erste Ziffer immer ein1
.Es gibt also zwei Möglichkeiten - die Binärzeichenfolge ist alle Eins, oder es gab mindestens eine Null. Wir unterscheiden zwischen jenen mit einem pseudoternären Index von
$a.count-eq1
. Wenn die Binärdatei mindestens eine Null hat, nehmen wir im linken Fall das Minimum der Länge der ersten[0]
Zeichenfolge von1
s und der letzten[-1]
Zeichenfolge (gefunden von|sort
und dann[0]
). Je kürzer das ist, desto mehr Paare können wir entfernen, also multiplizieren wir das mit2
. Beachten Sie, dass , wenn die ursprünglichen Binärkette Enden in eine0
, wie für die Eingabe8
, die dann[-1].length
wird auch0
(da es sich um eine leere Zeichenfolge ist), die , wenn sie multipliziert mit2
noch ist0
.Andernfalls nehmen wir bei allen binären Zeichenfolgen nur
$b
(die zuvor als Länge der ersten festgelegt wurde)[0]
Zeichenfolge festgelegt wurde, in diesem Fall die Gesamtheit der Binärzeichenfolge).In beiden Situationen verbleibt dieses Ergebnis in der Pipeline und die Ausgabe ist implizit.
quelle
JavaScript (ES6), 57 Byte
Nimmt die Binärdatei und versucht, alle
1s
oder fehlgeschlagene Werte mit der gleichen Anzahl von führenden und nachfolgenden zu vergleichen1s
.quelle
Netzhaut , 48 Bytes
Probieren Sie es online aus
Erläuterung:
quelle
133 Bytes
Funktion, die die Härte zurückgibt. Übernimmt eine Ganzzahl aus dem Argument.
Nun, heute habe ich es
'1' + '1' = 98
in C # herausgefunden.quelle
'1'
liegt daran, dass das ASCII-Zeichen 49 und 49 + 49 = 98 ist.1 + 1 = 2
nicht funktioniert hat. @FlipTackC
898885 BytesZwei Bytes gespart, weil @FlipTack auf eine nutzlose Deklaration hinwies.
f()
Mit der zu testenden Nummer anrufen , die Ausgabe wird von der Funktion zurückgegeben.Probiere es auf ideone aus .
quelle
JavaScript (ES6),
59-58ByteTestfälle
Code-Snippet anzeigen
quelle
Jelly , 14 Bytes
Probieren Sie es online!
quelle
C,
1371321221191171149894928785 BytesZeit zum Golfen B-)
Hier ist der Beweis
und die Ausgabe;
quelle
Java (OpenJDK) ,
181156150 BytesProbieren Sie es online!
quelle
Mathematica,
6356 BytesErläuterung
Generieren Sie die Basis-2-Darstellung der Eingabe, umschlossen mit einem
List
. Bewahren Sie das inl
Wenn das Element min von
l
1 ist, geben Sie 1 aus. Wenn nicht, geben Sie 2 aus. Multiplizieren Sie dies mit ...Teilt
l
in Läufe.Nimm das erste und das letzte Element.
Nehmen Sie die Summe von beiden.
Finde den kleineren zwischen den beiden.
(Multiplizieren Sie das erste Ergebnis (1 oder 2) mit diesem Ergebnis).
quelle
Oktave,
5654 BytesProbieren Sie es online!
Erläuterung:
binäre Darstellung von
n
Nehmen Sie kumulative min von
d
und kumulative min von flippedd
Matrixmultiplikation durchführen
mit 2 multiplizieren, wenn alle Ziffern 1 sind;
quelle
Pyth, 18 Bytes
Ein Programm, das die Eingabe einer Ganzzahl akzeptiert und das Ergebnis ausgibt.
Testsuite (Erste Zeile zur Formatierung)
Wie es funktioniert
quelle
APL, 26 Bytes
Testfälle:
Erläuterung:
quelle
J, 22 Bytes
Dies basiert auf dem tollen Trick, der aus dieser Herausforderung gelernt wurde .
Probieren Sie es online!
Erläuterung
quelle
PHP,
8374 Bytes3 + 6 Bytes gespeichert von Jörg
nimmt Eingaben von STDIN entgegen; renn mit
-nR
.Nervenzusammenbruch
quelle
<?=~($s=decbin($argn))[$a=strspn($s,1)]?2*min($a,strspn(strrev($s),1)):$a;
JavaScript (ES6), 83 Bytes
Ungolfed:
quelle
Mathematica, 62 Bytes
Reine Funktion, wobei
#
das erste Argument darstellt.(h=0;...;h)&
setzth=0
, macht ein paar Sachen...
, gibt dann zurückh
(die Härte). Schauen wir uns die ganzen Sachen an:Vielen Dank an Greg Martin für die Einführung in diesen Trick .
quelle
Haskell ,
94-92BytesProbieren Sie es online! Verwendung:
Erläuterung:
b
Konvertiert eine Zahl in eine Binärzahl und gibt eine Liste mit Nullen und Einsen mit dem niedrigstwertigen Bit zuerst zurück. Inh
wird diese Liste umgekehrt und elementweise mit der ursprünglichen Liste multipliziert und dannspan(>0)
nach dem Anfangsbuchstaben1
s aufgeteilt:Das resultierende Tupel wird mit
(c,_:_)
dem Muster abgeglichen, mit dem_:_
eine nicht leere Liste übereinstimmtc = [1,1]
. Da die Bytes vorne und hinten entfernt werden,c++c = [1,1,1,1]
werden sie zurückgegeben und schließlich summiert, um die digitale Härte zu erhalten .Wenn die zweite Liste des Tupels leer ist, enthält die Binärdarstellung nur Einsen, und die Anzahl der Einsen ist die digitale Härte. Mit dem Mustervergleich fehlgeschlagen
h
eben das zurückgegebenn
, was nochmal aufsummiert wird.quelle
Perl, 61 Bytes
Das Herzstück ist der reguläre Ausdruck,
/^(1+).*\1$/
bei dem das Zweifache der Länge$1
die Antwort ist. Der Rest des Codes ist Overhead und beschäftigt sich mit dem Spezialfall all 1.quelle
sprintf
Argumente weglassen . Außerdem können Sie mit-p
flag ein vollständiges Programm schreiben, das kürzer ist als Ihre Funktion, da Sie es weglassen könnensub f{...}
(stattdessen müssen Sie mit enden,$_=...
aber das ist immer noch eine Verbesserung um 4 Byte). Schließlich können Sie anstelle von Ihremlength(...)
tun/0/&&s/^(1+).*\1$/$1$1/;$_=y///c
. Dies sollte Sie auf 51 Bytes bringen.PHP, 65 Bytes
Online Version
quelle
CJam, 14 Bytes
Erläuterung:
quelle