Ceylon 386 333 252 230 222 216 171 153 131 111
String t(String s,Integer l)=>s.size<l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains)else l-3)]+"...";
Ungolfed Original:
String truncate(String text, Integer length) {
if(text.size < length) {
return text;
}
Boolean spacePredicate(Character char) {
return char == ' ' || char == '-';
}
Integer? spaceIndex = text[0:length-2].lastIndexWhere(spacePredicate);
if(exists spaceIndex) {
return text[0:spaceIndex] + "...";
}
return text[0:length-3]+"...";
}
นี่คือ 386 ไบต์ / ตัวอักษร คุณสมบัติที่น่าสนใจบางอย่างที่นี่:
x[y:z]
ไวยากรณ์น้ำตาลประโยคสำหรับx.measure(y, z)
และผลตอบแทน subrange ของx
เริ่มต้นที่y
มีความยาวz
- สำหรับสตริงนี้เป็นสตริงย่อย (นอกจากนี้ยังมีx[y..z]
ไวยากรณ์ซึ่งเป็นช่วงจากดัชนี y ถึง z ทั้งแบบรวมและครึ่งเปิดx[...z]
และx[y...]
.)
List.lastIndexWhere
ใช้เพรดิเคต (เช่นฟังก์ชันที่รับอิลิเมนต์อิลิเมนต์และส่งคืนบูลีนเช่นที่นี่ a Callable<Boolean, [Character]>
) และให้ดัชนีของอิลิเมนต์รายการสุดท้ายที่เพรดิเคตเป็นจริง (หรือเป็นโมฆะ ในฐานะที่เป็นสตริงเป็นรายการสิ่งนี้ก็ใช้ได้กับสตริงด้วยเช่นกัน
ผลลัพธ์ของสิ่งนี้spaceIndex
เป็นประเภทInteger|Null
หรือInteger?
สั้น - นั่นคือสามารถเป็นจำนวนเต็มหรือnull
(ค่าชนิดNull
เท่านั้น) (ชื่อspaceIndex
มาจากเมื่อฉันไม่ทราบว่า-
เป็นพิเศษ - ฉันเดาว่าbreakIndex
จะดีกว่า)
ด้วยexists spaceIndex
เราสามารถตรวจสอบว่าspaceIndex
ไม่เป็นโมฆะและทำสิ่งที่แตกต่างจากนั้น (ภายใน if-block คอมไพเลอร์รู้ว่ามันไม่เป็นโมฆะ ... โดยที่มันจะบ่นถ้าฉันใช้spaceIndex
เพื่อเข้าถึงสตริง)
แทนที่จะเป็นฟังก์ชั่นท้องถิ่นspacePredicate
เรายังสามารถใช้ฟังก์ชั่นที่ไม่ระบุชื่อ
(Character char) => char == ' ' || char == '-'
นี่ทำให้เรามี 333 ตัวอักษร:
String truncate(String text, Integer length) {
if(text.size < length) {
return text;
}
Integer? spaceIndex = text[0:length-2].lastIndexWhere(
(Character char) => char == ' ' || char == '-');
if(exists spaceIndex) {
return text[0:spaceIndex] + "...";
}
return text[0:length-3]+"...";
}
การปรับให้เหมาะสมครั้งต่อไปคือการใช้ชื่อตัวแปรและฟังก์ชั่นที่สั้นลงซึ่งทำให้เราลดลง 81 ไบต์ถึง 252:
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
Integer? i = s[0:l-2].lastIndexWhere(
(Character e) => e == ' ' || e == '-');
if(exists i) {
return s[0:i] + "...";
}
return s[0:l-3]+"...";
}
ฟังก์ชันเพรดิเคตจริง ๆ แล้วไม่จำเป็นต้องประกาศชนิดของอาร์กิวเมนต์ซึ่งสามารถอนุมานได้โดยคอมไพเลอร์ เหมือนกันสำหรับประเภทของi
(ซึ่งเรายังต้องเขียนvalue
เพื่อทำเครื่องหมายว่าเป็นการประกาศ) ขณะนี้การประกาศสั้นพอที่จะใส่หนึ่งบรรทัดทำให้เราลงไปที่ 230:
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
value i = s[0:l-2].lastIndexWhere((e) => e == ' ' || e == '-');
if(exists i) {
return s[0:i] + "...";
}
return s[0:l-3]+"...";
}
แทนที่จะเป็นe == ' ' || e == '-'
เราสามารถเขียนได้e in [' ', '-']
(หรือe in {' ', '-'}
นี่คือตัวสร้างที่ทำซ้ำได้แทนที่จะเป็นอันดับหนึ่ง) in
ประกอบการแมปกับวิธีการ Category.contains ซึ่งจะนำเราไปสู่ความคิดที่ว่าเราสามารถส่งผ่านของ tuple ว่าcontains
วิธีการโดยตรง (มันเป็น callable สละวัตถุใด ๆ จึงยังยอมรับตัวอักษร) โดยไม่ต้อง(e) => ...
สำเร็จรูป (222 bytes):
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
value i = s[0:l-2].lastIndexWhere([' ', '-'].contains);
if(exists i) {
return s[0:i] + "...";
}
return s[0:l-3]+"...";
}
" -"
อันที่จริงมีอีกหมวดหมู่หนึ่งเดียวกันตัวละครทั้งสองเป็นสองสายตัวอักษร (นอกจากนี้ยังมีสารตั้งต้น แต่มันไม่เจ็บที่นี่) 216 ไบต์
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
value i = s[0:l-2].lastIndexWhere(" -".contains);
if(exists i) {
return s[0:i] + "...";
}
return s[0:l-3]+"...";
}
ฉันเดาว่าเราได้ประโยชน์มากที่สุดจากบรรทัดนี้ลองหันไปหาคนอื่น ๆ ... ประโยคส่งคืนสองประโยคสุดท้ายมีความคล้ายคลึงกันซึ่งเราสามารถใช้ประโยชน์ได้ - พวกเขาต่างกันตรงข้ามi
กับl-3
และใช้i
เมื่อมันไม่เป็นโมฆะl-3
. โชคดีที่นี่เป็นสิ่งที่else
ผู้ดำเนินการสร้างขึ้นมาเพื่อ!
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
value i = s[0:l-2].lastIndexWhere(" -".contains);
return s[0:(i else l-3)] + "...";
}
(ดูเหมือนว่าจำเป็นต้องใส่วงเล็บในที่นี้เนื่องจากelse
มีลำดับความสำคัญต่ำกว่า[:]
) นี่คือ 171 อักขระ ตอนนี้i
ใช้เพียงครั้งเดียวเพื่อให้เราสามารถอินไลน์มันนำเราไปที่ 153 ตัวอักษร:
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
return s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
}
นอกจากนี้เรายังสามารถแทนที่นี้if-return-return
รวมกันด้วยการผสมผสานที่then
และผู้ประกอบการในหนึ่งelse
return
( then
return เป็น operand ที่สองเมื่ออันแรกเป็นจริงไม่เช่นนั้น null ซึ่งอนุญาตให้else
ส่งคืนตัวถูกดำเนินการตัวที่สองได้) 131 ไบต์ (แม้ว่าการประหยัดบางอย่างเป็น white space ซึ่งเราจะกำจัดออกไป)
String t(String s, Integer l) {
return s.size < l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
}
ฟังก์ชั่นที่มีการส่งคืนเพียงครั้งเดียวพร้อมนิพจน์สามารถเขียนด้วยเครื่องหมาย "fat arrow" ได้โดยให้ 123:
String t(String s, Integer l) =>
s.size < l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
การลบช่องว่างที่ไม่จำเป็นทำให้เรามี 111 ไบต์สุดท้าย:
String t(String s,Integer l)=>s.size<l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains)else l-3)]+"...";
นอกจากนี้ยังเป็นฟังก์ชันที่พิมพ์ตัวอย่างจากคำถาม (ใช้ชื่อt
ที่ใช้หลังจากขั้นตอนที่สอง):
shared void testTruncate() {
value testInputs = {
["This is some very long text.", 25],
["This-is-some-long-hyphen-separated-text.", 33],
["Programming Puzzles & Code Golf is a question and answer site for programming puzzle enthusiasts and code golfers.", 55],
["abcdefghijklmnopqrstuvwxyz", 20],
["a b c", 4],
["Very long.", 100]
};
for(input in testInputs) {
print(t(*input));
}
}