2의 2 제곱의 합 또는 차이


27

당신의 도전이며, 정수 주어, 당신이 그것을 받아들이 선택해야합니다 K >= 1, 음이 아닌 정수를 찾을 수 AB 같은 그 홀드 다음 두 가지 조건 중 하나 이상 :

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

이 같은 존재하지 않는 경우 AB, 프로그램은 어떤 방식으로 작동 할 수 있습니다. (명확 A하고 B동일 할 수 있습니다.)

테스트 사례

여러 가지 솔루션이 종종 있지만 몇 가지가 있습니다.

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 

마지막 테스트 케이스는 17179867136, 10 초 이상에서 실행해야 어떤 상대적으로 현대적인 기계에. 이것은 코드 골프이므로 바이트 단위의 가장 짧은 프로그램이 이깁니다. 당신은 전체 프로그램이나 기능을 사용할 수 있습니다.


5
A는 B 같을 수 있습니까 ?
Dennis

2
@ 데니스 나는 왜 안보이는 지 모르겠다.
Conor O'Brien

... 그리고위한 16, 모두 5,43,3유효합니다.
Titus

사실 지금은 그것에 대해 생각, 수 A, B음수? (예 : -1, -11의 경우)
Sp3000

@ Sp3000 아니요, 좋은 지적입니다.
Conor O'Brien

답변:


3

젤리 , 11 10 바이트

;0+N&$BL€’

@xnor의 Python 답변 에서 비트 트위들 링 트릭 적용

TryItOnline 에서
테스트 모든 테스트 사례는 TryItOnline 에서도 수행됩니다 .

방법?

;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

파이썬 2, 43 바이트

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

그 말 n==2^a ± 2^b과를 a>b. 그러면 최대 2의 거듭 제곱 n2^b입니다 2^b = n&-n. 비트 트릭을 사용하여 찾을 수 있습니다 . 즉 우리가 계산할 수 있습니다 2^b + n중 하나에 해당하는, 2^a + 2 * 2^b또는 단지 2^a. 둘 중 하나의 길이는 a* 와 길이가 같습니다 . 따라서 이진 표현의 길이에서 계산 된 n&-n및 의 비트 길이를 출력합니다 (n&-n)+n. Python 3은의 parens에 대해 1 바이트 더 깁니다 for k in(n,0)].

* 2^a + 2^bwith a==b+1는 하나의 비트 길이가 더 길지만이를로 해석 할 수 있기 때문에 2^(a+1)-2^b좋습니다.


멋진-나는 약간의 바이올린을 찾았지만 그것을 해결할 수 없었습니다. 단지 젤리로 향했습니다.
Jonathan Allan

시도 n=4하거나 8또는 16하시기 바랍니다.
Titus

@Titus f(2**n)반환 (n+1,n)2**(n+1)-2**n=2**n때문에 문제가 없습니다.
Jonathan Allan

아 ... bin()파이썬 에서 형식은 무엇입니까 ?
Titus

@Titus 그것은 선도적의 문자열입니다 0b, 따라서를 -3.
Jonathan Allan

8

자바 스크립트 (ES6), 73 바이트

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

뺄셈의 경우 첫 번째 숫자는 이진 표현의 자릿수이고 두 번째 숫자는 후행 0입니다. 덧셈의 ​​경우 첫 번째 숫자에서 1을 뺍니다. 이진 표현이 모두 1이고 그 뒤에 0이 있으면 덧셈의 경우를 가정하고 그렇지 않으면 빼기의 경우를 가정합니다. JavaScript에서 B≤30에 대해서만 작동하는 @xnor 버전의 36 바이트 포트 :

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

2
@ETHproductions 확실히, 그러나 나는 36까지 골프를했다.
Neil

내 나쁜, 나는 36 바이트 버전이 170 억 테스트 사례에서 작동하지 않는다고 생각했다.
ETHproductions

@ETHproductions 그것은 비트 단위 연산을 사용했기 때문에 포트 번호를 사용하지는 않았지만 포트를 삭제하지 않았습니다.
Neil

죄송합니다, 여기 다시 있습니다 : n=>[n,0].map(k=>((n&-n)+k).toString(2).length-1)그리고 두 버전 모두 [34,11]마지막 테스트 사례에서 돌아옵니다 (FF 48을 사용하고 있습니다).
ETHproductions

@ETHproductions Aha이므로 두 번째 결과가 30 이하일 때 더 정확하게 작동합니다.
Neil

6

펄, 52 49 32 바이트

이전 솔루션 (49 바이트)

에 +1 포함 -p

STDIN에 입력하십시오 :

pow2.pl <<< 17179867136

pow2.pl

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

그러나 xnor 알고리즘을 사용하고 트위스트를 추가하면 32 바이트가 제공됩니다.

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

코드 만 :

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

이것은 13/9 = 1.444...상당히 반올림하기 때문에 심각한 반올림 오류를 겪습니다 1/log 2 = 1.44269...( log자체도 반올림 오류가 있지만 너무 작아서 13/9의 분석에서 마무리 할 수 ​​있습니다). 그러나 어떤이 이후 2**big - 2** small로 수정됩니다 2** big이되지 이잖아요 않는 로그와에 대한 계산을하기 전에 2**big + 2 * 2**small너무 아래로 잘립니다도 안전합니다 .. 그리고 범위의 다른 측면 2**n+2**(n-1)범위에서 충분히 증가되지 않습니다 [0,64]내가 제대로 (수 없습니다 를 사용하여 정수 범위 이상을 지원 &하면 잘못된 결과가 발생할 수 있습니다 (다수의 곱셈기 1.5는 너무 멀리 떨어져 있습니다).


5

Brachylog , 23 바이트

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

온라인으로 사용해보십시오!

이것은 필요한 것보다 훨씬 빠릅니다. 예를 들어 TIO에서는 여전히 10 초 미만 입니다.

설명

이것은 기본적으로 최적화가없는 공식의 직접적인 전사입니다.

,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
이 문제는 언어 위해 만들어진 것 같습니다 : D
코너 오브라이언

4

파이썬, 69 바이트

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

테스트는 이데온에 있습니다

유효하지 않은 입력은 무엇이든 할 수 있으므로 입력에 정확히 2 비트가 설정되어 있으면 2의 2 제곱의 합이며 그렇지 않으면 (유효한 경우) 일부 비트 수의 실행이됩니다. 단 1 비트의 가능성)과 MSB와 LSB 세트보다 2의 다음 최고 전력의 차이가됩니다.


4

자바 7,142 ,140, 134 바이트

이것은 내가 팁에게 골프에 대한 의견을 주시면 대단히 감사 것입니다! PPCG 내 첫 번째 게시물입니다
덕분에 냉동을 2 바이트를 저장하는

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

언 골프

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

이데온


1
안녕, 매듭! 수수께끼에서 또 다른 방랑자. 40=2**3+2**5예를 들어 작동하지 않는 것 같습니다 . 그것을보고, 나는 왜 전사 오류가 있었는지 알 수 없다 .
Jonathan Allan

1
@JonathanAllan 이제는 잘 작동합니다. 실제로이 줄에서 대괄호가 누락되었습니다. ) 그리고 감사합니다.
Numberknot

1변수를 선언하는 대신 리터럴을 사용할 수 없습니까?
Titus

1
리터럴 1을 사용하면 @TItus 리터럴 1을 사용하면 java에 자동으로 INT 메모리 공간이 할당 되므로이 테스트 케이스 (17179867136)는 불가능합니다.
Numberknot

1
j를 i와 함께 선언 할 수 있습니다.for(int i=-1,j;[...]
Frozn

4

매스 매 티카, 57 54 바이트

LegionMammal978 덕분에 3 바이트를 절약했습니다!

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

실제로 1 개의 적절한 쌍 {a, b}를 모두 인쇄합니다 . 입력을 나타낼 때 나타날 수있는 2Log@#+1최대 값의 상한입니다 (엄격한 상한은 Log [2 #] / Log [2] = 1.44 ... Log [#] + 1입니다). 테스트 입력에서 거의 즉각적으로 실행되며 100 자리 입력에서 1/4 초 (새롭지 만 상용 컴퓨터)에서 실행됩니다.a#

1 분들께 a1 대신 0의 기본 값으로 시작은 2 바이트를 저장; 입력이 2 일 때 출력 {0,0}이 누락되지만이 경우 출력 {2,1}을 찾으면 충분합니다.


모든 * 적절한 쌍? (또한, If[Abs[2^a-#]==2^b,Print@{a,b}]대체 될 수있는 Abs[2^a-#]==2^b&&Print@{a,b}3 바이트를 저장한다.)
LegionMammal978

좋은 관찰, 나는 그것을 얻는다! "모두 *"는 각주 였지만 지금은 더 명확합니다.
Greg Martin

3

MATL , 23 22 바이트

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

온라인으로 사용해보십시오! 또는 모든 테스트 사례를 확인하십시오 .

설명

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

펄 6 , 41 바이트

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

(알고리즘 은 펄 5 답변 에서 뻔뻔스럽게 복사되었습니다 )

설명:

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

용법:

# 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 바이트

Jonathan의 Pyhton 2 솔루션을 54 바이트 (+13 오버 헤드)로 복사 할 수
있었지만 다른 것을 생각해 내고 싶었습니다.

파일에 저장 한 다음 php또는 로 실행하십시오 php-cgi.

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

밑줄로 인쇄 a하고 b분리하며 해결책이 없습니다.

독특한 솔루션, 96 바이트

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

밑줄로 인쇄 a하고 b구분합니다. 해결책이없는 유일한 밑줄.

또한 11 바이트 더 작업을 알려줍니다 .
코드의 첫 번째 밑줄을로 바꿉니다 '-+'[!$m[2]].


echo strlen ($ n = decbin ($ argv [1]))-!! strpos ($ n, '01 ')에서 67을 시도하면'-+ '[! $ n [2]]. strpos (strrev ( $ n), 49); 그것은 나에게 6 +0을 돌려 준다 65
Jörg Hülsermann

@ JörgHülsermann : 67에는 해결책이 없습니다. 솔루션에 대한 동작은 정의되어 있지 않습니다. 67에 인쇄되는 내용은 중요하지 않습니다.
Titus

0

PHP, 117 바이트

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

확장 버전 4 사례

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

짧은 버전 통합 사례 1과 3은 사례 3과 차이를 만들고 두 버전 모두 사례 4는 출력을 제공하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.