답변:
변수와 공백이 PHP의 언어 구성과 어떻게 상호 작용하는지 이해하십시오.
필자의 짧은 골프에서 변수와 공백과 상호 작용할 때 PHP의 언어 구성 (예 : echo, return, for, while 등)이 직관적이지 않은 방식으로 작동한다는 것을 알았습니다.
echo$v;
예를 들어, return$v;
다른 유사한 구성과 마찬가지로 완벽하게 유효합니다 . 공백의 이러한 작은 감소는 길이의 상당한 누적 감소로 이어질 수 있습니다.
그러나 다음 예제와 같이 언어 구성 이전의 변수 에는 공백이 필요 하다는 점에 유의하십시오 .
foreach($a AS$b){}
때문에 AS
언어 구조이며, 공간이 변수 전에 필요하지 않습니다 $b
,하지만 하나의 공간을 생략한다면 그것은 이전 의 결과로, $aAS
이 구문 오류에 변수 이름과 리드로 분석된다.
foreach($a[1]as$b)
공백이 필요 없습니다. 이것은 언어 구성과 변수가 아니라 다른 단어의 단어 문자 사이의 공백에 관한 것입니다.
echo $a+5." text"
PHP가를 .
소수점으로 생각하기 때문에 작동하지 않습니다 5
. 작동하려면 다음과 같은 공간을 추가해야합니다.echo $a+5 ." text"
echo$a+5," text";
. echo
구조는 여러 매개 변수를 전달할 수 있습니다. 어디에 써야하는지 쓸 echo"result: ".($a+5)."!";
수 있습니다 echo"result: ",$a+5,"!";
. 실제로 여러 매개 변수를 하나에 전달하는 echo
것은 마이크로 최적화입니다. 코드가 조금 더 빨리 실행되므로 (출력을 연결하지 않고 별도로 보내므로). 가장 빠른 코드를 작성하는 데 어려움이 있으면 작은 작은 조각에 도움이 될 수 있습니다.
echo
하지만 다음 과는 작동 하지 않습니다. print
(표현식에 넣는 경우 필요합니다. echo
반환 값이없는 순수한 구조 이지만 함수로 작동 print
할 수 있습니다 . 괄호가 필요하지 않지만 항상을 반환합니다 int(1)
.
print
.
현명하게 끈을 사용하십시오.
이 답변은 두 가지입니다. 첫 번째 부분은 문자열을 선언 할 때 공간을 절약하기 위해 PHP의 알 수없는 상수를 문자열로 암시 적으로 변환하여 활용할 수 있다는 것입니다.
@$s=string;
이 @
경고가 무시되도록해야합니다. 전반적으로 한 문자를 줄입니다.
때로는 자주 사용하는 함수의 이름으로 변수를 설정하는 것이 공간적으로 효과적 일 수 있습니다. 일반적으로 다음이있을 수 있습니다.
preg_match(..);preg_match(..);
그러나 골프를 타면 다음과 같이 쉽게 단축 할 수 있습니다.
@$p=preg_match;$p(..);$p(..);
"preg_match"인스턴스가 두 개만 있으면 단일 문자 만 저장하지만 함수를 많이 사용할수록 더 많은 공간을 절약 할 수 있습니다.
E_DEPRECATED
)가 허용됩니다
php.ini
파일 에서 억제 할 수 있다고 생각 합니다
항상 조건부 검사를 작성할 필요는 없습니다. 예를 들어, 일부 프레임 워크는 파일 맨 위에서 이것을 사용하여 액세스를 차단합니다.
<?php defined('BASE_PATH')||die('not allowed');
또는 정상적인 기능
$value && run_this();
대신에
if($value) { run_this(); }
PHP 5.4부터 배열 대신 array()
함수 대신 JavaScript와 같이 대괄호를 사용하여 배열을 선언 할 수 있습니다 .
$arr=['foo','bar','baz'];
// instead of
$arr=array('foo','bar','baz');
5 바이트가 절약됩니다.
그러나 연관 배열에 "구멍"이 있으면 바이트가 필요할 수 있습니다.
$arr=array(,1,,3,,5);
// is one byte shorter than
$arr=[1=>1,3=>3,5=>5];
구멍을 "빈"값으로 채울 수 있으면 단점이 약간 늦습니다.
$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);
[,$a,$b,$c]=$argv;
.
배열 조작을 수행하지 않는 한 배열 인덱스에 대한 대부분의 참조 $a[$i]
는 간단히로 대체 할 수 있습니다 $$i
. 정수는 PHP에서 유효한 변수 이름이므로 인덱스가 정수인 경우에도 마찬가지입니다 (예 : 리터럴에는 대괄호가 필요하지만 ${0}
).
Rabonowitz Wagon 스피 곳의 다음 구현을 고려하십시오.
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;);
이는 두 배열 참조 $a[$g]
를 $$g
대신 대신 하여 6 바이트 개선 할 수 있습니다 .
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;);
라이브러리 함수의 큰 부분 집합을 배우십시오 .
PHP의 라이브러리는 매우 커서 다양한 작업을 크게 단축시킬 수있는 편리한 기능을 제공합니다. 무언가를 시도 할 때마다 검색 할 수 있지만 시간을 넘어서서 특정 검색과 일치하는 항목을 찾지 못할 수도 있습니다. 가장 좋은 방법은 라이브러리에 익숙해지고 함수 이름과 기능을 암기하는 것입니다.
문자열 내에서 함수 실행
이 시도:
$a='strlen';
echo "This text has {$a('15')} chars";
또는 이것을 시도하십시오 :
//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
이것은 ""
및 heredocs를 사용하는 문자열에서만 작동합니다 (nowdocs와 혼동하지 마십시오).
중첩 함수 사용은 중첩 heredoc 내에서만 가능합니다 (또는 구문 분석 오류가 발생합니다)!
you will run into parse errors
직접 읽을 수 없습니까? 성가신 젠드 엔진은 이것을 어떻게 결합 시키는가
!!$foo
진실 값을 true
(또는 1
출력으로), 거짓 값 (0, 빈 문자열, 빈 배열)을 false
(또는 빈 출력)으로 바꿉니다
. 코드 골프에서는 거의 필요하지 않습니다. 대부분의 경우 부울이 필요한 경우에는 어쨌든 암시 적 캐스트.
(int)$foo
$foo|0
또는 로 쓸 수 foo^0
있지만 괄호가 필요할 수 있습니다.
부울 및 문자열의 경우 $foo*1
또는 +$foo
int로 캐스트하는 데 사용할 수 있습니다.
10
0을 추가 할 수 있습니다 *10
.-> .0
. 그러나이 경우 PHP는 점을 소수점으로 가져 가서 불평합니다. (문자열에 가변적 인 양의 0이 있으면 다릅니다.)join
대신을 사용하십시오 implode
. join($a)
같은 않습니다join('',$a)
$s=a;$s++;
은 $s=b;
. 대문자와 소문자로 작동합니다. $s=Z;$s++;
결과 $s=AA;
. aZ
to bA
, A1
to A2
, A9
to B0
및 z99Z
to aa00A
. 문자열 NULL
). $n="001";$n++;
생산 $n="002";
. 나는 그들이 그것을 제거 조금 슬프다.어떤 골프를하든 항상 운전자 우선 순위 테이블 을 갖습니다 .
일반적인 코드에서는 <?php
and 를 사용하는 것이 좋습니다 ?>
. 그러나 이것은 정상적인 코드 가 아닙니다 . 코드 골프 코드를 작성하고 있습니다. 대신을 <?php
쓰십시오 <?
. 대신을 <?php echo
쓰십시오 <?=
. ?>
끝에 입력하지 마십시오 . 완전히 선택 사항입니다. ?>
어떤 이유로 든 텍스트 가 필요한 경우 (예 : 텍스트를 출력하는 방법이 더 짧거나 세미콜론을 앞에 두지 마십시오) 세미콜론을 ?>
의미 하므로 필요하지 않습니다 .
잘못됨 (확실히 너무 큼) :
<?php echo ucfirst(trim(fgets(STDIN)));?>s!
옳은:
<?=ucfirst(trim(fgets(STDIN)))?>s!
문자열을 반복
26 바이트 또는 24에서 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&$b
비트 단위와 (의 아스키 코드)의 문자에 수행 $a
과 $b
의 짧은 같은 길이가 문자열의 결과 $a
와 $b
.
ord($s[$p++])
대안 for(;$s+=ord($argv[++$i])%32?:die($s==100););
에 대한 for(;$c=$argv[++$i];)$s+=ord($c)%32;echo$s==100;
이 질문에 codegolf.stackexchange.com/questions/116933/...
~
숫자로만 작업하는 사례를 추가하십시오
~$c
접근 방식에 대한 경고를 표시합니다 .
if(a==2){some code;}else{some other code;}
이것을 약자로 사용할 수 있습니다 :
(a==2?some code:some other code);
더 짧아?
a?aa:ab?aba:abb:b
그런 식으로 평가 (a?aa:ab)?(aba):(abb)
합니다.
$a?:$b
와 동일합니다 $a?$a:$b
.
||
는 PHP에서 부울로 캐스팅됩니다.
사용하다 ...
join
대신에 implode
chop
대신 rtrim
( chop
PERL은 다릅니다!)die
대신에 exit
fputs
대신에 fwrite
is_int
is_integer
또는 대신is_long
is_real
is_float
또는 대신is_double
key_exists
대신에 array_key_exists
mysql
대신에 mysql_db_query
... 가장 중요한 별칭의 이름을 지정합니다. 자세한 내용 은 http://php.net/aliases 를 참조하십시오.
die
매개 변수 가 있거나없는 것을 알고 있습니까? die(1)
오류 코드와 함께 프로그램을 종료합니다 1
(완전히 확실하지는 않습니다. 테스트가 필요합니다). die
코드로 종료됩니다 0
, 및 die("Hello")
코드와 함께 종료됩니다 0
인쇄 한 후 Hello
.
+
연산자 와 병합 될 수 있습니다 .대신에:
$merged = array_merge($a, $b);
사용하다:
$merged = $a + $b;
메모 +
뿐만 아니라 인덱스 배열과 운영자 작업을하지만, 아마도 당신이 원하는 것을하지 않습니다.
+
인덱스가 구별되는 한을 사용하여 숫자 형 배열을 병합 할 수도 있습니다 . 그렇지 않은 경우 첫 번째 배열의 값을 array_merge와 같이 두 번째 배열의 값으로 덮어 씁니다. 차이점 +
은 인덱스를 재정렬하지 않습니다.
변수 변수 에 대한 몇 가지 흥미로운 사실
난 그냥 (I도 전에 공유했다 확인 중 적어도 하나는 골프를하는 데 도움이) :
$x=a;$$x=1;$x++;$$x=2;echo"$a,$b";
인쇄 1,2
$a=1;$$a=5;$a++;$$a=4;${++$a}=3;echo${1},${2},${3};
인쇄 543
.[0-9a-zA-Z_]
변수 이름뿐만 아니라 모든 문자열에 사용할 수 있습니다 : $x="Hello!";$$x="Goodbye.";echo${"Hello!"};
prints Goodbye.
.[a-zA-Z_][a-zA-Z_0-9]*
변수 이름을 제외한 모든 것은 문자 그대로 사용하기 위해 중괄호가 필요합니다.$$x=1
sets ${NULL}
는 ${false}
and와 동일합니다 ${""}
. $a=1;$$a=5;
뿐만 아니라 설정하지 ${1}
뿐만 아니라 ${true}
.
하나 더, 내가 지금까지 찾은 가장 이상한 것 : 시도 $a=[];$$a=3;echo${[]};
. 예, 인쇄합니다 3
!
대부분의 이유 : 변수 이름은 항상 문자열로 평가됩니다.
(
나를 지적 해준 @Christoph에게 감사한다.) 그래서, 당신 print
이나 당신 echo
이 표현할 때마다 그것이 변수 이름으로 얻는 것입니다.
[]
로 변환 Array
: ${[]} = 5;echo $Array;
인쇄합니다 5
. 나는 당신이 그것을 알고 있다고 확신하지만 모든 사람에게 분명하지는 않을 것입니다 :)
가능한 한 따옴표를 피하십시오
PHP는 알 수없는 단어를 리터럴 문자열로 내재적으로 캐스트합니다.
$foo=foo;
$foo='foo';
( foo
키워드 또는 정의 된 상수가 아니라고 가정) 와 동일 $foo=echo;
합니다. 작동하지 않습니다.
그러나 : $p=str_pad;
않습니다; 로 $p(ab,3,c)
평가됩니다 abc
.
따옴표없이 문자열 리터럴을 사용하면 Use of undefined constant
; 그러나 error_reporting
(CLI 매개 변수 -n
)에 기본값을 사용하면 표시되지 않습니다.
-n
플래그로 누를 수 있음 ). 7.2 수율 경고; 이후 버전에서는 오류가 발생합니다!
PHP 7.4는 현재 RC2 버전에 있으며 약 2 개월 후에 출시 될 것입니다. 새로운 기능 목록이 여기에 있습니다 (이 페이지는 7.4가 릴리스 될 때 실제로 업데이트 될 수 있습니다). 7.4에서 마지막으로 PHP는 화살표 함수를 얻었으므로 이제 함수 응답이 짧아 질 수있을뿐만 아니라 다른 함수에 클로저를 전달하는 것도 훨씬 짧아 질 수 있습니다. 다음은 몇 가지 예입니다.
리턴 입력 + 1 :
익명 함수 (클로저)-25 바이트- 온라인으로 사용해보십시오!
function($n){return$n+1;}
화살표 기능-12 바이트- 온라인으로 사용해보십시오!
fn($n)=>$n+1
첫 번째 입력 항목 (int 배열)에 두 번째 입력 (int) 곱하기 :
익명 함수 (클로저)-72 바이트- 온라인으로 사용해보십시오!
function($a,$n){return array_map(function($b)use($n){return$b*$n;},$a);}
화살표 기능-38 바이트- 온라인으로 사용해보십시오!
fn($a,$n)=>array_map(fn($b)=>$b*$n,$a)
명령문 $n
없이 내부 함수에서 액세스 할 수 있다는 것을 알고 use $n
있습니까? 예, 그것은 화살표 기능 기능 중 하나입니다.
우리가 그들에게 이름을 줄 수 있기 때문에 변수의 폐쇄로 저장하는 것은 같은 보조 노트로서, 나는 (자체 내부의 같은 화살표 함수를 호출) 재귀 작업에 기능을 화살표 가져올 수 없습니다 $f
하지 않습니다 $f
접근 withing에 자신을 (슬픈 ). 따라서이 예제 는 작동하지 않으며$f
첫 번째 줄에서 사용 하면 치명적인 오류가 발생합니다.
$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"
그러나 다른 화살표 함수를 사용하여 화살표 함수를 호출하면 작동합니다.
$f1=fn($n)=>$n+1;
$f2=fn($n)=>$f1($n-1);
$f1(2) // Returns 3
$f2(2) // Returns 2
$f=fn($n)=>$n?$f($n-1):0;
어떻게 $f=$F=fn($n)=>$n?$F($n-1):0;
? 작동합니까? 그리고 $(5)
평소와 같이 전화하십시오 .
이 특별한 경우 double array_flip은 10 바이트를 절약합니다
($f=array_flip)($k=$f($c)))
어레이의 모든 더블 값을 제거하고 난이 떨어졌다 $c=[],
, |in_array($o,$c)
그리고 교체 array_keys($c)
와 함께$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
에 맞서
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
array_unique에 대해 2 바이트를 절약합니다.
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
이 프로그램에서 버그를 발견하고 더 이상 double array_flip으로 교체 $x[$i]==$o?:$c[$x[$i]]=$o
할 ($p=$x[$i])==$o?:$k[$c[$p]=$o]=$p
필요가 없었습니다.
array_unique
. 예이!
교차 문자열
join("DELIMITER",str_split($s))
(31 바이트) 또는 심지어
preg_replace(".","DELIMITER",$s)
(32 바이트)를 사용해 본 적이
있습니까?
거기에 내장되어 있습니다.
시도하십시오 chunk_split($s,1,"DELIMITER")
(29 바이트).
세 번째 매개 변수를 생략하면 chunk_split
사용합니다 \r\n
; 7 또는 8 바이트를 절약 할 수 있습니다.
그러나주의 : chunk_split
또한 문자열에 구분 기호를 추가
하므로 원하는 것을 정확하게 얻지 못할 수 있습니다.
(청크 길이를 제공하지 않으면 76을 사용합니다. 코드 골프에서는 드문 일이지만 누가 아는가)
strtr
이 아이디어를 좋아하는 것과 함께 예제를 추가해야 할 수도 있습니다 .
경우에 따라 문자를 입력 할 수 있으며 각 문자마다 0보다 큰 입력을 반복하여 출력해야합니다.
for(;--$z?:($c=$argn[$i++]).$z=$argn[$i++];)echo$c;
(52 바이트)보다 짧다
for(;~$c=$argn[$i++];)echo str_repeat($c,$argn[$i++]);
또는
for(;~$c=$argn[$i++];)echo str_pad($c,$argn[$i++],$c);
(각 54 바이트)
a1b2c1
$z
설정되지 않았으며 (암시 적 NULL
) --$z
아무 것도 설정 하지 않고 거짓입니다.
$c="a"
, $z="1"
및 $i=2
-> $c.$z="a1"
truthy 인 -> 출력"a"
--$z=0
; 그래서 우리는 설정 $c="b"
, $z="2"
(그리고 $i=4
) -> $c.$z="b2"
입니다 truthy -> 출력"ab"
--$z=1
-> 출력 "abb"
--$z=0
; 그래서 우리는 설정 $c="c"
하고 $z=1
$c.$z="c1"
진정한 출력입니다"abbc"
--$z=0
그렇게 $c=""
하고 $z=""
-> $c.$z=""
입니다 falsy -> 루프 나누기
for
루프 결합다음 형식의 코드가 있다고 가정하십시오.
for($pre1; $cond1; $post1) for($pre2; $cond2; $post2) $code;
일반적으로 다음 형식으로 다시 롤업 할 수 있습니다.
for($pre1; $cond2 • $post2 || $cond1 • $pre2 • $post1; ) $code;
여기서 •
일반 결합 연산자를 나타냅니다. 이것은 일반적으로 바이트 수를 줄이지 만 창의력이 필요할 것입니다. $cond2
처음부터 실패 할 수 있도록 작성해야합니다. $post1
미리 실행하는 것이 더 쉬울 수 있지만 처음에는 실행에 실패해야합니다 $post1
.
세 개 이상의 중첩 루프로 작업하는 경우 먼저 두 개를 결합한 다음 다른 루프를 결합 할 수 있습니다. 나는 내부에서 바깥쪽으로 결합하는 것이 일반적으로 더 쉽다는 것을 알았습니다.
예를 들어, H- 카펫 프랙탈 ( 97 바이트 )에 대한 다음 솔루션을 고려하십시오 .
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;
이것은 다음과 같은 방식으로 재구성 될 수 있습니다.
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&&print
print
첫 번째 반복을 방지 하고 증가하지 않습니다 $i
.
그리고 마지막으로 ( 93 바이트 ) :
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
두 변수가 모두 정의되지 않아 처음으로 실패합니다.
join(explode(" ",$string));
에 비해 1 개의 문자를 저장합니다
str_replace(" ","",$string);
""
어쨌든별로 유용하지 않습니다.
)
. 그리고 strtr($string,[" "=>""])
더 짧습니다.
array_push($a,...$b);
1 바이트보다 짧다
$a=array_merge($a,$b);
연관 배열에서 동일하게 작동하지 않습니다
strtoupper()
및 대신 부울 연산자를 사용하십시오.strtolower()
알파벳 문자로 구성된 문자열로만 작업하는 경우 부울 연산자를 사용하여 PHP의 내장 함수보다 키 입력 횟수가 적은 대문자 또는 소문자로 변경할 수 있습니다.
// 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
임의 길이의 문자열에는 약간 까다 롭지 만 &
and ^
연산자는 결과를 짧은 입력 문자열의 길이로 자릅니다. 그래서 예를 들어,이 $W
긴 입력 한 적어도 자리의 문자열이 $s
다음 ~$W&$s
에 상당 strtoupper($s)
하고, $s|$W^$s
동일하다 strtolower($s)
(반면 $s|$W
않는 공간 부가 된 문자열을 생성한다 자체 $s
와 $W
동일한 길이이다).
사용되지 않는 기능을 사용
하면 표현 사용에 5 개 이상의 바이트를 낭비하지 않고 대신 PERL 정규식의 POSIX를 사용할 수있는 경우 ereg
나 eregi
대신 preg_match
, split
나 spliti
대신 preg_split의. 대부분의 구분 기호
split
에 explode
대한 동의어로 사용할 수도 있습니다 .
이 기능은 더 이상 사용되지 않는 것으로 표시되어 E_DEPRECATED
알림을 표시 하지만 (지금 소스를 찾을 수 없음) 경고와 알림이 정상임을 읽은 것 같습니다.