İki gücün toplamı veya farkı


27

Meydan okumanız, kabul etmeyi seçmeniz durumunda, bir tamsayı verildiğinde K >= 1, negatif olmayan bir tamsayı bulmak Ave B aşağıdaki iki koşuldan en az birinin geçerli olmasını sağlamaktır:

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

Eğer böyle bir şey yoksa Ave Bprogramınız herhangi bir şekilde davranabilir. (Açıklık için, Ave Beşit olabilir.)

Test durumları

Genellikle bir sayı için birden fazla çözüm vardır, ancak burada birkaç tane vardır:

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 

Geçen test durumu, 17179867136, 10 saniyenin altında çalıştırmalısınız herhangi nispeten modern makine üzerinde. Bu bir kod golf, yani bayt cinsinden en kısa program kazanır. Tam bir program veya işlev kullanabilirsiniz.


5
Can A eşit B ?
Dennis,

2
@Dennis Neden olmasın anlamıyorum.
Conor O'Brien,

... ve için 16, hem 5,4ve 3,3geçerlidir.
Titus,

Aslında şimdi düşünüyorum A, Bolumsuz olabilir mi? (örn -1, -1. 1 için)
Sp3000

@ Sp3000 Hayır, iyi nokta.
Conor O'Brien,

Yanıtlar:


3

Jöle , 11 10 bayt

;0+N&$BL€’

Python cevaptan bit twitter hilesi uygulanıyor @xnor

En Test edin TryItOnline
Tüm test durumlarda altındadır TryItOnline

Nasıl?

;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]

15

Python 2, 43 bayt

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

Söyle n==2^a ± 2^bile a>b. Daha sonra, en büyük güç-of-2 faktör nolduğunu 2^bve biz bit hile kullanarak bulabilirsiniz 2^b = n&-n. Bu bize 2^b + nya 2^a + 2 * 2^bda sadece eşit olan hesaplama yapmamıza izin veriyor 2^a. İkisinden biri a* ile aynı uzunlukta bit uzunluğuna sahiptir . Yani, biz çıktı bit-uzunlukları n&-nve (n&-n)+nbunların ikili temsiller uzunlukları hesaplanan. Python 3, parensler için bir bayt daha uzundur for k in(n,0)].

* Haricinde 2^a + 2^bolan a==b+1bir uzun bit uzunluğa sahiptir, ancak yolunda biz bu kadar yorumlayabilir çünkü 2^(a+1)-2^b.


Harika - Biraz keman aradım ama çözemedi, sadece Jelly'e aktardım.
Jonathan Allan

Deneyin n=4ya 8da 16lütfen.
Titus,

@Titus f(2**n)döner (n+1,n)ve 2**(n+1)-2**n=2**nbu yüzden sorun olmaz.
Jonathan Allan,

ah ... bin()Python'da formatı nedir?
Titus,

@Titus 0b, önde gelen bir dizedir , dolayısıyla -3.
Jonathan Allan,

8

JavaScript (ES6), 73 bayt

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

Çıkarma durumu için ilk sayı, ikili gösterimdeki hane sayısıdır ve ikinci sayı, izleyen sıfır sayısıdır. Ekleme durumu için, ilk sayıdan 1 çıkardık. İkili gösterimin tümü 1 saniye ve ardından bazı 0lar ise, toplama durumu varsayılır, aksi takdirde çıkarma durumu varsayılır. JavaScript’te yalnızca B≤30 için çalışan @ xnor’ın 36 baytlık bağlantı noktası:

n=>[(l=Math.log2)(n+(n&=-n))|0,l(n)]

2
@ETHproductions Tabii, ama ben 36'ya kadar golf oynadım.
Neil

Benim hatam, 36 baytlık versiyonun 17 milyar test durumu için işe yaramadığını düşündüm.
ETHProductions

@ETHproductions Öyle değil, ama sonra hatırladığım kadarıyla bağlantı noktanız da yoktu (silindiğinden beri iç içe geçmiş yorum), çünkü bitsel işlemler kullandı.
Neil

Üzgünüz, işte yine:: n=>[n,0].map(k=>((n&-n)+k).toString(2).length-1)Her iki sürüm [34,11]de son test senaryosuna geri dönüyor (FF 48 kullanıyorum).
ETHProductions

@ETHproductions Aha, böylece ikinci sonuç 30 veya daha az olduğunda daha doğru çalışırlar.
Neil

6

Perl, 52 49 32 bayt

Eski çözüm (49 bayt)

İçin +1 içerir -p

STDIN'e giriş verin:

pow2.pl <<< 17179867136

pow2.pl

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

Bununla birlikte, xnor algoritmasını kullanarak ve bir twist ekleyerek 32 bayt verir:

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

Sadece kod:

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

Bu, ciddi yuvarlama hatasından muzdariptir, çünkü 13/9 = 1.444...oldukça fazladır 1/log 2 = 1.44269...( logkendisinin de yuvarlama hatası vardır, ancak bu, 13/9 analizinde kapatabileceğimizden daha küçüktür). Ancak herhangi bir kütükten önce 2**big - 2** smalldüzeltildiği için 2** bigbu önemli değildir ve hesaplamanın 2**big + 2 * 2**smallkesilmesi de aynı şekilde güvenlidir. Ve aralığın diğer tarafında aralıkta 2**n+2**(n-1)yeterince artmaz [0,64](Düzgün yapamam) &yanlış sonuçlara yol açması için kullanılması nedeniyle herhangi bir tamsayı aralığından daha fazla destek (çarpanı 1.5ancak çok büyük sayılar için çok uzak olacaktır).


5

Brachylog , 23 bayt

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

Çevrimiçi deneyin!

Bu gerekenden çok daha hızlıdır, örneğin bu TIO'da hala 10 saniyenin altında .

açıklama

Bu, temel olarak, optimizasyon olmadan formülün doğrudan bir transkripsiyonudur:

,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

2
Bu meydan okuma dili için yapıldığı
anlaşılıyor

4

Python, 69 bayt

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

Testler ideone üzerinde

Geçerli olmayan girdiler her şeyi yapabildiğinden, giriş tam olarak 2 bit ayarlanmışsa, bu 2 gücün toplamının 2 olduğunu ve aksi takdirde (eğer geçerliyse) bazı bitlerin bir çalışması olacağını biliyoruz. sadece 1 bit olasılığı) ve 2'nin bir sonraki en yüksek gücü arasındaki fark MSB ve LSB setinden farklı olacaktır.


4

JAVA 7,142 ,140, 134 BYTES

Bu benim PPCG benim ilk yazı! Golf ipuçları hakkında geri bildirim için gerçekten takdir ediyorum 2 bayt tasarruf
için dondurulmuş teşekkürler

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


1
Merhaba numara! Şaşkınlıktan başka bir gezgin görüyorum. 40=2**3+2**5Örneğin, işe yaramadı . Şuna bakarsak, neden olmadığını
Jonathan Allan

1
@JonathanAllan Şimdi iyi çalışıyor. Aslında ((bir << i) + (bir << j) == n | (bir << j) - (bir << i) == n eğer parantez bu satırda eksikti. ) ve teşekkürler.
Sayı

1Bunun için bir değişken bildirmek yerine bir hazır bilgi kullanamazsınız ?
Titus,

1
Eğer değişmez 1 kullanırsam @ttus o zaman bu test çantası (17179867136) mümkün olmaz, çünkü değişmez 1 kullanırsanız java otomatik olarak bir INT bellek alanı tahsis eder.
Sayı

1
J ile birlikte i ilan edebilirsiniz:for(int i=-1,j;[...]
Frozn

4

Mathematica, 57 54 bayt

LegionMammal978 sayesinde 3 bayt kurtarıldı!

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

Aslında tüm basar 1 uygun çiftleri {a, b}. girişi temsil ederken ortaya çıkabilecek 2Log@#+1en büyükler için bir üst sınırdır (sıkı üst sınır Günlük [2 #] / Günlük [2] = 1.44 ... Günlük [#] + 1). Neredeyse anında test girişinde ve çeyrek saniyeden daha kısa bir sürede (yeni ama kullanıma hazır bilgisayarımda) 100 basamaklı girişlerde çalışır.a#

1 Letting a1 yerine 0 varsayılan değeri ile başlangıç iki bayt kaydeder; giriş 2 olduğunda {0,0} çıkışının kaçırılmasına neden olur, ancak bu durumda {2,1} çıkışını bulur, bu da yeterince iyidir.


Tüm * uygun çiftler? (Ayrıca, 3 bayt kaydetmek If[Abs[2^a-#]==2^b,Print@{a,b}]için ile değiştirilebilir Abs[2^a-#]==2^b&&Print@{a,b}.)
LegionMammal978 10:16

Güzel gözlem, anladım! "Hepsi *" bir dipnot idi, ama şimdi daha açık.
Greg Martin

3

MATL , 23 22 bayt

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

Çevrimiçi deneyin! Veya tüm test durumlarını doğrulayın .

açıklama

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

3

Perl 6 , 41 bayt

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

(Algoritma , Perl 5 cevabından utanmadan kopyalandı )

Açıklama:

# 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
}

Kullanımı:

# 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)

1

PHP, 73 bayt

Jonathan'ın Pyhton 2 çözümünü 54 bayt (+13 tepegöz) kopyalayabilirdim,
ama farklı bir şey bulmak istedim.

dosyaya kaydedin, sonra phpveya ile çalıştırın php-cgi.

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

bir alt çizgi ile yazdırılır ave bayrılır, çözüm bulunmayan bir şey.

kendine özgü çözüm, 96 bayt

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

bir alt çizgi ile yazdırır ave bayrılır; çözüm için tek bir alt çizgi.

İşlemi size 11 bayt daha söyler:
Koddaki ilk alt çizgiyi yerine koymanız yeterlidir '-+'[!$m[2]].


Eğer 67 eko strlen ($ n = decbin ($ argv [1]))) - !! strpos ($ n, '01 '). $ n), 49); bana 6 + 0 olan 65
Jörg Hülsermann

@ JörgHülsermann: 67'nin bir çözümü yoktur; hiçbir çözüm için davranış tanımsızdır; bu yüzden 67 için ne yazdırdığı önemli değil.
Titus

0

PHP, 117 Bayt

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");

Genişletilmiş sürüm 4 Kılıf

$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";

Kısa versiyon birliği Durum 1 ve 3'ü oluşturur ve Durum 3 için bir fark yaratır ve her iki versiyonda da Durum 4 çıktı vermez.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.