无法读取,1830 1796 1791 1771 1762 1745 1736 1727 1626 1606 1577字节
输出是按相反的字母顺序(z
到a
),但是根据您的允许的规则。
'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “'”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“ “'”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” '“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”““”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“'”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“ “”“”“'”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” '“”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“'”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”'“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “'”“'”“”“”“”“”“”“”“”“”“”“”“”“'”“”“”“”“”“”“”“”“ “”“”“'”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“” '“”“”“'”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“” “”“”“'”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”'“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “'”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“ '“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”'“”“'”“”“”“”“”“”“”“”“”“”“”“'”“”“”“”“”“”“”“”“”“”“”“” “'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“'”“”“”“”“”“”“”“”“”“”“”“”
说明
首先,给人一种难以理解的印象,这是它的基本操作:
- 你有一个无限大小的任意大小的整数单元
- 您没有像Brainfuck中那样的内存指针。相反,您可以按单元在磁带上的位置取消引用单元。这意味着您可以“读取值#4”或“读取值#(读取值#4)”(双重引用)。
- 您只能读写存储单元(不能像Brainfuck那样直接增加/减少)。
- 您可以在表达式中增加/减少值。因此,要增加一个存储单元,您必须读取,增加,写入或以其他方式放置:
write(x, inc(read(x)))
。
- 有while循环和三元条件只能检查零与非零。
该程序如下使用磁带。变量名称将在下面的伪代码中使用。此外,本文档还记录了第一个版本(1830字节)。请参阅底部的修改,以了解自那时以来所做的更改。
- 储存格0:可变
q
- 细胞1:变量
a
,p
,ch
- 单元格2:变量
hash
,v
- 细胞3:变量
b
,r
- 单元格4:变量
aa
,l
- 单元格5:保留为0,以标记十进制数字字符串的“结尾”
- 单元格6–95:向后存储十进制数字的字符串
- 单元格96–121:存储要从用户
a
(96)减至z
(121)的票数(字母的ASCII码减一)。
- 单元格4657–7380:记住已遇到多少个投票者/投票者组合。这些单元格只有4个可能的值:
0
=尚未见过,-1
=见过一次,-2
=见过两次,-3
=见过任何次数大于2的次数。
该算法基本上如下进行:
- 继续阅读成对的字符
a
和b
。计算哈希值(a-2)*(a-1)+b-1
,它对于字母a–z的每个组合都是唯一的。
- 检查该哈希值(
*hash
)处的存储单元。如果是-3
,则该用户已经有资格进行投票删除,因此请递增*(b-1)
。否则,递减*hash
。如果是现在 -3
,用户刚刚成为资格投票取出后三种表现,因此增加*(b-1)
的3
。
- 之后,以相反的顺序浏览字符(
z
至a
),然后输出需要扣除票数的字符。这需要手动将整数除以10才能将数字转换为十进制数字。
澄清了所有这些之后,程序看起来像是伪代码:
// Read pairs of characters
while (a = read) + 1 {
b = read
// Calculate hash = (a-1)*(a-2)/2 + b-1
// This also sets a = b-1
hash = 0
while --a {
aa = a
while --aa {
++hash
}
}
while --b {
++a
++hash
}
// If this combination has just been seen for the third time,
// increment *a by 3; if more than third time, increment *a by 1
*a = (*hash + 3) ? ((--*hash) + 3 ? *a : (*a+3)) : (*a+1)
}
// Loop through the characters z to a
l = 27
while --l { // l loops from 26 to 1 (not 0)
(v = *(ch = l + 95)) ? { // 'a' is ASCII 97, but cell 96
print (ch+1) // print the votee
// Now we need to turn the number v into decimal.
// p points to where we are storing decimal digits.
p = 5
while v {
// Integer division by 10 (q=quotient, r=remainder)
r = (q = 0)
while v {
--v
(++r - 10) ? 1 : {
r = 0
++q
}
}
// Store digit ASCII character
*(++p) = r + 48 // 48 = '0'
v = q
}
// Now output all the digit ASCII characters in reverse order
while *p {
print *(--p + 1)
}
} : 1
}
编辑1,1830→1796:意识到我可以在一个地方重用while循环的返回值。
编辑 2,1796 →1791:如果我不使用6–95单元格,而是将十进制数字存储在负数单元格中(从1开始),则表明程序稍小。作为一项额外的奖励,该计划不再仅限于10票!
编辑3,1791→1771:不是指定的结果*(ch = l + 95)
来v
,我现在把它分配给q
,然后分配移动v = q
到while条件,采取代码1777个字节。然后交换q
和v
在磁带上的位置,因为q
现在比常见1 v
。
编辑4,1771→1762: Du。初始化hash
为1而不是0的时间要短9个字节。哈希码现在增加了1,这无关紧要。
编辑5,1762→1745:如果我初始化q
并设置r
为1而不是0,我必须-1
在适当的位置撒一些s来使它正确,而且似乎都被抵消了-除了while v { --v; [...] }
循环现在需要执行更少的迭代之外,我可以这样说while --v { [...] }
,即短了26个字符。
编辑6,1745→1736:相反{ r = 1; ++q }
,我们可以编写q = *((r = 1)+1)+1
。这取决于q
位于可变插槽2中的事实。如果它在#1插槽中,它甚至会更短,但是整个程序的整体长度会更长。
编辑7,1745→1727:恢复编辑6,而是通过将最里面的while循环内联到计算数字ASCII码的表达式中来实现保存,该表达式也以1736字节结尾...但是随后保存了一个减量指令(9字节) )更改((++r) - 11) ? r :
为(r - 10) ? ++r :
。
编辑8,1727→1626:重做哈希计算。现在,它减少了一个while循环。单元格位置现在是其实际的ASCII码(不再关闭1)。重新排列的变量到磁带上的不同位置,因为它们现在以不同的频率出现。
编辑9,1626→1606:更疯狂的内联。现在,第一个while循环的主体看起来像这样:
// b = next char
*(b = (hash = read)) = {
// hash = b + (a-1)*(a-2)/2
while (a2 = --a) {
while --a2 {
++hash
}
}
// If this combination has just been seen for the third time,
// increment *b by 3; if more than third time, increment *b by 1
(*hash + 3) ? ((--*hash) + 3 ? *b : (*b+3)) : (*b+1)
}
现在变量分配几乎已完全更改。
编辑10,1606→1577:我观察到a
和a2
均递减到0在while循环,因此,如果我能配对p
与任一那些,但不与ch
,我不会需要初始化p
到0
(花费29个字节)。原来我可以通过交换p
和来做到这一点r
。现在,最新的变量分配(及其在代码中的出现频率)为:
0 = v (3) (total 3)
1 = hash (6), r (5), ch (2) (total 13)
2 = b (4), q (5) (total 9)
3 = a (3), p (5) (total 8)
4 = a2 (3), l (4) (total 7)
nanananananananabatman
测试用例。