两个的两个幂的和或差


27

如果您选择接受它,那么您面临的挑战是,给定整数K >= 1,找到非负整数,A并且B 使以下两个条件中的至少一个成立:

  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吗?
丹尼斯

2
@丹尼斯,我不明白为什么不这样做。
科纳·奥布赖恩

...和16,对于5,43,3都有效。
泰特斯(Titus)2016年

实际上,我现在考虑AB可以否定吗?(例如-1, -11)
Sp3000

@ Sp3000不,很好。
Conor O'Brien

Answers:


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

Python 2,43个字节

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

n==2^a ± 2^ba>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中的paren的长度增加了一个字节for k in(n,0)]

*除了2^a + 2^bwith a==b+1具有更长的位长,但这很好,因为我们可以将其解释为2^(a+1)-2^b


太好了-我找了些小提琴,但无法解决,只能移植到果冻。
乔纳森·艾伦

尝试n=4816讨好。
泰特斯(Titus)

@Titus f(2**n)返回(n+1,n)2**(n+1)-2**n=2**n因此没有问题。
乔纳森·艾伦

啊... bin()Python 的格式是什么?
泰特斯(Titus)2013年

@Titus是带前导的字符串0b,因此是-3
乔纳森·艾伦

8

JavaScript(ES6),73个字节

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

对于减法情况,第一个数字是二进制表示形式的位数,第二个数字是尾随零的数量。对于加法情况,我们从第一个数字中减去1。如果二进制表示形式全为1,然后为0,则假定为加法情况,否则为减法情况。@xnor版本的36字节端口,仅适用于JavaScript中的B≤30:

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

2
@ETHproductions可以,但是我打到了36。–
Neil

不好意思,我认为36字节的版本不适用于170亿个测试用例。
ETHproductions's

@ETHproductions它没有,但是您的端口也没有,正如我记得的那样(注释删除,叹气),因为它使用了按位运算。
尼尔

抱歉,再次出现:n=>[n,0].map(k=>((n&-n)+k).toString(2).length-1)两个版本都[34,11]在最后一个测试用例上返回(我使用的是FF 48)。
ETHproductions's

@ETHproductions Aha,因此更准确地说,当第二个结果为30或更小时,它们可以工作。
尼尔

6

Perl,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
Conor O'Brien

4

Python,69个字节

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

测试在ideone上

由于无效输入可以执行任何操作,因此我们知道如果输入恰好设置了2位,则它是这2的2的幂的和,否则(如果有效)它将是一些位数的乘积(包括(可能只有1位),并且将是MSB和LSB设置的下一个最高功率2之差。


4

JAVA 7,142140,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现在工作正常。实际上,这一行缺少括号if((a << i)+(a << j)== n |(a << j)-(a << i)== n ),谢谢。
Numberknot

您不能使用文字1而不是为其声明变量吗?
泰特斯(Titus)2013年

1
@TItus如果我使用文字1,那么将无法使用该testcase(17179867136),因为如果您使用文字1,则Java将自动为其分配一个INT内存空间。
Numberknot

1
您可以与i一起声明j:for(int i=-1,j;[...]
Frozn

4

Mathematica,57 54字节

感谢LegionMammal978,节省了3个字节!

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

实际上打印出所有1对适当的对{a,b}。2Log@#+1a表示输入时可能出现的最大值的上限#(严格的上限是Log [2#] / Log [2] = 1.44 ... Log [#] + 1)。在测试输入上几乎立即运行,并在不到四分之一秒(在我的新的但现成的计算机上)上运行100位输入。

1点a在1而不是默认值0开始保存两个字节; 当输入为2时,它会导致输出{0,0}被遗漏,但在这种情况下,找到输出{2,1}就足够了。


所有*合适的对吗?(此外,If[Abs[2^a-#]==2^b,Print@{a,b}]可以替换为Abs[2^a-#]==2^b&&Print@{a,b}以节省3个字节。)
LegionMammal978

不错的观察,我明白了!“全部*”是一个脚注,但现在更清楚了。
格雷格·马丁

3

MATL23 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

Perl 6,41个字节

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

(从Perl 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);

打印ab用下划线分隔,任何没有解决方案的东西。

独特的解决方案,96字节

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

打印ab用下划线分隔;没有解决方案的唯一下划线。

它甚至还告诉您11个字节的操作:
只需将代码中的第一个下划线替换为'-+'[!$m[2]]


如果我在echo 67中尝试67 strlen($ n = decbin($ argv [1]))-!! strpos($ n,'01').'- +'[!$ n [2]]。strpos(strrev( $ n),49); 它给我靠背6 + 0,这是65
约克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均不输出。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.