PHP'de golf oynamak için ipuçları


37

PHP'de golf oynamak için hangi genel ipuçlarınız var? Genel olarak golf problemlerini kodlamak için uygulanabilecek fikirlere bakıyorum (en azından PHP'ye özgüdür) (örneğin, "yorumları kaldır" bir cevap değildir). Lütfen cevap başına bir ipucu gönderin.


Bekle, doğru yapıyorum mu? ... Neyse, bunu gerçekten merak ediyorum. PHP birçok kişi ve golfçü tarafından kullanılır, ancak bir PHP kodunu nasıl çalacağım hakkında hiçbir fikrim yok.
JiminP

Kısa etiketleri kullanın <??> Birkaç bayt kaydedebilir.
Mob

Yanıtlar:


22

Değişkenlerin ve boşlukların PHP'nin dil yapılarıyla nasıl etkileşimde bulunduğunu anlayın.

Benim kuşkusuz kısa zaman süren golf oyunlarımda PHP'nin dil yapılarının (örneğin, echo, return, for, vb.) Değişkenler ve boşluklarla etkileşime girerken sezgiselden daha az bir şekilde davrandığını buldum.

echo$v;örneğin, olduğu gibi return$v;ve diğer benzer yapılar için tamamen geçerlidir . Boşluktaki bu küçük azalmalar, uzunlukta önemli bir kümülatif azalmaya neden olabilir.

Bununla birlikte, dil yapıları önündeki değişkenlerin aşağıdaki örnekte olduğu gibi sonra bir boşluk gerektirdiğini unutmayın:

foreach($a AS$b){}

Çünkü ASbir dil oluşumu olduğundan, bir uzay değişkeni önce gerekli değildir $b, ama bir boşluk atlamak olsaydı ondan önce sonuçlanan $aASbu bir sözdizimi hatası bir değişken adı ve kurşun olarak çözümlenen.


3
foreach($a[1]as$b)beyaz boşluk gerekmez. Bu, dil yapıları ve değişkenler ile ilgili değil, farklı kelimelerin sözcük karakterleri arasındaki boşluklarla ilgilidir.
Titus,

1
Boşluğa ihtiyaç duyduğunuz bir başka örnek dize bitiştirmedir. Örneğin, echo $a+5." text"PHP bunun .için bir ondalık sayı olduğunu düşündüğü için çalışmayacak 5. Çalışması için, şöyle bir boşluk eklemeniz gerekir:echo $a+5 ." text"
Business Cat

@BasicSunset Bu deyim olarak yazılabilir echo$a+5," text";. echoYapı Birden parametreleri geçmesine izin verir. birinin yazmak zorunda kaldığı bir yere echo"result: ".($a+5)."!";yazabilirsiniz echo"result: ",$a+5,"!";. Aslında, birden fazla parametreyi a'ya geçirmek bir echomikro-optimizasyondur çünkü kod biraz daha hızlı çalışacaktır (çıktıyı bir araya getirmediğiniz, ancak ayrı olarak gönderdiğiniz için). En hızlı kodu yazma konusundaki zorluklar için, bu küçücük küçücük küçücük parçaya yardımcı olabilir.
Ismael Miguel

@IsmaelMiguel İle çalışır echo, ancak bununla çalışmaz print(bir ifadenin içine koyarsanız ihtiyacınız olan: echodönüş değeri olmayan saf bir yapıdır print , işlev olarak işlev görür: parantez gerektirmez, ancak her zaman geri döner int(1).)
Titus

@Titus hakkında bir şey söylemedim print.
Ismael Miguel,

22

Dizeleri akıllıca kullanın.

Bu cevap iki katlıdır. İlk bölüm dizeleri bildirirken, PHP'nin bilinmeyen sabitlerin örtük olarak dizgelere dönüştürülmesinden faydalanabileceğinizi, örneğin:

@$s=string;

Bunun @üreteceği uyarıları geçersiz kılmak için gereklidir. Genel olarak, bir karakterlik bir indirim ile bitirdiniz.

Bu bazen, sık kullanılan bir fonksiyonun ismine bir değişken ayarlamak için etkili olabilir. Normalde şunlara sahip olabilirsiniz:

preg_match(..);preg_match(..);

Ancak golf oynarken, bu kolayca kısaltılabilir:

@$p=preg_match;$p(..);$p(..);

Yalnızca iki "preg_match" örneğiyle, yalnızca tek bir karakter kaydedersiniz, ancak bir işlevi ne kadar çok kullanırsanız, o kadar fazla alan kazanırsınız.


10
kod kodlayıcıda @ gerekli değildir; bildirimler ve uyarılar (dahil E_DEPRECATED) kabul edilebilir
Titus

3
@Titus Ancak PHP'de, uyarılar standart dosya çıktısına gönderilir, bu yüzden ihtiyaç duyulur.
brianush1

1
@Titus Sana bunları bastırmak inanıyoruz php.inidosyası
Stan Strum

12

Her zaman şartlı çekler yazmanıza gerek yoktur. Örneğin, bazı çerçeveler erişimi engellemek için bunu dosyalarının üstünde kullanır:

<?php defined('BASE_PATH')||die('not allowed');

Veya normal fonksiyonlarda

$value && run_this();

yerine

if($value) { run_this(); }

JS'de de çalışıyor
Евгений Новиков

8

Kısa dizi sözdizimini kullan

PHP 5.4'ten beri, array()işlevler yerine köşeli parantezler (JavaScript gibi) kullanılarak diziler bildirilebilir :

$arr=['foo','bar','baz'];
// instead of
$arr=array('foo','bar','baz');

Beş bayt kurtaracak.


Ancak ilişkili bir dizide "delik" varsa, bu bayt mal olabilir:

$arr=array(,1,,3,,5);
// is one byte shorter than
$arr=[1=>1,3=>3,5=>5];

delikleri "boş" değerlerle doldurabilirseniz, dezavantaj biraz sonra gelir:

$arr=[0,1,0,3,0,5,0,7,0,9,10,11];
// costs two byte more than
$arr=array(,1,,3,,5,,7,,9,,11);

2
PHP 7.1 kısa liste atama tanıtıldı: [,$a,$b,$c]=$argv;.
Titus

7

$ A [0], $ a [1], $ a [2] yerine $ {0}, $ {1}, $ {2} kullanın ...

Bir dizi manipülasyonu yapmadığınız sürece, bir dizi indeksine yapılan çoğu referans $a[$i]basit bir şekilde değiştirilebilir $$i. Dizin bir tamsayıysa, bu da geçerlidir, çünkü tamsayılar PHP'deki geçerli değişken isimleridir (değişmezler, örneğin parantez gerektirecektir ${0}).

Rabonowitz Wagon tertibatının aşağıdaki uygulamasını göz önünde bulundurun:

3.<?for(;$g?$d=0|($a[$g]=$d*$g--/2+($a[$g]?:2)%$g*1e4)/$g--:238<<printf($e?'%04d':'',$e+$d/$g=1e4)^$e=$d%$g;);

Bu, her iki dizi referansını $a[$g]bununla değiştirerek, yalnızca 6 baytla geliştirilebilir $$g:

3.<?for(;$g?$d=0|($$g=$d*$g--/2+($$g?:2)%$g*1e4)/$g--:238<<printf($e?'%04d':'',$e+$d/$g=1e4)^$e=$d%$g;);

1
Bununla sadece 3 bayt kurtardım: vitrin .
Titus,

6

Kütüphane işlevlerinin büyük bir alt kümesini öğrenin .

PHP'nin kütüphanesi oldukça büyüktür ve çeşitli görevleri büyük ölçüde kısaltan bir dizi kullanışlı işlev sunar. Bir şey yapmaya her çalıştığınızda sadece arama yapabilirsiniz, ancak zamanınızı boşa harcayarak belirli aramanızla eşleşen hiçbir şey bulamayabilirsiniz. En iyi yol, sadece kütüphaneyi tanımak ve işlev isimlerini ve ne yaptıklarını ezberlemektir.


6
Bu, özellikle çok sayıda fonksiyonun tutarsız isimlendirilmesinden dolayı, çok fazla ezberleme ;-)
Joey

@Joey Anlaşıldı. Java kütüphanesini ezberlemeye benzer, bunun dışında daha ayrıntılı olacağı için tartışmasız daha az faydalı olacaktır.
Matthew

3
Şimdiye kadar karşılaştığım zorluklar için en önemli fonksiyonların string manipülasyon ve dizi manipülasyon fonksiyonları olduğunu buldum. Bunların yaratıcı kullanımı gerçekten kodu azaltabilir.
migimaru

6

Dizgelerin içinde çalışan fonksiyonlar.

Bunu dene:

$a='strlen';
echo "This text has {$a('15')} chars";

Veya şunu deneyin:

//only php>=5.3
$if=function($c,$t,$f){return$c?$t:$f;};
echo <<<HEREDOCS
    Heredocs can{$if(true,' be','not be')} used too and can{$if(<<<BE
{$if(true,1,0)}
BE
,'','not')} be nested
HEREDOCS;
//Expected output: Heredocs can be used too and can be nested

Bu sadece ""ve heredocs komutunu kullanarak çalışır (nowdocs ile karışıklık yapmaz).

Yuvalanmış işlevleri kullanmak, yalnızca yuvalanmış heredocs içinde mümkündür (veya ayrıştırma hatalarıyla karşılaşırsınız)!


you will run into parse errorsKendim okuyamıyorum? Sinir bozucu Zend motoru bunu nasıl bir araya getirdi?
Stan Strum,

Bir dahaki sefere "PHP iyi bir programlama dilidir" tartışmasında bulunduğumda, bunu bir karşı nokta olarak kullanacağım. Vay.
primo

@primo O kadar kötü mü? : O
Ismael Miguel

5

türevleri ile eğlenceli

  • !!$fooherhangi bir rutubet değerini true(veya 1çıktıda), sahte değerlere (0, boş dize, boş dizi) false(veya boş çıktıya) dönüştürür.
    Bu , bir booleye ihtiyaç duyduğunuz çoğu durumda, kod golfünde nadiren gerekli olacaktır. Zaten kapalı bir oyuncu kadrosu.

  • (int)$fooolarak yazılabilir $foo|0veya foo^0ancak parantez gerekebilir.
    Boolean'ler ve dizgiler için, $foo*1veya +$fooint.

  • Diğer dillerin çoğundan farklı olarak, PHP, sayı olarak sayısal değerleri olan dizeleri işler. Bu yüzden hesaplamak zorunda olduğunuz bir sayı içeren herhangi bir dizginiz varsa, sadece hesaplayın.
  • Diğer yol yapan değil bir değişkendeki herhangi bir sayıda çarpmak için: eser 10bir sıfır eklemek olabilir: *10-> .0. Fakat bu durumda, PHP noktayı ondalık nokta olarak alır ve şikayet eder. (Bir dizede değişken miktarda sıfır varsa, yine de farklıdır.)
  • Diziyi dizgeye dönüştürmek için joinyerine kullanın implode.
    Sınırlayıcıya ihtiyacınız join($a)yoksa, kullanmayın: Aynıjoin('',$a)
  • Dizeleri arttırmak: En şaşırtıcı özellik imo $s=a;$s++;üretmek $s=b;. Bu, büyük ve küçük harf karakterlerle çalışır. $s=Z;$s++;sonuçlanır $s=AA;.
    Bu aynı zamanda karışık durumda çalışır: aZiçin bA, A1için A2, A9için B0ve z99Ziçin aa00A.
    Azaltma yok değil dizeleri üzerinde çalışmak. (Ve açık değil NULL).
    PHP 3'te $n="001";$n++;üretildi $n="002";. Bunu kaldırdıkları için üzgünüm.

Ne golf oynarsanız yapın: daima operatör öncelik tablosunu bulundurun.


4

Kısa etiketler kullan

Normal kodunda, bu iyi kullanmak uygulamadır <?phpve ?>. Ancak, bu normal bir kod değil - bir kod golf kodu yazıyorsunuz. Bunun yerine <?php, yazın <?. Bunun yerine <?php echo, yazın <?=. Yazmayın ?>sonunda - bu tamamen isteğe bağlıdır. Bir ?>nedene ihtiyacınız varsa (örneğin, metin çıktısı almak ve bir şekilde daha kısa olması veya başka bir şey için), ondan önce noktalı virgül koyma - ?>noktalı virgül anlamına gelmez .

Yanlış (kesinlikle çok uzun):

<?php echo ucfirst(trim(fgets(STDIN)));?>s!

Doğru:

<?=ucfirst(trim(fgets(STDIN)))?>s!

İle -r(bayrak ücretsiz geliyor ), hiç bile herhangi etiketleri düğünle (ve herhangi kullanmasına izin Sen).
Titus,

4

dizeleri arasında döngü

26 bayt ile veya 24 ile 18 arası ile yapılabilir:

foreach(str_split($s)as$c)  # A) 26 - general
for($p=0;a&$c=$s[$p++];)    # B) 24 - general
for($p=0;$c=$s[$p++];)      # C) 22 - if $s has no `0` character
for(;a&$c=$s[$p++];)        # D) 20 - if $p is already NULL or 0 (does NOT work for false)
for(;$c=$s[$p++];)          # E) 18 - both C and D

for(;$o=ord($s[$p++]);)     # F) 23 - work on ASCII codes, if $s has no NULL byte and D
for(;~$c=$s[$p++];)         # G) 19 - if $s has no chr(207) and D

$a&$bikilik VE (bir ASCII kodları) karakterlerin üzerine yaptığı $ave $b
kısa aynı uzunlukta olan bir dizede ve sonuçları $ave $b.


Eklemek misiniz ord($s[$p++])alternatif olarak for(;$s+=ord($argv[++$i])%32?:die($s==100););karşı da for(;$c=$argv[++$i];)$s+=ord($c)%32;echo$s==100;bu soruyu içinde codegolf.stackexchange.com/questions/116933/...
Jörg Hülsermann

Lütfen ~sadece rakamlarla çalıştığınız davaları ekleyin
Jörg Hülsermann

PHP 7.2'nin ~$cyaklaşım için uyarılar verdiğini unutmayın .
Titus

4

Üçlü işleçleri kullan

if(a==2){some code;}else{some other code;}

bu kısaltılabilir:

(a==2?some code:some other code);

Daha kısa, ha?


“Koşullu kısaltmalar”? Gerçek adını söylesen iyi edersin, böylece daha fazla ayrıntıya ilgi duyanlar belgelerde bulabilirler: üçlü operatör .
Manatwork

3
Soru biraz PHP'ye özgü olan ipuçları ister. Bu, tüm dillere ilişkin ipuçlarına dahil edilmiştir .
Peter Taylor,

3
Üçlü operatör, iç içe geçirirseniz, PHP'de garip bir davranış sergiler. veya bunun gibi bir şeyi a?aa:ab?aba:abb:bdeğerlendirir (a?aa:ab)?(aba):(abb).
Titus,

1
PHP 5.3 ile başlayarak, ikinci işleci ihmal edebilirsiniz: $a?:$baynıdır $a?$a:$b.
Titus,

1
@Cyoce ||PHP'de boolean atar.
Titus

3

başka bir adla ... işlev takma adları

kullan ...

  • join yerine implode
  • chopyerine rtrim( chopPERL'de farklı!)
  • die yerine exit
  • fputs yerine fwrite
  • is_intyerine is_integerveyais_long
  • is_realyerine is_floatveyais_double
  • key_exists yerine array_key_exists
  • mysql yerine mysql_db_query

... en önemli takma adı vermek için. Bir göz atın http://php.net/aliases daha fazlası.


Oh ... ve dieparametresiz ve parametresiz çalıştığını biliyor muydunuz ? die(1)hata koduyla programdan çıkacak 1(bu konuda tamamen emin değil; test edilmesi gerekiyor); diekodla çıkacak 0ve yazdırdıktan sonra die("Hello")kodla çıkacak . 0Hello
Titus

3

İlişkili diziler +operatör ile birleştirilebilir .

Yerine:

$merged = array_merge($a, $b);

kullanın:

$merged = $a + $b;

+Operatörün dizine alınmış dizilerle de çalıştığını unutmayın , ancak muhtemelen istediğiniz şeyi yapmaz.


Nitekim, tam olarak aynı olmasa da, sıklıkla iyi bir değişiklik: pastebin.com/seYeaP38
manatwork

Ah evet, cidden, aslında "ilişkisel diziler ..." unvanını aldım ve sonra çıkardım. Açıklayacağım, teşekkürler.
Alex Howansky,

Sayısal diziler +, dizinler farklı olduğu sürece kullanılarak birleştirilebilir . Olmazsa, ilk diziden elde edilen değerlerin üzerine ikinci olandan yazılacaktır (sadece array_merge gibi). Fark: +dizinleri yeniden sıralamaz.
Titus

3

array_earch vs array_search

kullanım

array_flip($array)[$value]

yerine

array_search($value,$array)

Her bir değerin oluşumunun benzersiz olduğu dizilere 1 Byte kazandırmak


3

Değişken değişkenlerle ilgili bazı ilginç bilgiler

Onları paylaşmak zorundaydım ( en az birinin golf oynamaya yardımcı olduğunu doğrulamadan önce bile ):

  • Harfleri kullan: $x=a;$$x=1;$x++;$$x=2;echo"$a,$b";yazdırır, 1,2
    ancak diğer aritmetik işlemler harflerle çalışmaz.
  • Gibi primo Daha önce de belirttiğimiz : değişken adları gibi saf numaralarını kullanabilirsiniz
    $a=1;$$a=5;$a++;$$a=4;${++$a}=3;echo${1},${2},${3};baskılar 543.
  • Yalnızca [0-9a-zA-Z_]değişken adları için değil , HER dizede de kullanabilirsiniz:
    $x="Hello!";$$x="Goodbye.";echo${"Hello!"};yazdırır Goodbye..
  • Ancak: [a-zA-Z_][a-zA-Z_0-9]*Değişken isimleri dışında herşey değişmez kullanım için diş telleri gerektirir.
  • Tanımlanmış değişkenler ile $$x=1setleri ${NULL}ile aynıdır, ${false}ve ${""}.
  • $a=1;$$a=5;sadece ayarlamaz ${1}, aynı zamanda ${true}.

  • bir tane daha, şu ana kadar bulduğum en garip olanı: dene $a=[];$$a=3;echo${[]};. Evet, yazdırıyor 3!

Bunun çoğunun nedeni: değişken isimleri her zaman dizgilere göre değerlendirilir.
(İşaretlediğiniz için teşekkürler @Christoph.)
Öyleyse, siz printveya echoifadeniz ne olursa olsun, değişken adı olarak elde ettiğiniz şey budur.


1
Değişken isimleri, listenizdeki son üç noktayı açıklayan dizgelere dönüştürülür. []dönüştürür Array: ${[]} = 5;echo $Array;yazdırır 5. Bunu bildiğinize eminim ama herkes için açık olmayabilir :)
Christoph

@Jeff Yazım hatasını düzelttim. Fark ettiğiniz için teşekkürler.
Titus

2

satır kesmelerinin
çıkış satır sonları gerektiriyorsa fiziksel bir satır sonu (1 bayt) yerine kullanmak, "\n"
tek ve çift tırnak arasına seçilmek için Bu aynı zamanda olası bir fayda sağlar.


2

mümkün olduğunda alıntı yapmaktan kaçının

PHP dolaylı olarak bilinmeyen kelimeleri değişmez dizgelere aktarır.

$foo=foo;aynıdır $foo='foo';( fooanahtar kelime veya tanımlanmış bir sabit olmadığını varsayarsak ): $foo=echo;çalışmaz.

AMA: $p=str_pad;yapar; ve $p(ab,3,c)değerlendirir abc.

Dize değişmezlerini tırnak işaretleri olmadan kullanmak Use of undefined constant; ancak error_reporting(CLI parametresi -n) için varsayılan değeri kullanırsanız bu gösterilmez .


Daha yeni farkettim: Bu cevap codegolf.stackexchange.com/a/2916/55735 adresinin biraz uzatılmış / güncellenmiş bir kopyasıdır .
Titus

Not: 7.2'den önce PHP Bildirimleri ( -nbayrağını seçebileceğiniz ) bildirmiştir ; 7.2 uyarı verir; sonraki sürümlerde Hatalar atılacak!
Titus

2

PHP 7.4'te ok işlevleri

PHP 7.4 şimdi RC2 versiyonunda ve umarım yaklaşık 2 ay içerisinde piyasaya sürülecektir. Yeni özelliklerin listesi burada (bu sayfa 7.4 piyasaya sürüldüğünde güncellenebilir). 7.4'te, sonunda PHP ok fonksiyonlarına sahip, bu nedenle sadece fonksiyon cevapları artık daha kısa değil, aynı zamanda diğer fonksiyonlara kapanmaları da çok daha kısa olabilir. İşte birkaç örnek:

Dönüş girişi + 1:

Anonim işlev (kapatma) - 25 bayt - Çevrimiçi deneyin!

function($n){return$n+1;}

Ok işlevi - 12 bayt - Çevrimiçi deneyin!

fn($n)=>$n+1

İlk girişin (ints dizisinin) öğelerini ikinci girişin (int) ile çarpın:

Anonim işlev (kapatma) - 72 bayt - Çevrimiçi deneyin!

function($a,$n){return array_map(function($b)use($n){return$b*$n;},$a);}

Ok işlevi - 38 bayt - Çevrimiçi deneyin!

fn($a,$n)=>array_map(fn($b)=>$b*$n,$a)

$nİç fonksiyonda bir use $nifade olmadan erişilebilir olduğunu farkettiniz mi? Evet bu ok fonksiyon özelliklerinden biridir.


Bir yandan not olarak, tekrarlayan bir şekilde çalışmak için ok işlevlerini alamadım (aynı ok işlevini kendi içinde çağırın), çünkü onlara bir ad veremiyoruz ve bir değişken olarak kapanma olarak saklıyoruz $f, $fkendisiyle birlikte olmadıkça (üzücü) ). Yani bu örnek çalışmıyor ve $filk satırda kullanmak ölümcül bir hataya neden oluyor:

$f=fn($n)=>$n?$f($n-1):0;
$f(5); // Causes error: "PHP Notice: Undefined variable: f" + "PHP Fatal error: Uncaught Error: Function name must be a string"

Ancak farklı bir ok işlevine sahip bir ok işlevini çağırmak işe yarar:

$f1=fn($n)=>$n+1;
$f2=fn($n)=>$f1($n-1);
$f1(2) // Returns 3
$f2(2) // Returns 2

Ya $f=fn($n)=>$n?$f($n-1):0;senin yerine $f=$F=fn($n)=>$n?$F($n-1):0;? Işe yarar mı? Ve sonra $(5)her zamanki gibi diyorsun .
Ismael Miguel,

@IsmaelMiguel hala aynı hatayı atıyor gibi görünüyor. Dennis, PHP bir süre önce 7.4 RC2 olarak güncellediğinden, aslında tio.run # php'yi kendiniz deneyebilirsiniz .
Gece2,

Çalışması mümkün değil. Sadece önceden tanımlanmış değişkenlerin mevcut olduğu görülüyor.
Ismael Miguel


1

Fonksiyonlardan doğrudan çıkarım dizileri.

Örneğin, bunun yerine:

$a = foo();
echo $a[$n];

Yapabilirsin:

echo foo()[$n];

Bu da yöntemlerle çalışır:

echo $obj->foo()[$n];

Ayrıca doğrudan dizi bildirimlerini dreference edebilirsiniz:

echo [1, 2, 3, 4, 5][$n];

1

Yerine end()kullanınarray_pop()

end()Sadece dizinin sonuna iç işaretçi hareket etmiyor fonksiyonu, aynı zamanda son değeri döndürür. Elbette bu değeri kaldırmayacağına dikkat edin, bu nedenle dizinin sonradan ne içerdiğini umursamıyorsanız, bunun yerine kullanabilirsiniz array_pop().


1

double array_flip vs in_array vs array_unique

bu özel durumda bir çift array_flip 10 bayt kazandırır

($f=array_flip)($k=$f($c)))Dizideki tüm çift değerleri kaldırın ve bu düşmüş $c=[],, |in_array($o,$c)ve değiştirme array_keys($c)ile$k

for([,$x,$y]=$argv;a&$o=$y[$i];$i++)
$x[$i]==$o?:$c[$x[$i]]=$o; # if char string 1 not equal char string 2 set key=char1 value=char2
echo strtr($x,($f=array_flip)($k=$f($c)))==$y # boolean replacement string 1 equal to string 2
    ?join($k)." ".join($c) # output for true cases
:0; #Output false cases

Çevrimiçi sürüm

karşısında

for($c=[],[,$x,$y]=$argv;a&$o=$y[$i];$i++)
  $x[$i]==$o|in_array($o,$c)?:$c[$x[$i]]=$o; # if char string 1 not equal char string 2 set key=char1 value=char2
echo strtr($x,$c)==$y # boolean replacement string 1 equal to string 2
  ?join(array_keys($c))." ".join($c) # output for true cases
  :0; #Output false cases

Çevrimiçi sürüm

array_unique karşı 2 bayt kaydeder

for([,$x,$y]=$argv;a&$o=$y[$i];$i++)
  $x[$i]==$o?:$c[$x[$i]]=$o; # if char string 1 not equal char string 2 set key=char1 value=char2
echo strtr($x,array_unique($c))==$y # boolean replacement string 1 equal to string 2
  ?join(array_keys($c))." ".join($c) # output for true cases
  :0; #Output false cases

Çevrimiçi sürüm

Bu programda bir hata bulduktan ve çift array_flip'e değiştirildikten $x[$i]==$o?:$c[$x[$i]]=$osonra ($p=$x[$i])==$o?:$k[$c[$p]=$o]=$partık gerekli değildi.


ilişkisel güvenli array_unique. Yuppi!
Titus

@Titus Önerinizi
ekledim

1

kesişen dizeler

Hiç
join("DELIMITER",str_split($s))(31 bayt) ya da
preg_replace(".","DELIMITER",$s)(32 bayt) kullandınız
mı?

Bunun için bir yerleşik var:

Deneyin chunk_split($s,1,"DELIMITER")(29 bayt).


Üçüncü parametreyi atlarsanız chunk_splitkullanacaksınız \r\n; bu size 7 veya 8 bayt kazandırabilir.

Ancak dikkat: chunk_splitayrıca sınırlayıcıyı dizeye ekler,
böylece tam olarak ne istediğinizi alamayabilirsiniz.

(Eğer yığın uzunluğunu sağlamıyorsanız, 76 kullanır. Kod golf için alışılmadık, ama kim bilir.)


Belki de strtrbu fikri sevdiğimle birlikte bir örnek eklemelisin .
Jörg Hülsermann

1

unset () vs INF

Bir durumda, bir dizideki minimum ifadeyi aramak yerine kullanabilirsiniz.

unset($var[$k]);

$var[$k]=INF;

3 bayt kaydetmek için


1

str_repeat

Bazı durumlarda, bir karakter girişine sahipsiniz ve bunları her karakter için daha büyük bir girişle tekrar tekrar yazmalısınız.

for(;--$z?:($c=$argn[$i++]).$z=$argn[$i++];)echo$c;

(52 bayt) kısa olduğundan

for(;~$c=$argn[$i++];)echo str_repeat($c,$argn[$i++]);

veya

for(;~$c=$argn[$i++];)echo str_pad($c,$argn[$i++],$c);

(Her biri 54 bayt)

Örnek girdi için nasıl çalışır? a1b2c1

$zayarlanmamış (örtük NULL), --$zhiçbir şey yapmaz ve sahtedir;

$c="a", $z="1"ve $i=2-> $c.$z="a1"truthy -> çıktı"a"

--$z=0; öyleyse biz koyduk $c="b", $z="2"(ve $i=4) -> $c.$z="b2"truthy -> output"ab"

--$z=1 -> çıktı "abb"

--$z=0; bu yüzden biz ayarladık $c="c"ve $z=1 $c.$z="c1"gerçek çıktı"abbc"

--$z=0böylece $c=""ve $z=""-> $c.$z=""olduğu falsy -> döngü kırılır


1

Birleştirici fordöngüler

Aşağıdaki formun koduna sahip olduğunuzu varsayalım:

for($pre1; $cond1; $post1) for($pre2; $cond2; $post2) $code;

bu genellikle aşağıdaki biçimde yeniden sarılabilir:

for($pre1; $cond2  $post2 || $cond1  $pre2  $post1; ) $code;

burada , genel bir birleştirme operatörü göstermektedir. Bu genellikle bir bayt sayısı azalmasıyla sonuçlanır, ancak büyük olasılıkla biraz yaratıcılık gerektirir. $cond2ilk kez başarısızlıkla sonuçlanacak şekilde yazılması gerekecek. $post1Ayrıca, ilk kez gerçekleştirilememelidir, ancak önceden yok sayılmasının daha kolay olmasına rağmen $post1, mevcut olmaması.

Üç veya daha fazla iç içe döngü ile çalışıyorsanız, önce ikisini birleştirebilir, sonra bunu başka bir öğeyle birleştirebilirsiniz. İçten dışa doğru birleştirmenin genellikle daha kolay olduğunu buluyorum.


Örnek olarak, H-halı fraktalına ( 97 bayt ) aşağıdaki çözümü göz önünde bulundurun :

for(;$i<$n=3**$argn;$i+=print"$s\n")for($s=H,$e=1;$e<$n;$e*=3)$s.=str_pad($i/$e%3&1?$s:'',$e).$s;

Bu şu şekilde yeniden düzenlenebilir:

for(;($i+=$e&&print"$s\n")<$n=3**$argn;)for($s=H,$e=1;$e<$n;$e*=3)$s.=str_pad($i/$e%3&1?$s:'',$e).$s;

$e&&printprintilk yinelemeyi önler ve ayrıca artmaz $i.

ve son olarak ( 93 bayt ):

for(;$H>$e*=3or$e=($i+=$e&&print"$s\n")<${$s=H}=3**$argn;)$s.=str_pad($i/$e%3&1?$s:'',$e).$s;

$H>$e*=3 Her iki değişken tanımsız olduğundan ilk kez başarısız olur.


1

Bir dizedeki karakterleri kaldırma

join(explode(" ",$string));

ile karşılaştırıldığında 1 karakter kaydeder

str_replace(" ","",$string);

Bunun sadece karakter değil, tüm (boş olmayan) karakter dizileri için işe yaradığını unutmayın.
Hesap MakinesiFeline

@CalculatorFeline Neden boş dizgiler için işe yaramaz? Hiçbir anlamı yok ya da bu dava.
Jörg Hülsermann

Peki, ilk sürüm işe yaramadı ""ve zaten çok yararlı değil.
Hesap MakinesiFeline

1
@CalculatorFeline Ve bu durumda, sıfır baytlık bir çözüm çok daha iyidir. Bunu böyle yapmak hiç mantıklı değil.
Jörg Hülsermann

3
Birleştirme örneğiniz eksik ). Ve strtr($string,[" "=>""])daha da kısa.
Titus


1

Yerine bağlaçlar kullanın strtoupper()vestrtolower()

Yalnızca alfabe karakterlerinden oluşan dizelerle çalışıyorsanız, boolean operatörlerini PHP'nin yerleşik işlevlerinden daha az tuşa basarak daha büyük veya küçük harfe değiştirmek için kullanabilirsiniz.

Örnek:

// Convert lowercase to uppercase
$s = "g";
echo strtoupper($s);  // Outputs 'G', uses 20 characters
echo~" "&$s;          // Outputs 'G', uses 12 characters

// Convert uppercase to lowercase
$s = "G";
echo strtolower($s);  // Outputs 'g', uses 20 characters
echo$s^" ";           // Outputs 'g', uses 11 characters

// Switch case of each character
$s = "Gg";
echo$s^"  ";          // Outputs 'gG', uses 12 characters

İşler isteğe bağlı uzunluktaki dizeler için biraz daha zorlayıcıdır, ancak &ve ^operatörler sonucu daha kısa giriş dizesinin uzunluğuna göre keser. Bu nedenle, örneğin, eğer $Wuzun bir giriş olarak, en azından boşlukların bir dizidir $s, o zaman ~$W&$seşdeğerdir strtoupper($s)ve $s|$W^$seşdeğerdir strtolower($s)(oysa $s|$Wsürece ilave boşluklarla bir dizi üretecektir tek başına $sve $Weşit uzunlukta).


0

kaldırılan işlevleri kullanmak
ifadenin, kullanımı üzerine fazla 5 bayt israf etmeden yerine PERL regex ait POSIX kullanabiliyorsa eregveya eregiyerine preg_match, splitya splitiyerine preg_split ait.
splitAyırıcıların explodeçoğu için eşanlamlı olarak da kullanılabilir .

Bu işlevler kullanımdan kaldırıldı olarak işaretlendi ve E_DEPRECATEDbildirimler yayınlayacak , ancak (kaynağı şimdi bulamıyor) uyarıların ve bildirimlerin tamam olduğunu okudum.


2
Dikkat et! Bunlar PHP 7.0'da kaldırıldı.
Şemsiye,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.