Answers:
通常,取模运算的结果与第一个操作数的符号相同是令人讨厌的。例如,-5 3%
给出-2
而不是1
。通常,您不希望后者。天真的解决方法是应用模,一次添加除数,然后再次应用模:
3%3+3%
但这又长又丑。相反,我们可以使用以下事实:数组索引始终是模块化的,并且可以正确地与负索引一起使用。因此,我们只需将除数变成一个范围并访问该范围:
3,=
应用于-5
,这给出1
了预期的结果。而且它仅比内置长一个字节%
!
如果模数是2的幂,则可以使用按位算术(这也快很多)来保存另一个字节。相比:
32,=
31&
对于特殊情况,65536 == 2^16
可以通过使用字符类型的包装行为来保存另一个字节:
ci
包含所有数字的字符串"0123456789"
可以写成
A,s
大写ASCII字母(A-Z
)可以按
'[,65>
它会生成所有字符(最多Z个)的字符串,然后丢弃前65个字符(最多@)。
所有ASCII字母(A-Za-z
)均可按
'[,65>_el+
如上操作,然后创建一个副本,转换为小写并追加。
但是,有一种更短的方法!
然后经常被忽略的^
运算符(列表的对称差异)允许在保留三个字节的同时创建相同的范围:
'[,_el^
'[,
创建所有ASCII字符到Z的范围,_el
创建小写副本,并^
仅保留两个字符串中出现在一个中的字符,但不同时出现在两个中。
由于第一个字符串中的所有字母均为大写字母,第二个字符串中的所有字母均为小写字母,并且两个字符串中的所有非字母字符都包含在字符串中,因此结果为字母字符串。
A-Za-z0-9+/
可以使用上述技术并添加非字母来推送RFC 1642 Base64字母():
'[,_el^A,s+"+/"+
同样短的推入字符串的方法仅利用对称差异:
"+,/0:[a{A0":,:^
我们如何在开头找到字符串?
所有使用的字符范围(A-Z
,a-z
,0-9
,+
,/
)可以被推作为到范围对称差开始在空字节,即'A,'[,^
,'a,'{,^
,'0,':,^
,'+,',,^
和'/,'0,^
。
因此,执行:,:^
对"A[a{):+,/0"
将推动期望的字符,但不能以正确的顺序。
我们如何找到正确的订单?蛮力抢救!该程序
'[,_el^A,s+"+/"+:T;"0:A[a{+,/0"e!{:,:^T=}=
遍历字符串的所有可能排列,应用:,:^
并将结果与所需的输出(permalink)进行比较。
.-9A-Za-z
可以使用上述方法来生成例如由crypt()使用的基数64字母:
".:A[a{":,:^
这是我知道的最短的方法。
由于所需输出中的所有字符均为ASCII顺序,因此不需要遍历排列。
并非可以使用来按所需顺序推送所有串联的字符范围:,:^
。
例如,0-9A-Za-z;-?
不能通过:,:^
对进行任何排列来推动范围"0:A[a{;@"
。
但是,通过使用代码,我们可以找到所需字符串的旋转变体
A,'[,_el^'@,59>]s2*:T;"0:A[a{;@"e!{:,:^T\#:I)}=Ip
它将打印(永久链接)以下内容:
10
0:@[a{A;
这意味着
"0:@[a{A;":,:^Am>
与...具有相同的效果
A,'[,_el^'@,59>]s
只能在不加[
。的情况下用于空堆栈。
假设您在堆栈上有一个整数。如果是奇数,则要将其乘以3并加1;否则,请为0。否则,您要将其除以2。
“正常”的if / else语句如下所示:
_2%{3*)}{2/}?
但是,使用块通常不是可行的方法,因为{}{}
已经添加了四个字节。?
也可以用于选择堆栈中的两个项目之一:
_2%1$3*)@2/?
这少了一个字节。
块-?空的if语句始终是不可行的。例如,
{}{2/}?
比2个字节长
{2/}|
相反,如果你有
{2/}{}?
并且您要检查的是非负整数,您可以执行
g)/
新的{}&
和{}|
方便的,但是如果您不能使堆栈混乱,则有时会出现问题。
不过,在
_{…}{;}?
您可以改用临时变量:
:T{T…}&
!)/
并且g)/
在示例中更短。
CJam没有switch语句。嵌套的if语句也可以正常工作,但是{{}{}?}{}?
已经是12个字节长...
如果可以将条件转换为较小的非负整数,则可以将所有case语句转换为带分隔符的字符串并评估相应的结果。
例如,如果我们想执行code0
如果堆栈的整数是0,code1
如果它是1,并且code2
如果它是2,我们既可以使用
_{({code2}{code1}?}{;code0}?
要么
[{code0}{code1}{code2}]=~
要么
"code0 code1 code2"S/=~
S/
将字符串拆分为["code0" "code1" "code2"]
,=
提取相应的块,然后~
评估代码。
单击此处查看运行中的switch语句。
最后,正如@ jimmy23013和@RetoKoradi所建议的那样,在某些情况下,我们甚至可以缩短开关的时间。说code0
,code1
和code2
具有长度大号0,大号1和大号2分别。
如果大号0 = L 1 ≥大号2
"code0code1code2"L/=~
可以替代地被使用,其中L
是大号0。而不是在定界符处分割,而是在/
这里将字符串分割成相等长度的块。
如果大号0 ≥大号1 ≥大号2 ≥大号0 - 1,
"cccooodddeee012">3%~
可以代替使用。>
从字符串的开头删除0、1或2个元素,并3%
提取每第三个元素(从第一个元素开始)。
"code0code1code2"5/=~
?对我来说似乎更直接,而且长度相同。
有时会出现一些短数组或字符串,例如初始化网格。天真的,这些可能花费4个或更多的字节,因此值得寻找将产生相同结果的内置值操作。特别是基本转换通常很有用。
[0 1]
可以写成2,
。[1 0]
可以写为YYb
(即二进制2)。[1 1]
可以写为ZYb
(即二进制3)。[[0 1] [1 0]]
可以写成2e!
。[LL]
可以写成SS/
(用空格分隔一个空格)。"\"\""
可以写成L`
。"{}"
可以写成{}s
。后者可以扩展到希望所有括号类型都保存另一个字节的情况:
"[{<()>}]"
可以写成{<()>}a`
。"()<>[]{}"
可以写成{<()>}a`$
。特别是对于一些时而突然出现的晦涩的情况,基本转换技巧很有用。例如[3 2]
为E4b
(以4为底的14)。
在更罕见的情况下,您甚至可能会发现分解运算符mf
很有用。例如[2 7]
是Emf
。
如果您遇到其他任何示例,请随时扩展此列表。
如果您只想清除整个堆栈,请将其包装在数组中并弹出:
];
更为棘手的是,如果您做了很多计算,但只想保留顶部堆栈元素并丢弃下面的所有内容。天真的方法是将顶部元素存储在变量中,清除堆栈,推送变量。但是还有一个更短的选择:将堆栈包装在数组中并提取最后一个元素:
]W=
(感谢Optimizer在前几天向我展示了这一点。)
当然,如果堆栈上只有两个元素,\;
则较短。
\;
只会弹出TOS下方的元素。你是说;;
吗
e
和十次方与其他许多语言一样,您可以编写1e3
而不是1000
使用CJam。
这适用于非整数基数,甚至也适用于非整数指数。例如,1.23e2
按123.0和1e.5
按3.1622776601683795(10的平方根)。
并非立即显而易见的1e3
是实际上是两个令牌:
1
将整数1压入堆栈。
e3
将其乘以1000。
为什么这么重要?
您可以调用e<numeric literal>
已在堆栈中的内容。
2 3 + e3 e# Pushes 5000.
您可以映射e<numeric literal>
到数组。
5 , :e3 e# Pushes [0 1000 2000 3000 4000].
计算向量的欧几里得范数(即其元素的平方和的平方根)的直接方法是:
2f#:+mq
但是,有一种更短的方法。
mh
斜边运算符,从堆栈中弹出两个整数a和b并压入sqrt(a 2 + b 2)。
如果我们有一个向量x:= [x 1 …x n ],则堆栈上n> 1,:mh
(通过斜边减少)将实现以下功能:
首先将x 1和x 2压入并mh
执行,将sqrt(x 1 2 + x 2 2)留在堆栈上。
然后,推入x 3并mh
再次执行,将
sqrt(sqrt(x 1 2 + x 2 2)2 + x 3 2)= sqrt(x 1 2 + x 2 2 + x 3 2)留在堆栈上。
处理完x n后,剩下的是sqrt(x 1 2 +…x n 2),x的欧几里得范数。
如果n = 1且x 1 <0,则上面的代码将产生错误的结果。:mhz
无条件工作。(感谢@MartinBüttner指出这一点。)
我在这个答案中第一次使用了这个技巧。
CJam使用以下公式将列表转换为数字:A 0 * n l + A 1 * n l-1 + A 2 * n l-2 + A l * n 0(带非负数n
)。n
是基数,l
是列表长度。这意味着A i可以是任何整数,而不必在的范围内[0,n)
。
一些例子:
0b
提取最后一项并将其转换为整数。像W=i
并且保存一个字节(如果不是整数)。但是列表中的所有其他内容也必须能够转换为整数。1b
返回总和。像这样工作:i:+
,如果不是整数,则保存两个字节。它也适用于空白列表,而:+
不能使用空白列表。[i{_1&9 32?_@\m2/}16*;]W%:c
将字符转换为由行尾和制表符组成的字符串,可使用将其转换回2bc
。但是,编码功能并不容易在代码高尔夫程序中使用。但是您通常不需要。您可以使用以下代码将字符串转换为非16位的Unicode字符,可以使用将其转换回2A#b128b:c
。(说明将在以后添加。或者稍后再写一个新版本。)
128b2A#b " Convert to base 1024. ";
W%2/)W%\:+ " Convert to two base 1024 digit groups. ";
[0X@
{
_54+
@I+_Am>@\-
_Am<@+ 0@-@1^
}fI
]);)
@\+[~+]2A#b_2G#<!{2A#b}*
\W%+:c
如果您找到某种方法来去除最高有效位数,则类似的方法适用于n
具有不同mod值的任何整数集n
。
假设您有一个嵌套列表,例如矩阵:
[[0 1 2][3 4 5][6 7 8]]
或字符串数组:
["foo""bar"]
您想将一个块映射到嵌套级别(即,将其应用于每个数字或每个字符)。天真的解决方案是嵌套的%
:
{{...}%}%
但是,您实际上可以将内部块推入堆栈,然后使用f%
。f
是“带有附加参数的地图”,因此它将%
使用块作为第二个参数映射到外部列表:
{...}f%
保存两个字节。
做类似事情的另一个巧妙技巧for (i=0; i<5; ++i) for (j=0; j<5; ++j) {...}
是
5,_f{f{...}}
外部f
将映射到第一个范围,并提供第二个范围作为附加参数。但是现在,如果f
再次使用,则只有顶部堆栈元素是一个数组,因此您f
将内部块映射到该数组,并提供外部“迭代变量”作为附加参数。这意味着内部块与i
和一起运行j
在堆栈上。
它具有与将一个块映射到一个笛卡尔积上相同的字符数(尽管如果您需要将对作为数组,则后者会变短):
5,_m*{~...}%
不同之处在于,此版本针对所有对产生单一结果数组,而对f
生成嵌套列表,如果要将结果存储在网格中(迭代器变量为坐标)列表很有用。
感谢Dennis向我展示了这个技巧。
f
并且:
现在通过雇用包括他们自己在内的任何其他运营商得到了极大的改善。这意味着您现在可以保存更多的字节。现在,将运算符映射到嵌套列表的过程变得更短了:
{:x}%
{x}f%
::x
但是,这实际上对将块映射到嵌套列表没有帮助。
至于将块或算符应用于笛卡尔积,对于块和算符,现在也变得更短了:
5,_f{f{...}}
5,_ff{...}
5,_f{fx}
5,_ffx
很好的是,您现在可以嵌套这些。因此,您可以轻松地将运算符应用于列表的第三级:
:::x
或一些诡计多端的方块:
{...}ff%
f~
...
对于许多ASCII艺术挑战,生成两个不同的模式以在以后叠加它们很有用。向量化运算符对实现不同类型的叠加非常有帮助。
运算符向量化的一个有用特性是,对于较短的字符串/数组的每个元素,该运算符仅执行一次,而没有对应字符串/数组的较大元素的元素则保持不变。
.e<
最少的运算符可e<
用于成对的字符串,字符,数组和整数。它从堆栈中弹出两个项目,然后将较低的部分推回e。
由于空格的代码点低于所有其他可打印的ASCII字符,.e<
因此可用于“擦除”所生成模式的部分:
"\/\/\/\/\/" " " .e<
e# This pushes " \/\/\/".
有关完整示例,请参阅我对“ 我想要蜂窝”的回答。
.e>
最大运算符e>
充当最小运算符,结果相反。
同样,由于空格的代码点少,.e>
可以用来在空格块中插入可打印字符的模式:
[[" " " " " " " "] [" " " " " " " "]][["+" "" "-" ""]["" "*" "" "/"]] ..e>
e# This pushes [["+" " " "-" " "] [" " "*" " " "/"]].
有关完整示例,请参见我对“ 七个斜杠显示”的回答。
.e&
如果逻辑AND运算符e&
是伪造的,则将其左参数推入,否则将其右参数推入。
如果两个模式都不包含伪造元素,则可以将其有条件地强加于另一个模式:
"################" " * * * *" .e&
e# This pushes " * * * *########".
.e|
逻辑OR运算符e|
可以按相反的参数顺序使用:
" * * * *" "################" .e|
e# This pushes " * * * *########".
z
和非矩形阵列zip运算符z
转置二维1数组A的行和列的元素也可以是可迭代的。
对于非矩形数组–与zip
Python中的内置函数(例如,将行截断为相同长度)或Ruby(使用pad nil
填充行)不同,CJam只是将数组的列转换为行,而忽略其长度,并且差距。
例如,压缩数组
[
[1]
[2 4]
[3 5 6]
]
相当于压缩数组
[
[1 4 6]
[2 5]
[3]
]
或数组
[
[1]
[2 4 6]
[3 5]
]
随着这三个动作的推进
[
[1 2 3]
[4 5]
[6]
]
在堆栈上。
尽管这z
并不是内卷(有时会有用),但它有一些应用。
例如:
我们可以通过两次压缩将数组的列对齐到顶部(即,将第一个数组变成第二个):
zz
对上述方法的较小修改可以用于类似的问题。
例如,要将数组的列与底部对齐(即,将第二个数组变成第一个数组),我们可以按相反的行顺序压缩两次:
W%zzW%
给定一个字符串数组,我们可以像这样计算最长字符串的长度:
:,:e>
但是,通过压缩并计算结果的行数,我们可以节省三个字节:
z,
1 如果有任何的“行”的一个不迭代,z
将它们视为单身,所以荏苒任意阵列的作品。
z
将列转换为行,而跳过空值,则行为将更加合乎逻辑。在此示例中,输入中的第一列为1、2、3,第二列为4、5(跳过空位置),第三列为6。然后是结果的行。
所有例外在CJam中都是致命的。由于默认情况下忽略输出到STDERR的输出,因此我们可以利用它来发挥优势。
CJam中的所有运算符都通过从堆栈中弹出零个或多个元素,执行某些任务并向堆栈中推入零个或多个元素来工作。执行任务时会发生异常,因此这仍会弹出元素,但不会返回任何内容。
以下是一些用例:
清理一小堆
要清除包含两个元素的堆栈,@
可以使用。@
尝试弹出三个堆栈元素,但在弹出第二个元素后失败。
弹出三个元素的任何其他运算符都将达到相同的目的。
看到它在这里行动。
从堆栈中删除两个或三个元素
未针对这些特定元素实现的任何运算符都可以用于在退出之前从堆栈中弹出两个或三个元素。
要弹出两个元素,b
如果其中一个是字符,或者都不是整数,则可以工作。
要弹出三个元素,t
如果最下面的两个元素都不是可迭代的,最下面的可迭代元素为空或都不是整数,则可以工作。
退出循环
有时,当整数变为零或字符串变得太短时,我们需要退出循环。如果涉及的操作失败零,空字符串或单例,则无需测试这些条件,我们只需让程序顺其自然即可。
有关涉及算术的示例,请参见此处。
有关涉及字符串的示例,请参见此处。
有条件的执行
如果不应为某些类型的输入执行源代码,则有时我们可以使用使此类输入失败的运算符。
例如,对于i
不为整数ew
的字符串将失败,对于长度为0或1的字符串将失败。
看到它在这里行动。
这是初学者的一个!
当您需要从数组中找到最大或最小数目时,最简单和最小的方法是对数组进行排序,然后取出第一个或最后一个元素。
所以如果数组在变量中 A
A$W=
是最大值,
A$0=
是最小的。
同时获得两个也是可能的
A$)\0=
阅读后,这看起来似乎很明显,但是任何人的第一次尝试都倾向于使用数组e<
或e>
通过数组进行迭代,这就像
A{e<}*
如果要同时使用max和min,则要长2个字节,甚至更长。
(
and )
代替0=
and W=
。
:e<
和:e>
如果您需要一个非常大但任意的数字,通常可以使用科学记号9e9
或将较大的内置变量之一提升为相似的幂,例如KK#
。但是,如果您不关心实际数字是多少,并且不必保持一致(例如,作为随机数的上限),则可以使用两个字节
es
代替。这将以毫秒为单位给出当前时间戳,大约为10 12
e9
。
有时,当两个字符串或数组不相等时,您需要一个真值,而在两个字符串或数组不相等时,您需要一个假值。显而易见的解决方案是两个字节:
=!
检查是否相等,然后求逆。但是,在某些情况下,您可以使用
#
当#
应用于两个数组时,它将实际上搜索第二个数组作为第一个的子数组(并为您提供该子数组开始的索引)。因此,如果两个数组相同,则子数组将在开始时找到并给出0
,这是虚假的。但是,如果找不到第二个数组,它将给出-1
真实的结果。
我们在两个数组上需要一些附加条件的原因是,如果第二个数组是第一个数组的重要前缀,则这也会产生虚假的值,例如:
"abc""ab"#
给出0
尽管字符串不相同。排除这种情况的最简单条件是,如果您知道两个数组的长度相同-在这种情况下,如果一个数组是另一个数组的前缀,则知道它们相等。但是在特定情况下,可能存在较弱的条件也足够了。例如,如果您知道字符串已排序,则前缀将始终是第一个字符串,而不是第二个。
假设您有一个数组,并且想要一个包含该数组所有可能子集的数组。诀窍是从一个空数组开始,然后对于每个元素,复制您已经拥有的子集,然后向其中添加新元素(在没有添加元素的情况下保留先前的结果)。请注意,您需要使用基本情况(即仅包含一个空数组的数组)来初始化堆栈:
[1 2 3 4 5]La\{1$f++}/
这样做的好处是,您可以立即在子集上运行一些计算,而无需添加字符。假设您需要所有子集的产品。在这种情况下,基本情况是一个包含以下内容的数组1
,并且在每个步骤中,您将获取可能的产品的先前列表,对其进行复制,然后将复制品中的所有内容乘以新元素:
[1 2 3 4 5]1a\{1$f*+}/
CJam具有向左旋转运算符m<
,通常应使用该将数组向左旋转任意数量的单位。
在某些情况下,您还可以使用(+
shift和追加:
[1 2 3] (+ e# Pushes [2 3 1].
[[1] [2] [3]] (+ e# Pushes [[2] [3] 1].
第二个示例不起作用,因为数组的第一个元素也是可迭代的,因此被+
串联而不是附加。
另外,如果您想将旋转后的数组转储到堆栈中,则可以:\
无条件使用(通过交换减少):
[1 2 3] :\ e# Pushes 2 3 1.
[[1] [2] [3]] :\ e# Pushes [2] [3] [1].
只要您没有open [
,此技巧还可以用于旋转整个堆栈,即,将最底部的堆栈项移到顶部:
]:\
可以说您的堆栈中有一个字符串/数字/等的列表。在上面,下面还有其他一些项目。即
123 "waste" ["a" "b" "rty" "print" "me" "please"]
现在,您只对打印最后一个列表感兴趣,因此您可以
S*]W=
哪个输出
a b rty print me please
当我们使用清除堆栈技巧并仅打印带有空格的列表时,这似乎真的很聪明(有时可能不是打印列表的理想方式)。
这可以打得更远!
p];
短2个字节!
如果列表中除了堆栈之外只有1个项目,则它会更短!
p;
的美丽 p
是,它从堆栈中删除了最上面的项目,对其进行了字符串化(在末尾还添加了换行符),并立即打印到STDOUT,而无需等待代码完成。
所以上面的代码会输出
["a" "b" "rty" "print" "me" "please"]
这是列表在堆栈中的确切表示!
CJam有一个内置的笛卡尔积计算器m*
,该计算器可以计算堆栈中最上面的两个arraylist / strings并从中创建所有可能的对。例如
[1 2 3 4]"abc"m*
树叶
[[1 'a] [1 'b] [1 'c] [2 'a] [2 'b] [2 'c] [3 'a] [3 'b] [3 'c] [4 'a] [4 'b] [4 'c]]
作为堆栈
但是,如果您希望从两个以上的列表/字符串中获取所有可能的组合,该怎么办。您使用m*
了多少次?例如
[1 2 3 4][5 6]"abc"m*m*
将以下内容放在堆栈上
[[1 [5 'a]] [1 [5 'b]] [1 [5 'c]] [1 [6 'a]] [1 [6 'b]] [1 [6 'c]] [2 [5 'a]] [2 [5 'b]] [2 [5 'c]] [2 [6 'a]] [2 [6 'b]] [2 [6 'c]] [3 [5 'a]] [3 [5 'b]] [3 [5 'c]] [3 [6 'a]] [3 [6 'b]] [3 [6 'c]] [4 [5 'a]] [4 [5 'b]] [4 [5 'c]] [4 [6 'a]] [4 [6 'b]] [4 [6 'c]]]
请注意,产品仍然是配对,其中一项是配对本身。这是意料之外的,我们希望拼合组合。
有一个简单的方法可以做到这一点。只需将所需的笛卡尔积的每个列表包装在一个数组中,成对创建笛卡尔积并每次对其进行展平:
[1 2 3 4][5 6]"abc"]{m*{(+}%}*
这离开
[['a 5 1] ['b 5 1] ['c 5 1] ['a 6 1] ['b 6 1] ['c 6 1] ['a 5 2] ['b 5 2] ['c 5 2] ['a 6 2] ['b 6 2] ['c 6 2] ['a 5 3] ['b 5 3] ['c 5 3] ['a 6 3] ['b 6 3] ['c 6 3] ['a 5 4] ['b 5 4] ['c 5 4] ['a 6 4] ['b 6 4] ['c 6 4]]
在堆栈上。
想要维持订单吗?,只需交换,然后再将弹出的项目添加回数组即可。即
{m*{(\+}%}*
只想要排列吗?
{m*{(+$}%_&}*
想要组合中仅包含独特元素吗?
{m*{(+_&}%}*
那是所有人。现在。
]:m*:e_
使用任意数量的数组进行操作
有时,如果您使用复杂的数据结构,而其中的项目很简单,则转换为字符串可能会有所帮助。
例如,如果要获取二维位数组中的前几项或后几项,并且不关心返回的类型,请sA<
从0=A<
或保存一个字节:+A<
。
或者,如果您想修改输入中的某些位,则可以在评估字符串之前先对其进行修改。
或者,如果您具有此结构并将其转换为简单列表,则:
[[[[[[[[[1]2]3]4]5]6]7]8]9]
您可以通过其他方式对许多字符进行处理:
[a{~)\}h;]W%
但是使用字符串可能会更短:
s:~
即使它的数字可能超过一个数字,它也会更短:
[`La`-~]
要么:
`']-~]
如果不需要另一个包含许多此类数组的数组。
e_
现在
s
仍然更好。
假设您有一个字符串,"abbcdbbfghbdbb"
并且想将其分割b
"abbcdbbfghbdbb"'b/
这留在堆栈上:
["a" "" "cd" "" "fgh" "d" "" ""]
注意空字符串吗?那里是因为两个b
人在一起,而他们之间什么也没有。有时,您想避免这种情况。你可以这样做
"abbcdbbfghbdbb"'b/La-
或过滤掉空字符串
"abbcdbbfghbdbb"'b/{},
但这是3个额外的字节。
对于此特定用例,鲜为人知的运算符是%
。除了进行mod和map以及基于数字("abcd"2%
= "ac"
)%
进行拆分外,还可以在字符串/数组上进行拆分。因此,对于上述用例:
"abbcdbbfghbdbb"'b%
会离开
["a" "cd" "fgh" "d"]
在堆栈上。
感谢@ user23013今天在我的答案之一中指出了这一点。
我们:x
是{x}%
and和{x}*
(或取决于x
一元或二进制)的简写。不幸的是,没有等效的infix运算符可以缩短{x}/
。但是,通常,当我们这样做时{x}/
,x
实际上是一个二元运算符,它会反复修改位于堆栈下面的项目。如果是这种情况,并且所说的项目不是数组,我们可以通过使用foreach的fold / reduce来节省一个字节:
5 [1 2 3 4]{-}/ e# Gives -5
5 [1 2 3 4]+:-
这是可行的,因为折叠总是使第一个元素保持不变。不幸的是,当修改的元素是数组时,它不会保存字节,因为添加它会解开它。然而,有时您很幸运,您的数组已经在前面包含了该元素,在这种情况下,请记住reduce(而不是{}/
在剩余部分上使用之前手动删除该元素)。
CJam具有print
运算符:o
。它可以工作,但是在执行完所有代码后立即打印堆栈。如果在程序末尾清除堆栈,则可以停止它。只需将其结尾:
];
要打印,您可以使用oNo
或p
(用作`oNo
)
o
和之间的差异更大p
。p
首先将要打印的项目转换为明确的字符串表示形式。p
等于执行`oNo
。