Какие общие советы у вас есть для игры в гольф на PHP? Я ищу идеи, которые могут быть применены к проблемам гольф-кода вообще, которые, по крайней мере, несколько специфичны для PHP (например, «удалить комментарии» - это не ответ). Пожалуйста, оставьте один совет за ответ.
37
Ответы:
Понять, как переменные и пробелы взаимодействуют с языковыми конструкциями PHP.
В моем (по общему признанию) времени игры в гольф я обнаружил, что языковые конструкции PHP (например, echo, return, for, while и т. Д.) Ведут себя менее интуитивно, когда взаимодействуют с переменными и пробелами.
echo$v;
Например, совершенно справедливо, какreturn$v;
и другие подобные конструкции. Эти небольшие сокращения пробелов могут привести к значительному кумулятивному уменьшению длины.Имейте в виду, однако, что переменные перед языковыми конструкциями требуют пробела после, как в следующем примере:
Поскольку
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,"!";
. Фактически, передача нескольких параметров в aecho
является микрооптимизацией, поскольку код будет работать чуть-чуть быстрее (поскольку вы не объединяете выходные данные, а отправляете их отдельно). Для задач по написанию самого быстрого кода это может помочь крошечным крошечным кусочком.echo
, но не сprint
(который вам нужен, если вы поместите его в выражение:echo
это чистая конструкция без возвращаемого значения, в то время какprint
может действовать как функция: она не требует скобок, но всегда возвращаетint(1)
.print
.Используйте строки с умом.
Этот ответ двоякий. Первая часть заключается в том, что при объявлении строк вы можете использовать неявное преобразование PHP неизвестных констант в строки для экономии места, например:
@
Необходимо переопределить предупреждения этого будет производить. В целом вы получаете сокращение на один символ.в том, что иногда может быть полезно установить переменную для имени часто используемой функции. Обычно вы можете иметь:
Но при игре в гольф это можно легко сократить до:
Имея только два экземпляра preg_match, вы сохраняете только один символ, но чем больше вы используете функцию, тем больше места вы сэкономите.
источник
E_DEPRECATED
) являются приемлемымиphp.ini
файлеВам не всегда нужно выписывать условные проверки. Например, некоторые платформы используют это в верхней части своих файлов, чтобы заблокировать доступ:
Или в нормальных функциях
вместо того
источник
Использовать короткий синтаксис массива
Начиная с PHP 5.4, массивы могут быть объявлены с использованием квадратных скобок (как JavaScript) вместо
array()
функции:Это сэкономит пять байтов.
Но это может стоить байтов, если у вас есть «дыры» в ассоциативном массиве:
недостаток наступает чуть позже, если вы можете заполнить отверстия «пустыми» значениями:
источник
[,$a,$b,$c]=$argv;
.Используйте $ {0}, $ {1}, $ {2}, ... вместо $ a [0], $ a [1], $ a [2], ...
Если вы не выполняете манипуляции с массивами, большинство ссылок на индекс массива
$a[$i]
можно просто заменить$$i
. Это даже верно, если индекс является целым числом, поскольку целые числа являются допустимыми именами переменных в PHP (хотя для литералов, например, потребуются скобки${0}
).Рассмотрим следующую реализацию втулки Rabonowitz Wagon:
Это может быть улучшена за счет 6 байт, просто заменив обе ссылки на массивы
$a[$g]
с$$g
вместо этого:источник
Изучите большое подмножество функций библиотеки .
Библиотека PHP довольно большая и предоставляет множество удобных функций, которые могут значительно сократить время выполнения различных задач. Вы можете просто искать каждый раз, когда пытаетесь что-то сделать, но, не теряя времени, вы можете не найти ничего, соответствующего вашему конкретному поиску. Лучший способ - просто ознакомиться с библиотекой и запомнить имена функций и то, что они делают.
источник
Запуск функций внутри строк.
Попробуй это:
Или попробуйте это:
Это работает только с использованием строк
""
и heredocs (НЕ путайте с nowdocs).Использование вложенных функций возможно только внутри вложенных heredocs (или вы столкнетесь с ошибками разбора)!
источник
you will run into parse errors
Я не могу прочитать это сам? Как надоедливый движок Zend соединяет все этовеселье с типами
!!$foo
превратит любое истинное значение вtrue
(или1
в выходной), ложные значения (0, пустую строку, пустой массив) вfalse
(или пустой выходной).Это редко понадобится в коде Golf, так как в большинстве случаев, когда вам нужен логический тип, есть неявное приведение в любом случае.
(int)$foo
может быть записано как$foo|0
илиfoo^0
, но может потребоваться скобки.Для логических значений и строк,
$foo*1
или+$foo
может использоваться для приведения к типу int.10
, вы можете добавить ноль:*10
->.0
. Но в этом случае PHP примет точку как десятичную точку и пожалуется. (Это отличается, хотя, если у вас есть переменное количество нулей в строке.)join
вместоimplode
.Если вам не нужен разделитель, не используйте его:
join($a)
делает то же самое, что иjoin('',$a)
$s=a;$s++;
производит$s=b;
. Это работает с прописными и строчными буквами.$s=Z;$s++;
результаты в$s=AA;
.Это также работает со смешанным регистром:
aZ
tobA
,A1
toA2
,A9
toB0
иz99Z
toaa00A
.Decrement не работает на строках. (И это не вкл
NULL
).Вернуться в PHP 3,
$n="001";$n++;
производится$n="002";
. Мне немного грустно, что они удалили это.Что бы вы ни играли в гольф: всегда держите под рукой таблицу приоритетов оператора .
источник
Используйте ярлыки
В нормальном коде рекомендуется использовать
<?php
и?>
. Однако это не нормальный код - вы пишете код для игры в гольф. Вместо того<?php
, чтобы писать<?
. Вместо того<?php echo
, чтобы писать<?=
. Не печатайте?>
в конце - это совершенно необязательно. Если вам?>
по какой-то причине нужно (например, выводить текст, и он как-то короче, или что-то еще), не ставьте точку с запятой перед ним - это не нужно, поскольку?>
подразумевает точку с запятой.Неверно (определенно слишком долго):
Правильный:
источник
-r
флагом ( который поставляется бесплатно ) у вас нет вообще никаких тегов (и вам не разрешено их использовать).цикл через строки
может быть сделано с 26 байтами или с 24 до 18:
$a&$b
выполняет побитовое И для (ascii-кодов) символов в$a
и$b
и приводит к строке, которая имеет ту же длину, что и короче
$a
и$b
.источник
ord($s[$p++])
качестве альтернативногоfor(;$s+=ord($argv[++$i])%32?:die($s==100););
AGAINSTfor(;$c=$argv[++$i];)$s+=ord($c)%32;echo$s==100;
в этом вопросе codegolf.stackexchange.com/questions/116933/...~
для случаев, когда вы работаете только с цифрами~$c
подхода.Используйте троичные операторы
может быть сокращено до этого:
Короче, а?
источник
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
.Ассоциативные массивы могут быть объединены с
+
оператором.Вместо того:
Использование:
Обратите внимание, что
+
оператор работает и с индексированными массивами, но, вероятно, не делает то, что вы хотите.источник
+
, если индексы различны. Если это не так, значения из первого массива будут перезаписаны значениями из второго (точно так же как array_merge). Разница:+
не переупорядочивать индексы.array_flip vs array_search
использование
вместо того
сохранить 1 байт в массивах, где уникальность каждого значения
источник
некоторые интересные факты о переменных переменных
Я просто должен был поделиться ими (даже прежде чем я убедился, что хотя бы один из них помогает в игре в гольф):
$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};
print543
.[0-9a-zA-Z_]
имена переменных, но и КАЖДУЮ строку:$x="Hello!";$$x="Goodbye.";echo${"Hello!"};
printGoodbye.
.[a-zA-Z_][a-zA-Z_0-9]*
имен переменных требует фигурных скобок для буквального использования.$$x=1
устанавливает${NULL}
, что совпадает с${false}
и${""}
.$a=1;$$a=5;
не только установить${1}
, но и${true}
.еще один, самый странный, который я нашел до сих пор: попробуй
$a=[];$$a=3;echo${[]};
. Да, это печатает3
!Причина большинства из этого: имена переменных всегда оцениваются как строки.
(Спасибо @Christoph за указание.)
Итак, все, что вы получаете, когда вы
print
илиecho
выражение, это то, что вы получаете как имя переменной.источник
[]
преобразует вArray
:${[]} = 5;echo $Array;
печать5
. Я почти уверен, что вы это знаете, но это может быть не очевидно для всех :)разрывы строк,
если вывод требует разрывов строк, используйте физический разрыв строки (1 байт) вместо этого.
"\n"
Это также дает вам возможное преимущество выбора между одинарными и двойными кавычками.
источник
по возможности избегайте кавычек
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
PHP 7.4 находится на версии RC2 и, надеюсь, выйдет примерно через 2 месяца. Список новых функций здесь (эта страница может быть обновлена после выхода 7.4). В 7.4, наконец, PHP получил функции стрелок, так что теперь не только ответы на функции могут быть короче, но и передача замыканий другим функциям также может быть намного короче. Вот несколько примеров:
Вернуть вход + 1:
Анонимная функция (закрытие) - 25 байт - попробуйте онлайн!
Функция стрелки - 12 байт - попробуйте онлайн!
Умножьте элементы первого ввода (массива целых) на второй ввод (int):
Анонимная функция (закрытие) - 72 байта - попробуйте онлайн!
Функция стрелки - 38 байт - попробуйте онлайн!
Вы заметили, что
$n
доступно во внутренней функции безuse $n
оператора? Да, это одна из функций стрелок.В качестве примечания, я не мог заставить функции стрелок работать рекурсивно (вызывать одну и ту же функцию стрелок внутри себя), потому что мы не можем дать им имя и сохранить их как замыкание в переменной, как
$f
не делает$f
доступным внутри себя (печально) ). Так что этот пример не работает и использование$f
в первой строке вызывает фатальную ошибку:Но вызов функции стрелки с использованием другой функции стрелки работает:
источник
$f=fn($n)=>$n?$f($n-1):0;
тебя это сделать$f=$F=fn($n)=>$n?$F($n-1):0;
? Будет ли это работать? И тогда вы звоните,$(5)
как обычно.Относительно файлового ввода / вывода:
Ссылка на другой связанный вопрос , ответы на который здесь уместны.
источник
Непосредственно разыменование массивов, возвращаемых из функций.
Например, вместо этого:
Ты можешь сделать:
Это работает и с методами:
Вы также можете напрямую разыменовать объявления массива:
источник
Используйте
end()
вместоarray_pop()
end()
Функция не просто перемещает внутренний указатель на конец массива, она также возвращает последнее значение. Заметьте, конечно, что это значение не удаляется , поэтому, если вам все равно, что массив содержит впоследствии, вы можете использовать его вместоarray_pop()
.источник
двойной массив_флип против in_array против массив_unique
в этом особом случае двойной array_flip сохраняет 10 байт
($f=array_flip)($k=$f($c)))
удалить все двойные значения в массиве, и я удалил это$c=[],
,|in_array($o,$c)
и заменитьarray_keys($c)
на$k
Онлайн версия
против
Онлайн версия
против array_unique экономит 2 байта
Онлайн версия
Обнаружив ошибку в этой программе и замену
$x[$i]==$o?:$c[$x[$i]]=$o
к($p=$x[$i])==$o?:$k[$c[$p]=$o]=$p
двойному array_flip не надо было большеисточник
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
Я люблю эту идею.unset () против INF
В случае поиска минимума в массиве вы можете использовать вместо
сохранить 3 байта
источник
str_repeat
В некоторых случаях у вас есть ввод символов, и вы должны выводить их повторно с вводом большего нуля для каждого символа.
(52 байта) короче
или
(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"
правдиво -> вывод"ab"
--$z=1
-> вывод"abb"
--$z=0
; поэтому мы установили$c="c"
и$z=1
$c.$z="c1"
верно вывод"abbc"
--$z=0
так$c=""
и$z=""
->$c.$z=""
ложь -> разрывы циклаисточник
Объединяя
for
петельПредположим, у вас есть код следующей формы:
это обычно может быть повторно свернуто в следующей форме:
где
•
представляет общий оператор объединения. Это обычно приводит к уменьшению количества байтов, но, вероятно, потребует некоторой креативности.$cond2
нужно будет написать так, чтобы он потерпел неудачу в первый раз.$post1
также не может быть выполнен в первый раз, хотя может быть проще выполнить рефакторинг заранее, чтобы$post1
его не было.Если вы работаете с тремя или более вложенными циклами, вы также можете сначала объединить два, а затем объединить это с другим и так далее. Я считаю, что в целом легче было комбинировать изнутри наружу.
В качестве примера рассмотрим следующее решение фрактала с H-ковром ( 97 байт ):
Это можно переформулировать следующим образом:
$e&&print
предотвращаетprint
на первой итерации, а также не увеличивает$i
.и наконец ( 93 байта ):
$H>$e*=3
потерпит неудачу в первый раз, так как обе переменные не определены.источник
Удаление символов в строке
сохраняет 1 символ по сравнению с
источник
""
и в любом случае она не очень полезна.)
. Иstrtr($string,[" "=>""])
еще короче.массив_мердж против массива_пуш
на один байт короче
Не работает то же самое с ассоциативными массивами
Переменная arg-list PHP> 5.6
источник
Используйте логические операторы вместо
strtoupper()
иstrtolower()
Если вы работаете исключительно со строками, состоящими из букв алфавита, вы можете использовать логические операторы, чтобы изменить их на прописные или строчные с меньшим количеством нажатий клавиш, чем встроенные функции PHP.
Пример:
Вещи немного сложнее для строк произвольной длины, но
&
и^
операторы усечения результат длины короткой строки ввода. Так, например, если$W
это строка пробелов, по крайней мере такая же длинная, как любой ввод$s
, то~$W&$s
она эквивалентнаstrtoupper($s)
и$s|$W^$s
эквивалентнаstrtolower($s)
(тогда как$s|$W
сама по себе создаст строку с дополнительными пробелами, если$s
и$W
они не имеют равную длину)источник
используйте устаревшие функции
Если вы можете использовать POSIX вместо регулярного выражения PERL, не тратя больше 5 байт на выражение, используйте
ereg
илиeregi
вместоpreg_match
,split
илиspliti
вместо preg_split.split
Может также использоваться как синонимexplode
для большинства разделителей.Эти функции помечены как устаревшие и будут выдавать
E_DEPRECATED
уведомления, но (не могу найти источник сейчас) Я думаю, что я прочитал, что предупреждения и уведомления в порядке.источник