Summe oder Differenz zweier Zweierpotenzen

27

Ihre Herausforderung besteht darin, bei einer bestimmten Ganzzahl K >= 1nicht negative Ganzzahlen zu finden, Aund zwar B so, dass mindestens eine der beiden folgenden Bedingungen zutrifft:

  1. K = 2^A + 2^B
  2. K = 2^A - 2^B

Wenn es ein solches Aund nicht gibt B, kann sich Ihr Programm auf irgendeine Weise verhalten. (Zur Verdeutlichung Aund Bkann gleich sein.)

Testfälle

Es gibt oft mehrere Lösungen für eine Zahl, aber hier sind einige:

K => A, B
1 => 1, 0
15 => 4, 0                      ; 16 - 1 = 15
16 => 5, 4                      ; 32 - 16 = 16; also 3, 3: 8 + 8 = 16
40 => 5, 3                      ; 2^5 + 2^3 = 40
264 => 8, 3
17179867136 => 34, 11           ; 17179869184 - 2048 = 17179867136 

Der letzte Test Fall 17179867136, muss in unter 10 Sekunden läuft auf jede relativ moderne Maschine. Dies ist ein Codegolf, also gewinnt das kürzeste Programm in Bytes. Sie können ein vollständiges Programm oder eine Funktion verwenden.

Conor O'Brien
quelle
5
Kann A gleich B sein ?
Dennis
2
@ Tennis Ich verstehe nicht, warum nicht.
Conor O'Brien
... und für 16, beide 5,4und 3,3sind gültig.
Titus
Kann eigentlich jetzt, wo ich darüber nachdenke A, Bnegativ sein? (zB -1, -1für 1)
Sp3000
@ Sp3000 Nein, guter Punkt.
Conor O'Brien

Antworten:

3

Jelly , 11 bis 10 Bytes

;0+N&$BL€’

Anwenden des Bit-Twiddling-Tricks aus der Python-Antwort von @xnor

Testen Sie es bei TryItOnline
Alle Testfälle finden Sie auch bei TryItOnline

Wie?

;0+N&$BL€’ - main link takes an argument, k, e.g 15
;0         - concatenate k with 0, e.g. [15, 0]
     $     - last two links as a monad
   N       - negate, e.g. -15
    &      - bitwise and, e.g. -15&15=1 since these two are called as a monad (one input)
  +        - add, vectorises, e.g. [16,1]
      B    - convert to binary, vectorises, e.g. [[1,0,0,0,0],[1]]
       L€  - length for each, e.g. [5,1]
         ’ - decrement, vectorises, e.g. [4,0]
Jonathan Allan
quelle
15

Python 2, 43 Bytes

lambda n:[len(bin((n&-n)+k))-3for k in n,0]

Sag das n==2^a ± 2^bmit a>b. Dann ist der größte Faktor der nZweierpotenz 2^b, und wir können ihn mit dem Bit-Trick finden 2^b = n&-n. Damit können wir berechnen 2^b + n, was entweder 2^a + 2 * 2^boder nur gleich ist 2^a. Entweder hat man die gleiche Bitlänge wie a*. Wir geben also die Bitlängen von n&-nund aus (n&-n)+n, berechnet aus den Längen ihrer binären Darstellungen. Python 3 ist für parens in ein Byte länger for k in(n,0)].

* Außer das 2^a + 2^bmit a==b+1einer längeren Bitlänge, aber das ist in Ordnung, weil wir das so interpretieren können 2^(a+1)-2^b.

xnor
quelle
Wunderbar - ich habe ein bisschen nach Geige gesucht, konnte es aber nicht herausfinden, nur nach Jelly portiert.
Jonathan Allan
Versuchen Sie n=4oder 8oder 16bitte.
Titus
@Titus f(2**n)kehrt zurück (n+1,n)und 2**(n+1)-2**n=2**nes gibt kein Problem.
Jonathan Allan
ah ... Was ist das Format bin()in Python?
Titus
@Titus ist ein String mit einem führenden 0b, daher der -3.
Jonathan Allan
8

JavaScript (ES6), 73 Byte

(n,[s,f,z]=/^1+(.*1)?(0*)$/.exec(n.toString(2)))=>[s.length-!!f,z.length]

Für den Subtraktionsfall ist die erste Zahl die Anzahl der Ziffern in der Binärdarstellung und die zweite Zahl die Anzahl der nachgestellten Nullen. Für den Additionsfall subtrahieren wir 1 von der ersten Zahl. Wenn die binäre Darstellung alle 1s gefolgt von einigen 0s ist, wird der Additionsfall angenommen, andernfalls wird der Subtraktionsfall angenommen. 36-Byte-Port von @ xnors Version, der nur für B≤30 in JavaScript funktioniert:

n=>[(l=Math.log2)(n+(n&=-n))|0,l(n)]
Neil
quelle
2
@ETHproductions Sicher, aber ich habe es auf 36 golfen.
Neil
Leider dachte ich, dass die 36-Byte-Version für den 17-Milliarden-Testfall nicht funktioniert.
ETHproductions
@ETHproductions Tut es nicht, aber dann hat es, wie ich mich erinnere, auch nicht Ihren Port getan (Kommentar seitdem gelöscht, seufz), da er bitweise Operationen verwendete.
Neil
Entschuldigung, hier ist es wieder: n=>[n,0].map(k=>((n&-n)+k).toString(2).length-1)Und beide Versionen kehren [34,11]zum letzten Testfall zurück (ich verwende FF 48).
ETHproductions
@ETHproductions Aha, also genauer arbeiten sie, wenn das zweite Ergebnis 30 oder weniger ist.
Neil
6

Perl, 52 49 32 Bytes

Alte Lösung (49 Bytes)

Beinhaltet +1 für -p

Geben Sie Input auf STDIN:

pow2.pl <<< 17179867136

pow2.pl

#!/usr/bin/perl -p
$_=reverse sprintf"%b",$_;/()1(?:1+|0*)/;$_="@+"

Wenn Sie jedoch den Algorithmus von xnor verwenden und einen Twist hinzufügen, erhalten Sie 32 Bytes:

perl -nE 'say 13/9*log|0for$;=$_&-$_,$_+$'

Nur der Code:

say 13/9*log|0for$;=$_&-$_,$_+$

Dies leidet unter schwerwiegenden Rundungsfehlern, da sie 13/9 = 1.444...weit darüber liegen 1/log 2 = 1.44269...( logselbst hat sie einen Rundungsfehler, der jedoch so viel kleiner ist, dass wir ihn in der Analyse von 13/9 zusammenfassen können). Aber da jedes 2**big - 2** smallkorrigiert wird, 2** bigbevor das Protokoll erstellt wird, spielt das keine Rolle und die Berechnung für 2**big + 2 * 2**smallwird abgeschnitten, ist also auch sicher. Und auf der anderen Seite des Bereichs 2**n+2**(n-1)wird der Bereich nicht genug vergrößert [0,64](ich kann nicht richtig Unterstützung mehr als der ganzzahlige Bereich sowieso aufgrund der Verwendung von &), um zu einem falschen Ergebnis zu führen (Multiplikator 1.5wäre jedoch für große Zahlen zu weit entfernt).

Tonne Hospel
quelle
5

Brachylog , 23 Bytes

,A:B#+.:2rz:^a{+|-}?,.=

Probieren Sie es online!

Dies ist viel schneller als erforderlich, z. B. bei TIO noch unter 10 Sekunden .

Erläuterung

Dies ist im Grunde eine direkte Transkription der Formel ohne Optimierung:

,A:B     The list [A, B]
#+       Both A and B are greater than or equal to 0
.        Output = [A, B]
:2rz     The list [[2, A], [2, B]]
:^a      The list [2^A, 2^B]
{+|-}?   2^A + 2^B = Input OR 2^A - 2^B = Input
,.=      Assign a value to A and B which satisfy those constraints
Tödlich
quelle
2
Es sieht so aus, als ob diese Herausforderung für die Sprache gemacht wurde: D
Conor O'Brien
4

Python, 69 Bytes

def f(k):b=bin(k)[::-1];return len(b)-2-(b.count('1')==2),b.find('1')

Tests sind auf ideone

Da nicht gültige Eingaben alles können, wissen wir, dass wenn für die Eingabe genau 2 Bits gesetzt sind, dies die Summe dieser 2 Zweierpotenzen ist. Andernfalls wird (sofern gültig) eine Reihe von Bits (einschließlich) ausgeführt die Möglichkeit von nur 1 Bit) und wird die Differenz zwischen der nächsthöheren Potenz von 2 als dem MSB und dem LSB-Satz sein.

Jonathan Allan
quelle
4

JAVA 7,142 ,140, 134 Bytes

Dies ist mein erster Beitrag zu PPCG! Ich würde mich sehr über Feedback zu Golftipps freuen.
Danke an frozen für das Sparen von 2 Bytes

void f(long n){for(int i=-1,j;i++<31;)for(j=0;j++<34;){long a=1,x=a<<i,y=a<<j;if(x+y==n|y-x==n){System.out.println(j+" "+i);return;}}}

UNGOLF

void f(long n){
    for(int i=-1,j;i++<31;)
         for(j=0;j++<34;){
          long a=1,x=a<<i,y=a<<j;
            if(x+y==n|y-x==n){
            System.out.println(j+" "+i);
        return;
        }
            }
    }

ideone

Zahlenknoten
quelle
1
Hallo numberknot! Ein weiterer Wanderer aus Rätsel sehe ich. 40=2**3+2**5Zum Beispiel scheint es nicht zu funktionieren . Wenn ich es mir ansehe, kann ich nicht verstehen, warum nicht, vielleicht habe ich einen Transkriptionsfehler gemacht ...
Jonathan Allan
1
@JonathanAllan Jetzt funktioniert es einwandfrei. Tatsächlich fehlten die Klammern in dieser Zeile, wenn ((a << i) + (a << j) == n | (a << j) - (a << i) == n ) und danke.
Numberknot
Können Sie kein Literal verwenden, 1anstatt eine Variable dafür zu deklarieren?
Titus
1
@TItus Wenn ich Literal 1 verwende, ist dieser Testfall (17179867136) nicht möglich. Wenn Sie Literal 1 verwenden, weist Java ihm automatisch einen INT-Speicherplatz zu.
Numberknot
1
Sie können j zusammen mit i deklarieren:for(int i=-1,j;[...]
Frozn
4

Mathematica, 57 54 Bytes

3 Bytes gespart dank LegionMammal978!

Do[Abs[2^a-#]==2^b&&Print@{a,b},{a,2Log@#+1},{b,0,a}]&

Druckt tatsächlich alle 1 passenden Paare aus {a, b}. 2Log@#+1ist eine Obergrenze für die größte a, die möglicherweise bei der Darstellung der Eingabe auftreten kann #(die enge Obergrenze ist Log [2 #] / Log [2] = 1,44 ... Log [#] + 1). Läuft fast augenblicklich auf dem Testeingang und in weniger als einer Viertelsekunde (auf meinem neuen, aber handelsüblichen Computer) auf 100-stelligen Eingängen.

1 Wenn Sie amit dem Standardwert 1 anstelle von 0 beginnen, werden zwei Bytes gespeichert. es führt dazu, dass die Ausgabe {0,0} verfehlt wird, wenn die Eingabe 2 ist, findet aber in diesem Fall die Ausgabe {2,1}, was gut genug ist.

Greg Martin
quelle
Alle * passenden Paare? ( If[Abs[2^a-#]==2^b,Print@{a,b}]Kann auch durch ersetzt werden Abs[2^a-#]==2^b&&Print@{a,b}, um 3 Bytes zu sparen.)
LegionMammal978
Gute Beobachtung, ich verstehe! "Alle *" war eine Fußnote, aber jetzt ist es klarer.
Greg Martin
3

MATL , 23 22 Bytes

BnQ:qWtG-|ym)1)tG-|hZl

Probieren Sie es online! Oder überprüfen Sie alle Testfälle .

Erläuterung

B      % Implicit input. Convert to binary. Gives n digits
nQ:q   % Range [1 ... n+1]
W      % 2 raised to that, element-wise: gives [1 2 4 ... 2^(n+1)] (*)
tG-|   % Duplicate. Absolute difference with input, element-wise (**)
y      % Push a copy of (*)
m      % True for elements of (**) that are members of (*)
)      % Use as logical index to select elements from (*)
1)     % Take the first element. Gives power of the first result
tG-|   % Duplicate. Absolute difference with input. Gives power of the second result
hZl    % Concatenate. Take binary logarithm. Implicit display
Luis Mendo
quelle
3

Perl 6 , 41 Bytes

{.base(2).flip~~/1[1+|0*]/;$/.to,$/.from}

(Algorithmus schamlos aus der Perl 5-Antwort kopiert )

Erläuterung:

# bare block lambda with implicit parameter 「$_」
{
  # turn into binary
  # ( implicit method call on 「$_」 )
  .base(2)

  # flip the binary representation
  .flip

  ~~ # smartmatch that against:

  /
    1      # a 「1」
    [
      | 1+ # at least one 「1」
      | 0* # or any number of 「0」
    ]
  /;

  # returns a list comprised of

  # the position of the end of the match (larger of the two)
  $/.to,
  # the position of the beginning of the match
  $/.from
}

Verwendung:

# give it a lexical name for clarity
my &bin-sum-diff = {.base(2).flip~~/1[1+|0*]/;$/.to,$/.from}

say bin-sum-diff 15; # (4 0)
say bin-sum-diff 16; # (5 4)

say bin-sum-diff 20; # (4 2)
# 2**4==16, 2**2==4; 16+4 == 20

say bin-sum-diff 40; # (5 3)
say bin-sum-diff 264; # (8 3)
say bin-sum-diff 17179867136; # (34 11)
Brad Gilbert b2gills
quelle
1

PHP, 73 Bytes

Ich hätte Jonathans Pyhton 2-Lösung für 54 Bytes (+13 Overhead) kopieren können, wollte mir
aber etwas anderes einfallen lassen.

In Datei speichern, dann mit phpoder ausführen php-cgi.

<?=strlen($n=decbin($argv[1]))-!!strpos($n,'01')._.strpos(strrev($n),49);

druckt aund bdurch einen Unterstrich getrennt, alles für keine Lösung.

unverwechselbare Lösung, 96 Bytes

<?=preg_match('#^(10*1|(1+))(0*)$#',decbin($argv[1]),$m)?strlen($m[0])-!$m[2]._.strlen($m[3]):_;

druckt aund bdurch einen Unterstrich getrennt; Ein einziger Unterstrich für keine Lösung.

Es sagt Ihnen sogar die Operation für 11 weitere Bytes:
Ersetzen Sie einfach den ersten Unterstrich im Code durch '-+'[!$m[2]].

Titus
quelle
Wenn ich 67 in echo strlen versuche ($ n = decbin ($ argv [1])) - !! strpos ($ n, '01 ') .'- +' [! $ N [2]]. Strpos (strrev ( $ n), 49); es gibt mir 6 + 0 zurück, was 65 ist
Jörg Hülsermann
@ JörgHülsermann: 67 hat keine Lösung; Verhalten für keine Lösung ist undefiniert; Es spielt also keine Rolle, was für 67 gedruckt wird.
Titus
0

PHP, 117 Bytes

if(preg_match("#^(1+|(10*1))0*$#",$b=decbin($k=$argv[1]),$t))echo($l=strlen($b))-($t[2]?1:0).",",$l+~strrpos($b,"1");

Extended Version 4 Cases

$l=strlen($b=decbin($k=$argv[1]));
// Case 1: n=2(n-1)=n+n or n=n*(2-1)=2n-n 
if(preg_match('#^100*$#',$b))echo($l-2).'a+'.($l-2).':'.$l.'a-'.($l-1);
// Case 2: n-m
elseif(preg_match('#^1+0*$#',$b)){echo $l.'b-',strpos($b,"0")?$l-strpos($b,"0"):0;}
// Case 3: n+m 
elseif(preg_match('#^10*10*$#',$b))echo ($l-1).'c+',$l-strrpos($b,"1")-1;
else echo "Nothing";

die Kurzversion vereint Fall 1 und 3 und unterscheidet sich von Fall 3 und in beiden Versionen liefert Fall 4 keine Ausgabe.

Jörg Hülsermann
quelle