เคล็ดลับสำหรับการเล่นกอล์ฟใน Scala


24

คุณมีเคล็ดลับทั่วไปอะไรสำหรับการเล่นกอล์ฟใน Scala ฉันกำลังมองหาแนวคิดที่สามารถนำไปใช้กับปัญหาเกี่ยวกับการเขียนโค้ดกอล์ฟโดยทั่วไปซึ่งอย่างน้อยค่อนข้างเฉพาะกับ Scala (เช่น "ลบความคิดเห็น" ไม่ใช่คำตอบ) กรุณาโพสต์หนึ่งเคล็ดลับต่อคำตอบ

(นี่เป็นสำเนาที่ไร้ยางอายของ ... ใน Python)

คำตอบ:


5

ข้อจำกัดความรับผิดชอบ: บางส่วนของคำตอบนี้เป็นภาพรวมของคำตอบอื่น ๆ ที่นี่

ใช้ lambdas โดยไม่ระบุประเภทอาร์กิวเมนต์

มันได้รับอนุญาตให้ส่งอะไรเช่นนี้แทนa=>a.size(a:String)=>a.size

ใช้สัญลักษณ์ ASCII เป็นตัวระบุ

!%&/?+*~'-^<>|เหล่านี้รวมถึง เนื่องจากพวกเขาไม่ได้เป็นตัวอักษรพวกเขาจึงถูกแยกคำเมื่อแยกตัวอักษร

ตัวอย่าง:

a=>b       //ok
%=>%        //error, parsed as one token
% => %      //ok
val% =3     //ok
&contains+  //ok
if(x)&else* //ok

ใช้การตั้งค่าแทนประกอบด้วย

if (Seq(1,2,3,'A')contains x)... //wrong
if (Set(1,2,3,'A')(x))...         //right

Set[A] extends (A => Boolean)เพราะนี่คือความเป็นไปได้

ใช้ฟังก์ชั่น curried เมื่อคุณต้องการสองข้อโต้แย้ง

(a,b)=>... //wrong
a=>b=>...  //right

ใช้_-syntax เมื่อเป็นไปได้

กฎสำหรับเรื่องนี้ค่อนข้างคลุมเครือคุณต้องเล่นไปรอบ ๆ เพื่อหาวิธีที่สั้นที่สุด

a=>a.map(b=>b.size)) //wrong
a=>a.map(_.size)     //better
_.map(_.size)        //right

ใช้แอปพลิเคชั่นบางส่วน

a=>a+1 //wrong
_+1    //better, see above
1+     //right; this treats the method + of 1 as a function

ใช้""+แทนtoString

a=>a.toString //wrong
a=>a+""       //right

ใช้สตริงเป็นลำดับ

"" บางครั้งเป็นวิธีที่สั้นที่สุดในการสร้างลำดับที่ว่างหากคุณไม่สนใจประเภท actula

ใช้ BigInt เพื่อแปลงตัวเลขเป็นและจากสตริง

วิธีที่สั้นที่สุดในการแปลงตัวเลขเป็นสตริงในฐานอื่นที่ไม่ใช่ฐาน 10 คือtoString(base: Int)วิธีของ BigInt

Integer.toString(n,b) //wrong
BigInt(n)toString b   //right

หากคุณต้องการแปลงสตริงเป็นตัวเลขให้ใช้ BigInt.apply(s: String, base: Int)

Integer.parseInt(n,b) //wrong
BigInt(n,b)           //right

โปรดทราบว่าสิ่งนี้จะส่งคืน BigInt ซึ่งสามารถใช้งานได้เหมือนกับจำนวนครั้งส่วนใหญ่ แต่ไม่สามารถใช้เป็นดัชนีสำหรับลำดับได้

ใช้ Seq เพื่อสร้างลำดับ

a::b::Nil   //wrong
List(...)   //also wrong
Vector(...) //even more wrong
Seq(...)    //right
Array(...)  //also wrong, except if you need a mutable sequence

ใช้สตริงสำหรับ Seqences of chars:

Seq('a','z') //wrong
"az"         //right

ใช้ประโยชน์จาก Stream สำหรับลำดับที่ไม่มีที่สิ้นสุด

ความท้าทายบางอย่างถามหาองค์ประกอบที่ n ของลำดับที่ไม่มีที่สิ้นสุด สตรีมเป็นตัวเลือกที่สมบูรณ์แบบสำหรับสิ่งนี้ โปรดจำไว้ว่าStream[A] extends (Int => A)นั่นคือสตรีมคือฟังก์ชันจากดัชนีไปยังองค์ประกอบที่ดัชนีนั้น

Stream.iterate(start)(x=>calculateNextElement(x))

ใช้โอเปอเรเตอร์สัญลักษณ์แทนคู่คำที่มีคำ

:\และ:/แทนที่จะเป็นfoldRightและfoldLeft

a.foldLeft(z)(f) //wrong
(z/:a)(f)        //right
a.foldRight(z)(f) //wrong
(a:\z)(f)         //right

hashCode -> ##

throw new Error() -> ???

ใช้&และ|แทน&&และ||

มันทำงานเหมือนกันสำหรับ booleans แต่จะประเมินตัวถูกดำเนินการทั้งสองเสมอ

นามแฝงวิธียาวเป็นฟังก์ชั่น

def r(x:Double)=math.sqrt(x) //wrong
var r=math.sqrt _            //right; r is of type (Double=>Double)

รู้หน้าที่ในไลบรารีมาตรฐาน

โดยเฉพาะอย่างยิ่งนี้ใช้กับวิธีการรวบรวม

วิธีการที่มีประโยชน์มากคือ:

map
flatMap
filter
:/ and :\ (folds)
scanLeft and scanRight
sliding
grouped (only for iterators)
inits
headOption
drop and take
collect
find
zip
zipWithIndex3
distinct and/or toSet
startsWith

11

Seq.fillทางที่สั้นที่สุดของการทำซ้ำบางสิ่งบางอย่างที่มี

1 to 10 map(_=>println("hi!")) // Wrong!
for(i<-1 to 10)println("hi!") // Wrong!
Seq.fill(10)(println("hi!")) // Right!

10

ตัวระบุที่น่าสงสัย:

คุณสามารถใช้ได้ ? เป็นตัวระบุ:

val l=List(1,2,3)
val? =List(1,2,3)

ที่นี่ไม่ได้ช่วยอะไรคุณเลยเพราะคุณไม่สามารถติดมันกับเครื่องหมายเท่ากับ:

val ?=List(1,2,3) // illegal

แต่ในภายหลังมันมักจะบันทึกอักขระหนึ่งตัวเนื่องจากคุณไม่จำเป็นต้องใช้ตัวคั่น:

print(?size)  // l.size needs a dot
def a(? :Int*)=(?,?tail).zipped.map(_-_)

อย่างไรก็ตามมันมักจะใช้ยาก:

       print(?size)
3
       print(?size-5)
<console>:12: error: Int does not take parameters
       print(?size-5)
              ^

9

คอลเลกชัน

ตัวเลือกแรกสำหรับคอลเลกชันมักจะเป็นแบบสุ่มรายการ ในหลายกรณีคุณสามารถแทนที่ด้วยSeqซึ่งจะบันทึก instantan หนึ่งอักขระ :)

แทน

val l=List(1,2,3)
val s=Seq(1,2,3)

และในขณะที่ s.head และ s.tail เป็นสง่ามากขึ้นในรหัสปกติเป็นอีกครั้งหนึ่งในตัวละครที่สั้นกว่าs(0)s.head

แม้จะสั้นกว่าในบางกรณี - ขึ้นอยู่กับฟังก์ชันการทำงานที่จำเป็นคือ tuple:

val s=Seq(1,2,3)
val t=(1,2,3)

ประหยัด 3 ตัวอักษรทันทีและสำหรับการเข้าถึง:

s(0)
t._1

มันเหมือนกันสำหรับการเข้าถึงดัชนีโดยตรง แต่สำหรับแนวความคิดที่ซับซ้อน tuples ล้มเหลว:

scala> s.map(_*2)
res55: Seq[Int] = List(2, 4, 6)

scala> t.map(_*2)
<console>:9: error: value map is not a member of (Int, Int, Int)
       t.map(_*2)
         ^

ปรับปรุง

def foo(s:Seq[Int])
def foo(s:Int*)

ในการประกาศพารามิเตอร์ Int * จะบันทึก 4 อักขระเหนือ Seq [Int] ไม่เทียบเท่า แต่บางครั้ง Int * จะทำ


8

โดยปกติคุณสามารถใช้mapแทนforeach:

List("a","b","c") foreach println

สามารถถูกแทนที่ด้วย

List("a","b","c") map println

แตกต่างเพียงพิมพ์กลับ ( UnitVS List[Unit]) foreachซึ่งคุณจะไม่ได้รับความสนใจในการอยู่แล้วเมื่อมีการใช้


7

กำหนดประเภทที่สั้นกว่า:

หากคุณมีการประกาศหลายประเภทเช่น

def f(a:String,b:String,c:String) 

มันสั้นกว่าเพื่อกำหนดนามแฝงประเภทและใช้แทน:

type S=String;def f(a:S,b:S,c:S)

ความยาวดั้งเดิมคือ 3 * 6 = 18 รหัสการเปลี่ยนคือ 8 (ชนิด S =;) + 6 + 3 * 1 (= ความยาวใหม่) = 17

ถ้า (n * length <8 + length + n) แสดงว่าเป็นข้อได้เปรียบ

สำหรับคลาสที่สร้างอินสแตนซ์จากโรงงานเราสามารถตั้งชื่อตัวแปรให้สั้นลงเพื่อชี้ไปยังวัตถุนั้น แทน:

val a=Array(Array(1,2),Array(3,4))

เราสามารถเขียน

val A=Array;val a=A(A(1,2),A(3,4))

สิ่งนี้ใช้ได้กับ C ++ เช่นกัน#defineแต่ฉันยอมรับว่ามันดีdefและvalสั้นกว่า
Matthew อ่าน

ฮึ่ม defเป็นคำหลักเพื่อกำหนดวิธีการและการแปลง่าย ๆ สำหรับ c ++ สำหรับvalคือ 'const' และเป็นการประกาศ แต่มักจะอนุมานประเภท การตัดทอนเป็นกรณีแรกtype=ที่ใกล้เคียงที่สุดtypedef- ใช่ไหม? ตัวอย่างที่สองไม่ได้มาจากฉันและเป็นเรื่องใหม่สำหรับฉัน ฉันต้องระวังที่จะใช้
ผู้ใช้ที่ไม่รู้จัก

typedef long long ll;เหมือนกัน#define ll long longดังนั้นหลังจะสั้นลงด้วย 1 แต่ใช่แล้วtypedefทำงานได้ ดูvalตัวอย่างอีกครั้งฉันอ่านผิดอย่างแน่นอน ดูเหมือนว่ายิ่งสกาล่าน้อยลง x = thingWithAReallyLongComplicatedNameForNoReasonเป็นกลยุทธ์ที่ค่อนข้างทั่วไป: P
Matthew อ่าน

@userunknown เมื่อคุณสร้างอินสแตนซ์ListหรือArrayอื่น ๆ ด้วยไวยากรณ์val x = List(1,2,3)คุณเพียงแค่เรียกapplyเมธอดบนListวัตถุ (เทคนิคนี้สำหรับการสร้างวัตถุเป็นที่รู้จักกันว่าเป็น "การโรงงาน" ในทางตรงกันข้ามกับที่ใช้กับคอนสตรัคnew.) Arrayดังนั้นข้างต้นเราเพียงแค่ทำให้ตัวแปรใหม่ที่ชี้ไปยังวัตถุเดี่ยวเช่นเดียวกับชื่อตัวแปร เนื่องจากเป็นสิ่งเดียวกันจึงมีวิธีการทั้งหมดรวมapplyอยู่ด้วย
Luigi Plinge

7

ใช้ไวยากรณ์ของ infix เพื่อลบความต้องการ.อักขระ คุณไม่จำเป็นต้องเว้นวรรคเว้นแต่รายการที่อยู่ติดกันจะเป็นทั้งตัวอักษรและตัวเลขหรือทั้งสองอย่างในตัวดำเนินการ (ดูที่นี่ ) และไม่คั่นด้วยอักขระที่สงวนไว้ (วงเล็บ, จุลภาค ฯลฯ )

เช่น

List(1,2,3,4).filter(_ % 2 == 0) // change to:
List(1,2,3,4)filter(_%2==0)

7

trueและfalseตัวอักษรจะสั้นกว่าที่จะเขียนเป็น2>1สำหรับความจริงและ1>2เท็จ



6

เปลี่ยนชื่อเมธอดหากชื่อของพวกเขายาวและหากใช้หลายครั้ง - ตัวอย่างโลกจริง:

 x.replaceAll(y,z)

 type S=String; def r(x:S,y:S,z:S)=x.replaceAll(y,z)

ขึ้นอยู่กับความเป็นไปได้ที่จะบันทึก 'S = String' ในที่ต่างๆด้วยเช่นกันสิ่งนี้จะประหยัดถ้าคุณเปลี่ยนอย่างน้อย 3 ครั้งแทนทั้งหมด


3

เริ่มต้นตัวแปรหลายตัวพร้อมกันโดยใช้ tuple:

var(a,b,c)=("One","Two","Three") //32 characters

เมื่อเทียบกับ

var a="One";var b="Two";var c="Three" //37 characters

0

คุณยังสามารถใช้แทนการใช้=>สำหรับนิยามฟังก์ชัน


1
สวัสดีและยินดีต้อนรับสู่ PPCG เนื่องจากเวลาส่วนใหญ่คำตอบจะนับเป็นไบต์แทนที่จะเป็นตัวอักษรเคล็ดลับของคุณมีขอบเขต จำกัด เท่านั้น ฉันจะอยู่ที่นี้และยังเพิ่มชื่อปลายเหมือนสั้นคำจำกัดความของฟังก์ชั่นในตัวละครนับตามความท้าทายรหัสกอล์ฟ
Jonathan Frech
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.