Apa tips umum yang Anda miliki untuk bermain golf di PHP? Saya mencari ide yang dapat diterapkan pada masalah kode golf secara umum yang setidaknya agak spesifik untuk PHP (mis. "Hapus komentar" bukan jawaban). Silakan kirim satu tip per jawaban.
37
Jawaban:
Memahami bagaimana variabel dan spasi putih berinteraksi dengan konstruksi bahasa PHP.
Dalam golf waktu saya (memang singkat), saya telah menemukan bahwa konstruksi bahasa PHP (misalnya gema, return, untuk, sementara, dll) berperilaku dengan cara yang kurang intuitif ketika berinteraksi dengan variabel dan spasi.
echo$v;
, misalnya, sangat valid, sebagaimana adanyareturn$v;
dan konstruksi serupa lainnya. Pengurangan kecil ini di ruang putih dapat menyebabkan penurunan kumulatif yang signifikan dalam panjang.Perlu diingat, bahwa variabel sebelum konstruksi bahasa memerlukan spasi setelah, seperti dalam contoh berikut:
Karena
AS
merupakan konstruksi bahasa, spasi tidak diperlukan sebelum variabel$b
, tetapi jika ada yang menghilangkan spasi sebelum itu , menghasilkan$aAS
, ini akan diurai sebagai nama variabel dan menyebabkan kesalahan sintaks.sumber
foreach($a[1]as$b)
tidak membutuhkan ruang putih. Ini bukan tentang konstruksi dan variabel bahasa, tetapi tentang ruang antara kata-karakter dari kata-kata yang berbeda.echo $a+5." text"
tidak akan berfungsi karena PHP berpikir bahwa itu.
adalah titik desimal untuk5
. Untuk membuatnya bekerja, Anda perlu menambahkan ruang seperti ini:echo $a+5 ." text"
echo$a+5," text";
. Theecho
membangun memungkinkan Anda untuk melewati beberapa parameter. di mana orang harus menulisecho"result: ".($a+5)."!";
, Anda dapat menulisecho"result: ",$a+5,"!";
. Faktanya, meneruskan beberapa parameter ke sebuahecho
adalah optimasi mikro, karena kode akan berjalan sedikit lebih cepat (karena Anda tidak menggabungkan output, tetapi mengirimkannya secara terpisah). Untuk tantangan tentang penulisan kode tercepat, ini mungkin membantu sedikit sangat kecil.echo
, tetapi tidak denganprint
(yang Anda perlukan jika Anda memasukkannya ke dalam ekspresi:echo
adalah konstruksi murni tanpa nilai balik sambilprint
dapat bertindak sebagai fungsi: tidak memerlukan tanda kurung, tetapi selalu kembaliint(1)
.print
.Gunakan string dengan bijak.
Jawaban ini dua kali lipat. Bagian pertama adalah ketika mendeklarasikan string, Anda dapat memanfaatkan konversi implisit PHP dari konstanta yang tidak diketahui ke string untuk menghemat ruang, misalnya:
Hal
@
ini diperlukan untuk mengganti peringatan yang akan dihasilkannya. Secara keseluruhan, Anda berakhir dengan pengurangan satu karakter.adalah bahwa kadang-kadang, mungkin ruang yang efektif untuk mengatur variabel ke nama fungsi yang sering digunakan. Biasanya, Anda mungkin memiliki:
Tetapi ketika bermain golf, ini dapat dipersingkat dengan mudah ke:
Dengan hanya dua contoh "preg_match", Anda hanya menyimpan satu karakter, tetapi semakin banyak Anda menggunakan fungsi, semakin banyak ruang yang akan Anda simpan.
sumber
E_DEPRECATED
) dapat diterimaphp.ini
fileAnda tidak selalu perlu menulis cek bersyarat. Misalnya, beberapa kerangka kerja menggunakan ini di bagian atas file mereka untuk memblokir akses:
Atau dalam fungsi normal
dari pada
sumber
Gunakan sintaks array pendek
Sejak PHP 5.4, array dapat dideklarasikan menggunakan tanda kurung siku (seperti halnya JavaScript) alih-alih
array()
fungsinya:Ini akan menghemat lima byte.
Tetapi mungkin biaya byte jika Anda memiliki "lubang" dalam array asosiatif:
kerugiannya hit sedikit kemudian jika Anda bisa mengisi lubang dengan nilai "kosong":
sumber
[,$a,$b,$c]=$argv;
.Gunakan $ {0}, $ {1}, $ {2}, ... daripada $ a [0], $ a [1], $ a [2], ...
Kecuali jika Anda melakukan manipulasi array, sebagian besar referensi ke indeks array
$a[$i]
dapat diganti dengan sederhana$$i
. Ini bahkan benar jika indeks adalah bilangan bulat, karena bilangan bulat adalah nama variabel yang valid di PHP (meskipun literal akan memerlukan tanda kurung, misalnya${0}
).Pertimbangkan implementasi keran Rabonowitz Wagon berikut ini:
Ini dapat ditingkatkan dengan 6 byte, cukup dengan mengganti kedua referensi array
$a[$g]
dengan$$g
:sumber
Pelajari sebagian besar fungsi perpustakaan .
Pustaka PHP cukup besar dan menyediakan banyak fungsi mudah yang dapat sangat mempersingkat berbagai tugas. Anda bisa saja mencari setiap kali Anda mencoba melakukan sesuatu, tetapi melebihi membuang waktu Anda mungkin tidak menemukan apa pun yang cocok dengan pencarian khusus Anda. Cara terbaik adalah membiasakan diri dengan perpustakaan dan menghafal nama-nama fungsi dan apa yang mereka lakukan.
sumber
Menjalankan fungsi di dalam string.
Coba ini:
Atau coba ini:
Ini hanya berfungsi dengan menggunakan string
""
dan heredocs (JANGAN membuat kebingungan dengan nowdocs).Menggunakan fungsi bersarang hanya mungkin di dalam heredocs bersarang (atau Anda akan mengalami kesalahan parse)!
sumber
you will run into parse errors
Saya tidak bisa membacanya sendiri? Bagaimana mesin Zend yang sial menyatukan inibersenang-senang dengan typecasts
!!$foo
akan mengubah nilai kebenaran apa pun menjaditrue
(atau1
dalam output), nilai falsy (0, string kosong, array kosong) menjadifalse
(atau output kosong)Ini jarang diperlukan dalam kode golf, karena dalam banyak kasus di mana Anda memerlukan boolean, ada pemeran implisit pula.
(int)$foo
dapat ditulis sebagai$foo|0
ataufoo^0
, tetapi mungkin membutuhkan tanda kurung.Untuk booleans dan string,
$foo*1
atau+$foo
bisa digunakan untuk cast ke int.10
, Anda bisa menambahkan nol:*10
->.0
. Tetapi dalam kasus ini, PHP akan mengambil titik sebagai titik desimal dan mengeluh. (Namun berbeda jika Anda memiliki jumlah nol nol dalam sebuah string.)join
sebagai gantiimplode
.Jika Anda tidak membutuhkan pembatas, jangan gunakan:
join($a)
lakukan hal yang samajoin('',$a)
$s=a;$s++;
menghasilkan$s=b;
. Ini berfungsi dengan karakter huruf besar dan kecil.$s=Z;$s++;
hasil dalam$s=AA;
.Ini juga bekerja dengan case campuran:
aZ
kebA
,A1
keA2
,A9
keB0
danz99Z
keaa00A
.Pengurangan tidak bekerja pada string. (Dan itu tidak menyala
NULL
).Kembali di PHP 3,
$n="001";$n++;
diproduksi$n="002";
. Saya sedikit sedih mereka menghapus itu.Apa pun yang Anda main golf: selalu sediakan meja prioritas operator .
sumber
Gunakan shorttags
Dalam kode normal, itu praktik yang baik untuk digunakan
<?php
dan?>
. Namun, ini bukan kode normal - Anda sedang menulis kode kode golf. Alih-alih<?php
, tulis<?
. Alih-alih<?php echo
, tulis<?=
. Jangan mengetik?>
di akhir - itu sepenuhnya opsional. Jika Anda perlu?>
untuk beberapa alasan (misalnya untuk menghasilkan teks, dan entah bagaimana lebih pendek, atau sesuatu, jangan meletakkan tanda titik koma di depannya - itu tidak diperlukan, seperti yang?>
menyiratkan titik koma.Salah (pasti terlalu panjang):
Benar:
sumber
-r
bendera ( yang gratis ), Anda bahkan tidak diberi tag sama sekali (dan Anda tidak diizinkan menggunakannya).perulangan melalui string
dapat dilakukan dengan 26 byte atau dengan 24 hingga 18:
$a&$b
melakukan bitwise AND pada (kode ascii) karakter dalam$a
dan$b
dan menghasilkan string yang memiliki panjang yang sama dengan yang lebih pendek dari
$a
dan$b
.sumber
ord($s[$p++])
sebagai alternatiffor(;$s+=ord($argv[++$i])%32?:die($s==100););
terhadapfor(;$c=$argv[++$i];)$s+=ord($c)%32;echo$s==100;
pertanyaan ini codegolf.stackexchange.com/questions/116933/…~
untuk kasus Anda hanya bekerja dengan angka~$c
pendekatan tersebut.Gunakan operator ternary
dapat disingkat menjadi ini:
Lebih pendek, ya?
sumber
a?aa:ab?aba:abb:b
mengevaluasi ke(a?aa:ab)?(aba):(abb)
atau sesuatu seperti itu.$a?:$b
sama dengan$a?$a:$b
.||
cast ke boolean dalam PHP.dengan nama lain ... alias fungsi
gunakan ...
join
dari padaimplode
chop
alih-alihrtrim
(chop
dalam PERL berbeda!)die
dari padaexit
fputs
dari padafwrite
is_int
bukannyais_integer
atauis_long
is_real
bukannyais_float
atauis_double
key_exists
dari padaarray_key_exists
mysql
dari padamysql_db_query
... untuk menyebutkan nama alias yang paling penting. Lihatlah http://php.net/aliases untuk informasi lebih lanjut.
sumber
die
berfungsi dengan dan tanpa parameter?die(1)
akan keluar dari program dengan kode kesalahan1
(tidak sepenuhnya yakin tentang ini; perlu pengujian);die
akan keluar dengan kode0
, dandie("Hello")
akan keluar dengan kode0
setelah mencetakHello
.Array asosiatif dapat digabungkan dengan
+
operator.Dari pada:
Menggunakan:
Perhatikan bahwa
+
operator juga bekerja dengan array yang diindeks, tetapi mungkin tidak melakukan apa yang Anda inginkan.sumber
+
, selama indeksnya berbeda. Jika tidak, nilai-nilai dari array pertama akan ditimpa dengan yang dari array yang kedua (seperti array_merge). Perbedaannya:+
tidak menyusun ulang indeks.array_flip vs array_search
menggunakan
dari pada
untuk menyimpan 1 Byte dalam array di mana kemunculan setiap nilai unik
sumber
beberapa fakta menarik tentang variabel variabel
Saya hanya harus membagikannya (bahkan sebelum saya memverifikasi bahwa setidaknya satu dari mereka membantu bermain golf):
$x=a;$$x=1;$x++;$$x=2;echo"$a,$b";
cetak1,2
tetapi operasi aritmatika lainnya tidak berfungsi dengan huruf.
$a=1;$$a=5;$a++;$$a=4;${++$a}=3;echo${1},${2},${3};
cetakan543
.[0-9a-zA-Z_]
untuk nama variabel, tetapi SETIAP string:$x="Hello!";$$x="Goodbye.";echo${"Hello!"};
cetakanGoodbye.
.[a-zA-Z_][a-zA-Z_0-9]*
sebagai nama variabel membutuhkan kawat gigi untuk penggunaan literal.$$x=1
set${NULL}
, yang sama dengan${false}
dan${""}
.$a=1;$$a=5;
tidak hanya diatur${1}
, tetapi juga${true}
.satu lagi, yang paling aneh yang saya temukan sejauh ini: Coba
$a=[];$$a=3;echo${[]};
. Ya, itu mencetak3
!Alasan sebagian besar dari ini: nama variabel selalu dievaluasi ke string.
(Terima kasih @Christoph untuk menunjukkan.)
Jadi, apa pun yang Anda dapatkan ketika Anda
print
atauecho
ekspresi, itulah yang Anda dapatkan sebagai nama variabel.sumber
[]
dikonversi keArray
:${[]} = 5;echo $Array;
cetakan5
. Saya cukup yakin Anda tahu itu, tetapi mungkin tidak jelas bagi semua orang :)jeda baris
jika output membutuhkan jeda baris, gunakan jeda garis fisik (1 byte) sebagai gantinya
"\n"
Ini juga memberi Anda kemungkinan manfaat untuk memilih antara tanda kutip tunggal dan ganda.
sumber
hindari kutipan jika memungkinkan
PHP secara implisit melemparkan kata-kata yang tidak dikenal ke string literal.
$foo=foo;
sama dengan$foo='foo';
(dengan asumsi itufoo
bukan kata kunci atau konstanta yang didefinisikan):$foo=echo;
tidak berfungsi.TAPI:
$p=str_pad;
apakah; dan$p(ab,3,c)
mengevaluasi keabc
.Menggunakan string literal tanpa tanda kutip akan menghasilkan Pemberitahuan untuk
Use of undefined constant
; tetapi itu tidak akan muncul jika Anda menggunakan nilai default untukerror_reporting
(parameter CLI-n
).sumber
-n
bendera); 7.2 menghasilkan Peringatan; versi yang lebih baru akan menampilkan Kesalahan!Fungsi panah di PHP 7.4
PHP 7.4 sekarang dalam versi RC2 dan mudah-mudahan akan dirilis dalam waktu sekitar 2 bulan. Daftar fitur baru ada di sini (halaman ini sebenarnya dapat diperbarui ketika 7.4 dirilis). Pada 7.4, akhirnya PHP memiliki fungsi panah, jadi tidak hanya jawaban fungsi yang dapat lebih pendek sekarang, tetapi juga melewati penutupan ke fungsi lain juga bisa jauh lebih pendek. Berikut ini beberapa contoh:
Masukan kembali + 1:
Fungsi anonim (penutupan) - 25 byte - Cobalah online!
Fungsi panah - 12 byte - Cobalah online!
Lipat gandakan input pertama (array int) dengan input kedua (int):
Fungsi anonim (penutupan) - 72 byte - Cobalah online!
Fungsi panah - 38 byte - Cobalah online!
Apakah Anda memperhatikan bahwa
$n
fungsi internal dapat diakses tanpause $n
pernyataan? Ya itu adalah salah satu fitur fungsi panah.Sebagai catatan, saya tidak bisa mendapatkan fungsi panah untuk bekerja secara rekursif (memanggil fungsi panah yang sama di dalam dirinya sendiri), karena kita tidak bisa memberi mereka nama dan menyimpannya sebagai penutup dalam variabel seperti
$f
tidak membuat$f
diakses dengan sendirinya (sedih ). Jadi contoh ini tidak berfungsi dan menggunakan$f
di baris pertama menyebabkan kesalahan fatal:Tetapi memanggil fungsi panah dengan fungsi panah yang berbeda berfungsi:
sumber
$f=fn($n)=>$n?$f($n-1):0;
Anda tidak melakukannya$f=$F=fn($n)=>$n?$F($n-1):0;
? Apakah itu akan berhasil? Dan kemudian Anda menelepon$(5)
seperti biasa.Mengenai file I / O:
Menautkan ke pertanyaan terkait lainnya , jawaban yang cocok di sini.
sumber
Array dereferensi langsung dikembalikan dari fungsi.
Misalnya, alih-alih ini:
Anda dapat melakukan:
Ini bekerja dengan metode juga:
Anda juga dapat langsung mendeklarasikan deklarasi array:
sumber
Gunakan
end()
sebagai gantiarray_pop()
The
end()
fungsi tidak hanya memindahkan pointer internal ke akhir array, juga mengembalikan nilai terakhir. Perhatikan tentu saja bahwa itu tidak menghapus nilai itu, jadi jika Anda tidak peduli apa isi array setelahnya, Anda dapat menggunakannya sebagai gantinyaarray_pop()
.sumber
double array_flip vs in_array vs array_unique
dalam kasus khusus ini, array_flip ganda menghemat 10 Bytes
($f=array_flip)($k=$f($c)))
hapus semua nilai ganda dalam array dan saya telah menjatuhkan ini$c=[],
,|in_array($o,$c)
dan gantiarray_keys($c)
dengan$k
Versi Online
melawan
Versi online
terhadap array_unique menghemat 2 Bytes
Versi Online
Setelah menemukan bug dalam program ini dan penggantian
$x[$i]==$o?:$c[$x[$i]]=$o
ke($p=$x[$i])==$o?:$k[$c[$p]=$o]=$p
array_flip ganda tidak diperlukan lagisumber
array_unique
. Yay!string berpotongan
Pernahkah Anda menggunakan
join("DELIMITER",str_split($s))
(31 byte) atau bahkanpreg_replace(".","DELIMITER",$s)
(32 byte)?
Ada builtin untuk itu:
Coba
chunk_split($s,1,"DELIMITER")
(29 byte).Jika Anda menghilangkan parameter ketiga,
chunk_split
akan digunakan\r\n
; yang dapat menghemat 7 atau 8 byte.Namun berhati-hatilah:
chunk_split
juga menambahkan pembatas pada string,jadi Anda mungkin tidak mendapatkan apa yang Anda inginkan.
(Jika Anda tidak memberikan panjang chunk, itu akan menggunakan 76. Agak tidak biasa untuk golf kode, tetapi siapa yang tahu.)
sumber
strtr
Saya suka ide ini.tidak disetel () vs INF
Dalam pencarian kasus untuk minimum dalam array, Anda dapat menggunakan sebagai gantinya
untuk menyimpan 3 Bytes
sumber
str_repeat
Dalam beberapa kasus, Anda memiliki input karakter dan Anda harus menampilkannya berulang dengan input nol lebih besar untuk setiap karakter.
(52 byte) lebih pendek dari
atau
(Masing-masing 54 byte)
Cara kerjanya misalnya input
a1b2c1
$z
tidak diatur (implisitNULL
), jadi--$z
tidak melakukan apa-apa dan palsu;$c="a"
,$z="1"
dan$i=2
->$c.$z="a1"
benar -> keluaran"a"
--$z=0
; jadi kita atur$c="b"
,$z="2"
(dan$i=4
) ->$c.$z="b2"
benar - output"ab"
--$z=1
-> output"abb"
--$z=0
; jadi kami mengatur$c="c"
dan$z=1
$c.$z="c1"
merupakan output yang benar"abbc"
--$z=0
begitu$c=""
dan$z=""
->$c.$z=""
falsy -> loop breaksumber
Menggabungkan
for
loopMisalkan Anda memiliki kode dari formulir berikut:
ini umumnya dapat digulung kembali dalam bentuk berikut:
di mana
•
merupakan operator penggabungan generik. Ini biasanya menghasilkan pengurangan jumlah byte, tetapi kemungkinan akan membutuhkan beberapa kreativitas.$cond2
perlu ditulis agar gagal pertama kali.$post1
harus juga gagal mengeksekusi pertama kali, meskipun mungkin lebih mudah untuk refactor sebelumnya sehingga$post1
tidak ada.Jika Anda bekerja dengan tiga atau lebih loop bersarang, Anda juga bisa menggabungkan dua terlebih dahulu, lalu menggabungkannya ke yang lain, dan seterusnya. Saya menemukan bahwa umumnya lebih mudah untuk menggabungkan dari dalam ke luar.
Sebagai contoh, pertimbangkan solusi berikut untuk fraktal H-carpet ( 97 byte) ):
Ini dapat dirumuskan kembali dengan cara berikut:
$e&&print
mencegahprint
pada iterasi pertama, dan juga tidak bertambah$i
.dan akhirnya ( 93 byte ):
$H>$e*=3
akan gagal pertama kali karena kedua variabel tidak terdefinisi.sumber
Menghapus karakter dalam sebuah string
menghemat 1 karakter dibandingkan dengan
sumber
""
dan itu tidak terlalu berguna.)
. Danstrtr($string,[" "=>""])
bahkan lebih pendek.array_merge vs array_push
lebih pendek satu byte dari
Tidak berfungsi sama dengan array asosiatif
variabel-arg-list PHP> 5.6
sumber
Gunakan operator boolean bukan
strtoupper()
danstrtolower()
Jika Anda bekerja secara eksklusif dengan string yang terdiri dari karakter alfabet, Anda dapat menggunakan operator boolean untuk mengubahnya menjadi huruf besar atau kecil dengan penekanan tombol lebih sedikit daripada fungsi bawaan PHP.
Contoh:
Hal-hal sedikit lebih rumit untuk string dengan panjang sewenang-wenang, tetapi operator
&
dan^
akan memotong hasilnya dengan panjang string input yang lebih pendek. Jadi misalnya, jika$W
string spasi setidaknya selama input apa pun$s
, maka~$W&$s
setara denganstrtoupper($s)
, dan$s|$W^$s
setara denganstrtolower($s)
(sedangkan$s|$W
dengan sendirinya akan menghasilkan string dengan spasi tambahan kecuali$s
dan$W
dengan panjang yang sama).sumber
gunakan fungsi yang tidak digunakan lagi
Jika Anda dapat menggunakan POSIX sebagai ganti PERL regex tanpa membuang lebih dari 5 byte pada ekspresi, gunakan
ereg
ataueregi
alih-alihpreg_match
,split
atauspliti
alih-alih preg_split.split
Dapat juga digunakan sebagai sinonimexplode
untuk sebagian besar pembatas.Fungsi-fungsi ini ditandai sudah usang dan akan membuang
E_DEPRECATED
pemberitahuan, tetapi (tidak dapat menemukan sumbernya sekarang) Saya pikir saya telah membaca bahwa peringatan dan pemberitahuan itu ok.sumber