输出数字最大为2 ^ n-1,“已排序”


38

以一个正整数n作为输入,并输出可以使用n位创建的(一些)十进制数,按以下方式排序:

首先列出仅可以使用一个创建的所有数字,1其余0以二进制表示形式(已排序)列出,然后使用两个连续的 1,其余的0,然后连续的 三个依次创建的所有数字1

让我们看一下n = 4的情况

0001  -  1
0010  -  2
0100  -  4
1000  -  8
0011  -  3
0110  -  6
1100  -  12
0111  -  7
1110  -  14
1111  -  15

因此,n = 4的输出为:1、2、4、8、3、6、12、7、14、15(可选输出格式)。

测试用例:

n = 1
1

n = 2
1 2 3

n = 3
1, 2, 4, 3, 6, 7

n = 8
1, 2, 4, 8, 16, 32, 64, 128, 3, 6, 12, 24, 48, 96, 192, 7, 14, 28, 56, 112, 224, 15, 30, 60, 120, 240, 31, 62, 124, 248, 63, 126, 252, 127, 254, 255

n = 17
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 3, 6, 12, 24, 48, 96, 192, 384, 768, 1536, 3072, 6144, 12288, 24576, 49152, 98304, 7, 14, 28, 56, 112, 224, 448, 896, 1792, 3584, 7168, 14336, 28672, 57344, 114688, 15, 30, 60, 120, 240, 480, 960, 1920, 3840, 7680, 15360, 30720, 61440, 122880, 31, 62, 124, 248, 496, 992, 1984, 3968, 7936, 15872, 31744, 63488, 126976, 63, 126, 252, 504, 1008, 2016, 4032, 8064, 16128, 32256, 64512, 129024, 127, 254, 508, 1016, 2032, 4064, 8128, 16256, 32512, 65024, 130048, 255, 510, 1020, 2040, 4080, 8160, 16320, 32640, 65280, 130560, 511, 1022, 2044, 4088, 8176, 16352, 32704, 65408, 130816, 1023, 2046, 4092, 8184, 16368, 32736, 65472, 130944, 2047, 4094, 8188, 16376, 32752, 65504, 131008, 4095, 8190, 16380, 32760, 65520, 131040, 8191, 16382, 32764, 65528, 131056,16383, 32766, 65532, 131064, 32767, 65534, 131068, 65535, 131070, 131071

这是,因此每种语言中最短的代码胜出!

强烈建议您提供很好的解释,也要提供“普通语言”的解决方案!



2
@zeppelin我一开始也这么认为,但是这个非常不同。
ETHproductions'2

1
有关。(略)
马丁安德

6
如果有人在没有任何形式的基础转换的情况下(使用简单的旧数学)执行此操作,将获得虚构的奖励。
Stewie Griffin'2

写这是两者之间的混合,我想在线尝试!
PrincePolka '18

Answers:


38

Python,53字节

f=lambda n,i=1:n*[f]and[i]+f(n-1,2*i)+i%2*f(n-1,i-~i)

在线尝试!

递归函数生成排序列表,作为沿着这棵树的预订(例如n=4):

      1
     / \
    2   3
   /   / \
  4   6   7
 /   /   / \
8   12  14  15

1 2 4 8 3 6 12 7 14 15

左分支的值是该值的两倍,而右分支则是i->i*2+1并且仅存在于奇数i。因此,非叶子的预订步行为T(i)=[i]+T(i*2)+i%2*T(i*2+1)

树终止于depth n,即n输入的位置。这是通过n在每次降低时递减并在其为0时停止来实现的。

一种替代策略是终止于i超过的值2**n,而不是跟踪深度。我发现这要再长一个字节:

f=lambda n,i=1:2**n/i*[f]and[i]+f(n,2*i)+i%2*f(n,i-~i)
f=lambda n,i=1:[f][i>>n:]and[i]+f(n,2*i)+i%2*f(n,i-~i)

4
哇。这不仅是一个非常酷/聪明的把戏,而且非常有效。+1,非常好回答!
DJMcMayhem

2
[f]是一个有趣的接触,不能说我以前见过。
FryAmTheEggman

18

果冻,6个字节

Ḷ2*ẆS€

这符合想象中的奖金

在线尝试!

这个怎么运作

Ḷ2*ẆS€  Main link. Argument: n

Ḷ       Unlength; yield [0, ..., n-1].
 2*     Yield [2**0, ..., 2**(n-1)].
   Ẇ    Sliding window; yield all subarrays of consecutive elements.
        The subarrays are sorted by length, then from left to right.
    S€  Map the sum atom over the substrings.

1
是针对此挑战的理想内置组件,并且已实现,因此结果以正确的顺序应对此挑战。做得好:-)
ETHproductions '17

这不是12个字节(至少在UTF-8中)吗?
Gareth

1
@Gareth是的,但是Jelly也支持单字节字符集,其中仅包含它可以理解的256个符号。
丹尼斯,

9

Mathematica,40个字节

Join@@Table[2^j(2^i-1),{i,#},{j,0,#-i}]&

所需列表中的每个数字都是2的2的幂的差,因此我们只需按顺序生成它们Table,然后使用平坦的列表即可。我认为这可以赚到Stewie Griffin的想象中的奖金:)

Mathematica,35个字节

Tr/@Rest@Subsequences[2^Range@#/2]&

Dennis的Jelly算法的一个端口。我之前不知道Subsequences!(我也没有看到英里已经发布了这个确切的答案 ...快去投票吧!)


1
注意:此解决方案与@mile的Mathematica代码相同,该代码在@GregMartin编辑之前5个小时发布。但是,根据元共识,此答案仍然有效。
JungHwan Min

gh,我没看到,感谢您指出来。
格雷格·马丁

8

JavaScript(ES6),59 58 55字节

for(q=prompt(n=1);p=q--;n-=~n)for(m=n;p--;m*=2)alert(m)

一个完整的程序,通过提示输入并连续警告每个数字。这也有资格获得假想的奖金

测试片段

(注意:使用console.log代替alert


建议(在必须选中“不要再显示弹出窗口”之后):更改为console.log以获取测试代码段。
Tejas Kale

@TejasKale好主意,谢谢!
ETHproductions's

7

JavaScript(ES6),55 51字节

返回以空格分隔的整数列表。

n=>(F=k=>k>>n?--j?F(k>>j|1):'':k+' '+F(k*2))(1,j=n)

虚构的奖金友善。

格式化和评论

n => (                    // main function, takes n as input
  F = k =>                // recursive function, takes k as input
    k >> n ?              // if k is greater or equal to 1 << n:
      --j ?               //   decrement j ; if j is > 0:
        F(k >> j | 1)     //     do a recursive call with an additional bit set
      :                   //   else
        ''                //     stop recursion
    :                     // else
      k + ' ' + F(k * 2)  //   append k to output and do a recursive call with k * 2
  )(1, j = n)             // start the recursion with k = 1 and j = n

测试用例



6

Mathematica,35个字节

Tr/@Rest@Subsequences[2^Range@#/2]&



4

Haskell,47个字节

f n=[1..n]>>= \b->take(n-b+1)$iterate(2*)$2^b-1

用法示例:f 4-> [1,2,4,8,3,6,12,7,14,15]在线尝试!

工作原理:每个号码b[1..n],开始2^b-1和反复双重价值,并采取n-b+1从这个列表中的元素。



4

Groovy,90 89字节

{(0..<2**it).collect{0.toBinaryString(it)}.sort{it.count("1")}.collect{0.parseInt(it,2)}}

二进制转换太笨拙了。

-1感谢Gurupad Mamadapur


3
28字节的二进制转换样板,非常痛苦。
魔术章鱼缸

1
{(1..<2**it)...保存一个字节。
Gurupad Mamadapur


3

Bash + Unix实用程序,51字节

dc<<<2i`seq -f%.f $[10**$1-1]|grep ^1*0*$|sort -r`f

在线尝试!

输入n在参数中传递。

使用seq打印n个或更少数字的所有数字。(这些是以10为底的数字,因此这里有很多额外的数字。这既浪费又费时,但这就是代码高尔夫!)

对grep的调用仅保留正好由1和0组成的数字。

然后使用sort -r按相反的字典顺序对它们进行排序。

最后,dc设置为以2为基数的输入-将排序后的数字压入堆栈,然后从上至下打印堆栈。(这将打印出最后一个按入的最后一个项目,等等,这就是为什么我使用sort -r而不是sort的原因。)

更正了一个错误:我已经省略了-eq%f选项给seq,从1000000开始的整数计数需要此选项。(感谢@TobySpeight指出存在问题。)


浪费和费时 ”…… 聪明!谢谢您-提醒您在打高尔夫球时故意忽略计算效率。当您余下的时间都在编写快速清晰的代码时,这真的很难...
Toby Speight

缺少一些值:dc<<<2i`seq $[10**7-1]|grep ^1*0*$|sort -r`f | wc -仅报告12个值。我想你想grep ^1[01]*$代替。
Toby Speight'2

@TobySpeight谢谢-有一个错误,我已更正。问题不在于正则表达式。问题是seq需要一个选项。(我不确定为什么您只得到12个输出值-即使不正确的版本也产生了21个正确的28个输出值。如果您在TIO上运行它,则可能已经超过了TIO的1分钟时限。)我已经在Linux和OS X上对此进行了测试。
米切尔·史佩克特

1
实际上,我误解了这个问题-“连续”这个重要词以某种方式直接越过了我!
Toby Speight


2

Perl 6、38个字节

->\n{map {|(2**$_-1 X+<0..n-$_)},1..n}

这个怎么运作

->\n{                                }  # A lambda with argument n.
                                 1..n   # Numbers from 1 to n.
     map {                     },       # Replace each one with a list:
            2**$_-1                     #   2 to that power minus 1,
                    X+<                 #   bit-shifted to the left by each element of
                       0..n-$_          #   the range from 0 to n minus the number.
          |(                  )         #   Slip the list into the outer list.

即它构造这样的数字:

1 2 4 8 = (2^1)-1 bit-shifted to the left by 0 1 2 3 places
3 6 12  = (2^2)-1 bit-shifted to the left by 0 1 2   places
7 14    = (2^3)-1 bit-shifted to the left by 0 1     places
15      = (2^4)-1 bit-shifted to the left by 0       places      n rows
                                                  
             n                                     n-1

编码:


Perl 6,44个字节

->\n{map {|(2**$_-1,* *2...^*>2**n-1)},1..n}

这是我想到上述(实际上更简单)的移位解决方案之前的第一种方法。

这个怎么运作

->\n{                                      }  # A lambda with argument n.
                                       1..n   # Numbers from 1 to n.
     map {                           }        # Replace each one with:
            2**$_-1                              # 2 to that power minus 1,
                   ,* *2                         # followed by the result of doubling it,
                        ...^                     # repeated until (but not including)
                            *>2**n-1             # it's larger than 2^n-1.
          |(                        )            # Slip the list into the outer list.

即它构造这样的数字:

1 2 4 8 = (2^1)-1, times 2, times 2, times 2
3 6 12  = (2^2)-1, times 2, times 2
7 14    = (2^3)-1, times 2
15      = (2^4)-1                                 n rows
                                    
             n                       as many columns as possible in
                                     each row without exceeding (2^n)-1

2

Haskell 59 46字节

我开始与 f n=[0..n]>>= \b->take(n-b).iterate(*2).sum.map(2^)$[0..b]

从以上nimi的答案中sum.map(2^)$[0..x]可以得出的见解可以浓缩为2^x-1

结束于

e n=[1..n]>>= \x->map(\y->2^y*(2^x-1))[0..n-x]

[1..n] -列出我们要循环通过的连续位数

>> =-大致翻译左侧列表中的每个元素,将其传递到右侧的函数中,并连接所有结果

\ x-> -带一个参数的lambda函数声明

映射xy-将函数x应用于列表y的所有成员

在我们的例子中,x = (\ y-> 2 ^ y *(2 ^ x-1)) -另一个lambda函数2 ^ y *(2 ^ x-1))。该公式由两个二进制数的右加零(例如0001到0010)相乘而得。2 ^ x-1是我们正在使用的位数。因此对于11我们有2 ^ 0 * 3(即完全不移动)== 0011,然后2 ^ 1 * 3 = 0110然后2 ^ 2 * 3-1100。

[0..nx]生成可以移位多少次的列表。如果我们使用单个1,则查看0001,我们想移动3次(4-1)。如果我们工作两个11,我们想要4-2,依此类推。


2

Python 3,59个字节

注意:这与ovsDennis的解决方案无关,尽管两者非常相似。

lambda n:[(2<<i)-1<<j for i in range(n)for j in range(n-i)]

这个怎么运作:

for i in range(n)for j in range(n-i)  # Iterate over number of ones, then number of places
                                      # shifted over. i = ones, j = shifts

(2<<i)                                # Create a one followed by i zeroes
      -1                              # Subtract one from above to get i ones.
        <<j                           # Shift j places.

在线尝试!

始终欢迎提示(包括编码和现金)!


2

Japt,11个字节

o@o!²ãXÄ mx

在线测试!

说明

这几乎使用@Dennis的方法:

o@ o!²  ãXÄ  mx
oX{o!p2 ãX+1 mx}
                  // Implicit: U = input integer
oX{            }  // Create the range [0...U) and map each item X by this function:
   o              //   Create the range [0...U)
    !p2           //     and map each item Z to 2.p(Z); that is, 2**Z.
                  //     (p2 would map each item Z to Z.p(2); ! reverses the arguments.)
        ãX+1      //   Get all overlapping slices of length X + 1.
             mx   //   Map each of these slices Z through Z.x(); that is, sum each slice.
                  // Implicit: output result of last expression


2

PHP,59 56 53字节

for(;$p>($k*=2)?:($p=1<<$argn)>$k=$i+=$i+1;)echo$k,_;

接受STDIN的输入;与运行-R

分解

for(;$p>($k*=2)         // 3. inner loop: shift-0 $k while $k<$p (false in first iteration)
    ?:
    ($p=1<<$argvn)      // 1. init $p=2^N, outer loop:
    >$k=$i+=$i+1        // 2. shift-1 $i while $i<$p, init $k to new $i
;)
    echo$k,_;           // 4. print $k

您可以使用$argn很好的主意。阅读我在我的头上有超过200字节的解决问题后
约尔格Hülsermann

@JörgHülsermann感谢您提醒我STDIN。我只是喜欢合并循环。
泰特斯

1

J,19个字节

(0-.~&,>:+/\2&^)@i.

这使用@Dennis 解决方案中的相同方法。

在线尝试!

说明

(0-.~&,>:+/\2&^)@i.  Input: integer n
                 i.  Range [0, 1, ..., n-1]
(              )@    Operate on that range
            2&^        Compute 2^x for each x in that range
       >:              Increment each in that range
           \           For each overlapping sublist of size (previous) in powers of 2
         +/              Reduce by addition
 0                     The constant 0
     &,                Flatten each
  -.~                  Remove zeroes

1

Python 3,91个字节

a=int(input())
print(*[int('1'*-~b,2)<<c for b in range(a)for c in range(a-b)],sep=', ')

完整程序,按指定的逗号和空格分隔输出。

说明:

星号符号可解压缩列表。因此print(*[1,2,3])与相同print(1,2,3)。向int()构造函数传递一个连续的'1'字符串。

-~b的计算结果为b+1,但是在乘以字符串时不必用方括号括起来。

对生成的整数进行位移位的次数越来越多。print()具有可选的sep参数,用于指定要在解压缩列表中每个项目之间插入的字符串。


2
您可以只打印列表。输出格式不是很严格。
mbomb007 '17

1

Java 7,108字节

static void x(int i){int a=0,t=1<<i,b;while((a=(a<<1)+1)<t){b=a;do System.out.println(b);while((b<<=1)<t);}}

只要结果小于,就将初始值加倍2^n。之后,将初始值更新为(initial_value * 2) + 1,然后从那里重新开始,直到最终达到(2^n)-1

例如n=4

0001 -> init
0010
0100
1000
return, double init and add one
0011 -> init
0110
1100
return, double init and add one
0111 -> init
1110
return, double init and add one
1111 -> init
done

在线尝试!


1

Ruby,50个字节

->r{1.upto(r){|x|p a=2**x-1;p a while(a*=2)<2**r}}

我尝试了一些“聪明”的方法,但这似乎是最短的方法(按照说明进行操作)

说明:

每次迭代都从2 ^ n-1开始,然后乘以2,直到达到上限。没什么,只是基础数学。


1

QBIC,37个字节-想象中的奖励=仍为37个字节...

:[a|e=2^b-1┘while e<2^a┘?e┘e=e*2┘wend

不好意思,我尚未内置while-wend到QBIC中。

:       Get N from the command line
[a|     For b = 1 to N; The sequence is reset N times
e=2^b-1 Set the first number of this sub-sequence (yields 1, 3, 7, 15 ...)
┘       Line-break - syntactic separation of commands because there's no command for WHILE yet.
while   Pure QBasic code - lower-case is not (really) interpreted by QBIC
e<2^a   Continue as long as we don't exceed the maximum value
┘?e     Print the number in the sequence
┘e=e*2  Double the number
┘wend   And loop as long as we're not exceeding maximum, reset the sequence otherwise.
        FOR loop auto-closed by QBIC

编辑:QBIC现在支持WHILE

:[a|e=2^b-1≈e<2^a|?e┘e=e*2

这只有26个字节!这是WHILE

≈e<2^a|          ≈ = WHILE, and the TRUE condition is everything up to the |
       ...       Loop code goes here
          ]      Close construct: adds a WEND instruction
                 In the program above, this is done implicitly because of EOF.


1

R69 48 46字节

n=scan();for(i in 1:n)print((2^i-1)*2^(i:n-i))

i in 1..n二进制系统中与一对应的每个十进制数都乘以2^(0..n-i),即二的第一n-i+1幂(1、2、4,...)。

在线尝试!


1

Stax,9 个字节

übg▓}╥é►╪

在线运行和调试!

说明

如果有人在没有任何形式的基础转换的情况下(使用简单的旧数学)执行此操作,将获得虚构的奖励。

好吧,这里没有基本转换。

使用解压后的版本(10字节)进行解释。

m|2vx_-DQH
m             For input=`n`, loop over `1..n`
 |2v          Power of two minus one
    x_-D      Do `n-j` times, where `j` is the current 1-based loop index
        Q     Output the current value
         H    And double it

0

批,92-0 = 92字节

@for /l %%i in (1,1,%1)do @for /l %%j in (%%i,1,%1)do @cmd/cset/a"(1<<%%i)-1<<%%j-%%i"&echo(

@StewieGriffin的假想奖金减去0。

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.