我将使用Javascript作为语言
使这很容易理解使用ascii作为字母表,并给出所有可能的"陈述"使用ascii形成的长度为N的多少将是一个有效的JS程序。长度为8的示例
var i=0; //Is a string 8 characters long, and valid JS
jar i=0; //Is a string 8 characters long, but invalid JS
gfjsjhh3 //Is a string 8 characters long, but invalid JS
now imagine we have all possible strings 8 characters long.
How many will be valid JS?
进一步的规则:
1)变量尽可能短
2)除非必要,否则没有空格
更正式的问题定义:
如果我们给出了字母K的语法G,以及可以用K(或K *直到长度N)形成的长度为N的所有可能组合(语句)的集合,那么这些语句中有多少将是满足语法G.
我知道你认为这是一些学术性的,远离现实的东西。但是,如果程序的语句数远远少于组合的总数,则可以使用小的#34;数字"指的是这些稀疏程序出现在组合海洋中的位置,并且能够发送这个"地址"而不是整个程序,大大减少了有效载荷
答案 0 :(得分:1)
语法通常只是有效性检查的一个方面,请查看ES6 §5.3。语法很难捕捉到你“尽可能短”的要求。但语法是推理事物的好工具,所以让我们专注于此。它仍然允许无效程序和具有长变量名称的程序,但作为概念证明的起点(无论你的概念是什么)它应该足够了。
您可以从基于JS的某些derivation trees语法考虑BNF开始。类似于ES6标准的第11节到第15节,但要确保您使用的语法下降到字符级别,而不是将整个标识符视为单个终端。对于您的假设压缩方案,如果您在树的每个节点上对选项进行编码,则会有类似于您描述的压缩效果。
为了计算给定长度的节目数,您可以对BNF规则进行dynamic programming。所以,如果你有一个说
的规则IndexedMemberExpression ::= MemberExpression '[' Expression ']'
(在ES6 §12.3之后松散建模)然后您知道长度 n 的IndexedMemberExpression
由MemberExpression
长度 i组成和Expression
长度 n - i - 2,对于某些0≤ i ≤ n - 2,所以如果你知道有多少种方式,你知道整个表达方式。每个BNF非终端都有一个长度为1000的数组,按照长度增加的顺序填充它们,并获得根规则的派生树数(即语法正确的程序)。
实际上,IndexedMemberExpression只是一种MemberExpression,你想要将所有这些加起来。所以它更像是这样:
allocate an arry of size 1000 for each non-terminal,
and initialize all the elements to zero
for n from 0 to 1000:
…
# compute PrimaryExpression[n] first
# rule MemberExpression ::= PrimaryExpression
MemberExpression[n] = PrimaryExpression[n]
# rule MemberExpression ::= MemberExpression '[' Expression ']'
if n >= 2:
for i from 0 to n - 2:
MemberExpression[n] += MemberExpression[i] * Expression[n-i-2]
# rule MemberExpression ::= MemberExpression '.' IdentifierName
if n >= 1:
for i from 0 to n - 1:
MemberExpression[n] += MemberExpression[i] * IdentifierName[n-i-1]
…
对所有规则执行此操作,确保在右侧第一次使用之前,确保完全更新增量左侧的每个非终端。
请注意,对于几乎任何长度为 n 的字符序列,相应的字符串文字将是长度为 n + 2的有效JS表达式。所以不要指望与任意字符序列的数量相比,具有完全不同的渐近行为的有效程序的数量。