使用Digraphs的23个独特字符。(25个)。没有UB。
使用C ++ 11大括号初始化器语法,通过int var{};
避免=
和将列表整数初始化为零0
。(或者在您的情况下,避免使用global iiii
)。除了全局变量(不同于局部变量,它们被静态初始化为零)之外,这还为您提供了零的来源。
当前的编译器默认情况下接受此语法,而无需启用任何特殊选项。
(整数环绕技巧很有趣,并且可以在禁用优化的情况下打高尔夫球,但是在ISO C ++中,有符号溢出是未定义的行为。启用优化会将这些环绕循环变成无限循环,除非您使用gcc / clang -fwrapv
进行编译以使有符号整数溢出良好定义的行为:2的补回。
有趣的事实:ISO C ++ std::atomic<int>
具有定义明确的2的补码环绕! int32_t
如果完全定义,则必须为2的补码,但是溢出行为是未定义的,因此对于那些类型之一为32位,无填充和2的补码的机器int
或long
在任何机器上,它仍然可以是typedef 。)
在这种情况下没有用:
您还可以将新变量初始化为现有变量的副本,并使用花括号或(使用非空的初始值设定项)对原变量进行直接初始化。
int a(b)
或int a{b}
等于int a = b;
但是int b();
声明一个函数而不是初始化为零的变量。
同样,您可以使用int()
或来获得零char()
,即对匿名对象进行零初始化。
我们可以通过简单的逻辑转换将您的<=
比较替换为<
比较:在比较之后而不是在循环的底部进行循环计数器的递增。IMO比人们提出的替代方案更简单,例如++
在a的第一部分中使用for()
将0变成1。
// comments aren't intended as part of the final golfed version
int n;
std::cin >> n; // end condition
for(int r{}; r < n;) { // r = rows from 0 .. n-1
++r;
for(int i{}; i < r;) {
++i;
std::cout << i << ' ';
}
std::cout << std::endl;
}
我们可以将其降低到最低水平,for(int r{}; r++ < n;)
但是IMO对于人类来说不那么容易阅读。我们并未针对总字节数进行优化。
如果我们已经在使用h
,则可以为'
或节省"
空间。
假设在ASCII或UTF-8环境中,空格为a char
,值为32。我们可以很容易地在变量中创建它,然后cout << c;
char c{};
c++; c++; // c=2
char cc(c+c+c+c); // cc=8
char s(cc+cc+cc+cc); // s=32 = ' ' = space in ASCII/UTF-8
其他值显然可以++
根据其二进制表示形式的位从或加倍的序列中创建。在加倍为新变量之前,将0(无)或1(++)有效地移入LSB。
此版本使用h
代替'
或"
。
它比任何一个现有版本都快得多(不依赖长循环),并且没有Undefined Behavior。它编译与没有警告g++ -O3 -Wall -Wextra -Wpedantic
,并用clang++
。 -std=c++11
是可选的。这是合法且可移植的ISO C ++ 11 :)
它也不依赖于全局变量。我使用具有含义的变量名使其更易于阅读。
唯一字节数:25,不包括我删除的注释g++ -E
。并且排除空格和换行符,例如您的柜台。我使用了sed 's/\(.\)/\1\n/g' ladder-nocomments.cpp | sort | uniq -ic
来自这个askubuntu的方法来计算每个字符的出现次数,然后将其输入wc
到管道中以计算我拥有多少个独特字符。
#include<iostream>
int main() {
char c{};
c++; c++; // c=2
char cc(c+c+c+c); // cc=8
char s(cc+cc+cc+cc); // s=32 = ' ' = space in ASCII/UTF-8
int n;
std::cin >> n; // end condition
for(int r{}; r < n;) { // r = rows counting from 0
++r;
for(int i{}; i < r;) {
++i;
std::cout << i << s;
}
std::cout << std::endl;
}
}
仅有2个f
字符来自for
。while
如果我们有使用,则可以改用循环w
。
我们可以将循环重写为汇编语言样式,i < r || goto some_label;
以在循环底部或任何其他位置编写条件跳转。(但使用or
代替||
)。不,那是行不通的。 goto
是类似于if
Perl中的语句,并且不能像Perl中那样成为表达式的子组件。否则,我们可以使用它删除(
和)
字符。
我们可以换f
为g
与if(stuff) goto label;
替代的for
,并且两个回路始终运行至少1次迭代因此我们只需要在底部有一个循环分支,像一个正常的ASM do{}while
循环结构。假设用户输入的整数> 0 ...
有向图和有向图
幸运的是,自ISO C ++ 17起,三字母组合已被删除,因此对于最新的C ++修订版??>
,}
如果我们使用唯一标识,就不必使用。
但仅特定于三部曲:ISO C ++ 17仍然具有:>
for ]
和%>
for 等二字}
。因此,在使用的成本%
,我们可以同时避免 {
和}
,并使用%:
了#
用于2个更少的唯一字符的净储蓄。
和C ++具有操作关键字,如not
对!
经营者,或bitor
为|
运营商。使用xor_eq
for ^=
,您可以使用来将变量清零i xor_eq i
,但是该变量具有多个未使用的字符。
当前g++
,即使没有-std=gnu++17
,当前也已默认忽略三部曲;您必须使用-trigraphs
它们来启用它们,或者使用-std=c++11
某些严格遵守包含它们的ISO标准的东西。
23个唯一字节:
%:include<iostream>
int main() <%
int n;
std::cin >> n;
for(int r<% %>; r < n;) <%
++r;
for(int i<%%>; i < r;) <%
++i;
std::cout << i << ' ';
%>
std::cout << std::endl;
%>
%>
在线尝试!
最终的版本使用'
单引号代替h
或"
为空格分隔符。我不想把这些char c{}
东西写成图,所以我删除了。打印字符比打印字符串更有效,因此我使用了它。
直方图:
$ sed 's/\(.\)/\1\n/g' ladder-nocomments.cpp | sort | uniq -ic | tee /dev/tty | wc -l
15 // newline
95 // space
11 %
2 '
3 (
3 )
4 +
9 :
10 ;
14 <
8 >
2 a
4 c
6 d
3 e
2 f
12 i
2 l
2 m
11 n
5 o
7 r
5 s
11 t
3 u
25 // total lines, including space and newline
空格分隔符(仍未解决)
在一个现已删除的答案中,Johan Du Toit建议使用备用分隔符,特别是std::ends
。这是一个NUL字符,char(0)
并且在大多数终端上以零宽度打印。所以输出看起来像1234
不是1 2 3 4
。更糟糕的是,在没有默默崩溃的东西上被垃圾隔开'\0'
。
如果您可以使用任意分隔符,那么使用即可0
轻松创建数字cout << some_zeroed_var
。但是没有人想要10203040
,这比没有分隔符还要糟糕。
我试图考虑一种无需使用或字符串字面量即可创建std::string
" "
char
保全的方法。也许要添加一些东西?通过一个构造函数创建长度为1 []
的第一个字节后,也许有一个用于将第一个字节设置为的值的有向图32
?
Johan还建议了std::ios
fill()成员函数,该函数返回当前的填充字符。流的默认设置为std::basic_ios::init()
,并且为' '
。
std::cout << i << std::cout.fill();
替换<< ' ';
但使用.
代替'
。
使用-
,我们可以获取一个指针cout
并用于->fill()
调用成员函数:
std::cout << (bitand std::cout)->fill()
。还是没有,我们都没有使用b
过,所以我们最好也使用它&
而不是词汇上的等价物bitand
。
不带.
或调用成员函数->
将其放在一个类中,并定义 operator char() { fill(); }
// not digraphed
struct ss : std::ostream { // default = private inheritance
// ss() { init(); } // ostream's constructor calls this for us
operator char() { return fill(); }
}
然后ss s{}
在循环之前和循环std::cout << i << s;
内部。伟大的,它编译并运行正常,但我们不得不使用p
和h
进行operator char()
,至少我们避免了为1的净亏损b
,以使成员函数public
使用struct
代替class
。(protected
如果有帮助,我们可以重写继承)。