Tips umum apa yang Anda miliki untuk bermain golf di Perl? Saya mencari ide yang dapat diterapkan pada masalah kode golf secara umum yang setidaknya agak spesifik untuk Perl (mis. "Hapus komentar" bukan jawaban). Silakan kirim satu tip per jawaban.
Itulah tip golfing Perl yang paling penting yang perlu Anda ketahui. Setiap kali Anda melihat urutan karakter terlalu lama yang harus Anda miliki untuk menyelesaikan tugas, tanyakan pada diri sendiri apakah tidak ada cara lain untuk mendapatkan efek yang sama menggunakan fitur yang berbeda. Biasanya ada. Ini hanya beberapa:
~~
menegakkan konteks skalar dan 4 karakter lebih pendek dari scalar
.
y///c
adalah satu char lebih pendek dari length
ketika mendapatkan panjang $_
.
Perlu mengulangi karakternya $_
? Ganti split//
dengan /./gs
. (Atau gunakan /./g
jika Anda juga ingin melewatkan baris baru.) Ini berfungsi dengan variabel lain: ganti split//,$x
dengan $x=~/./gs
.
Setiap Perl dibangun mengembalikan sesuatu. print
mengembalikan 1, misalnya, untuk menunjukkan I / O berhasil. Jika Anda perlu menginisialisasi $_
ke nilai sebenarnya, misalnya, $_=print$foo
memungkinkan Anda untuk membunuh dua burung dengan satu batu.
Hampir setiap pernyataan dalam Perl dapat ditulis sebagai ekspresi, yang memungkinkannya untuk digunakan dalam berbagai konteks yang lebih luas. Beberapa pernyataan dapat menjadi beberapa ekspresi yang dirangkai bersama dengan koma. Pengujian dapat dilakukan dengan operator hubungan arus pendek ?:
&&
||
, dan juga dengan and
dan or
, yang melakukan hal yang sama tetapi dengan diutamakan lebih rendah dari semua operator lain (termasuk penugasan). Loop dapat dilakukan melalui map
atau grep
. Bahkan kata kunci suka next
, last
dan return
dapat digunakan dalam konteks ekspresi, meskipun tidak kembali! Mempertahankan transformasi semacam ini dalam pikiran memberi Anda peluang untuk mengganti blok kode dengan ekspresi yang dapat dimasukkan ke dalam berbagai konteks yang lebih luas.
$_=print""
lebih pendek dari$_=print$foo
.$foo
. Kalau tidak,$_=1
jauh lebih pendek daripada$_=print""
dan memiliki efek yang sama.$x
? Kalau tidak, Anda hanya bisa melakukan/./gs
dan/./g
.Variabel khusus penyalahgunaan Perl!
Seperti disebutkan dalam jawaban sebelumnya
$/
dan$"
diinisialisasi secara default untuk"\n"
dan" "
, masing-masing.$,
dan$\
keduanya diaturundef
secara default, dan 3 karakter lebih pendek.Pengaturan
$\
ke nilai akan menyebabkannya ditambahkan ke setiapprint
. Sebagai contoh:perl -ple '$\="=".hex.$/'
adalah konverter hex-to-desimal berguna.Jika Anda tidak membaca file dari baris perintah, Anda dapat menggunakan
-i
saklar baris perintah sebagai saluran tambahan untuk memasukkan string. Nilainya akan disimpan di$^I
.$=
memaksa apa pun yang ditugaskan padanya untuk menjadi bilangan bulat. Coba jalankanperl -ple '$_=$==$_'
dan berikan berbagai inupts. Demikian juga,$-
memaksa nilainya menjadi bilangan bulat non-negatif (yaitu tanda hubung utama diperlakukan sebagai karakter non-numerik).Anda dapat menggunakan
$.
sebagai boolean flag yang secara otomatis di-reset ke nilai true (bukan nol) pada setiap iterasiwhile(<>)
loop.sumber
-n
dan kurung keriting yang tak tertandingiDiketahui bahwa saklar baris perintah
-n
dapat digunakan untuk mengeksekusi skrip sekali untuk setiap baris.perl --help
mengatakan:Apa yang tidak dikatakannya secara eksplisit adalah bahwa Perl tidak hanya mengasumsikan loop di sekitar program; itu benar - benar membungkusnya
while (<>) { ... }
.Dengan cara ini, perintah berikut ini setara satu sama lain:
-p
dan kurung keriting yang tak tertandingiDemikian pula dengan yang di atas,
-p
saklar membungkuswhile (<>) { ... ; print }
program.Dengan menggunakan kurung keriting yang tidak tertandingi,
perl -p 'code}{morecode'
hanya akan mencetak sekali setelah mengeksekusicode
untuk semua jalur input, diikuti olehmorecode
.Karena
$_
tidak ditentukan saatmorecode;print
dieksekusi, pemisah catatan output$\
dapat disalahgunakan untuk mencetak output yang sebenarnya.Sebagai contoh
membaca satu nomor per baris dari STDIN dan mencetak jumlahnya.
sumber
#!perl -n
di baris pertama, kan?-p
dan$\
) untuk pertama kalinya di salah satu jawaban Perl @primo . Untuk membaca jawaban-jawabannya adalah tip Perl yang baik pada dirinya sendiri.}for(...){
di sela-sela kawat gigi seringkali cukup berguna juga, misalnya codegolf.stackexchange.com/a/25632Gunakan
$_
untuk menghilangkan referensi skalar. Ini adalah variabel khusus yang digunakan sebagai default oleh sebagian besar fungsi, dan hanya menyisakan parameter adalah jalan pintas untuk referensi variabel ini.Dengan mengubah
$n
ke$_
, Anda dapat mengubah$n=<>;chop$n;print$n
ke$_=<>;chop;print
Di sini,
print
fungsi mencetak konten$_
secara default, danchop
juga berfungsi$_
.sumber
$_=<>;
wajib, tidak<>;
membaca baris ke$_
otomatis?$_=<>;print
dan<>;print
. Yang pertama mengulangi kembali kepada saya apa yang saya ketik, sedangkan yang lain tidak.print while(<>)
. Tidak yakin apakah ini kasus khusus atau ada beberapa logika yang koheren di belakangnya, tidak ada<>
bagianperlop
atau punwhile
bagian yangperlsyn
menyebutkan perilaku ini.while(<>)
adalah kasus khusus, didokumentasikan dalam perlsyn, I / O Operator: 'Jika dan hanya jika simbol input adalah satu-satunya hal di dalam syarat pernyataan "sementara" (bahkan jika disamarkan sebagai "untuk (;;)" loop), nilai tersebut secara otomatis ditetapkan ke variabel global $ _, menghancurkan apa pun yang ada sebelumnya. "Gunakan variabel khusus Perl kapan pun Anda bisa, misalnya:
$"
sebagai ganti" "
$/
sebagai ganti"\n"
Mereka memiliki manfaat tambahan sebagai pengidentifikasi panjang satu karakter yang dijamin, dengan bantuan dari lexer. Ini memungkinkan untuk merekatkannya ke kata kunci yang mengikutinya, seperti pada:
print$.for@_
Daftar semua variabel khusus tersedia di sini: Variabel Khusus
sumber
Jangan gunakan
qw
. Ini adalah pemborosan dari dua karakter yang dapat digunakan dengan cara yang lebih baik. Misalnya, jangan menulis yang berikut ini.Alih-alih menggunakan kata kunci.
Atau jika Anda tidak dapat menggunakan kata kunci, gunakan
glob
sintaks.glob
sintaksis juga dapat digunakan untuk efek yang menarik.sumber
Gunakan pengubah pernyataan alih-alih pernyataan majemuk.
Pernyataan majemuk cenderung membutuhkan tanda kurung untuk argumen dan kurung untuk blok, sedangkan pengubah pernyataan tidak membutuhkan keduanya.
Membandingkan:
$a++,$b++while$n--
vs.while($n--){$a++;$b++}
chop$,if$c
vs.if($c){chop$,}
Perhatikan bahwa contoh terakhir ada hubungannya
$c&&chop$,
, tetapi mulai benar-benar bersinar untuk sebagian besar operasi multi-pernyataan. Pada dasarnya apa pun yang kehilangan prioritas operator&&
.sumber
Jangan
use strict
. (jangan mengutip saya tentang ini, konteks PCG.SE agak penting) Dan, yang lebih penting, jangan kode seolah-olah di bawah ketat. Tersangka yang biasa:my
-deklarasikan variabel jika Anda bisa menghindarinya. Satu-satunya variabel yang benar-benar dibutuhkanmy
adalah yang Anda inginkan dicakup secara leksikal. Itu hampir tidak ada dari mereka ketika bermain golf, di mana Anda tidak membutuhkan perlindungan ruang lingkup dan cenderung untuk sepenuhnya mengendalikan rekursi.sumber
print hello
tidak akan bekerja Ini sebenarnya berartiprint hello $_
(cetak$_
ke filehandlehello
).print
, dan sekarang saya tidak dapat menemukan contoh yang bagus dan pendek)Saya yakin beberapa di antaranya memiliki nama resmi dan saya tidak menyadarinya.
print $n++ while ($n < 10)
$var = join('',<>)
print ('X'*10) . "\n";
lebih lama daripadaprint ('X'*10) . $/;
say
Fungsi Perl lebih pendek daripadaprint
, tetapi Anda harus menjalankan kode dengan-E
alih - alih-e
a..z
atau bahkanaa..zz
. Jika diperlukan sebagai string, gunakanjoin
.$z = 'z'; print ++$z;
akan ditampilkanaa
Hanya itu yang bisa saya pikirkan saat ini. Saya dapat menambahkan lagi nanti.
sumber
print ('X'*10) . $/;
seharusnya dilakukan? Bagi saya itu mencetak0
dan tidak ada baris baru. Untuk satu hal, tanda kurung menjadi argumen panggilan fungsi-gayaprint
, yang mengikat lebih ketat dari.
. Dan apakah yang Anda maksudkanx
bukan*
atau sesuatu?while
,join'',<>;
juga berfungsi tanpa tanda kurung .Gunakan karakter bukan kata sebagai nama variabel
Menggunakan
$%
alih-alih$a
dapat memungkinkan Anda untuk menempatkan nama variabel tepat di sebelahif
,for
atauwhile
membuat seperti pada:@r=(1,2,3,4,5);$%=4;
print$_*$%for@r
Banyak yang dapat digunakan, tetapi periksa dokumen dan jawaban @ BreadBox yang mana yang memiliki efek ajaib!
Gunakan peta saat Anda tidak dapat menggunakan pengubah pernyataan
Jika Anda tidak dapat menggunakan pengubah pernyataan sesuai jawaban @ JB , peta mungkin menyimpan byte:
for(@c){}
vs.map{}@c;
dan berguna jika Anda ingin melakukan iterasi bersarang karena Anda dapat menempatkan
for
loop postfix di dalammap
.Gunakan semua variabel Ekspresi Reguler sihir
Perl memiliki variabel ajaib untuk 'teks sebelum pertandingan' dan 'teks setelah pertandingan' sehingga dimungkinkan untuk dipecah menjadi kelompok dua dengan karakter yang berpotensi lebih sedikit:
Ini juga bisa berfungsi sebagai pengganti untuk
substr
:Jika Anda membutuhkan konten pertandingan,
$&
dapat digunakan, misalnya:Ganti kapal selam dengan nama panjang dengan nama pendek
Jika Anda menelpon katakan
print
empat kali atau lebih dalam kode Anda (ini jelas berbeda dengan panjang rutin yang Anda panggil), gantilah dengan sub nama yang lebih pendek:vs.
Ganti incrementor / decrementor kondisional
Jika Anda memiliki kode seperti:
Anda dapat gunakan:
alih-alih menyimpan beberapa byte.
Konversikan ke integer
Jika Anda tidak menetapkan ke variabel dan tidak bisa menggunakan tip kotak roti , Anda bisa menggunakan ekspresi
0|
:Namun perlu dicatat daripada Anda tidak perlu menggunakan integer untuk mengakses indeks array:
sumber
redo
menambahkan perilaku loop ke blok tanpafor
atauwhile
.{redo}
adalah loop tak terbatas.sumber
Jangan kurung panggilan fungsi.
Perl memungkinkan Anda memanggil fungsi yang dikenal (inti atau yang telah dideklarasikan) menggunakan
NAME LIST
sintaks. Ini memungkinkan Anda menjatuhkan&
sigil (jika Anda masih menggunakannya) serta tanda kurung.Sebagai contoh:
$v=join'',<>
Dokumentasi lengkap
sumber
Cobalah untuk menggunakan nilai ekspresi penugasan, seperti:
Ini berfungsi karena
$n
2 karakter dalam Perl. Anda dapat mengubah$n
ke()
tanpa biaya, dan menghemat 1 titik koma dengan memindahkan tugas ke dalam tanda kurung.sumber
Anda dapat menjalankan beberapa pernyataan berbeda dalam logika terner bersarang.
Misalkan Anda memiliki besar
if
-elsif
pernyataan. Ini bisa berupa logika dan sejumlah pernyataan.Anda dapat menggunakan
(cmd1, cmd2, cmd3)
di dalam operator ternary untuk menjalankan semua perintah.Berikut ini contoh tiruannya:
sumber
Gunakan
select(undef,undef,undef,$timeout)
sebagai gantiTime::HiRes
(Diambil dari https://stackoverflow.com/a/896928/4739548 )
Banyak tantangan yang mengharuskan Anda tidur dengan presisi lebih tinggi daripada bilangan bulat.
select()
Argumen batas waktu dapat melakukan hal itu.jauh lebih efisien daripada:
Yang pertama hanya 20 byte, sedangkan yang terakhir memakan waktu 39. Namun, yang pertama mengharuskan Anda tidak menggunakan
$u
dan tidak pernah mendefinisikannya.Jika Anda akan menggunakannya, banyak yang diimportensikan
Time::HiRes
terbayar, tetapi jika Anda hanya membutuhkannya sekali saja, menggunakanselect($u,$u,$u,0.1)
simpanan 19 byte, yang jelas merupakan peningkatan dalam banyak kasus.sumber
Persingkat pernyataan cetak Anda
Kecuali jika tantangannya menentukan sebaliknya, Anda tidak perlu membuntuti baris baru.
'Tantangan' kami mengatakan 'mengeluarkan angka acak dari 0 hingga 9 ke STDOUT'. Kita dapat mengambil kode ini (28 byte):
Dan persingkat menjadi ini (25 byte):
hanya dengan mencetak variabel. Yang terakhir ini hanya berlaku untuk tantangan ini secara khusus (19 byte):
tetapi itu hanya berfungsi ketika Anda tidak perlu melakukan apa pun pada variabel di antara tugas dan pencetakan.
sumber
Gunakan gumpalan seperti string literal
Kadang-kadang (sering ketika berhadapan dengan tantangan quine atau sumber terbatas ) Anda mendapat manfaat besar dari kemampuan untuk bersarang string literal. Biasanya, Anda akan melakukan ini dengan
q(…)
. Namun, tergantung pada karakter apa yang Anda butuhkan di dalam string, Anda mungkin dapat menyimpan byte dan menggunakan<…>
, operator glob. (Perhatikan bahwa apa yang ada di dalam kurung sudut tidak dapat terlihat seperti filehandle, dan tidak terlihat seperti itu dimaksudkan untuk diperluas menjadi daftar nama file, yang berarti bahwa cukup banyak karakter tidak akan berfungsi dengan benar.)sumber
Gunakan ekspresi regexe.
Ilustrasi yang layak untuk hal ini adalah kode berikut yang membentuk input menjadi gelombang sinus:
Seperti yang Anda lihat, ini cara yang ringkas untuk mengulangi karakter dalam input standar. Anda bisa menggunakan regex lain untuk mengubah cara semuanya dicocokkan.
sumber