解码虚空


25

无效列表是一个不包含任何非列表对象的列表。或者,如果您喜欢递归定义

  • 空清单无效

  • 仅包含其他无效列表的列表是无效的

所有无效列表的深度都是有限的。

以下是空白列表的一些示例(使用python语法):

[]
[[]]
[[],[]]
[[[]]]
[[[]],[]]
[[],[[]]]

以下是一些不是无效列表的示例:

["a"]
[[...]]
[1]
2
[[],([],[])]

任务

编写两个单独的函数(或根据需要编写程序)。一个应采用一个正整数(如果需要,还可以包括零)作为参数并返回一个无效列表,另一个应采用一个无效列表并将其返回一个整数。这两个函数应始终彼此相反。也就是说,如果你传递的输出fg你应该得到的原始输入f的结果g。这意味着映射必须为1:1,即,对于每个整数,可能仅存在一个为其g提供该整数的空列表,而对于每个空隙列表,应仅存在一个为其提供该空列表的整数f

您实质上是在创建双射

您可以选择使用无效列表的字符串表示形式(带或不带逗号和空格),而不是语言的本机列表类型。

计分

您的分数将是两个职能的总和。这是因此您应力争将这一总和最小化。



1
这个问题要求两个功能,而重复项仅要求前一半。
伊恩·米勒

3
老鼠 我几乎发布了我所写的最佳答案,但它不符合其他挑战。
卡勒布·克利夫特

2
@IanMiller我要说的是,与此相比,另一个挑战在编码方面有不同的准则。
卡勒布·克里夫特

1
对于这个问题,仅仅是解码器也许更有意义?因为已经有关于编码器的问题。

Answers:


7

Pyth,27 + 29 = 56字节

f

L?bol`NS{sm[d+d]Y]d)ytb]Y@y

测试套件

g

L?bol`NS{sm[d+d]Y]d)ytb]Yxyl`

测试套件

系统非常简单:我生成的所有可能列表的数量不超过一定数量[的。然后,我对它们进行排序,以使我尚未生成的列表接近尾声。全部由功能完成y,在两个程序中相同。它写为

L?bol`NS{sm[d+d]Y]d)ytb]Y

然后,我为该列表建立索引f,并在中搜索g

选择我生成的列表的数量要足够大,以至于我生成了所有可能出现在无限排序列表中所需位置或之前的列表。

程序允许/返回0作为选项。


5

Python 2,96个字节

在线尝试!测试双射。

f=lambda l:len(l)and f(l[0])*2+1<<f(l[1:])

将无效列表取为非负整数。42个字节

g=lambda n:n*[g]and[g(n/(n&-n)/2)]+g(len(bin(n&-n))-3)

将非负整数作为无效列表。54个字节。更递归的尝试给出了相同的长度。

g=lambda n,i=0:n*[g]and[g(n/2,i+1),[g(n/2)]+g(i)][n%2]

1

Java 7,725字节

f(int)325个字节):

String f(int i){String s="";for(int j=0,e=0;e<i;e+=v(s))s=Integer.toBinaryString(j++);return"["+s.replace("1","[").replace("0","]")+"]";}int v(String s){for(;!s.isEmpty();s=s.replaceFirst("1","").replaceFirst("0",""))if(s.replace("1","").length()!=s.replace("0","").length()|s.charAt(0)<49|s.endsWith("1"))return 0;return 1;}

g(String)75 + 325字节):

int g(String s){int r=0;for(String i="10";!i.equals(s);i=f(++r));return r;}

由于method g使用method f来遍历可能的void列表,直到找到一个等于所输入的void的方法,才能计算出结果,因此的字节f计数了两次(因为在此挑战下,两种方法都应该能够在没有其他方法的情况下运行)。

说明:

通常,方法f仅循环所有整数的二进制字符串表示形式,并在每次找到有效的计数器时增加一个计数器。针对此挑战的有效二进制字符串符合以下规则:它们以a开头,以a 1结尾0。它们具有相等的1和0。每次删除第一个10再次验证剩下的内容时,这两个规则仍然适用。计数器等于输入后,二进制字符串转换为字符串空隙列表,更换所有1[所有0]

至于method g:我们从"[]"(代表void-list 0)开始,然后f在增加整数的同时继续使用method ,直到它与input-String匹配为止。

String f(int i){         // Method `f` with integer parameter and String return-type
  String s="";           //  Start with an empty String
  for(int j=0,e=0;e<i;   //  Loop as long as `e` does not equal the input
      e+=v(s))           //    And append increase integer `e` if String `s` is valid
    s=Integer.toBinaryString(j++);
                         //   Change `s` to the next byte-String of integer `j`
                         //  End of loop (implicit / single-line body)
  return"["+             //  Return the result String encapsulated in "[" and "]"
    s.replace("1","[").replace("0","]")+"]";
                         //  after we've replaced all 1s with "[" and all 0s with "]"
}                        // End of method `f`

int v(String s){         // Separate method with String parameter and integer return-type
  for(;!s.isEmpty();     //  Loop as long as String `s` isn't empty
      s=s.replaceFirst("1","").replaceFirst("0",""))
                         //    After each iteration: Remove the first "1" and "0"
    if(s.replace("1","").length()!=s.replace("0","").length()
                         //   If there isn't an equal amount of 1s and 0s
       |s.charAt(0)<49   //   or the String doesn't start with a 1
       |s.endsWith("1")) //   or the String doesn't end with a 0
      return 0;          //    Return 0 (String is not valid)
                         //  End of loop (implicit / single-line body)
  return 1;              //  Return 1 (String is valid)
}                        // End of separate method

int g(String s){         // Method `g` with String parameter and integer return-type
  int r=0;               // Result integer
  for(String i="[]";!i.equals(s);
                         //  Loop as long as `i` does not equal the input String
      i=f(++r));         //   After each iteration: Set `i` to the next String in line
  return r;              //  Return the result integer
}                        // End of method `g`

输入和输出案例示例:

在这里尝试。(注意:在最后几个测试用例中,这相当慢。所有这些用例大约需要10-15秒。)

0   <-> []
1   <-> [[]]
2   <-> [[][]]
3   <-> [[[]]]
4   <-> [[][][]]
5   <-> [[][[]]]
6   <-> [[[]][]]
7   <-> [[[][]]]
8   <-> [[[[]]]]
9   <-> [[][][][]]
10  <-> [[][][[]]]
11  <-> [[][[]][]]
12  <-> [[][[][]]]
13  <-> [[][[[]]]]
14  <-> [[[]][][]]
50  <-> [[[][[[]]]]]
383 <-> [[[][]][[[][]]]]

1
我认为这[][]不是清单。也许我误解了Java的工作方式。将[...]所有这些加在一起并映射到0 []应该可以解决问题。
小麦巫师

@WheatWizard啊,好电话。将尝试解决此问题。我还没有足够的字节。; P
Kevin Cruijssen's

@WheatWizard好的,现在应该修复。艰难而有趣的挑战。我花了一段时间才明白您的意思,甚至花了更长的时间才能写出答案,但这很有趣。:)
凯文·克鲁伊森



0

Python 3-符号/ abs,73个字节

f=lambda n:[[[]]*(n<0),[[]]*abs(n)]
g=lambda l:[-1,1][not l[0]]*len(l[1])

在线尝试!

直接实现,支持负数。

整数i编码[sign(i), abs(i)],其中sign(i)=[] if i > 0 else [[]]abs(i)=[[]] * i,即长度为abs(i)的空列表的列表。

Python 3-二进制,126字节

这是一个更复杂的版本(并且更长的时间……),其中绝对值以二进制列表表示形式编码。

f=lambda n:[[[]]*(n<0),[[[]]*int(i)for i in f"{n:+b}"[1:]]]
g=lambda l:[-1,1][not l[0]]*int(''.join(map(str,map(len,l[1]))),2)

在线尝试!


1
对于更复杂的空列表不起作用:在线尝试!
吉斯

啊,我莫名其妙地错了,应该为每个无效列表都建立一个映射...您是对的。
movatica

0

Stax,共33个字节

这些程序彼此相反。它们在所有空列表和所有非负整数之间进行转换,因此包括0。这似乎是某种我不知道的代数的著名函数。为了解决这个问题,我首先将程序实现为python中的函数。

def convert_to_void(n):
    lst = []
    while n > 0:
        n -= 1
        choices = len(lst) + 1
        choice = n % choices
        cutpoint = len(lst) - choice
        n //= choices
        newgroup = lst[cutpoint:]
        del lst[cutpoint:]
        lst.append(newgroup)
    return lst

def convert_from_void(lst):
    n = 0
    while lst != []:
        newgroup = lst.pop()
        n *= len(lst) + len(newgroup) + 1
        n += len(newgroup) + 1
        lst.extend(newgroup)
    return n

stax程序具有相同的行为。

非负整数→空列表,15 个字节

ƒâ₧~└3BI─¿-rÅ;ì

运行并调试

无效列表→非负整数,18 个字节

Çäê[!σ`c↑Ö§░NR╥ç=Æ

运行并调试

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.