23 อักขระที่ไม่ซ้ำกันโดยใช้ Digraphs (ไม่รวม 25 รายการ) ไม่มี UB
การใช้ภาษา C ++ 11 ยัน initializer ไวยากรณ์ที่จะเริ่มต้นรายการจำนวนเต็มเป็นศูนย์ที่มีint var{};
การหลีกเลี่ยงและ=
0
(หรือในกรณีของคุณหลีกเลี่ยงทั่วโลกiiii
) สิ่งนี้ทำให้คุณมีแหล่งที่มาของเลขศูนย์ที่ไม่ใช่ตัวแปรทั่วโลก (ซึ่งเริ่มต้นเป็นศูนย์แบบคงที่เป็นศูนย์
คอมไพเลอร์ปัจจุบันยอมรับไวยากรณ์นี้เป็นค่าเริ่มต้นโดยไม่ต้องเปิดใช้งานตัวเลือกพิเศษใด ๆ
(เคล็ดลับจำนวนเต็มวิจิตรคือความสนุกและ ok สำหรับการเล่นกอล์ฟด้วยการเพิ่มประสิทธิภาพปิดการใช้งาน แต่ลงนามล้นเป็นพฤติกรรมที่ไม่ได้กำหนดไว้ใน ISO c ++. การเปิดใช้งานการเพิ่มประสิทธิภาพจะหันลูปวิจิตรที่เป็นลูปไม่มีที่สิ้นสุดจนกว่าคุณจะรวบรวมกับ gcc / เสียงดังกราว-fwrapv
ที่จะให้ลงนามจำนวนเต็มล้นดี พฤติกรรมที่กำหนดไว้: การเติมเต็ม 2 อย่าง
ความจริงแล้วสนุก: ISO C ++ std::atomic<int>
มีส่วนเสริม 2 อย่างที่กำหนดไว้! int32_t
จำเป็นต้องเป็นส่วนเสริม 2 ของหากกำหนดไว้ทั้งหมด แต่พฤติกรรมการโอเวอร์โฟลว์ไม่ได้กำหนดดังนั้นจึงยังสามารถเป็น typedef สำหรับint
หรือlong
บนเครื่องใด ๆ ที่หนึ่งในประเภทนั้นคือ 32 บิตไม่มีช่องว่างภายในและส่วนประกอบ 2 ของ)
ไม่มีประโยชน์สำหรับกรณีนี้โดยเฉพาะ:
นอกจากนี้คุณยังสามารถเริ่มต้นตัวแปรใหม่เป็นสำเนาของที่มีอยู่กับการจัดฟันหรือไม่ (ที่มีการเริ่มต้นที่ไม่ว่างเปล่า) parens สำหรับการเริ่มต้นโดยตรง
int a(b)
หรือint a{b}
เทียบเท่าint a = b;
แต่int b();
ประกาศฟังก์ชั่นแทนการเริ่มต้นตัวแปรเป็นศูนย์
นอกจากนี้คุณยังสามารถรับค่าศูนย์ด้วยint()
หรือchar()
เช่นการกำหนดค่าเริ่มต้นเป็นศูนย์ของวัตถุที่ไม่ระบุชื่อ
เราสามารถแทนที่การ<=
เปรียบเทียบของคุณด้วยการ<
เปรียบเทียบด้วยการแปลงเชิงตรรกะอย่างง่าย ๆ : ทำการเพิ่มตัวนับลูปทันทีหลังจากการเปรียบเทียบแทนที่จะเป็นที่ด้านล่างของลูป IMO นี้ง่ายกว่าทางเลือกที่ผู้คนเสนอเช่นใช้++
ในส่วนแรกของ a for()
เพื่อสร้าง 0 เป็น a 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 พื้นที่จะ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
แทนหรือ'
"
มันเร็วกว่าเวอร์ชันที่มีอยู่อย่างใดอย่างหนึ่ง (ไม่ต้องพึ่งพาการวนซ้ำยาว) และไม่มีพฤติกรรมที่ไม่ได้กำหนดอิสระจากพฤติกรรมที่ไม่ได้กำหนดมันรวบรวมมีคำเตือนที่ไม่มี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 มิฉะนั้นเราอาจจะใช้มันเพื่อลบ(
และ)
อักขระ
เราสามารถทางการค้าf
สำหรับg
กับif(stuff) goto label;
แทนfor
และลูปทั้งสองทำงานอย่างน้อย 1 ย้ำเสมอดังนั้นเราจะต้องมีเพียงหนึ่งวงสาขาที่ด้านล่างเช่น asm ปกติdo{}while
โครงสร้างห่วง สมมติว่าผู้ใช้ป้อนจำนวนเต็ม> 0 ...
Digraphs และ Trigraphs
โชคดีที่มีการลบ Trigraphs ออกจาก ISO C ++ 17ดังนั้นเราจึงไม่จำเป็นต้องใช้??>
แทน}
ถ้าเรากำลังเล่นกอล์ฟที่ไม่เหมือนใครสำหรับการแก้ไข C ++ ล่าสุด
แต่ trigraphs เฉพาะ: ISO C ++ 17 ยังคงมี digraphs เช่น:>
สำหรับ]
และ%>
}
สำหรับ ดังนั้นในค่าใช้จ่าย%
เราสามารถหลีกเลี่ยงทั้ง {
และ}
และใช้%:
สำหรับ#
การประหยัดสุทธิ 2 ตัวอักษรที่ไม่ซ้ำกันน้อยลง
และ C ++ มีคีย์เวิร์ดของโอเปอเรเตอร์เช่นnot
สำหรับ!
โอเปอเรเตอร์หรือbitor
สำหรับ|
โอเปอเรเตอร์ ด้วยxor_eq
สำหรับ^=
คุณสามารถเป็นศูนย์ตัวแปรด้วย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{}
สิ่งต่าง ๆ ดังนั้นฉันจึงลบมัน การพิมพ์ถ่านมีประสิทธิภาพมากกว่าการพิมพ์สตริงดังนั้นฉันจึงใช้มัน
Histogram:
$ 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
หรือตัวอักษรสตริง อาจจะต่อท้ายบางสิ่งด้วยหรือไม่ อาจจะใช้กับ digraph []
เพื่อตั้งค่าไบต์แรกให้เป็นค่า32
หลังจากสร้างหนึ่งที่มีความยาว 1 ผ่านหนึ่งในตัวสร้างหรือไม่
โจฮานยังแนะนำstd::ios
ฟังก์ชั่นสมาชิก () สมาชิกที่ส่งกลับตัวละครเติมปัจจุบัน ค่าเริ่มต้นสำหรับกระแสถูกกำหนดโดยและเป็น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
ในกรณีที่เคยช่วย)