Tổng hoặc hiệu của hai lũy thừa của hai


27

Thử thách của bạn, nếu bạn chọn chấp nhận nó, được đưa ra một số nguyên K >= 1, tìm các số nguyên không âm AB sao cho ít nhất một trong hai điều kiện sau giữ:

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

Nếu không tồn tại như vậy AB, chương trình của bạn có thể hoạt động theo bất kỳ cách nào. (Để làm rõ, ABcó thể bằng nhau.)

Các trường hợp thử nghiệm

Thường có nhiều giải pháp cho một số, nhưng đây là một vài:

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 

Trường hợp thử nghiệm cuối cùng 17179867136, phải chạy trong vòng dưới 10 giây trên bất kỳ máy tương đối hiện đại nào. Đây là một mã golf, vì vậy chương trình ngắn nhất tính bằng byte sẽ thắng. Bạn có thể sử dụng một chương trình đầy đủ hoặc một chức năng.


5
A có thể bằng B không?
Dennis

2
@Dennis Tôi không thấy tại sao không.
Conor O'Brien

... Và cho 16, cả hai 5,43,3đều hợp lệ.
Tít

Thực sự bây giờ tôi nghĩ về nó, có thể A, Blà tiêu cực? (ví dụ: -1, -11)
Sp3000

@ Sp3000 Không, điểm tốt.
Conor O'Brien

Câu trả lời:


3

Thạch , 11 10 byte

;0+N&$BL€’

Áp dụng thủ thuật vặn vẹo bit từ câu trả lời Python của @xnor

Kiểm tra nó tại TryItOnline
Tất cả các trường hợp thử nghiệm cũng có tại TryItOnline

Làm sao?

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

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

Nói vậy n==2^a ± 2^bvới a>b. Sau đó, yếu tố sức mạnh lớn nhất của 2 n2^b, và chúng ta có thể tìm thấy nó bằng cách sử dụng bit-trick 2^b = n&-n. Điều đó cho phép chúng tôi tính toán 2^b + n, bằng 2^a + 2 * 2^bhoặc chỉ 2^a. Một trong hai có độ dài bit có cùng độ dài là a*. Vì vậy, chúng tôi xuất ra độ dài bit n&-n(n&-n)+n, được tính từ độ dài của biểu diễn nhị phân của chúng. Python 3 dài hơn một byte cho parens in for k in(n,0)].

* Ngoại trừ việc 2^a + 2^bvới a==b+1có một chút dài lâu hơn, nhưng điều đó tốt vì chúng ta có thể giải thích rằng như 2^(a+1)-2^b.


Thật tuyệt vời - Tôi đã tìm kiếm một chút bí ẩn, nhưng không thể giải quyết được, chỉ chuyển sang Jelly.
Jonathan Allan

Hãy thử n=4hoặc 8hoặc 16xin vui lòng.
Tít

@Titus f(2**n)trở lại (n+1,n)2**(n+1)-2**n=2**nvì vậy không có vấn đề gì.
Jonathan Allan

ah ... Những gì định dạng của bin()Python trong Python?
Tít

@Titus đó là một chuỗi có hàng đầu 0b, do đó -3.
Jonathan Allan

8

JavaScript (ES6), 73 byte

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

Đối với trường hợp trừ, số thứ nhất là số chữ số trong biểu diễn nhị phân và số thứ hai là số lượng các số 0 ở cuối. Đối với trường hợp bổ sung, chúng tôi trừ 1 từ số đầu tiên. Nếu biểu diễn nhị phân là tất cả 1 giây theo sau là 0 thì trường hợp cộng được giả sử nếu không thì trường hợp trừ được giả sử. Cổng 36 byte của phiên bản @ xnor chỉ hoạt động cho B≤30 trong JavaScript:

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

2
@ETHproductions Chắc chắn, nhưng tôi đã đánh gôn xuống 36.
Neil

Thật tệ, tôi nghĩ rằng phiên bản 36 byte không hoạt động cho trường hợp thử nghiệm 17 tỷ.
Sản xuất ETH

@ETHproductions Nó không, nhưng sau đó, cổng của bạn cũng không, như tôi nhớ (nhận xét kể từ khi xóa, thở dài), vì nó sử dụng các hoạt động bitwise.
Neil

Xin lỗi, đây là một lần nữa: n=>[n,0].map(k=>((n&-n)+k).toString(2).length-1)Và cả hai phiên bản đều quay trở lại [34,11]trong trường hợp thử nghiệm cuối cùng (Tôi đang sử dụng FF 48).
Sản xuất ETH

@ETHproductions Aha, vì vậy chính xác hơn là chúng hoạt động khi kết quả thứ hai là 30 hoặc ít hơn.
Neil

6

Perl, 52 49 32 byte

Giải pháp cũ (49 byte)

Bao gồm +1 cho -p

Cung cấp đầu vào trên STDIN:

pow2.pl <<< 17179867136

pow2.pl

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

Tuy nhiên, sử dụng thuật toán của xnor và thêm một vòng xoắn cho 32 byte:

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

Chỉ cần mã:

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

Điều này bị lỗi làm tròn nghiêm trọng vì 13/9 = 1.444...ở trên khá một chút 1/log 2 = 1.44269...( logbản thân nó cũng có lỗi làm tròn nhưng nhỏ hơn nhiều đến mức chúng ta có thể gói nó trong phân tích của ngày 13/9). Nhưng vì bất kỳ điều gì 2**big - 2** smallđược sửa chữa 2** bigtrước khi nhật ký, điều này không có nghĩa và tính toán cho việc 2**big + 2 * 2**smallcắt giảm nên cũng an toàn .. Và ở phía bên kia của phạm vi 2**n+2**(n-1)không được tăng đủ trong phạm vi [0,64](Tôi không thể đúng hỗ trợ nhiều hơn bất kỳ phạm vi số nguyên nào do sử dụng &) để dẫn đến một kết quả sai ( 1.5tuy nhiên bộ nhân sẽ quá xa đối với số lượng lớn).


5

Brachylog , 23 byte

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

Hãy thử trực tuyến!

Điều này nhanh hơn nhiều so với yêu cầu, ví dụ: điều này vẫn còn dưới 10 giây trên TIO .

Giải trình

Về cơ bản, đây là phiên âm trực tiếp của công thức mà không tối ưu hóa:

,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
Có vẻ như thử thách này được thực hiện cho ngôn ngữ: D
Conor O'Brien

4

Python, 69 byte

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

Các bài kiểm tra là trên ideone

Vì đầu vào không hợp lệ có thể làm bất cứ điều gì, chúng tôi biết rằng nếu đầu vào có chính xác 2 bit được đặt thì đó là tổng của 2 lũy thừa 2 và nếu không (nếu hợp lệ), nó sẽ chạy một số bit (bao gồm cả khả năng chỉ là 1 bit) và sẽ là sự khác biệt giữa công suất cao nhất tiếp theo là 2 so với bộ MSB và LSB.


4

JAVA 7,142 ,140, 134 B BYNG

Đây là bài viết đầu tiên của tôi trên PPCG! Tôi thực sự đánh giá cao phản hồi về các mẹo chơi gôn
Nhờ đóng băng để tiết kiệm 2 byte

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

thần tượng


1
Xin chào số! Một kẻ lang thang khác từ đánh đố tôi thấy. Nó dường như không hoạt động 40=2**3+2**5, ví dụ. Nhìn vào nó, tôi không thể hiểu tại sao không, có lẽ tôi đã mắc lỗi sao chép ...
Jonathan Allan

1
@Jonathan ALLan Bây giờ nó hoạt động tốt. Thực tế, dấu ngoặc bị thiếu trong dòng này nếu ((a << i) + (a << j) == n | (a << j) - (a << i) == n ) và cảm ơn.
Numberjack

Bạn có thể sử dụng một chữ 1thay vì khai báo một biến cho nó không?
Tít

1
@TItus nếu tôi sử dụng chữ 1 thì testcase này (17179867136) sẽ không thể thực hiện được vì nếu bạn sử dụng chữ 1 thì java sẽ tự động gán cho nó một không gian bộ nhớ INT.
Numberjack

1
Bạn có thể khai báo j cùng với i:for(int i=-1,j;[...]
Frozn

4

Toán học, 57 54 byte

Đã lưu 3 byte nhờ LegionMammal978!

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

Trên thực tế in ra tất cả 1 cặp thích hợp {a, b}. 2Log@#+1là giới hạn trên cho lớn nhất acó thể xuất hiện khi đại diện cho đầu vào #(giới hạn trên chặt chẽ là Nhật ký [2 #] / Nhật ký [2] = 1,44 ... Nhật ký [#] + 1). Chạy gần như ngay lập tức trên đầu vào thử nghiệm và trong chưa đầy một phần tư giây (trên máy tính mới nhưng có sẵn của tôi) trên đầu vào 100 chữ số.

1 Để abắt đầu ở giá trị mặc định là 1 thay vì 0 sẽ lưu hai byte; nó làm cho đầu ra {0,0} bị bỏ qua khi đầu vào là 2, nhưng tìm ra đầu ra {2.1} trong trường hợp đó, điều đó là đủ tốt.


Tất cả * cặp thích hợp? (Ngoài ra, If[Abs[2^a-#]==2^b,Print@{a,b}]có thể được thay thế bằng Abs[2^a-#]==2^b&&Print@{a,b}để lưu 3 byte.)
LegionMammal978

Quan sát tốt, tôi nhận được nó! "Tất cả *" là một chú thích, nhưng giờ thì rõ ràng hơn.
Greg Martin

3

MATL , 23 22 byte

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

Hãy thử trực tuyến! Hoặc xác minh tất cả các trường hợp thử nghiệm .

Giải trình

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 byte

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

(Thuật toán được sao chép một cách đáng xấu hổ từ câu trả lời Perl 5 )

Giải trình:

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

Sử dụng:

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

Tôi có thể đã sao chép giải pháp Jonathan Gians Pyhton 2 cho 54 byte (+13 trên không),
nhưng muốn đưa ra một cái gì đó khác biệt.

lưu vào tập tin, sau đó thực hiện với phphoặc php-cgi.

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

in ab phân tách bằng dấu gạch dưới, bất cứ điều gì không có giải pháp.

giải pháp đặc biệt, 96 byte

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

in abphân tách bằng dấu gạch dưới; một gạch dưới duy nhất cho không có giải pháp.

Nó thậm chí còn cho bạn biết hoạt động để có thêm 11 byte:
Chỉ cần thay thế dấu gạch dưới đầu tiên trong mã bằng '-+'[!$m[2]].


Nếu tôi thử 67 trong echo strlen ($ n = decbin ($ argv [1])) - !! strpose ($ n, '01 ') .'- +' [! $ N [2]]. Strpose (strrev ( $ n), 49); nó trả lại cho tôi 6 + 0 là 65
Jörg Hülsermann

@ JörgHülsermann: 67 không có giải pháp; hành vi cho không có giải pháp là không xác định; vì vậy nó không quan trọng những gì nó in cho 67.
Tít

0

PHP, 117 byte

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

Phiên bản mở rộng 4 trường hợp

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

phiên bản ngắn kết hợp Trường hợp 1 và 3 và tạo sự khác biệt cho Trường hợp 3 và trong cả hai phiên bản Trường hợp 4 không có đầu ra.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.