Tips bermain golf di Pip
Pip adalah bahasa golf penting dengan operator infix. Ia juga meminjam beberapa fitur dari pemrograman fungsional dan array.
Tip umum apa yang Anda miliki untuk bermain golf di Pip? Saya mencari pendekatan dan trik yang umumnya berguna untuk golf kode dan khusus untuk Pip (misalnya "hapus komentar" bukanlah jawaban).
Harap posting satu tip untuk setiap jawaban.
Jawaban
Gunakan variabel yang sudah diinisialisasi
Pip memiliki banyak variabel global yang telah diinisialisasi sebelumnya sehingga Anda dapat menghindari penulisan nomor / string / sesuatu yang lain secara manual.
Berikut beberapa di antaranya ( daftar lengkap ):
_Fungsi identitas (=={a})h100i0k", "lDaftar kosongm1000 (mnemonik: angka romawi M)nKarakter baris baruo1sKarakter luar angkasat10v-1wCocok dengan spasi\s+xString kosongzHuruf kecil alfabet a sampai zBBlok yang mengembalikan argumen keduanya ({b})GBlok yang mengembalikan daftar argumennya ({g})AZHuruf besar alfabet A sampai ZCZKonsonan huruf kecil b sampai zPASemua karakter A SCII P rintable , 32 hingga 126PI\$\pi\$ (3.141592653589793)VWHuruf vokal huruf kecil a sampai uVYHuruf vokal huruf kecil a sampai yXACocok dengan satu huruf Latin[A-Za-z](ada lebih banyakX*perintah)
Gunakan Yoperator
Dari survei singkat, sepertinya saya menggunakan Y(atau salah satu variannya, YPdan YO) dalam satu dari setiap tiga jawaban Pip - apalagi jawabannya semakin kompleks.
Menyimpan nilai
Ysingkatan dari "yank", yang biasa bagi pengguna Vim sebagai perintah yang menyalin baris atau pilihan saat ini ke dalam buffer. YOperator unary di Pip melakukan hal serupa: ia menyimpan salinan operannya di yvariabel global dan mengembalikan operan tidak berubah. Pada dasarnya, Y<expr>setara dengan y:<expr>, tetapi lebih pendek.
Ini saja membuat Y(dan yvariabel) berguna dalam banyak kasus. Perlu menyimpan sesuatu dalam variabel dan tidak peduli yang mana yang Anda gunakan? Ymenghemat satu byte dari tugas. Perlu menggunakan ekspresi dua kali? Tarik dan gunakan ydua kali sebagai gantinya. Jika ekspresi lebih panjang dari dua byte, Anda akan menghemat.
Tetapi Yjuga berguna dengan cara lain:
Memanipulasi prioritas operator
Misalkan kita ingin menghitung jumlah 0 di input dan kemudian memasukkan hitungan ke akhir input itu. (Misalnya, input dari 1001101harus menghasilkan 1001101 3.) Menghitung 0s adalah 0Na, dan jadi kami ingin melakukannya a.s.0Na. Tapi itu tidak akan berhasil karena Nlebih rendah daripada ., dan ekspresi akan mengurai sebagai ((a.s).0)Na. Untuk menegakkan didahulukan, kita dapat menggunakan tanda kurung: a.s.(0Na). Ini selalu berhasil, dan terkadang itu satu-satunya pilihan.
Namun seringkali, kita bisa menggunakan Ysebagai gantinya. Triknya adalah itu Ymemiliki prioritas yang sangat rendah - yang terendah, pada kenyataannya, bersama dengan Pdan O. Jadi ekspresi apa pun di sebelah kanan Yakan diurai sebagai Yoperan, sedangkan seluruh Yekspresi pada gilirannya akan menjadi operan kanan apa pun yang muncul di sebelah kirinya. Dan Yakan melewatkan operannya melalui tidak berubah (ditambah menetapkannya ke y, tetapi kami tidak peduli tentang itu selama kami tidak menggunakannya yuntuk hal lain). Jika kita menulis a.s.Y0Na, itu akan mem-parsing (a.s).(Y(0Na)), seperti jika kita telah mengurung 0Na. Tetapi harganya hanya satu byte, sedangkan tanda kurung harganya dua.
Peringatan
Sebuah Yekspresi hanya dapat digunakan pada sisi kanan operator biner, bukan kiri, karena Yakan mengambil segala sesuatu di sebelah kanan sebagai operan nya. Misalnya, jika kita ingin menambahkan jumlah 0 daripada menambahkannya, kita tidak dapat melakukan Y0Na.s.a--itu akan mengurai sebagai Y(0N(a.s.a)). Sebaliknya, kami harus kembali ke tanda kurung atau strategi lain.
Hanya ada satu yvariabel, jadi Anda tidak dapat menarik dua nilai yang berbeda dalam program yang sama (kecuali Anda dapat menyusun kode Anda sehingga Anda tidak memerlukan keduanya pada saat yang sama). Anda harus memilih satu untuk ditetapkan ke variabel lain. Cobalah kedua cara tersebut dan lihat mana yang menghemat lebih banyak byte.
Operator biner di Pip selalu mengevaluasi sisi kiri mereka terlebih dahulu, yang berarti Anda secara umum tidak dapat menggunakan nilai baru dari ydalam ekspresi yang sama di mana Anda menariknya: Jika Anda ingin menghitung kuadrat a+1, Anda tidak dapat melakukan y*Ya+1( ytidak akan a+1ketika dievaluasi, karena a+1belum ditarik); dan Anda tidak dapat melakukan Ya+1*a(yang akan mengurai sebagai Y(a+(1*a))). Dalam situasi seperti ini, Anda mungkin ingin mencabut nilai pertama, dalam ekspresi yang terpisah: Ya+1y*y. Jika Anda benar-benar perlu untuk melakukannya dalam satu ekspresi, Anda dapat mengurungkan yang Ybagian: (Ya+1)*y. Ini berfungsi karena sisi kiri dari *dievaluasi terlebih dahulu, sehingga ymemiliki nilai yang benar saat sisi kanan dievaluasi.
Ganti fungsi sederhana dengan lambda
Lambda umumnya merupakan cara yang baik untuk menghemat 2 byte (paling tidak), dibandingkan dengan fungsi biasa yang memerlukan tanda kurung.
Lambda Pip, bagaimanapun, tidak meniru atribut umum lambda, katakanlah, Python. Anda tidak dapat mempersingkat semua fungsi mandiri menjadi lambda.
Mereka adalah perpanjangan dari fungsi identitas _, di mana _ = {a}. Ini berarti Anda dapat membuat lambda dari suatu fungsi hanya jika Anda menulis fungsi dengan satu ekspresi.
Lambdas di Pip memiliki beberapa kegunaan menarik selain ekspresi tunggal. Misalnya, Anda dapat mereferensikan argumen fungsi utama tanpa menarik / menyalinnya.
Dari tutorial Dlosc tentang fungsi :
Fungsi
_+amenambahkan argumennya ke argumen baris perintah pertama program.amasih memiliki nilai tingkat atas karena tidak ada di dalam kurung kurawal.
Tangkapannya adalah Anda tidak dapat menggunakan perintah (If, Else if, Loops) dan semuanya harus turun ke satu pernyataan, karena umumnya dengan menerapkan operator pada fungsi.
Karena pembatasan tersebut, Pip lambda umumnya lebih cocok untuk fungsi pemetaan atau pemfilteran kecil. Selamat bermain golf!
Jika Anda menemukan kasus penggunaan yang menarik, beri tahu saya.
M dapat memetakan nilai alih-alih fungsi
Biasanya, Anda akan menggunakan Mseperti ini:
UC_M"abc"
dengan sisi kiri menjadi fungsi dan sisi kanan menjadi beberapa iterable yang ingin Anda petakan. Jika Anda perlu menukar argumen, "abc"MUC_berfungsi juga.
Tetapi dalam kasus di mana Anda hanya ingin mengganti setiap item dalam iterable dengan nilai konstan, Mdapat melakukannya juga - berikan non-fungsi sebagai sisi kirinya:
42M"abc"
Ini akan mengembalikan [42;42;42]: satu 42untuk setiap karakter di "abc". Jika Anda tidak keberatan mendapatkan list dan bukan string, ini satu byte lebih pendek dari 42X#"abc", dan dua byte lebih pendek dari padanan daftar 42RL#"abc".
Nilainya dapat berupa apa saja * yang bukan merupakan fungsi: Skalar, Pola, Daftar, Rentang, atau bahkan Nihil.
Trik ini juga berfungsi dengan beberapa operator peta lainnya:
aMJbmenggabungkan hasil menjadi string setelah pemetaan (mungkin sangat berguna ketikaabukan Skalar untuk memulai)aMMbakan memberi Anda daftar daria, panjang sublists yang cocok dengan panjang item dalambaMCbakan memberi Andabxbgrid (daftar bersarang) daria
Yang terakhir itu adalah alternatif yang berguna ZGketika Anda menginginkan nilai selain 0 ( misalnya ).
* Secara teknis, ini akan berperilaku berbeda jika diberi daftar yang berisi fungsi.
Pintasan untuk daftar tertentu
Biasanya, jika Anda memerlukan daftar konstanta, Anda cukup mengapit item dalam tanda kurung siku, dengan pemisah seperlunya ( [4 8 15 16 23 42]). Tetapi ada cara yang lebih pendek untuk membuat beberapa daftar yang umum digunakan:
- Pertama, jangan lupa Anda dapat menggunakan variabel preset jika Anda belum menetapkannya kembali. Daftar kosong bisa jadi
lsebagai pengganti[]. Menggunakaniuntuk0danountuk1dalam daftar dapat menghemat satu byte (atau bahkan dua) jika mereka berada di sebelah angka lain, karena variabel huruf kecil tidak memerlukan pemisah:[0 5]→[i5]. Menggunakanvfor-1,tfor10,hfor100, ataumfor1000juga menyimpan byte secara langsung, karena nama variabel lebih pendek dari angka yang diwakilinya. - Gunakan rentang jika memungkinkan:
[0 1]→[io]→,2. Ini masih menghemat satu byte jika berbasis-1 ([o2]→\,2) atau dimulai di beberapa nomor lain ([v0]→v,1). - Untuk daftar digit, pisahkan angka:
[1]→^1;[3o4o5 9]→^314159;[oi]→^t. Ini juga berfungsi untuk karakter:['#]→^'#;['h'i]→^"hi".
Perhatikan bahwa dua metode terakhir melibatkan operator dengan prioritas berbeda, yang perlu Anda perhitungkan. Jika mengerjakan prioritas terlalu merepotkan, Anda selalu dapat kembali ke sintaks daftar standar.