种植二元森林!


24

A014486的启发。

挑战

给定以10为底的整数输入,构造一个与输入对应的二进制森林的表示形式。表示形式包括但不限于嵌套数组和字符串。

怎么样?

将输入转换为二进制。1s代表分支,0s代表叶子。

为了使它更容易理解,我们以834(二进制的1101000010)为例。


我们从第一个数字开始。第一位数字是1,因此我们绘制分支:

\ /
 1个

或作为数组, {{1}}


下一个数字是1,因此我们绘制了更多分支(从左到右):

\ /
 1个
  \ /
    1个

或作为数组, {{1, {1}}}


下一位数字是0,因此我们放置了一片叶子:

0
 \ /
  1个
   \ /
     1个

或作为数组, {{1, {1, 0}}}


下一个数字是1,因此我们放置一个分支:

     \ /
0 1
 \ /
   1个
      \ /
         1个

或作为数组, {{1, {1, 0, {1}}}}


重复此过程,我们在第8位数字之后获得以下树:

    0 0
     \ /
0 1
 \ /
   1 0
      \ /
         1个

或作为数组, {{1, {1, 0, {1, 0, 0}}, 0}}


对于其余的数字,我们绘制更多的树:

第9位数字是0,因此我们放置了一片叶子(哇,这是嫩芽!)

    0 0
     \ /
0 1
 \ /
   1 0
      \ /
         1 0

或作为数组, {{1, {1, 0, {1, 0, 0}}, 0}, 0}


当我们使用所有数字时,我们最终得到:

    0 0
     \ /
0 1
 \ /
   1 0 0
      \ / \ /
         1 0 1

或作为数组, {{1, {1, 0, {1, 0, 0}}, 0}, 0, {1, 0}}


看起来很奇怪,所以我们填充零以完成树:

    0 0
     \ /
0 1
 \ /
   1 0 0 0
      \ / \ /
         1 0 1

或作为数组, {{1, {1, 0, {1, 0, 0}}, 0}, 0, {1, 0, 0}}

请注意,将数组展平会产生二进制的原始数字,但填充了零。

标准

  • 输出必须清楚地显示树和分支的分隔(如果它不是嵌套数组,请解释您的输出格式)。
  • 从输出中提取所有数字必须与输入的二进制表示相同(带有上述过程中填充的零)。

测试用例

只要符合条件,输出可能会有所不同。

0-> {0}
1-> {{1,0,0}}
44-> {{1,0,{1,{1,0,0},0}}}
63-> {{1,{1,{1,{1,{1,{1,0,0},0},0},0},0},0}}
404-> {{1,{1,0,0},{1,0,{1,0,0}}}}
1337-> {{1,0,{1,0,0}},{1,{1,{1,0,0},{1,0,0}},0}}

计分

这是,因此最低字节为准!


5
我会避免使用奖金 -通常不会改善挑战。
桑契斯

1
@Sanchises我添加了奖金,以查看可视化的答案...我还能如何鼓励人们尝试将可视化作为输出?
JungHwan Min

4
(您的评论)需要吗?
msh210 '16

1
@JungHwanMin看看我更详细的链接(尤其是评论);或者,在同一个Meta问题中,答案。您当前的问题要求张贴者创建2 ^ 2 = 4个程序,并在提交最佳评分程序之前计算每个程序的分数。当您认为它带来了更好的挑战时,可以选择它;或者,如果您认为它带来了更严峻的挑战,则将其删除。
桑契斯

2
@JungHwanMin公平。他们必须提交3个程序并计算每个分数,然后再提交答案。您在这里所面临的是三个挑战。我建议将可视化发布为一个单独的挑战。
桑契斯

Answers:


2

JavaScript(ES6),96 89 80 79 74 73字节

f=($,_=~Math.log2($))=>0>_?[(g=f=>$&1<<~_++&&[1,g(),g()])(),...f($,_)]:[]
<input type="number" value="1337" oninput="document.querySelector('#x').innerHTML=JSON.stringify(f(+this.value))"/><br/><pre id="x"></pre>

定义一个f返回嵌套数组的函数。HTML代码仅用于测试。


一秒钟我在想:“如果$&没有,到底该怎么.replace办?” :P
ETHproductions 2016年

@ETHproductions我有点无聊并且混淆了变量名。太糟糕的JS不允许其他单一符号的:D
PurkkaKoodari

9

Befunge,138个 117 104字节

p&1v
%2:_v#:/2p9p00+1:g00
3\9g<>$\:!v!:<
9g!v ^,"}"_1-\1-:
"0"_2\"1{",,:|:,
`#@_\:#v_"}",>$\:8
,"0":-1<^

在线尝试!

说明

第1行从stdin读取数字,第2行将其转换为二进制序列,并将其存储在第10行的playfield中。第3到5行然后遍历这些二进制数字,并在处理每个数字时输出适当的树表示形式。Befunge堆栈用于跟踪进入树的深度以及每个级别上剩余的叶空间,因此我们知道何时创建新分支。第6行和第7行处理最后的0填充,以填充所有空的叶子。

为了尽可能地打高尔夫球,我从输出以及多余的外部括号中删除了逗号。这仍然没有击败Mathematica解决方案,但是尝试很有趣。

如果要查看原始详细输出格式的外观,我在这里保存了较早版本的代码(131字节)。


1
(此投票不足:D)
Addison Crump

4

Mathematica,167,161字节

b=Append;a=If[#&@@#>0,a[Rest@#~b~0,a[#,#3[#,{1,#4,#2},##5]&,#3,#2,##4]&,#2,##3],
#2[Rest@#~b~0,0,##3]]&;a[#~IntegerDigits~2,If[c=#3~b~#2;Tr@#>0,a[#,#0,c],c]&,
{}]&

匿名函数。以数字作为输入,并返回任意嵌套的数字列表作为输出。为了清楚起见添加了换行符。使用某种涉及延续的机制,但是我太累了,无法再考虑它了。


#[[1]]#&@@#应保存一个字节。!#~FreeQ~1而不是#~MemberQ~1保存一个字节。
JungHwan Min

4

Mathematica,115 109 108 104 98字节

(i=#~IntegerDigits~2;f:=Switch[If[i=={},0,i={##2};#]&@@i,0,0,1,f~1~f];NestWhileList[f&,f,i!={}&])&

生成可以安全地忽略的错误消息。输出二进制森林。它与示例输出略有不同,因为它1是一个Head,而不是列表的第一个元素。(例如,1[0, 0]代替{1, 0, 0}

无错误版本(104字节)

(i=#~IntegerDigits~2;f:=Switch[If[i=={},i={0}];(i={##2};#)&@@i,0,0,1,f~1~f];NestWhileList[f&,f,i!={}&])&

说明

i=#~IntegerDigits~2;

将输入转换为以2为基的列表。将其存储在中i

f:=

SetDelay f以下内容(每次f调用时进行评估):

Switch[If[i=={},0,i={##2};#]&@@i,0,0,1,f~1~f]

Switch 声明。

首先,如果i为空,则输出0。如果不是,则输出的第一个元素i并将其从列表中删除。将输出用作控制变量。

如果控制变量为0输出0。如果为1,则输出1[f, f](递归)。

NestWhileList[f&,f,i!={}&]

i不为空时,继续调用f。输出结果,并用包裹List

(i=#~IntegerDigits~2;f:=Switch[If[i=={},0,i={##2};#]&@@i,0,0,1,f~1~f];NestWhileList[f&,f,i!={}&])&[1337]

{1[0, 1[0, 0]], 1[1[1[0, 0], 1[0, 0]], 0]}

替代解决方案(120字节)

与我的104字节解决方案相同,但是将输出转换为问题中给定的格式。

(i=#~IntegerDigits~2;f:=Switch[If[i=={},i={0}];(i={##2};#)&@@i,0,0,1,f~1~f];NestWhileList[f&,f,i!={}&]//.1[a__]:>{1,a})&

2

Python 2中,133个 118 117字节

部分递归,部分迭代。我尝试使用整数,但是树以最高有效位开头,因此我认为这不值得。

def t():global b;a=b[:1];b=b[1:];return a and'0'<a and[1,t(),t()]or 0
b=bin(input())[2:]
L=[]
while b:L+=t(),
print L

在线尝试


1

Java 8,367字节

打高尔夫球:

class f{static String r="";static int p=0;static void g(char[]s,int k){if(p>=s.length||s[p]=='0'){r+="0";p++;return;}else{r+="{1";p++;g(s,k+1);g(s,k+1);r+="}";}if(k==0&&p<s.length)g(s,0);}public static void main(String[]a){java.util.Scanner q=new java.util.Scanner(System.in);r+="{";g(Integer.toBinaryString(q.nextInt()).toCharArray(),0);r+="}";System.out.print(r);}}

取消高尔夫:

class f{
    static String r="";
    static int p=0;
    static void g(char[]s,int k){
        // if there's empty space in last tree or current character is a 0
        if(p>=s.length || s[p]=='0'){
            r+="0";
            p++;
            return;
        }
        // if current character is a 1
        else{
            r+="{1";
            p++;
            // left branch
            g(s,k+1);
            // right branch
            g(s,k+1);
            r+="}";
        }
        // if they're still trees that can be added
        if(k==0 && p<s.length)g(s,0);
    }
    public static void main(String[]a){
        java.util.Scanner q=new java.util.Scanner(System.in);
        r+="{";
        g(Integer.toBinaryString(q.nextInt()).toCharArray(),0);
        r+="}";
        System.out.print(r);
    }
}

1

DUP,84个字节(82个字符)

0[`48-$1_>][\10*+]#%1b:[$1>][2/b;1+b:]#[['{,1.b;1-b:FF'},][0.b;1-b:]?]⇒F[b;0>][F]#

由于打高尔夫球的原因,我摆脱了外面的花括号和逗号,因为它们对于重建树木不是必需的。

输出示例:

0      → 0
1      → {100}
44     → {10{1{100}0}}
63     → {1{1{1{1{1{100}0}0}0}0}0}
404    → {1{100}{10{100}}}
1023   → {1{1{1{1{1{1{1{1{1{100}0}0}0}0}0}0}0}0}0}
1024   → {100}00000000
1025   → {100}0000000{100}
1026   → {100}000000{100}
1027   → {100}000000{1{100}0}
1028   → {100}00000{100}
1337   → {10{100}}{1{1{100}{100}}0}
4274937288 → {1{1{1{1{1{1{10{1{100}{1{1{100}{10{1{1{10{1{1{100}{100}}0}}0}0}}}0}}}0}0}0}0}0}0}
4294967297 → {100}00000000000000000000000000000{100}

说明:

0[`48-$1_>][\10*+]#           While loop to read in the characters and convert them into a
                              base-10 integer.
0                             Push 0 (temporary value)
 [`48-$0>]       #            While input character-48 (digit)>-1
          [     ]
           \                      Swap top values
            10                    Push 10
              *                   Multiply (temporary value by 10)
               +                  Add to input value
%                                 Pop stack (EOL)
1b:                           Variable b=1 (bit count)
[$1>][2/b;1+b:]#              While loop to convert the number to base-2 digits on the
                              data stack, MSB on top. Each iteration increments bit count b.
[$1>]          #              While (DUP>1)
     [        ]#
      2                           Push 2
       /                          MOD/DIV (pushes both mod and div on the stack)
        b;1+b:                    Fetch b, increment, store b


[['{,1.b;1-b:FF'},][0.b;1-b:]?]⇒F     
[                             ]⇒F     Define operator F:
                                      pop top stack value
 [                ]          ?        if value != 0:
  '{,1.                                   print '{1'
       b;1-b:                             fetch b, decrement b, store b
             F                            execute operator F
              F                           execute operator F again
               '},                        print '}'
                   [        ]?        if value == 0:
                    0.                    print '0'
                      b;1-b:              fetch b, decrement b, store b
[b;0>][F]#
[b;0>]   #                            While (fetch b, b>0==true)
      [F]#                                execute operator F

使用quirkster.com上的在线Javascript DUP解释器进行尝试,或克隆用Julia编写的DUP解释器的GitHub存储库

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.