Какие общие советы у вас есть для игры в гольф в Mathematica? Я ищу идеи, которые могут быть применены к задачам по коду для гольфа в целом, которые, по крайней мере, несколько специфичны для Mathematica (например, «удалить комментарии» - это не ответ).
(Norm[#-#2]&)
вместоEuclideanDistance
.Некоторые встроенные функции с длинными именами можно заменить более короткими выражениями.
Например:
Total
=>Tr
Transpose
=>Thread
или\[Transpose]
True
=>1<2
False
=>1>2
Times
=>1##&
Alternatives
=>$|##&
IntegerQ
=>⌊#⌋==#&
a[[1]]
=>#&@@a
a[[All,1]]
=>#&@@@a
ConstantArray[a,n]
=>Array[a&,n]
илиTable[a,{n}]
Union@a
=>{}⋃a
илиa⋃a
ToExpression@n
=>FromDigits@n
еслиn
это числоDivisible[n,m]
=>m∣n
FromDigits[n,2]
=>Fold[#+##&,n]
еслиn
это список0
s и1
sComplex@z
=>{1,I}.z
гдеz
список формы{x,y}
источник
Thread[{{a,b},{c,d}}]
==Thread[List[{a,b},{c,d}]]
=={List[a,c],List[b,d]}
=={{a,c},{b,d}}
==Transpose[{{a,b},{c,d}}]
Fold
трюкFromDigits
также работает для любой другой базы, кроме10
. НапримерFromDigits[n,5]
->Fold[4#+##&,n]
(с бонусом сохранения дополнительного байта для баз100
и1000
).U+F3C7
.Echo
, что это вариант, потому что он печатает>>
(и пробел) в STDOUT перед печатью реальной строки.Complex[x,y] => {1,I}.{x,y}
я думаю, чтоx+y*I
намного короче с тем же эффектом?Списки с повторяющимися значениями
Это довольно распространенный вектор для работы с:
Оказывается, это можно сократить на байт:
Еще больше байтов сохраняется, если вектор длиннее двух нулей. Это также может использоваться для инициализации нулевых матриц, например, следующее дает матрицу 2x2 нулей:
Это также может быть использовано для ненулевых значений, если они достаточно большие или достаточно много или отрицательные. Сравните следующие пары:
Но помните, что начиная с 6 значений,
1~Table~6
в этом случае вам лучше (возможно, раньше, в зависимости от требований приоритета).Причина, по которой это работает, заключается в том, что
,
в список вводятся два аргумента, но пропущенные аргументы (в любом месте Mathematica) являются неявнымиNull
s. Кроме того, умножение естьListable
и0*x
есть0
почти для любогоx
(кроме таких вещей, какInfinity
иIndeterminate
), поэтому вот что происходит:Для списков
1
s вы можете использовать аналогичный прием, используя правила возведения в степень. Существует два разных способа сохранения байтов, если1
в списке есть как минимум три параметра:источник
1^{,,,}
на один байт меньше, чем0{,,,}+1
.{,,}^0
. Я буду редактировать пост.Знай свои чистые аргументы функции
При игре в гольф вы часто используете функциональный подход, когда вы используете анонимные (чистые) функции с
&
сокращенным синтаксисом. Существует множество различных способов доступа к аргументам такой функции, и вы часто можете сбрить пару байтов, хорошо разбираясь в возможностях.Доступ к отдельным аргументам
Вы, наверное, знаете это, если раньше использовали чистые функции. П - й аргумент называется
#n
, и#
действует в качестве псевдонима для#1
. Поэтому, если, скажем, вы хотите написать функцию, которая принимает в качестве параметров другую функцию и ее аргумент (чтобы передать аргумент этой функции), используйтеЭто не работает с отрицательными числами (например, вы можете использовать при доступе к спискам).
Доступ к именованным аргументам (новое в V10)
Одна из основных новых возможностей языка в Mathematica 10 - это
Association
s, которые в основном представляют собой карты значений ключей с произвольными типами ключей, написанными какЕсли такая связь передается в качестве первого аргумента чистой функции, вы можете получить доступ к некоторым ее аргументам в виде именованных параметров:
Обратите внимание, что
#
все еще относится ко всей ассоциации, как ожидалось. Чтобы именованные параметры работали, ключи должны быть строками (например, они не будут работать, если вы используете неопределенные переменные), и эти строки должны начинаться с буквы и содержать только буквы и цифры.«Я» аргумент
#0
Менее известной особенностью является то, что она
#0
также существует и предоставляет вам сам объект функции. Это может быть очень полезно в квази и обобщенных квази. На самом деле, самая короткая Mathematica Quine (я знаю)Немного раздражает то, что он не даст вам точных символов, которые вы ввели. Например, если использовать
@
для приложения функции, он все равно будет отображаться как[...]
и пробелы будут вставлены в некоторых местах. Обычно это приводит к тому, что квайн будет немного длиннее, чем хотелось бы, но он всегда будет работать, сначала играя в гольф, а затем просто копируя его вывод - который теперь должен быть настоящим квинем.Помимо кавычек это также означает, что вы можете писать рекурсивный код без необходимости называть вашу функцию. Сравните эти три (наивные, но играющие в гольф) реализации Фибоначчи:
Последовательности аргументов
Теперь здесь начинается настоящее волшебство. Последовательности не часто используются в гольфе, потому что
Sequence
это слишком длинное имя, чтобы стоить его большую часть времени. Но в чистых функциях это то, где они сияют. Если вы не знакомы с последовательностями, они в основном похожи на знаки в некоторых других языках, если вы используете последовательность вList
списке аргументов или в функции, ее элементы будут автоматически расширены в отдельные слоты. ТакТеперь в чистых функциях
##
или##1
есть последовательность всех аргументов. Аналогично,##2
это последовательность всех аргументов, начиная со второго,##3
всех аргументов, начинающихся с третьего и т. Д. Поэтому для начала мы можем просто переопределитьSequence
как##&
, сохранив 5 байтов. В качестве примера использования это дает нам альтернативуJoin@@list
(см. Этот совет ), которая не сохраняет байты, но о которой полезно знать в любом случае:Это эффективно выравнивает первый уровень вложенного списка. Что еще мы можем сделать с этим? Вот более короткая альтернатива на 2 байта
RotateLeft
:Только для этих вещей стоит помнить эту особенность. Тем не менее, мы можем сделать лучше! Последовательности становятся действительно интересными, если учесть, что операторы фактически реализованы как функции под капотом. Например, на
a+b
самом деле оцениваетPlus[a,b]
. Так что, если мы дадим эту последовательность ...Этот прием использовался в этом совете, чтобы сохранить байт
Times
, потому что технически сопоставление также просто оператор:Вы также можете использовать его для сохранения байта,
Unequal
если у вас есть односимвольное значение или переменная, которая, как вы знаете, отсутствует в ваших аргументах (N
вероятно, будет работать в 99% случаев):Это становится еще более интересным с унарные и
-
и/
- последние два фактически реализованы в терминах умножения и возведения в степень. Вот список вещей, которые вы можете сделать, где последний столбец предполагает, что функции переданы аргументыa, b, c
:Другие общие операторы
!=
,==
,&&
,||
. Менее распространенные из них , чтобы иметь в виду , являются|
,@*
,/*
. В заключение приведу небольшой бонусный трюк:Продолжайте экспериментировать с ними, и дайте мне знать, если вы найдете какие-либо другие полезные или особенно интересные приложения!
источник
Sqrt@2
или2^.5
=>√2
a[[1]]
=>a〚1〛
#+#2&
=>+##&
Flatten@a
=>Join@@a
(иногда)Function[x,x^2]
=>xx^2
или#^2&
a〚1;;-1;;2〛
=>a〚;;;;2〛
a〚2;;-1 ;;2〛
=>a〚2;;;;2〛
a〚All,1〛
=>a〚;;,1〛
{{1}}〚1,1〛
=>Tr@{{1}}
0&~Array~10
=>0Range@10
Range[10^3]
=>Range@1*^3
источник
〚
и〛
занимает 3 байта каждый (предположим, UTF8)Операторы как функции
Вдохновленный недавним открытием Дениса для Джулии, я подумал, что смогу изучить это для Mathematica. Я знал, что Mathematica определяет большое количество неиспользуемых операторов, но никогда не обращал на это особого внимания.
Для справки, список всех операторов можно найти здесь в виде таблицы приоритетов. Треугольник в последнем столбце указывает, имеет ли этот оператор встроенное значение или нет. Хотя не все те, которые не могут быть определены легко, большинство из них могут.
Удобно, что есть два неиспользуемых оператора с кодовой точкой менее 256, так что они могут использоваться как отдельные байты в кодированном исходном файле ISO 8859-1:
±
(0xB1) может использоваться либо как унарный префиксный оператор, либо как двоичный инфиксный оператор.·
(0xB7) может использоваться как оператор вариации или n-арного инфикса при n> 2.Однако есть еще одна загвоздка: по какой-то странной причине при определении этих операторов вам нужен один пробел перед ними, иначе Mathematica попытается проанализировать умножение. При их использовании вам не нужны пробелы:
Сравните это с:
Таким образом, это сохраняет один байт при определении функции и два байта при ее использовании. Обратите внимание, что определение
·
не будет сохранять байты для четырех операндов и начнет оценивать байты для большего количества операндов, но использование может все еще сохранять байты в зависимости от приоритета операторов, используемых в аргументах. Также хорошо отметить, что вы можете дешево определить функцию с переменным числом аргументов, которую затем можно вызывать гораздо эффективнее:Но обратите внимание, что эти переменные функции нелегко вызвать с одним аргументом. (Вы можете сделать
CenterDot[x]
или ,##&[]·x
но если вы на самом деле нужно , что есть хороший шанс , что вы лучше другое решение.)Конечно, это ничего не экономит для решений, в которых достаточно неназванной функции, но иногда вам нужно определить вспомогательные функции для последующего использования, а иногда короче определить именованные функции, например, чтобы установить разные определения для разных параметров. В этих случаях использование оператора может сэкономить приличное количество байтов.
Обратите внимание, что для использования этих файлов в кодировке ISO 8859-1 необходимо
$CharacterEncoding
установить совместимое значение, например, значение по умолчанию для WindowsWindowsANSI
. В некоторых системах это значение по умолчанию,UTF-8
которое не сможет считывать эти кодовые точки из одного байта.источник
Выбор значений на основе целого числа
Наивный подход выбрать между
y
иz
, в зависимости от того ,x
является0
или1
являетсяОднако есть более короткий путь:
Это работает , потому что
[[0]]
даетHead
выражения, в данном случаеy
, в то время как[[1]]
раз дает первый элемент - в этом случае первый аргумент,z
.Вы даже можете использовать это для выбора между более чем двумя значениями:
Обратите внимание, что это не будет работать, если
u
это функция, которая на самом деле что-то оценивает. Важно, чтобы Mathematica сохранила всеu[v,w]
как есть. Тем не менее, это работает в большинстве случаев, в том числе, еслиu
это число, строка или список.Кредиты для этого трюка идут на алефальфу - я обнаружил это в одном из его ответов.
Если
x
основано на 1 вместо нуля, просто используйтеили
В некоторых редких случаях вы можете даже использовать тот факт, что умножение не оценивается для некоторых значений:
Обратите внимание , что хотя Mathematica будет на самом деле изменить порядок аргументов, из умножения , если он остается невычисленным, поэтому выше идентичен с
источник
Альтернативы
Length
Это было полностью переписано с некоторыми предложениями от LegionMammal978 и Миши Лаврова. Большое спасибо им обоим.
Во многих случаях
Length
может быть немного сокращен путем использованияTr
. Основная идея состоит в том, чтобы превратить входные данные в список1
s, чтобыTr
они суммировались, что затем равняется длине списка.Наиболее распространенный способ сделать это - использовать
1^x
(для спискаx
). Это работает, потому чтоPower
естьListable
и1^n
для большинства атомарных значенийn
справедливо1
(включая все числа, строки и символы). Таким образом, мы уже можем сохранить один байт с этим:Конечно, это предполагает, что
x
это выражение с более высоким приоритетом, чем^
.Если
x
содержит только0
s и1
s, мы можем сохранить другой байт, используяFactorial
(предполагая, чтоx
имеет более высокий приоритет, чем!
):В некоторых редких случаях
x
может иметь более низкий приоритет, чем,^
но все же более высокий приоритет, чем умножение. В этом случае он также будет иметь более низкий приоритет, чем@
, поэтому нам действительно нужно сравнить сLength[x]
. Примером такого оператора является.
. В этих случаях вы все еще можете сохранить байт с помощью этой формы:Наконец, несколько замечаний о том, с какими списками это работает:
Как упоминалось выше, это работает с плоскими списками, содержащими только цифры, строки и символы. Тем не менее, он также будет работать с некоторыми более глубокими списками, хотя на самом деле он вычисляет что-то немного другое. Для n- D прямоугольного массива использование
Tr
дает вам самое короткое измерение (в отличие от первого). Если вы знаете, что внешнее измерение является самым коротким, или вы знаете, что они все одинаковы, тоTr
выражения-все равно эквивалентныLength
.источник
Length@x == Tr[1^x]
. Должен работать с большинством списков.Tr[x!]
вместо того,Tr[1^x]
чтобы сохранять один байт в особом случае, гдеx
только нули и единицы.Изучите рекурсивные решения - Mathematica является мультипарадигмой, но функциональный подход часто является наиболее экономичным.
NestWhile
может быть очень компактным решением для поисковых задач, а такжеNestWhileList
иFoldList
мощные , когда вам нужно возвратить или обработать результаты промежуточных итераций.Map (/@)
,Apply (@@, @@@)
,MapThread
, И на самом деле все на Вольфрам Функциональной программирования страницы документации является сильнодействующим материалом.Сокращенная форма для увеличения / уменьшения - например, вместо
While[i<1,*code*;i++]
вас можно сделатьWhile[i++<1,*code*]
Не забывайте, что вы можете предварительно увеличить / уменьшить - например,
--i
вместоi--
. Иногда это может сэкономить вам несколько байтов в окружающем коде, исключая подготовительную операцию.Следствие №5 Дэвида Каррахера: Когда одна и та же функция используется многократно, присвоение ей символа может сохранить байты. Например, если вы используете
ToExpression
4 раза в решении,t=ToExpression
позволяет использовать его вt@*expression*
дальнейшем. Однако, прежде чем сделать это, подумайте, означает ли повторное применение одной и той же функции возможность более экономичного рекурсивного подхода.источник
MapThread
часто может быть заменен на\[Transpose]
. TIO .Не использовать
{}
если вы используете@@@
.В некоторых случаях вы можете встретить выражение вроде:
Можно уменьшить байты, написав:
Alternatives
имеет очень низкий приоритет, поэтому обычно можно писать выражения (заметное исключение составляют чистые функции; вы можете использовать его только в крайнем левом элементеAlternatives
).Обратите внимание, что
f@@a|b|c
(вместоf@@{a,b,c}
) не работает, потому чтоApply
имеет более высокий приоритет, чемAlternative
.В этом случае вы должны просто использовать
f@@{a,b,c}
.источник
Только Mathematica 10
Операторские формы
Mathematica 10 поддерживает так называемые «операторные формы», что в основном означает, что некоторые функции могут быть карри. Каррирование функции - это создание новой функции путем фиксации одного из ее операторов. Скажем, вы используете
SortBy[list, somereallylongfunction&]
много разныхlist
с. Раньше вы, вероятно, назначалиSortBy
быs
и чистую функциюf
такТеперь вы можете карри
SortBy
, а это значит, что теперь вы можете сделатьТо же самое работает для многих других функций, которые принимают список или аргумент функции, включая (но не ограничиваясь)
Select
,Map
,Nearest
и т.д.ybeltukov на Mathematica.SE удалось составить полный список из них :
Композиция и Правильная Композиция
Есть новые сокращения для
Composition
(@*
) иRightComposition
(/*
). Очевидный надуманный пример, где они могут сохранять символы, виден в следующих трех эквивалентных строкахисточник
Не пишите функции с 0 аргументами
Нет необходимости в таком коде:
Вы можете просто использовать переменную с,
:=
чтобы вызвать переоценку правой части:Это также означает, что вы можете присвоить псевдониму любое действие, которое вы часто выполняете (даже если это просто что-то вроде
n++
), одному символу стоимостью 5 байт. Так что в случаеn++
его окупаемости после четвертого использования:источник
Используйте,
%
чтобы получить свободную переменнуюЭтот совет применим только в том случае, если можно использовать среду REPL Mathematica.
%
не определяется, когда код запускается как скрипт.Когда вы можете использовать функции REPL, не делайте этого:
Вместо этого помните, что Mathematica хранит последнее оцененное (завершенное символом новой строки) выражение в
%
:Добавленная новая строка стоит байт, но вы экономите два, удаляя
a=
, поэтому в целом это сохраняет один байт.В некоторых случаях (например, когда вы хотите напечатать значение в
a
любом случае), вы можете даже не указывать;
, сохраняя два байта:Один или два байта могут показаться довольно незначительными, но это важный случай, потому что он делает извлечение повторяющихся выражений (что является очень распространенной техникой) гораздо более полезным при игре в гольф:
Обычный метод извлечения повторяющихся выражений стоит четыре байта служебных данных, которые необходимо сохранить при дальнейшем использовании выражения. Вот краткая таблица минимального количества использований выражения (по длине выражения) для извлечения в именованную переменную для сохранения чего-либо:
Используя безымянную переменную, можно будет сэкономить пару байтов гораздо чаще:
Я не думаю
%%
и не%n
могу быть использован для игры в гольф, потому что, если вы не используете их хотя бы дважды, вы можете просто поместить выражение туда, где это необходимо. И если вы используете его дважды, дополнительный символ в имени переменной отменяет экономию от пропуска некоторыхx=
.источник
Проверка, отсортирован ли список
Это по сути следствие этого совета но это достаточно распространенная задача, которая, я думаю, требует своего собственного ответа.
Наивный способ проверить, находится ли список в порядке, состоит в использовании
Мы можем сделать один байт лучше с
Однако это не сработает, если у нас уже нет того, что мы хотим проверить в переменной. (Нам нужно что-то вроде
Sort[a=...]==a
этого, излишне длинное.) Однако есть еще один вариант:Лучше всего то, что это можно использовать для проверки того, является ли входная сортировка обратной сортировки для того же количества байтов:
Еще один байт может быть сохранен, если а) мы знаем, что элементы списка различны, и б) мы знаем нижнюю границу между 0 и 9 (включительно или верхнюю границу для обратного отсортированного порядка):
Чтобы понять, почему это работает, посмотрите «Последовательности аргументов» в подсказке, связанной сверху.
источник
##>0&@@a
. Аналогично для верхней границы для отсортированного.Повторение строки
Вместо
StringRepeat[str,n]
использования(0Range[n]+str)<>""
. Или, еслиstr
не зависит ни от каких аргументов слота, еще лучше,Array[str&,n]<>""
согласно этому совету.источник
StringRepeat[s,n+1]
использованияArray[s&,n]<>s
(даже если у вас уже естьn+1
переменная).Table[str,n]<>""
Если вам нужен список номеров, отсортированных в обратном порядке, не используйте
но
сохранить шесть байтов. Сортировка по отрицательному значению также полезна для
SortBy
сценариев:источник
-Sort@-x
?Вы можете вставить выражение, в
Break
котором можно сохранить один или два символа. Пример ( другие детали не указаны для ясности ):можно превратить в
чтобы сохранить один символ. Если рассматриваемое выражение не имеет более низкого приоритета, чем приложение-функция, вы даже можете сохранить другой символ:
можно превратить в
Несмотря на то, что недокументированный аргумент,
Break
похоже, возвращается окружающим циклом, что потенциально может привести к еще большей экономии.источник
Чтобы удалить все пробелы из строки
s
, используйтеТо есть используйте
StringSplit
значение по умолчанию (разделенное на непробельные компоненты) и просто соедините их вместе. То же самое, вероятно, по-прежнему самое короткое, если вы хотите избавиться от любого другого символа или подстроки:источник
Альтернативы
Range
Очень распространенная задача - применить какую-то функцию ко всем числам от 1 до a
n
(обычно задается как ввод). По сути, есть 3 способа сделать это (используя в качестве примера безымянную идентификационную функцию):Я склоняюсь к первому (по любой причине), но это редко лучший выбор.
С помощью
Array
вместоПриведенный выше пример показывает, что using
Array
имеет одинаковое количество байтов. Тем не менее, оно имеет преимущество в том, что оно является одним выражением. В частности, если вы хотите дополнительно обработать результат с помощью функции,f
вы можете использовать префиксную нотацию, которая сохраняет байты поверхRange
:Кроме того, вы можете опустить круглые скобки вокруг вашей безымянной функции, которая вам может понадобиться
Range
, например,Если вы не хотите использовать его дальше (или с оператором, который имеет меньший приоритет), вы можете вместо этого записать
Array
себя в инфиксную запись, а также сохранить байт:Следовательно,
Array
почти наверняка лучше, чемRange
.Используя
Table
вместоТеперь таблица должна составлять 3 байта или, по крайней мере, 2, когда инфиксная запись является опцией:
Если вы не используете инфиксную запись,
Table
вы можете пропустить круглые скобки, если ваша функция состоит из нескольких операторов:Это еще дольше, но дает дополнительную экономию в случае, указанном ниже.
Настоящая экономия связана с тем, что не следует
Table
сбрасывать со счетов название переменной. Часто у вас есть вложенные безымянные функции, в которых вы хотите использовать внешнюю переменную внутри одной из внутренних функций. Когда это произойдет,Table
короче, чемRange
:Вы не только сохраняете символы для назначения
i
, вы также можете свести функцию к одному выражению в процессе, что позволяет использовать инфиксную нотацию поверх нее. Для справки,Array
в этом случае также длиннее, но все же короче, чемRange
:Когда бы вы на самом деле использовали
Range
?Всякий раз, когда вам не нужен вызов функции для обработки значений, например, когда отображение может быть выполнено с помощью векторизованной операции. Например:
Конечно, это также короче, если вы вообще не хотите отображать какие-либо функции, например
источник
f/@Range[x]
регулярно использует ...Нахождение наименьшего числа, удовлетворяющего условию
Некоторые конструкции вроде бы
i=1;While[cond[i],i++]
хороши как есть, но есть альтернатива, которая на два байта короче:Приведенный выше код повторно заменяет номер
i
с вi+1
то время как она удовлетворяет условиеcond[i]
. В этом случаеi
начинается с1
.Обратите внимание, что максимальное число итераций по умолчанию составляет 2 ^ 16 (= 65536). Если вам нужно больше итераций,
While
было бы лучше. (MaxIterations->∞
слишком долго)источник
Злоупотребление оценка короткого замыкания
Иногда вы можете заменить
If
логическим оператором.Например, предположим, что вы хотите создать функцию, которая проверяет, является ли число простым, а print
2*(number) - 1
- если это правда:Короче, если вы используете
&&
вместо:Даже если у вас есть несколько выражений, вы все равно сохраняете байты:
Вы можете использовать
||
для случаев, когда вы хотите, чтобы условие былоFalse
:Эти приемы работают, потому что логические операторы могут быть закорочены ; второй аргумент и после этого даже не должны быть допустимыми логическими выражениями.
Конечно, это не работает, если вам нужно возвращаемое значение
If
или когда вам нужны как правдивые, так и ложные аргументыIf
.источник
Вот список с множеством форм ввода операторов, которые могут сократить многие вещи. Некоторые из них упоминались в других постах, но список длинный, и я всегда удивляюсь, обнаружив там несколько новых вещей:
источник
С помощью
Optional (:)
Optional (:)
может использоваться для расширения списков в заменах без необходимости определения отдельного правила для расширения.Этот ответ от меня и этот ответ @ngenisis являются примерами.
использование
Приведенная выше замена сначала использует шаблон
{p___, a_, b_, q___}
и находит совпадение, котороеb
удовлетворяет определенному условию.Когда такого совпадения не найдено, оно пропускает
a_
и вместо этого ищет{p___, b_, q___}
.a
не включается в поиск и предполагается, что имеет значение0
.Обратите внимание, что второй поиск по шаблону будет работать только для того,
b
что происходит в начале списка; еслиb
значение, удовлетворяющее условию, находится посередине, тогда{p___, a_, b_, q___}
(которое имеет более высокий приоритет) будет соответствовать ему.Замена эквивалентна добавлению,
0
когдаb
удовлетворение условия происходит в начале списка. (т.е. нет необходимости определять отдельное правило,{b_, q___} /; cond[b] :> ...
)источник
Знать, когда (а когда нет) использовать именованные аргументы чистой функции
Для кода гольф чистые
Function
аргументы чаще всего ссылаются с помощьюSlot
s; например,#
для первого аргумента,#2
для второго и т. д. (см. этот ответ для более подробной информации).Во многих случаях вы захотите вложить
Function
s. Например,1##&@@#&
aFunction
принимает список в качестве первого аргумента и выводит произведение его элементов. Вот эта функция вTreeForm
:Аргументы, передаваемые на верхний уровень,
Function
могут заполнять только теSlot
s иSlotSequence
s, которые присутствуют на верхнем уровне, что в этом случае означает, чтоSlotSequence
во внутреннемFunction
не будет никакого способа доступа к аргументам на верхнем уровнеFunction
.В некоторых случаях, однако, вы можете захотеть, чтобы
Function
вложенный в другой элементFunction
мог ссылаться на внешние аргументыFunction
. Например, вы можете захотеть что-то вродеArray[fun,...]&
, где функцияfun
зависит от аргумента верхнего уровняFunction
. Для конкретности, скажем, чтоfun
следует дать остаток от квадрата его ввода по модулю ввода до верхнего уровняFunction
. Один из способов сделать это - назначить аргумент верхнего уровня переменной:Где бы ни
x
появилось внутреннееFunction
Mod[#^2,x]&
, оно будет ссылаться на первый аргумент внешнегоFunction
, тогда как#
будет ссылаться на первый аргумент внутреннегоFunction
. Лучшим подходом является использование факта,Function
имеющего форму с двумя аргументами, где первый аргумент является символом или списком символов, которые будут представлять именованные аргументы дляFunction
(в отличие от безымянныхSlot
s). В конечном итоге это экономит нам три байта:
это трехбайтовый символ частного использования,U+F4A1
представляющий двоичный инфиксный оператор\[Function]
. Вы также можете использовать двоичную формуFunction
в другомFunction
:Это эквивалентно вышеизложенному. Причина в том, что, если вы используете именованные аргументы, то
Slot
s иSlotSequences
предполагается, что они принадлежат следующему,Function
который не использует именованные аргументы.То, что мы можем
Function
так вкладывать, не означает, что мы всегда должны это делать. Например, если мы хотим выделить те элементы списка, которые меньше входных, у нас может возникнуть соблазн сделать что-то вроде следующего:На самом деле это было бы короче, чтобы использовать
Cases
и избежать необходимости в целомFunction
:источник
Вы можете сохранить байт, работая вокруг
Prepend
илиPrependTo
:или
К сожалению, это не помогает для более распространенного
Append
, который, кажется, является кратчайшим эквивалентомArray.push()
в других языках.источник
Mathematica 10.2:
BlockMap
этоPartition
+Map
Этот совет также может быть озаглавлен «Прочитайте все заметки о выпуске». (Для справки, здесь приведены примечания к выпуску 10.2 и здесь сегодняшнего выпуска 10.3 .)
В любом случае, даже небольшие релизы содержат множество новых функций, и одной из наиболее полезных (для игры в гольф) из 10.2 является новая
BlockMap
функция. Он по сути объединяетPartition
иMap
, что отлично подходит для игроков в гольф, потому чтоPartition
используется довольно часто, и это действительно раздражающее длинное название функции. Новая функция не будет сокращатьсяPartition
сама по себе, но всякий раз, когда вы хотите отобразить функцию на разделы (что, вероятно, происходит чаще, чем нет), теперь вы можете сохранить один или два байта:Экономия становится еще больше, когда новая позиция безымянной функции позволяет вам сэкономить некоторые скобки:
К сожалению, я понятия не имею, почему не добавил,
BlockApply
пока они были на нем ...Также обратите внимание, что
BlockMap
не поддерживается 4-й параметр, который вы можете использоватьPartition
для получения циклического списка:источник
Хранение функций и выражений в переменной
Если ваш ответ в конечном итоге использует одни и те же функции или выражения несколько раз, вы можете рассмотреть возможность их хранения в переменных.
Если ваше выражение имеет длину
l
и вы используете егоn
раз, оно обычно используетl * n
байты.Однако, если вы храните его в переменной длины-1, он будет занимать только
3 + l + n
байты (или2 + l + n
байты, если вы назначите переменную там, где вам не нужныCompoundExpression (;)
или скобки).Например, давайте рассмотрим простую задачу: найти двойные простые числа меньше N.
Можно написать это 54-байтовое решение:
В этом примере функция
PrimeQ
используется три раза.Присваивая
PrimeQ
имя переменной, количество байтов может быть уменьшено. Оба из следующих 48 байтов (54 - 6 байтов):источник
Чтобы получить список значений по возрастанию, используйте
Sort
вместоSortBy
Для таких списков, как
list = {{1, "world"}, {0, "universe"}, {2, "country"}}
следующие три утверждения почти эквивалентны.Объединить
Select
иSortBy
Иногда нам нужно выбрать записи из большего набора и отсортировать их, чтобы найти минимум / максимум. При некоторых обстоятельствах две операции могут быть объединены в одну.
Например, как минимум, следующие два утверждения почти эквивалентны.
а также
1/0
являетсяComplexInfinity
, который "больше", чем все действительные числа.Для списка значений ключа, например:
источник
Решить и уменьшить: автоматический список переменных
Когда список переменных для
Solve
иReduce
опущен, они решают для всех свободных переменных в выражении (ях). Примеры:В частности ,
Solve
надIntegers
,NonNegativeIntegers
иPositiveIntegers
является чрезвычайно мощным для задач перечисления.источник
Значения по умолчанию
Значения по умолчанию эффективно обрабатывают отсутствующие аргументы шаблона. Например, если мы хотим сопоставить шаблон
Exp[c_*x]
в правиле для любого значенияc
, наивныйиспользует намного больше байтов, чем если бы мы использовали значение по умолчанию,
c
если оно отсутствует:Использование по умолчанию обозначается точкой после шаблона:
c_.
.Значения по умолчанию связаны с операциями: в приведенном выше примере операция находится
Times
вc_.*x
, и отсутствующее значение дляc_
, таким образом, берется из значения по умолчанию, связанного сTimes
, которое равно 1. ДляPlus
, значение по умолчанию равно 0:Для
Power
показателей по умолчанию установлено значение 1:источник