Wskazówki dotyczące gry w golfa w PHP


37

Jakie masz ogólne wskazówki dotyczące gry w golfa w PHP? Szukam pomysłów, które można by zastosować do problemów z golfem w kodzie, które są przynajmniej nieco specyficzne dla PHP (np. „Usuń komentarze” nie jest odpowiedzią). Proszę zamieścić jedną wskazówkę na odpowiedź.


Zaraz, czy robię to dobrze? W każdym razie jestem naprawdę ciekawa tego. PHP jest używane przez wielu ludzi i golfistów, ale prawie nie mam pojęcia, jak zagrać w kod PHP.
JiminP

Użyj krótkich tagów <??> Może zaoszczędzić kilka bajtów.
Tłum

Odpowiedzi:


22

Dowiedz się, w jaki sposób zmienne i białe znaki współdziałają z konstrukcjami językowymi PHP.

Podczas mojej (co prawda krótkiej) gry w golfa odkryłem, że konstrukcje języka PHP (np. Echo, return, for, while itp.) Zachowują się w mniej niż intuicyjny sposób podczas interakcji ze zmiennymi i białymi spacjami.

echo$v;, na przykład, jest całkowicie poprawny, podobnie jak return$v;i inne podobne konstrukcje. Te niewielkie redukcje białych znaków mogą prowadzić do znacznego skumulowanego zmniejszenia długości.

Pamiętaj jednak, że zmienne przed konstrukcjami językowymi wymagają spacji po, jak w poniższym przykładzie:

foreach($a AS$b){}

Ponieważ ASjest to konstrukcja językowa, spacja nie jest wymagana przed zmienną $b, ale jeśli pominiemy spację przed nią , w wyniku $aAStego zostanie ona przeanalizowana jako nazwa zmiennej i doprowadzi do błędu składniowego.


3
foreach($a[1]as$b)nie potrzebuje białej przestrzeni. Nie chodzi o konstrukcje językowe i zmienne, ale o spacje między znakami różnych słów.
Tytus

1
Innym przypadkiem, w którym potrzebujesz białych znaków, jest łączenie łańcuchów. Na przykład echo $a+5." text"nie zadziała, ponieważ PHP uważa, że .jest to przecinek dziesiętny 5. Aby to działało, musisz dodać takie miejsce:echo $a+5 ." text"
Business Cat

@BasicSunset To oświadczenie można zapisać jako echo$a+5," text";. echoKonstrukcja pozwala przekazać wiele parametrów. gdzie trzeba pisać echo"result: ".($a+5)."!";, możesz pisać echo"result: ",$a+5,"!";. W rzeczywistości przekazanie wielu parametrów do echojest mikrooptymalizacją, ponieważ kod będzie działał trochę szybciej (ponieważ nie łączysz danych wyjściowych, ale wysyłasz je osobno). W przypadku problemów związanych z pisaniem najszybszego kodu może to pomóc maleńkim drobiazgowi.
Ismael Miguel,

@ IsmaelMiguel Działa z echo, ale nie z print(czego potrzebujesz, jeśli umieścisz go w wyrażeniu: echojest to czysty konstrukt bez wartości zwracanej, a jednocześnie print może działać jako funkcja: nie wymaga nawiasów, ale zawsze zwraca int(1).
Titus

@Titus, o którym nic nie mówiłem print.
Ismael Miguel

22

Używaj mądrze łańcuchów.

Ta odpowiedź jest podwójna. Pierwsza część polega na tym, że deklarując ciągi, możesz użyć niejawnej konwersji nieznanych stałych na ciągi PHP, aby zaoszczędzić miejsce, np .:

@$s=string;

Konieczne @jest zastąpienie ostrzeżeń, które to spowoduje. Ogólnie rzecz biorąc, otrzymujesz redukcję o jedną postać.

polega na tym, że czasem efektywnym miejscem może być ustawienie zmiennej na nazwę często używanej funkcji. Zwykle możesz mieć:

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

Ale podczas gry w golfa można to łatwo skrócić do:

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

Tylko w dwóch przypadkach „preg_match” zapisujesz tylko jeden znak, ale im więcej używasz funkcji, tym więcej miejsca zaoszczędzisz.


10
@ nie jest potrzebne w codegolf; powiadomienia i ostrzeżenia (w tym E_DEPRECATED) są dopuszczalne
Tytus

3
@Titus Ale w PHP ostrzeżenia byłyby wypisywane na standardowe wyjście pliku, więc są potrzebne.
brianush1

1
@Titus Wierzę, że możesz je ukryć w php.iniaktach
Stan Strum

12

Nie zawsze musisz wypisywać czeki warunkowe. Na przykład niektóre frameworki używają tego w górnej części swoich plików do blokowania dostępu:

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

Lub w normalnych funkcjach

$value && run_this();

zamiast

if($value) { run_this(); }

Działa również w JS
Евгений Новиков

8

Użyj krótkiej składni tablicowej

Od PHP 5.4 tablice mogą być deklarowane za pomocą nawiasów kwadratowych (podobnie jak JavaScript) zamiast array()funkcji:

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

Zaoszczędzi to pięć bajtów.


Ale może to kosztować bajty, jeśli masz „dziury” w tablicy asocjacyjnej:

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

Wada pojawia się nieco później, jeśli można wypełnić dziury wartościami „pustymi”:

$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 wprowadzono także krótkie zadanie listy: [,$a,$b,$c]=$argv;.
Tytus

7

Użyj $ {0}, $ {1}, $ {2}, ... zamiast $ a [0], $ a [1], $ a [2], ...

O ile nie wykonujesz manipulacji tablicą, większość odniesień do indeksu tablic $a[$i]można zastąpić zwykłym $$i. Jest to nawet prawdziwe, jeśli indeks jest liczbą całkowitą, ponieważ liczby całkowite są poprawnymi nazwami zmiennych w PHP (chociaż literały będą wymagały np ${0}. Nawiasów ).

Rozważ następującą implementację czopa wagonu Rabonowitz:

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

Można to poprawić przez 6 bajtów, po prostu przez zastąpienie zarówno odniesienia tablicy $a[$g]z $$gzamiast:

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
Właśnie zapisałem 3 bajty z tym: prezentacja .
Tytus

6

Poznaj duży podzbiór funkcji bibliotecznych .

Biblioteka PHP jest dość duża i zapewnia mnóstwo wygodnych funkcji, które mogą znacznie skrócić różne zadania. Możesz po prostu wyszukiwać za każdym razem, gdy próbujesz coś zrobić, ale poza marnowaniem czasu możesz nie znaleźć niczego, co pasowałoby do określonego wyszukiwania. Najlepszym sposobem jest po prostu zapoznanie się z biblioteką i zapamiętanie nazw funkcji oraz ich czynności.


6
To dużo zapamiętywania, szczególnie biorąc pod uwagę dość niespójne nazewnictwo wielu funkcji ;-)
Joey

@Joey Agreed. Podobne do zapamiętywania biblioteki Java, z wyjątkiem tego, że byłaby prawdopodobnie mniej przydatna, ponieważ jest bardziej gadatliwa.
Matthew Przeczytał

3
Uważam, że najważniejszymi funkcjami dla wyzwań, które do tej pory tu spotkałem, są manipulacje ciągami i funkcje manipulacji tablicami. Kreatywne wykorzystanie tych może naprawdę obniżyć kod.
migimaru,

6

Uruchamianie funkcji wewnątrz ciągów.

Spróbuj tego:

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

Lub spróbuj tego:

//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

Działa to tylko z ciągami używającymi ""i heredocami (NIE myl z nowdocs).

Korzystanie z funkcji zagnieżdżonych jest możliwe tylko w zagnieżdżonych heredokach (w przeciwnym razie wystąpią błędy analizy)!


you will run into parse errorsNie mogę tego przeczytać? Jak to wulgaryzuje silnik Zend
Stan Strum

Następnym razem, gdy będę argumentował „PHP to dobry język programowania” , użyję tego jako kontrapunktu. Łał.
primo

@primo Czy to tak źle? : O
Ismael Miguel

5

zabawa z typecastami

  • !!$foozamieni dowolną prawdziwą wartość na true(lub 1na wyjściu), wartości fałszowania (0, pusty ciąg, pusta tablica) na false(lub na puste wyjście)
    Rzadko będzie to potrzebne w kodzie golfowym, ponieważ w większości przypadków, gdy potrzebujesz wartości logicznej, istnieje i tak niejawna obsada.

  • (int)$foomogą być zapisane jako $foo|0lub foo^0, ale mogą wymagać nawiasów.
    Dla booleanów i ciągów znaków $foo*1lub +$foomoże być użyte do rzutowania na int.

  • W przeciwieństwie do większości innych języków PHP obsługuje ciągi znaków o wartościach liczbowych jako liczby. Więc jeśli masz ciąg zawierający liczbę, którą musisz obliczyć, po prostu obliczyć.
  • Drugi sposób nie działa: Aby pomnożyć dowolną liczbę w zmiennej 10, możesz dodać zero: *10-> .0. Ale w tym przypadku PHP weźmie kropkę jako kropkę dziesiętną i narzeka. (Jest inaczej, jeśli masz zmienną liczbę zer w ciągu).
  • Aby przekształcić tablicę w ciąg, użyj joinzamiast implode.
    Jeśli nie potrzebujesz ogranicznika, nie używaj go: join($a)robi to samo cojoin('',$a)
  • Zwiększanie ciągów: Najbardziej niesamowitą funkcją imo jest to, że $s=a;$s++;produkuje $s=b;. Działa to z wielkimi i małymi znakami. $s=Z;$s++;powoduje w $s=AA;.
    Działa to również z przypadkami mieszanymi: aZdo bA, A1do A2, A9do B0i z99Zdo aa00A.
    Zmniejszenie nie działa na ciągi znaków. (I nie włącza się NULL).
    Powrót do PHP 3, $n="001";$n++;wyprodukowano $n="002";. Trochę mi przykro, że to usunęli.

Cokolwiek grasz w golfa: zawsze masz pod ręką tabelę pierwszeństwa operatora .


4

Używaj skrótów

W normalnym kodzie dobrą praktyką jest używanie <?phpi ?>. Nie jest to jednak normalny kod - piszesz kod golfowy. Zamiast <?phppisać <?. Zamiast <?php echopisać <?=. Nie pisz ?>na końcu - jest to całkowicie opcjonalne. Jeśli potrzebujesz ?>z jakiegoś powodu (na przykład, aby wydrukować tekst, a on jest jakoś krótszy, czy coś, nie umieszczaj przed nim średnika - nie jest potrzebny, ponieważ ?>oznacza średnik.

Źle (zdecydowanie za długo):

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

Poprawny:

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

Z -rflagą ( która jest bezpłatna ), w ogóle nie masz żadnych tagów (i nie możesz używać żadnych).
Tytus

4

zapętlanie łańcuchów

można to zrobić z 26 bajtami lub z 24 do 18:

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&$brobi bitowego oraz na (kody ASCII) bohaterów $ai $b
i wyniki w ciąg, który ma taką samą długość jak krótszy $ai $b.


czy możesz dodać ord($s[$p++])jako alternatywnego for(;$s+=ord($argv[++$i])%32?:die($s==100););Przeciw for(;$c=$argv[++$i];)$s+=ord($c)%32;echo$s==100;tej zapytania codegolf.stackexchange.com/questions/116933/...
Jorg Hülsermann

W ~przypadku przypadków, w których pracujesz tylko z cyframi,
dodaj

Zauważ, że PHP 7.2 wyświetla ostrzeżenia dla tego ~$cpodejścia.
Tytus

4

Użyj operatorów trójskładnikowych

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

może być skrócony do tego:

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

Krótszy, prawda?


„Stenogramy warunkowe”? Lepiej powiedz jego prawdziwą nazwę, aby zainteresowani bardziej szczegółowymi informacjami mogli ją znaleźć w dokumentacji: operator trójskładnikowy .
manatwork

3
Pytanie dotyczy wskazówek, które są nieco specyficzne dla PHP. Jest to jeden ze wskazówek dla wszystkich języków .
Peter Taylor

3
Operator trójskładnikowy zachowuje się dziwnie w PHP, jeśli go zagnieżdżasz. a?aa:ab?aba:abb:bocenia (a?aa:ab)?(aba):(abb)lub coś w tym stylu.
Tytus

1
I zaczynając od PHP 5.3, możesz pominąć drugi operator: $a?:$bjest taki sam jak $a?$a:$b.
Tytus

1
@Cyoce przesyła ||do logicznej w PHP.
Tytus

3

pod dowolną inną nazwą ... aliasy funkcji

posługiwać się ...

  • join zamiast implode
  • chopzamiast rtrim( chopw PERL jest inny!)
  • die zamiast exit
  • fputs zamiast fwrite
  • is_intzamiast is_integerlubis_long
  • is_realzamiast is_floatlubis_double
  • key_exists zamiast array_key_exists
  • mysql zamiast mysql_db_query

... żeby wymienić najważniejsze aliasy. Więcej informacji można znaleźć na stronie http://php.net/aliases .


Och ... i czy wiesz, że diedziała z parametrami i bez? die(1)zamknie program z kodem błędu 1(nie do końca pewny; wymaga testowania); diewyjdzie z kodem 0i die("Hello")wyjdzie z kodem 0po wydrukowaniu Hello.
Tytus

3

Tablice asocjacyjne można łączyć z +operatorem.

Zamiast:

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

Posługiwać się:

$merged = $a + $b;

Zauważ, że +operator działa również z indeksowanymi tablicami, ale prawdopodobnie nie robi tego, co chcesz.


Rzeczywiście, często dobry zamiennik, choć nie dokładnie taki sam: pastebin.com/seYeaP38
manatwork

Ach tak, do cholery, pierwotnie miałem tytuł „tablice asocjacyjne ...”, a potem go usunąłem. Wyjaśnię, dzięki.
Alex Howansky

tablice numeryczne można również łączyć +, o ile indeksy są różne. Jeśli nie są, wartości z pierwszej tablicy zostaną zastąpione wartościami z drugiej (podobnie jak array_merge). Różnica: +nie zmienia kolejności indeksów.
Tytus

3

array_flip vs array_search

posługiwać się

array_flip($array)[$value]

zamiast

array_search($value,$array)

aby zapisać 1 bajt w tablicach, w których występowanie każdej wartości jest unikalne


3

kilka interesujących faktów na temat zmiennych zmiennych

Po prostu musiałem je udostępnić (nawet zanim zweryfikowałem, że przynajmniej jeden z nich pomaga w grze w golfa):

  • Użyj liter: $x=a;$$x=1;$x++;$$x=2;echo"$a,$b";drukuje, 1,2
    ale inne operacje arytmetyczne nie działają z literami.
  • Jak wspomniano wcześniej primo , można używać czystych liczb jako nazw zmiennych:
    $a=1;$$a=5;$a++;$$a=4;${++$a}=3;echo${1},${2},${3};wypisuje 543.
  • Możesz używać nie tylko [0-9a-zA-Z_]nazw zmiennych, ale KAŻDY ciąg:
    $x="Hello!";$$x="Goodbye.";echo${"Hello!"};drukuje Goodbye..
  • Ale: Wszystko oprócz [a-zA-Z_][a-zA-Z_0-9]*nazw zmiennych wymaga nawiasów klamrowych do dosłownego zastosowania.
  • Bez zdefiniowanych zmiennych, $$x=1zestawy ${NULL}, które są takie same jak ${false}i ${""}.
  • $a=1;$$a=5;nie tylko ustawia ${1}, ale także ${true}.

  • jeszcze jeden, najdziwniejszy, jaki do tej pory znalazłem: spróbuj $a=[];$$a=3;echo${[]};. Tak, drukuje 3!

Przyczyna większości tego: nazwy zmiennych są zawsze przetwarzane na łańcuchy.
(Dzięki @Christoph za wskazanie.)
Tak więc, cokolwiek otrzymujesz, kiedy ty printlub echowyrażenie, otrzymujesz to jako nazwę zmiennej.


1
Nazwy zmiennych są konwertowane na ciągi wyjaśniające trzy ostatnie punkty na liście. []konwertuje na Array: ${[]} = 5;echo $Array;drukuje 5. Jestem pewien, że o tym wiesz, ale może nie być to oczywiste dla wszystkich :)
Christoph

@Jeff Naprawiłem literówkę. Dzięki za zauważenie.
Tytus

2

Podziały wiersza,
jeśli dane wyjściowe wymagają podziału wiersza, użyj fizycznego podziału wiersza (1 bajt) zamiast "\n"
tego. Daje to również możliwą korzyść z wyboru między pojedynczymi i podwójnymi cudzysłowami.


2

w miarę możliwości unikaj cudzysłowów

PHP domyślnie rzuca nieznane słowa na ciągi literalne.

$foo=foo;jest taki sam jak $foo='foo';(zakładając, że foonie jest to ani słowo kluczowe, ani stała stała): $foo=echo;nie działa.

ALE: $p=str_pad;robi; i $p(ab,3,c)ocenia abc.

Użycie literałów łańcuchowych bez cudzysłowów da komunikat dla Use of undefined constant; ale nie pokaże się, jeśli użyjesz domyślnej wartości error_reportingparametru (parametr CLI -n).


Właśnie zauważyłem: Ta odpowiedź jest nieco rozszerzonym / zaktualizowanym duplikatem codegolf.stackexchange.com/a/2916/55735 .
Tytus

Uwaga: PHP wcześniejszy niż 7.2 przyniósł Powiadomienia (które można opresować -nflagą); 7.2 daje Ostrzeżenia; późniejsze wersje będą zgłaszać błędy!
Tytus

2

Funkcje strzałek w PHP 7.4

PHP 7.4 jest teraz w wersji RC2 i mam nadzieję, że zostanie wydany za około 2 miesiące. Lista nowych funkcji jest tutaj (ta strona może zostać zaktualizowana po wydaniu wersji 7.4). W wersji 7.4 PHP posiada funkcje strzałek, więc nie tylko odpowiedzi na funkcje mogą być teraz krótsze, ale także przekazywanie zamknięć do innych funkcji może być znacznie krótsze. Oto kilka przykładów:

Zwróć wejście + 1:

Funkcja anonimowa (zamknięcie) - 25 bajtów - Wypróbuj online!

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

Funkcja strzałki - 12 bajtów - Wypróbuj online!

fn($n)=>$n+1

Pomnóż elementy pierwszego wejścia (tablica liczb całkowitych) przez drugie wejście danych (int):

Funkcja anonimowa (zamknięcie) - 72 bajty - Wypróbuj online!

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

Funkcja strzałki - 38 bajtów - Wypróbuj online!

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

Czy zauważyłeś, że $njest dostępna w funkcji wewnętrznej bez use $ninstrukcji? Tak, to jedna z funkcji funkcji strzałek.


Na marginesie, nie mogłem sprawić, by funkcje strzałek działały rekurencyjnie (wywołaj tę samą funkcję strzałki wewnątrz siebie), ponieważ nie możemy nadać im nazwy i przechowywanie ich jako zamknięcia w zmiennej takiej jak $fnie $fudostępnia się samemu sobie (smutne ). Ten przykład nie działa, a użycie $fw pierwszym wierszu powoduje błąd krytyczny:

$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"

Ale wywoływanie funkcji strzałki za pomocą innej funkcji strzałki działa:

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

Co jeśli zamiast $f=fn($n)=>$n?$f($n-1):0;ciebie $f=$F=fn($n)=>$n?$F($n-1):0;? Czy to zadziała? A potem dzwonisz $(5)jak zwykle.
Ismael Miguel

@ IsmaelMiguel nadal wydaje ten sam błąd. Możesz sam spróbować na tio.run # php, ponieważ Dennis już jakiś czas aktualizował PHP do 7.4 RC2.
Noc2

Nie mogę go uruchomić. Wydaje się, że dostępne są tylko zmienne zdefiniowane wcześniej .
Ismael Miguel


1

Tablice dereferencyjne zwracane bezpośrednio z funkcji.

Np. Zamiast tego:

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

Możesz to zrobić:

echo foo()[$n];

Działa to również z metodami:

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

Możesz także bezpośrednio odrzucić deklaracje tablicowe:

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

1

Użyj end()zamiastarray_pop()

end()Funkcja nie tylko przesunąć wewnętrzny wskaźnik do końca tablicy, ale także zwraca ostatnią wartość. Zauważ oczywiście, że nie usuwa tej wartości, więc jeśli nie zależy ci na zawartości tablicy, możesz jej użyć zamiast array_pop().


1

double array_flip vs in_array vs array_unique

w tym szczególnym przypadku podwójny obiekt tablicowy zapisuje 10 bajtów

($f=array_flip)($k=$f($c)))usunąć wszystkie wartości w tablicy podwójnych i spadły to $c=[],, |in_array($o,$c)i wymienić array_keys($c)z$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

Wersja online

przeciwko

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

Wersja online

przed array_unique zapisuje 2 bajty

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

Wersja online

Po znalezieniu błędu w tym programie i wymianę $x[$i]==$o?:$c[$x[$i]]=$odo ($p=$x[$i])==$o?:$k[$c[$p]=$o]=$ppodwójnego array_flip już nie było konieczne


bezpieczny asocjacyjny array_unique. Tak!
Tytus

@Titus Dodałem twoją sugestię
Jörg Hülsermann

1

przecinające się sznurki

Czy kiedykolwiek używałeś
join("DELIMITER",str_split($s))(31 bajtów) lub nawet
preg_replace(".","DELIMITER",$s)(32 bajty)
?

Jest do tego wbudowane:

Spróbuj chunk_split($s,1,"DELIMITER")(29 bajtów).


Jeśli pominiesz trzeci parametr, chunk_splitużyje \r\n; co pozwala zaoszczędzić 7 lub 8 bajtów.

Ale uwaga: chunk_splitdołącza również ogranicznik do łańcucha,
więc możesz nie otrzymać dokładnie tego, czego chcesz.

(Jeśli nie podasz długości fragmentu, użyje 76. Raczej nietypowe dla golfa kodowego, ale kto wie.)


Może powinieneś dodać przykład w połączeniu z strtrUwielbiam ten pomysł.
Jörg Hülsermann

1

unset () vs INF

W przypadku wyszukaj minimum w tablicy, której możesz użyć zamiast

unset($var[$k]);

$var[$k]=INF;

aby zapisać 3 bajty


1

str_repeat

W niektórych przypadkach wprowadzasz znaki i powinieneś wypisywać je powtórzone z wprowadzeniem większej wartości zero dla każdego znaku.

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

(52 bajty) jest krótszy niż

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

lub

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

(Po 54 bajty)

Jak to działa na przykład dane wejściowe a1b2c1

$znie jest ustawiony (domyślny NULL), więc --$znic nie robi i jest fałszem;

$c="a", $z="1"I $i=2-> $c.$z="a1"jest truthy -> wyjście"a"

--$z=0; więc ustawiamy $c="b", $z="2"(i $i=4) -> $c.$z="b2"jest prawdą -> wyjście"ab"

--$z=1 -> wyjście "abb"

--$z=0; więc ustawiamy $c="c"i $z=1 $c.$z="c1"jest to prawdziwy wynik"abbc"

--$z=0więc $c=""i $z=""-> $c.$z=""jest falsy -> pęka pętla


1

Łączenie forpętli

Załóżmy, że masz kod o następującej formie:

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

można to ogólnie przerzucić ponownie w następującej formie:

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

gdzie reprezentuje ogólny operator łączenia. Zwykle powoduje to zmniejszenie liczby bajtów, ale prawdopodobnie będzie wymagać kreatywności. $cond2będzie musiał zostać napisany, aby nie zawiódł za pierwszym razem. $post1powinien również nie zostać wykonany po raz pierwszy, chociaż może być łatwiej dokonać uprzedniej refaktoryzacji, aby $post1nie było go.

Jeśli pracujesz z trzema lub więcej zagnieżdżonymi pętlami, możesz również najpierw połączyć dwie, a następnie połączyć je z inną itd. Uważam, że ogólnie łatwiej było łączyć od wewnątrz na zewnątrz.


Jako przykład rozważ poniższe rozwiązanie fraktala H-carpet ( 97 bajtów ):

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;

Można to przeformułować w następujący sposób:

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&&printzapobiega printpierwszej iteracji, a także nie zwiększa $i.

i na koniec ( 93 bajty ):

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 zawiedzie po raz pierwszy, ponieważ obie zmienne są niezdefiniowane.


1

Usuwanie znaków w ciągu

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

zapisuje 1 postać w porównaniu do

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

Zauważ, że działa to dla wszystkich (niepustych) łańcuchów, nie tylko znaków.
CalculatorFeline

@CalculatorFeline Dlaczego nie powinien działać dla pustych ciągów? To nie ma sensu ani ta sprawa.
Jörg Hülsermann

Cóż, pierwsza wersja nie działa ""i i tak nie jest zbyt przydatna.
CalculatorFeline

1
@CalculatorFeline I w tym przypadku rozwiązanie zero bajtów jest znacznie lepsze. Nie ma sensu robić tego w ten sposób.
Jörg Hülsermann

3
W twoim przykładzie dołączenia brakuje ). I strtr($string,[" "=>""])jest jeszcze krótszy.
Tytus


1

Użyj operatorów logicznych zamiast strtoupper()istrtolower()

Jeśli pracujesz wyłącznie z łańcuchami składającymi się ze znaków alfabetu, możesz użyć operatorów logicznych, aby zmienić je na wielkie lub małe litery przy mniejszej liczbie naciśnięć klawiszy niż wbudowane funkcje PHP.

Przykład:

// 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

Sprawy są nieco trudniejsze w przypadku ciągów o dowolnej długości, ale operatory &i ^skracają wynik do długości krótszego ciągu wejściowego. Tak na przykład, jeśli $Wto ciąg miejsc co najmniej tak długo, jak każdy wejścia $s, a następnie ~$W&$sodpowiada strtoupper($s)i $s|$W^$sjest odpowiednikiem strtolower($s)(podczas gdy $s|$Wsam wytworzy ciąg miejsc, chyba że z dodatkowymi $si $Wmają równe długości).


0

używać nieaktualnych funkcji
Jeśli można użyć zamiast POSIX Perl regex nie tracąc więcej niż 5 bajtów na ekspresję, użytkowania ereglub eregizamiast preg_match, splitalbo splitizamiast preg_split.
splitMoże być również używany jako synonim explodewiększości separatorów.

Te funkcje są oznaczone jako przestarzałe i będą rzucać E_DEPRECATEDpowiadomienia, ale (nie mogę teraz znaleźć źródła) Myślę, że przeczytałem, że ostrzeżenia i powiadomienia są w porządku.


2
Uważaj! Zostały one usunięte w PHP 7.0.
Parasol
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.