Tips untuk bermain golf di Scala

24

Tips umum apa yang Anda miliki untuk bermain golf di Scala? Saya mencari ide yang dapat diterapkan pada masalah kode golf secara umum yang setidaknya agak spesifik untuk Scala (mis. "Hapus komentar" bukan jawaban). Silakan kirim satu tip per jawaban.

(Ini adalah salinan tak tahu malu dari ... dengan Python)

Pengguna tidak diketahui
sumber

Jawaban:

5

Penafian: bagian dari jawaban ini adalah generalisasi dari jawaban lain yang ditemukan di sini.

Gunakan lambdas tanpa menentukan jenis argumen mereka

Diizinkan mengirim sesuatu seperti ini: a=>a.sizealih-alih (a:String)=>a.size.

Gunakan simbol ascii sebagai pengidentifikasi.

Ini termasuk !%&/?+*~'-^<>| . Karena mereka bukan huruf, mereka diurai terpisah ketika mereka di sebelah huruf.

Contoh:

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

Gunakan Set bukannya berisi

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

Ini dimungkinkan karena Set[A] extends (A => Boolean).

Gunakan fungsi kari ketika Anda membutuhkan dua argumen.

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

Gunakan _-syntax jika memungkinkan

Aturan untuk ini agak tidak jelas, Anda harus bermain sedikit kadang-kadang untuk menemukan cara terpendek.

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

Gunakan aplikasi sebagian

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

Gunakan ""+sebagai gantitoString

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

Gunakan string sebagai urutan

"" terkadang merupakan cara terpendek untuk membuat urutan kosong jika Anda tidak peduli dengan jenis actula

Gunakan BigInt untuk mengonversi angka ke dan dari string

Cara terpendek untuk mengonversi angka menjadi string di basis selain basis 10 adalah melalui toString(base: Int)metode BigInt

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

Jika Anda ingin mengonversi string ke angka, gunakan BigInt.apply(s: String, base: Int)

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

Perlu diketahui bahwa ini mengembalikan BigInt, yang bisa digunakan seperti angka sebagian besar kali, tetapi tidak dapat digunakan sebagai indeks untuk urutan, misalnya.

Gunakan Seq untuk membuat urutan

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

Gunakan Strings untuk Seqences of chars:

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

Manfaatkan Stream untuk urutan yang tak terbatas

Beberapa tantangan meminta elemen ke-n dari urutan yang tak terbatas. Stream adalah kandidat yang sempurna untuk ini. Ingat bahwa Stream[A] extends (Int => A), yaitu, aliran adalah fungsi dari indeks ke elemen di indeks itu.

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

Gunakan operator simbolik alih-alih rekan bertele-tele mereka

:\dan :/bukannya foldRightdanfoldLeft

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

hashCode -> ##

throw new Error() -> ???

Gunakan &dan |bukannya &&dan||

Mereka bekerja sama untuk boolean, tetapi akan selalu mengevaluasi kedua operan

Metode panjang alias sebagai fungsi

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

Ketahui fungsi-fungsi di perpustakaan standar

Ini khususnya berlaku untuk metode pengumpulan.

Metode yang sangat berguna adalah:

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
corvus_192
sumber
11

Cara terpendek mengulangi sesuatu adalah dengan Seq.fill.

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

pengidentifikasi yang mencurigakan:?

Anda dapat gunakan ? sebagai pengidentifikasi:

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

Ini tidak menyelamatkan Anda apa pun, karena Anda tidak dapat menempelnya pada tanda yang sama:

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

Tapi nanti, sering kali menyimpan satu karakter, karena Anda tidak perlu pembatas:

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

Namun, seringkali sulit untuk menggunakan:

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

Koleksi

Pilihan pertama untuk koleksi acak seringkali adalah List . Dalam banyak kasus, Anda dapat menggantinya dengan Seq , yang menyimpan satu karakter instantan. :)

Dari pada

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

dan, sementara s.head dan s.tail lebih elegan dalam kode biasa, s(0) sekali lagi satu karakter lebih pendek dari s.head.

Bahkan lebih pendek dalam beberapa kasus - tergantung pada fungsionalitas yang diperlukan adalah tuple:

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

segera menyimpan 3 karakter, dan untuk mengakses:

s(0)
t._1

itu sama untuk akses indeks langsung. Tetapi untuk konsep yang diuraikan, tuple gagal:

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)
         ^

memperbarui

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

Dalam deklarasi parameter, Int * menyimpan 4 karakter di atas Seq [Int]. Ini tidak setara, tetapi kadang-kadang, Int * akan dilakukan.

Pengguna tidak diketahui
sumber
8

Anda biasanya dapat menggunakan mapalih-alih foreach:

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

dapat diganti dengan

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

Satu-satunya perbedaan adalah tipe pengembalian ( Unitvs List[Unit]), yang tidak Anda sukai ketika menggunakannya foreach.

Luigi Plinge
sumber
7

tentukan Jenis yang lebih pendek:

Jika Anda memiliki beberapa deklarasi tipe, seperti

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

lebih pendek untuk mendefinisikan jenis alias, dan menggunakannya sebagai gantinya:

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

Panjang asli adalah 3 * 6 = 18 Kode pengganti adalah 8 (tipe S =;) + 6 + 3 * 1 (= panjang baru) = 17

jika (n * panjang <8 + panjang + n), maka itu merupakan keuntungan.

Untuk kelas yang dipakai melalui pabrik, kita bisa mengatur nama variabel yang lebih pendek untuk menunjuk ke objek itu. Dari pada:

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

kita bisa menulis

val A=Array;val a=A(A(1,2),A(3,4))
Pengguna tidak diketahui
sumber
Ini berlaku untuk C ++ juga dengan #definemisalnya, tapi saya akui itu bagus defdan vallebih pendek.
Matius Baca
Hm defadalah kata kunci untuk mendefinisikan metode, dan terjemahan sederhana ke c ++ for valadalah 'const', dan ini adalah deklarasi, tetapi jenisnya sering disimpulkan. Pemendekan dalam kasus pertama type=yang lebih dekat typedef- bukan? Contoh kedua bukan dari saya dan ini baru bagi saya. Saya harus hati-hati, di mana menggunakannya.
pengguna tidak diketahui
typedef long long ll;sama dengan #define ll long long, jadi yang terakhir lebih pendek dengan 1. Tapi ya, typedefberhasil. Melihat valcontoh itu lagi saya pasti salah baca. Tampaknya bahkan kurang spesifik Scala. x = thingWithAReallyLongComplicatedNameForNoReasonadalah strategi yang cukup umum: P
Matthew Read
@userunknown Ketika Anda instantiate a Listatau Arraydll dengan sintaks val x = List(1,2,3)Anda hanya memanggil applymetode pada Listobjek. (Teknik untuk membuat objek ini dikenal sebagai "metode pabrik", berbeda dengan menggunakan konstruktor dengan new.) Jadi di atas, kami hanya membuat variabel baru yang menunjuk ke objek tunggal yang sama dengan nama variabel Array. Karena itu adalah hal yang sama, semua metode, termasuk apply, tersedia.
Luigi Plinge
7

Gunakan sintaks infix untuk menghapus kebutuhan .karakter. Anda tidak perlu spasi kecuali item yang berdekatan keduanya dalam alfanumerik atau keduanya dalam karakter operator (lihat di sini ), dan tidak dipisahkan oleh karakter yang dipesan (tanda kurung, koma dll).

Misalnya

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

The truedan falseliteral yang lebih pendek untuk menulis sebagai 2>1untuk benar dan 1>2untuk palsu

triggerNZ
sumber
7

Panggil dua kali fungsi yang sama untuk inisialisasi:

val n,k=readInt

(Terlihat di tempat lain, tetapi tidak dapat menemukannya sekarang).

Pengguna tidak diketahui
sumber
6

Ganti nama Metode, jika namanya panjang, dan jika digunakan berulang kali - contoh dunia nyata:

 x.replaceAll(y,z)

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

Tergantung pada kemungkinan untuk menyimpan 'S = String' di tempat yang berbeda juga, ini hanya akan ekonomis, jika Anda mengganti setidaknya ganti semua 3 kali.

Pengguna tidak diketahui
sumber
3

Inisialisasi beberapa variabel sekaligus menggunakan tuple:

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

vs.

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

Anda juga dapat menggunakan alih-alih menggunakan =>untuk definisi fungsi.

Varon
sumber
1
Halo dan selamat datang di PPCG. Karena sebagian besar waktu, jawaban dihitung dalam byte daripada karakter, tip Anda hanya memiliki ruang lingkup terbatas. Saya akan membahas ini dan juga menambahkan judul tip seperti definisi fungsi Shortening dalam tantangan golf kode berdasarkan jumlah karakter .
Jonathan Frech