从中取出一个字节!


24

给定一个无符号整数n,您的任务是找到可以通过删除单个字节(连续8位)的数据来创建的最大数字。


给定数字7831,我们首先将其转换为二进制(删除所有前导零):

1111010010111

然后,我们找到连续的8位组,将其删除后将产生最大的新结果。在这种情况下,有3个解决方案,如下所示

1111010010111
  ^      ^       
   ^      ^
    ^      ^

删除所有这些收益率11111,然后我们将其转换回其十进制值31作为答案。


测试用例

256        ->   1
999        ->   3
7831       ->   31
131585     ->   515
7854621    ->   31261
4294967295 ->   16777215 (if your language can handle 32 bit integers)

规则

  • 确保的位长n将大于8。
  • 理论上,您的解决方案应适用于n大于8的任何位长,但实际上,仅需要适用于255 <n <2 16的整数
  • 输入/输出应为十进制。
  • 您可以提交完整的程序或功能。
  • 这是,因此最短的程序(以字节为单位)获胜!

1
我不明白为什么人们会在挑战标题中加上惊叹号!我认为这可能是字符限制的事情!可能只是为了让人们注意到挑战!
dkudriavtsev

1
@Mendeleev这是必须的句子。这些通常以感叹号结尾。这只是正确的标点符号,为什么会让您不高兴?
亚瑟

1
@Mendeleev人们经常使用感叹号来表示一个笑话。OP强调了他在做双关语的事实。F.斯科特·菲茨杰拉德(F. Scott Fitzgerald)不喜欢它,但是在这种情况下,对我来说似乎不错。如果不存在,您可能会引起人们抱怨他的拼写。
–bornfromanegg

@Mendeleev,因为这是一个糟糕的双关语
FlipTack

@bornfromanegg我觉得人们会注意到双关语
-dkudriavtsev

Answers:


16

果冻,6 个字节

BḄ-8ƤṀ

单数链接,获取一个数字并返回一个数字。

在线尝试!

怎么样?

使用不错的快速的Ƥ英里开发的...

BḄ-8ƤṀ - Link: number
B      - convert to a binary list
    Ƥ  - for loop over some slices to be determined...
  -8   - this is a negative nilad, therefore: use overlapping outfixes of length 8
       -   (exactly what the specification asks us to inspect)
 Ḅ     -   convert from a binary list to an integer (vectorises)
     Ṁ - maximum

> _> ...哇,您击败了我10字节
Xcoder先生,2017年

8

J,12个字节

[:>./8#.\.#:

在线尝试!

          #:     to binary
     8  \.       remove consecutive groups of eight
      #.         convert each result to decimal
  >./            maximum
[:               do nothing, this lets me avoid parentheses

您在那里有什么漂亮的算法?您能补充说明吗?
Xcoder先生17年

@先生。Xcoder FrownyFrog将数字转换为二进制数字列表(#:),然后转换所有8前缀,或将去除了连续8位后缀的列表转换回十进制数字系统(8#。\。),最后将最大的一个。[:通过使> ./以单子形式执行(仅使用正确的参数)来简单地覆盖前两个动词
Galen Ivanov

您今天教了我关于点名的知识,谢谢!可惜的是,使用under-似乎并不短&.。这是完美的问题。
cole


6

JavaScript(ES6),54个字节

f=(n,v=n>>8,b=1,m=0)=>b>v?m:f(n,(v^n)&b^v,b+b,v>m?v:m)
<input type=number min=256 max=2147483647 oninput=o.textContent=f(this.value)><pre id=o>

适用于2 ** 31-1。因为有人问一个有点混乱的答案...



3

Mathematica,69个字节

Max@Array[Drop[#&@@s,#;;#+7]~FromDigits~2&,Last[s=#~RealDigits~2]-7]&

在线尝试!

该解决方案适用于大型数字在线试用!

来自KellyLowder的-3个字节


再保存3个字节:Max[c=#~RealDigits~2;Array[Drop[c[[1]],#;;#+7]~FromDigits~2&,Last@c-7]]&
Kelly Lowder

1
@KellyLowder不错!我golfed您的解决方案多一点
J42161217


3

Wolfram语言(Mathematica),46字节

Floor@If[#<256,0,Max[#/256,2#0[#/2]+#~Mod~2]]&

在线尝试!

这个版本最多只能处理2 518 -1的输入,否则我们将遇到Mathematica的堆栈大小限制。(Mathematica安装之间的界限可能有所不同。)此答案中的第二个解决方案可以避免这种情况。

怎么运行的

一种基于以下逻辑的递归方法:

  • 最大值应0小于的任何输入256,因为从数字中减去一个字节会吃掉整个数字。这是我们的基本情况,这就是为什么即使规范保证我们也不必处理此类输入,却将其包括在内的原因。
  • 否则,我们采用以下Max两种选择:吃掉最低字节(给我们输入除以256)或砍掉最低位,递归剩余的整数,并在完成后附加最低位。

Wolfram语言(Mathematica),55个字节

Max@Table[Mod[#,m=2^k]+Floor[#/m/2^8]m,{k,0,Log2@#-8}]&

在线尝试!

替代版本生成表而不是递归表,因此适用于Mathematica可以处理的任何大小的数字。


2
尽管mathematica可以处理更大的数字,但大于10 ^ 160的数字会超出递归深度。但我想OP是与它的罚款
J42161217

2

视网膜71 67 64字节

.+
$*
+`(1+)\1
$+0
01
1
.
$`_$'¶
_.{7}

A`_
O^`
1G`
+1`\B
:$`:
1

在线尝试!链接仅包括速度更快的测试用例,以免使Dennis的服务器过载。编辑:由于@MartinEnder,节省了3个字节。说明:

.+
$*
+`(1+)\1
$+0
01
1

从十进制转换为二进制。

.
$`_$'¶
_.{7}

A`_

构造一个通过以所有可能的方式删除8个连续数字获得的字符串列表。

O^`
1G`

以相反的顺序对它们进行排序,然后选择第一个(最大的)。

+1`\B
:$`:
1

转换回十进制。(请参阅@MartinEnder的说明。)


1
不久前,我想到了这种较短的二进制到十进制的转换。我已经在这个答案中解释了它是如何工作的。
Martin Ender


2

ReRegex294个 275字节

通过使用更好的“功能”定义节省了19个字节

我说这对于仅使用Regex的语言来说非常不错。

基本库的确允许在一元和十进制之间进行转换(因为挑战规范明确指出了十进制,所以需要此库),但是不支持二进制。因此,我必须将其编写为脚本的一部分,并向其中添加120个字节。

#import base
b(\d*):(_*)\2_b/b1$1:$2b/b(\d*):(_+)\2b/b0$1:$2b/b(\d+):b/$1/b:b/0/B(_*):1/B$1$1_:/B(_*):0/B$1$1:/B(_*):B/$1/j(\d*),\1(\d)(\d{7})(\d*):/j$1$2,$1$2$3$4:,B:$1$4B/j(\d*),\1\d{0,7}:,?(.*)/,$2,/,((_+)_+),(\2),/,$1,/,(_+),(\1_*),/,$2,/^,(_*),$/d<$1>/j,b:u<(?#input)>b:

在线尝试!

通过个人正则表达式。

#import base
b(\d*):(_*)\2_b/b1$1:$2b/
b(\d*):(_+)\2b/b0$1:$2b/
b(\d+):b/$1/
b:b/0/
B(_*):1/B$1$1_:/
B(_*):0/B$1$1:/
B(_*):B/$1/
j(\d*),\1(\d)(\d{7})(\d*):/j$1$2,$1$2$3$4:,B:$1$4B/
j(\d*),\1\d{0,7}:,?(.*)/,$2,/
,((_+)_+),(\2),/,$1,/
,(_+),(\1_*),/,$2,/
^,(_*),$/d<$1>/
j,b:u<(?#input)>b:

脚步

首先,我们导入“ base”库,该库提供了两个正则表达式。一转换u<numbers>为一元。和一个转换d<unary_underlines>回十进制。这是因为挑战需要在base10中使用IO。

然后,我们定义了少数将一元转换为二进制的正则表达式。

b(\d*):(_*)\2_b/b1$1:$2b/
b(\d*):(_+)\2b/b0$1:$2b/
b(\d+):b/$1/
b:b/0/

首先,b(\d*):(_*)\2_b/b1$1:$2b/搜索b,可选地后跟一些二进制数字,然后是a :,然后是任意数量的下划线,然后是完全相同数量的下划线再加上一个,最后是另一个b

然后,我们将其替换为,b1后跟之前的二进制数字,然后:是下划线的前半部分,最后是下划线b

因此,这将检查一元数是否不能被2整除,如果是,则将1附加为二进制数,然后将其减一并除以二。

第二个b(\d*):(_+)\2b/b0$1:$2b/几乎是无所事事的,但是不检查多余的内容_,这意味着它仅在被二可整的情况下才匹配,在这种情况下,前面要加上a 0

第三个检查我们是否用一位数表示,如果是,则去掉填充以只留下二进制数。

最后一个检查是否从未提供过任何二进制数字,在这种情况下,就离开了0

我们定义的下一组正则表达式将二进制转换回一元,并且稍微简单一些。

B(_*):1/B$1$1_:/
B(_*):0/B$1$1:/
B(_*):B/$1/

该组的第一个B(_*):1/B$1$1_:/,与它的对立相似,检测到a B,然后是任意数量的一进制数字,然后是:1B在这种情况下,它不会检查是否匹配,因为它一次只搜索一位数字。如果匹配,则将先前匹配的一进制数字加倍并加一,然后将其删除。

第二个()B(_*):0/B$1$1:/与第一个几乎一样,只是匹配a 0而不是a 1,并且不添加额外的一进制数字。

其中的最后一个B(_*):B/$1/,检查是否没有更多的二进制数字,如果是,则解开一进制。与其对立面不同,这不需要特殊的0情况。

接下来,我们定义正则j表达式,它们充当拆分功能。

j(\d*),\1(\d)(\d{7})(\d*):/j$1$2,$1$2$3$4:,B:$1$4B/
j(\d*),\1\d{0,7}:,?(.*)/,$2,/

首先,j(\d*),\1(\d)(\d{7})(\d*):/j$1$2,$1$2$3$4:,B:$1$4B/完成大部分繁重的工作。它搜索j,可选地后面跟着二进制数字,它们是“增量器”,然后是逗号,接着是增量器,然后是正好8个二进制数字,再跟其余的二进制数字,然后是a :。8位数字中的第一个数字附加到增量器上,从而对其进行递增,然后将二进制输入中除那8位数字之外的所有数字附加在:后面的a 后面,。因此(如果我们使用2位数而不是8位数)j,1001:将变为j1:1001:,01then j10:1001,01,11。此外,将附加的数组元素包装在中B,以将它们转换回一元。

另一个j(\d*),\1\d{0,7}:,?(.*)/,$2,/检查增量器之后是否还剩下少于8个二进制数,如果是,则除去包裹在,s中的数组以外的所有内容。例如。,_,___,

在创建数组期间和之后,我们定义比较正则表达式。

,((_+)_+),(\2),/,$1,/
,(_+),(\1_*),/,$2,/

首先,,((_+)_+),(\2),/,$1,/检查逗号,然后加上下划线,然后再检查逗号,再检查逗号,再加上下划线。然后用,s 包围的第一个元素中的下划线总数替换它。

后者,(_+),(\1_*),/,$2,/检查一个逗号,然后是下划线,然后是另一个逗号,然后是相同数量或更多的下划线,最后是逗号。相反,这将保留正确的元素。

最后,当剩下的元素如此匹配时^,(_*),$,我们删除周围的逗号并通过将其转换回十进制d<>。然后,不再有正则表达式可以触发并显示输出。

首先将输入放入模板中j,b:u<(?#input)>b:,该模板首先将十进制输入转换为一进制,例如5-> j,b:_____b:,然后将结果一元转换为二进制,j,101:然后拆分二进制(对于示例而言无效),获得最大的元素,然后进行转换返回十进制,然后完成。


2

C(gcc),91个字节

j;m;t;f(x){for(j=m=0;t=x>>j+8;m<t?m=t:j++)t=t<<j|x%(1<<j);return m;}

来自Colera Su的 -23个字节

最多支持 2**31-1

在线尝试!

从低8位开始(j=0),然后上升,如果[j,j+8)切除的位数大于我们的当前位数,则更改输出,并一直持续到x的位数不超过j+8


2
存储x>>j+8x>>j+8<<j|x%(1<<j)在一个变量(除去括号)中将其减少到68个字节
Colera Su


1

JavaScript(ES6),94 91字节

-3个字节,感谢Justin Mariner

f=(n,d='',c=n.toString(2).match(`(${d}).{8}(.*)`))=>c?Math.max('0b'+c[1]+c[2],f(n,d+'.')):0

只是抛出了一个基于JavaScript字符串的解决方案,但我希望有人能够发布一个单独的基于位的解决方案,以便我可能学到一些东西。

我的解决方案递归地从字符串中获取8位块,并采用找到的最大值。


1
我认为您可以删除+(...)转换'0b'+c[1]+c[2]为数字的,因为Math.max已经这样做了。在线尝试!规范以供将来参考
贾斯汀·马里纳

@JustinMariner,甜蜜,谢谢!
里克·希区柯克

1

C#(.NET Core)122 + 13 = 135 120 + 13 = 133字节

n=>{int m=0,i=0,t;for(var b=Convert.ToString(n,2);i<b.Length-7;m=t>m?t:m)t=Convert.ToInt32(b.Remove(i++,8),2);return m;}

在线尝试!

+13 using System;

我想象有一种无需使用即可完成此操作的方法Convert。无论哪种方式,我都可以减少。

致谢

-2个字节,感谢Kevin Cruijssen

松散

n=>{
    int m=0,
        i=0,
        t;

    // convert n to a binary string,
    // go through removing each possible byte,
    // check if this is the biggest int so far
    for (var b=Convert.ToString(n,2); i<b.Length-7; m=t>m?t:m)
        t=Convert.ToInt32(b.Remove(i++,8),2); // remove 8 bits from position i, then convert from binary string to int

    return m;
}

您可以通过更改保存一个字节whilefor并把var b它:for(var b=Convert.ToString(n,2);i<b.Length-7;)
凯文Cruijssen

您可以通过添加新的int变量,t而不使用来节省1个字节Math.Max,而是使用手动检查代替:n=>{int m=0,i=0,t;for(var b=Convert.ToString(n,2);i<b.Length-7;m=t>m?t:m)t=Convert.ToInt32(b.Remove(i++,8),2);return m;}120 + 13个字节
Kevin Cruijssen

1

PHP,67 + 1字节

do$r=max($r,$argn&($x=2**$i++-1)|$z=$argn>>8&~$x);while($z);echo$r;

与管道一起运行-nR在线尝试


1

Pyth,19个字节

eSmi.>>.<.BQd8d2a6l

替代答案:

eSmi.<<8.>.BQdd2a6l

说明:

eSmi.>>.<.BQd8d2a6lQ | Implicit Q at the end, where Q = input
  m             a6lQ | Map the over [0, 1, 2, ... , floor(log base 2 of Q) - 7]
         .BQ         |  Convert Q to binary string
       .<   d        |  Cyclically rotate left by d
      >      8       |  Get string from position 8 to end.
    .>        d      |  Cyclically rotate right by d
   i           2     |  Convert from binary string to integer
eS                   | Find the last element of sorted list (maximum value)

另一个答案使用类似的方法,除了它首先向右旋转,然后获取除最后8位以外的所有位。


1

MATL23 21字节

Bn8-:"GB[]@8:q+(XBvX>

在线尝试!

B                       % Implicitly grab input, convert to binary
 n8-:                   % Create list of 1,2,... n-8, with n the size of the binary string
     "                  % Loop over this list
      GB                % Grab the input again, convert to binary once more.
        @8:q+           % Create indices of a slice of length 8
             [](        % Index into binary string, delete the slice
                XB    % Convert the remainder from binary to integer
                  vX> % Get the maximum number so far.

可悲的是,Bn8-:8:!+q&)仅产生要删除的切片,而我们不想保留的其余部分。


这节省了几个字节:Bn8-:"GB[]@8:q+(XBvX>(分配[](代替使用&),并更换&::和加法)
路易斯Mendo

@LuisMendo谢谢。我误读了文档,该文档在某处说您只能将单个索引用于空赋值,但只能用于其他情况。
Sanchises


0

八度81 80字节

@(x)max(bin2dec(dec2bin(x*(c=2.^(0:(b=nextpow2(x+1)-8))))(:,[1:b b+9:end]))'./c)

在线尝试!

这是我最初尝试的另一种解决方案,另外节省了14个字节。

代码分解如下:

@(x)max(                                                                       )
        bin2dec(                                                          )'./c
                                                         (:,[1:b b+9:end])
                dec2bin(x*(                            ))
                           c=2.^(0:                   )
                                   (b=nextpow2(x+1)-8)

在第六行,通过找到比输入大的下一个幂2的指数(输入数的位数),并减去7来计算组数,因为我们要从每组中删除8位-结果数为存储在b以后。

然后,我们在第五行计算一个2的幂的数组,该数组足够大,可以删除所有可能的组。我们将其保存在变量中c以备后用。

在下一行(第四行)中,我们将输入乘以2的幂的数组(实际上是将每个数字向上移位),然后将结果转换为二进制。如果我们以7831为例,这将导致包含以下内容的2D数组:

000001111010010111
000011110100101110
000111101001011100
001111010010111000
011110100101110000
111101001011100000

如果我们随后将中心的8位切掉,则相当于删除每组8位。这是通过第三行完成的。

结果数组在第二行转换回十进制。我们还必须除以c撤销最初对每个组所做的缩放。

最后,在第一行声明一个匿名函数,并计算所有组的最大值。


  • 使用nextpow2(x+1)而不是保存1个字节nnz(bin2dec(x))


原始尝试-120 98 95字节

@(x)max(bin2dec(reshape(repmat(a=(d=@dec2bin)(x)',1,b=nnz(a)-7)(d(255*2.^(0:b-1))'<49),[],b)'))

在线尝试!

代码如下:

@(x)max(                                                                                      )
        bin2dec(                                                                             )
                reshape(                                                              ,[],b)'
                        repmat(a=(d=@dec2bin)(x)',1,b=nnz(a)-7)(                     )
                                                                d(255*2.^(0:b-1))'<49

基本上,它会计算一个包含可能要删除的值组的矩阵,然后算出最终给出最大数字的矩阵。

第五行逐行工作,计算可以删除的组。例如,取7831。这是一个13位数字,给出了组:

1111100000000
1111000000001
1110000000011
1100000000111
1000000001111
0000000011111

第五行的结果是可用于索引的2D逻辑数组。

代码的第四行将输入转换为一个位数组(表示为字符“ 0”和“ 1”),然后将其复制n-7次(n以位数表示),为每种可能的分组分配一行。上面的组掩码用于删除每个可能的组。

然后,在第三行上,对结果进行整形,以消除由于应用组蒙版而导致的不必要的展平。第二行转换回产生的十进制数字数组。第一行将匿名函数定义为可能组数组的最大值。


  • 通过使用数学生成组矩阵节省了22个字节。
  • 从二进制字符串到逻辑组掩码的转换节省了3个字节。



0

Perl,53个字节

use 5.10.1将perl提升到语言水平5.10.1的操作是免费的)

在STDIN上输入输入号码。大数字将耗尽内存,但是输入中的32位数字仍然不是问题

#!/usr/bin/perl
use 5.10.1;
$_=sprintf"%b",<>;/.{8}(?{\$F[oct"0b$`$'"]})^/;say$#F
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.