Напишите функцию, f
которая принимает положительное целое число и возвращает функцию.
Возвращенная новая функция должна быть идентичной f
. Однако, когда происходит «вызов завершения», f
вместо этого следует возвращать сумму всех переданных целых чисел.
Например, g=f(4)
(если f
первая функция) должна установить g
другую функцию. h=g(3)
будет делать то же самое. Однако, когда вы вызываете h
без аргументов (см. Подробности ниже), он должен вывести 7, так как это сумма предыдущих аргументов функции. Другими словами f(3)(4)() == 7
.
Обратите внимание, это не то же самое, что f(3,4)()
.
«Прекращение вызова» является одним из следующих вариантов (на ваш выбор):
- вызов без аргументов
- ноль в качестве аргумента
- любое неположительное значение
Произвольное количество вызовов функций должно поддерживаться, предопределенного ограничения нет.
Гарантируется, что общая сумма не будет больше 1000.
Мы можем предположить, что перед «завершением вызова» сделан хотя бы один вызов.
Ваш код не должен использовать статические переменные для каждой программы, поэтому должна быть возможность многократно запускать эксперимент в одно и то же время выполнения и наблюдать одно и то же поведение.
Примеры:
f(1)() == 1
f(4)(2)(7)() == 13
f(4)(2)(7)(5)(2)() == 20
источник
f(4)
возвращает новую функцию. Если эта новая функция вызывается без аргументов, она возвращается4
, но если она вызывается с другим аргументом, она снова возвращает новую функцию с той же семантикой, но с новым аргументом, добавленным к4
и так далее.q = f(2)(3); b = f(1)(2)(3); q(); b()
?Ответы:
JavaScript (ES6), 18 байт
Передайте ложное значение, чтобы получить сумму. Нули могут быть разрешены для стоимости 2 байта.
Попробуйте онлайн
Ungolfed:
источник
Haskell (GHC), 118 байт
Это 98 байт для кода и 20 байт для флага компилятора GHC
-XFlexibleInstances
, который включает расширение системы типов.Это определяет «функцию»
f
, которая может быть вызвана с произвольным числом целых чисел, за которыми следует единица()
, после чего она возвращает целое число. Тип аннотации обязательны. Попробуйте онлайн!объяснение
Чтобы заставить систему жестких типов Haskell разрешить это, требуется некоторое волшебство, а именно включение расширения GHC для гибких экземпляров классов типов. Как это работает, так
f
это параметрически полиморфная функция, ограниченная ограничением класса типа: ее тип естьF a => Int -> a
. Это означает, чтоf
принимает целое число и возвращает значение типаa
для любого типа,a
который принадлежит классу типовF
.F
это просто имя класса типов, который предоставляет функциюf
; это объявлено в первой строке.Следующие две строки являются двумя экземплярами
F
для разных типовa
. Во второй строке указывается, что тип функций от()
целых принадлежитF
(где()
это тип модуля, единственным членом которого является значение()
), а реализация -f n () = n
; функция возвращает свой первый аргумент. В последней строке указывается, что еслиa
принадлежитF
, то и тип функций из целых чисел вa
: из функцииf :: Int -> a
мы можем сгенерировать другую функциюf :: Int -> Int -> a
. Реализация таковаf m n = f (m+n)
(код использует комбинаторы, чтобы сделать его короче), гдеf
слева - новый, аf
справа - старый. Это по сути даетf
новый целочисленный аргумент, который добавляется к следующему. Несколько аргументов суммируются вместе следующим образом:f
На каждой линии имеет другой тип.Функции на Haskell каррируются автоматически, поэтому, если вы дадите
f
только целые числа, вы получите функцию.источник
f
, а не одну функцию, которая выполняет свою работу. Тем не менее, это так близко, как вы можете получить в Haskell. Я не думаю, что можно решить задачу с помощью одной функции из-за строгой системы типов.f
, а бесконечно много вызываемых функцийf
. (Один для каждого возможного числа аргументов.) Эти функции (из этого бесконечного семейства) имеют два вида определений, один вид, когда число аргументов равно нулю, и другой, когда это не так.f n()=n
иf=(f.).(+)
поэтому я бы назвал это определением двух функций.g 0 = 1
иg n = g (n-1) * n
, где есть два определения, но только одна функция. Здесь у нас есть два определения, но бесконечно много функций. (Каждый из разных типов.)ghci
загрузите вышеупомянутое и попробуйте:t f
- он скажетf :: F a => Int -> a
(имеется в виду, что еслиa
это экземпляр классаf
, тоf
это функцияInt -> a
). Таким образом, мы могли бы рассматривать это либо как одну функцию, либо как бесконечное множество, но, хотя у нее есть два вида определений (точно так же, как факториальная функция), я не вижу хорошей основы для того, чтобы считать ее двумя функциями.Python 2,
424136 байтЭто решение никогда не будет переполнено, так как Python поддерживает целые числа произвольной точности. Ноль - это «особая ценность».
Попробуйте онлайн
Ungolfed:
источник
C,
6258 байт, пограничный конкурирующийСохранено 4 байта благодаря Кевину! (До сих пор не удаляем typedef, потому что это нужно для вызова.)
Функция для вызова есть
f
; Вы перестаете звонить и получаете результат, звоня с неположительным числом, таким как0
. Попробуйте использовать тестовые ремни онлайн!Итак, насколько я могу судить, единственный способ «карри» функций с несколькими типами возвращаемых значений - это выполнить одно из следующих действий:
union
/,struct
который имеетint
подтипы и функцию / самоссылку.Я попытался сделать (2), но это казалось немного противоречащим духу вопроса и, откровенно говоря, почти невозможно отменить. Таким образом, в соответствии с духом задачи, я выбрал вариант (1). Это требует приведения каждой возвращаемой функции в функцию, чтобы ее можно было использовать.
Этот «карри» синтаксис выглядит немного странно, но довольно похоже. Чтобы подражать
f(21)(1)
, нужно было бы написать((B)((B)f(21))(1))(0)
. Я определилB
тип как функцию, которая принимает целое число и возвращает указатель на функцию, которая принимает целое число. В развернутом виде это выглядит так:источник
q;f(x){return x?(q+=x,f):q;}
.q
после каждого запуска, то эта функция больше не могла бы использоватьсяMathematica, 25 байтов
Попробуйте онлайн! (Используя математику.)
Можно портировать ответ на JavaScript на три байта меньше, но я хотел представить более идиоматическое решение Mathematica. Это
@
всего лишь синтаксический сахар, который делает решение эквивалентным:Так что да, идея в том, что в Mathematica вы не можете просто определить функцию,
f[x_]
но вы можете напрямую прикрепить значение к более сложному выражению, содержащемуf
, напримерf[x_]
, передав другой аргумент. Установив два определения для этого, мы можем получить желаемое поведение:f[x][y]
вызовf[x+y]
, тем самым потребляя один «вызов» и суммируя аргументы внутри. Это правило действует до тех пор, пока нас не оставятf[sum][]
.sum
.источник
C ++, 72 байта
Это определяет тип,
F
который действует как запрошенная функция, и переменнаяf
этого типа для вызова. Он действителен для C ++ 11 и работает с онлайн-версиями GCC, clang, icc и VC ++.Использование:
Объяснение:
После предварительной обработки и переформатирования это выглядит так:
Это обычно будет написано:
return a;
иreturn {+a};
делать то же самое, поскольку унарное+
не меняет значение, и допускаются избыточные скобки вокруг возвращаемого значения.int m
иint(m)
сделать то же самое, поскольку допускаются избыточные скобки вокруг имени переменной, включая параметры функции.return {m+a};
иreturn {int(m)+a};
делать то же самое, так как приведениеm
изint
вint
не меняет своего значения. Эти измененияoperator()
сближают две перегрузки по синтаксису, позволяя дважды вызывать одно определение макроса. Выбор правильного порядка для трех членов позволяет такжеint
включить в определение макроса первое слово следующей строки ( ).источник
operator()
чтобы сделать эту работу, была особенно крутой.Рубин, 23 байта
Использование:
источник
C
10496 байтИспользует метод по ссылке, которой поделилась @JulianWolf. Последний аргумент должен быть 0.
Попробуйте онлайн!
источник
Math.JS, 38 байт
Позвони с
f(number_a)(number_b)(...)(negative_number)
Если нам разрешено указать начальный вызов, 12 bytes (
f(x)=i(x,0)\n
) может быть отброшено, и его можно вызвать сi(number_one,0)(number_two)(...)(negative_number)
Попробуй!
Explination
Как показано в приведенном выше примере LaTex,
f(x)
просто вызываетi(x,0)
, затемi(x,y)
возвращает значениеy
ifx
меньше 0 или функциюj(z)=i(z,x+y)
, которая принимает один аргумент, который зацикливается. Добавление к стоимостиy
.источник
C
232206 байтЭто, вероятно, может быть значительно улучшено, но должно служить подтверждением концепции, что C можно использовать без каких-либо языковых расширений *, чтобы решить эту проблему, вызывая без аргументов, а не с магическим значением.
* @hvd отметил, что, хотя это работает «из коробки» с использованием gcc, некоторая часть поведения не определена в стандарте C, что означает, что это не может быть переносимым. Используйте на свой риск!
Ungolfed:
Компиляция и запуск с
gcc arbitrary-length-currying.c -o arbitrary-length-currying && ./arbitrary-length-currying
выходами (после некоторых предупреждений)источник
g
иh
продолжения цепочки макро-вызовов не гарантируется, так как не определено,g
появляется ли следующий в контексте расширения первогоg
. C11 добавляет пример к 6.10.3.4, чтобы объяснить, что он не указан. (IIRC, препроцессор TenDRA - это тот, который не будет расширять его так, как вы хотите.) Кроме того, ни одна версия языка не поддерживает как пустые макро-аргументы, так и неявный int, поэтому действительная программа на Си не может использовать оба. :) Тем не менее, хороший ответ. Вы ищете в гольф это дальше?*s
вместоstrlen(s)
. Строки C имеют неявную длину и заканчиваются наchar
значение со значением0
. Хороший макрос, позволяющий звонить с / без аргумента!8086 машинный код, 27 байт
Этот машинный код должен быть по адресу 0x100 и предполагает модель крошечного кода (cs = ds = es = ss). Расположение функции может быть изменено без затрат дополнительных байтов. Установка его со смещением
0
сэкономит байт (xor si,si
вместоmov si, 0x100
)Обязательное соглашение о вызовах
Это предполагает, что вызывающий предварительно выделил как минимум 27 байтов в стеке. Он принимает число
ax
и возвращает указатель на функциюbx
. Вызов этого указателя сax=0
завершает цепочку и возвращает сумму вbx
.Итак, для первого звонка:
Затем для каждого последующего вызова:
Чтобы прекратить:
Ungolfed (прокомментировал разборку машинного кода):
После вызова этого с ненулевым AX,
bx = sp
и буфер заполняется измененной копией машинного кода изfunction
. 16-битный непосредственно в первой инструкции содержит сумму. (Это написано последней инструкцией передret
.)push di
/pop bx
можно заменить наmov bx, di
(доrep movsb
), что упрощает, но не экономит.Требование к вызывающей стороне передать указатель на буфер dst
di
позволит сэкономить 4 байта по сравнению с вычислением его относительноsp
.Если сделать начальный адрес функции таким же, как размер функции, можно было бы сохранить byte (
mov cx, si
).источник
objdump -b binary
вместоhexdump -C
di
(4 байта). Сделайте начальный адрес функции = размер:mov cx, si
вместоmov cx, 0x1b
.C #, 62 байта
Для завершения вызова введите отрицательный номер, например
источник
null
или не указывая параметры до конца. Однако все способы, которые я пробовал, были намного длиннее!m
вместоm<0
и передатьnull
или0
в качестве последнего параметра?Boolean
можно использовать только aBoolean
... Я пробовал,null
но он стал длиннее. Я хотел использовать,??
что означает, что если LHS равен null, то RHS, но, как мне нужно, если LHS не равен null, сделать это, иначе сделать RHS, я не смог.Скала, 58 символов
Попробуйте онлайн
Ungolfed:
Объяснение:
Этот код определяет
case class
вызываемый f с конструктором, принимающим int. Определите класс case, который будет генерировать методы equals, hashcode, toString и copy, а также сопутствующий объект с тем же именем для создания объекта безnew
ключевого слова.Этот класс имеет перегруженный метод apply: для добавления требуется другое целое число и создается новый объект с обновленной суммой, а другой - без аргументов для получения суммы.
В Scala любой объект с методом apply может быть вызван как метод, то есть
o.apply(x)
записан какo(x)
. Это используется в стандартной библиотеке для массивов, списков, карт иFunction1
признаков, реализованных анонимными функциямиисточник
Pyth, 19 байт
Попробуйте онлайн!
Я впечатлен тем, что Javascript побеждает Pyth, но опять же Pyth не совсем предназначен для передачи функций.
источник
Perl 5, 36 байт
источник
-M5.016
? Кажется, вы должны быть в состоянии отбросить,-M5.016
а затем также сброситьmy
и сохранить пару байтов. Если это простоsay
, вы можете использовать-E
вместо этого флаг , который не активируетсяuse strict
, поэтому вы все равно можете сброситьmy
.__SUB__
), но я изменил это перед отправкой и не удалил бит о 5.16. Я удалю это. Я не думаю, что падениеmy
будет правильным, хотя.say
рассматриваю это как часть кода, это только для иллюстрации)my
безuse strict
,$n
это неявно является глобальной переменной. Это плохая форма в правильных сценариях Perl, но это довольно распространено в однострочниках, и, похоже, здесь работает.Brain-Flak , 6 байтов
На самом деле я только что заметил, что, поскольку ToS является допустимым возвращаемым форматом, выталкивание 0 на самом деле не нужно, что экономит 2 байта:
Попробуйте онлайн!
Оригинал (ы), 8 байт
Используется
0
как специальное значение:Попробуйте онлайн!
объяснение
С учетом аргументов a 1 , a 2 ,…, a n , 0 стек изначально выглядит так:
а н
⋮
2
1
0
Затем код продолжается, выдает каждые a i , накапливает их, выдает 0, добавляет их и отправляет результат:
Альтернативные решения, 8 байт
Вместо того, чтобы ставить 0 и добавлять его к сумме, мы также можем поменять стеки, так как правый изначально пуст:
Попробуйте онлайн!
Используя
-r
флаг, 0 находится на вершине стека, так что мы могли бы вытолкнуть его первым:Попробуйте онлайн!
Попробуйте онлайн!
источник
C (GCC), 83 байта
Мой первый C гольф! Есть несколько других C-решений, но это немного другое. Использование препроцессора чисто косметическое. Этот подход был впервые обсужден в ответе Конора О'Брайена здесь .
Терминальное значение равно нулю. Возвращаемое значение представляет собой объединение, поэтому для вызова результата используйте поле
f
, а для доступа к конечному значению используйте полеv
, напримерПопробуйте онлайн
Ограничения
Глобальная переменная содержит промежуточную сумму. Хотя это явно запрещено, отправка поддерживает повторные вызовы (общее значение сбрасывается при вызове терминала), что, по-видимому, и является причиной запрета глобального состояния.
Указатель на
f
сохраняется в возвращаемом объединении черезint
член, так что это явно не переносимо. Я не уверен, работает ли это на GCC на всех платформах, или только на Linux, или только на x86, или только с ELF или ... Если кто-нибудь знает какие-либо подробности об этом, пожалуйста, прокомментируйте или отправьте сообщение!источник
APL (Dyalog Classic) ,
48474644 32 байтаПопробуйте онлайн!
Завершается передачей в ноль. Синтаксис вызова:
((0 f 1) 2) 0
-15 байт благодаря @ngn
требует
⎕IO←0
Любые советы по гольфу приветствуются!
источник
:If x<0
на:If×x
и поменяйте местами предложения «if» и «else»r←⍎condition⊃'else' 'then'
Perl 6 , 31 байт
источник
Dyvil , 34 байта
Использование :
Трейлинг
()
может быть опущен.Пояснение :
Определяет оператор сопоставления, который берет два целых и добавляет их. Параметр
j
имеет значение0
по умолчанию для поддержки вызова без аргументов. В0
приведенных выше примерах это не имя, а литерал.источник
Юлия v0.5 +, 52 байта
Звоните как
F
. Вероятно, это можно было бы сделать намного короче, приняв метод менее ОО, но мне всегда нравится получать возможность использовать эту идиому.Если можно предположить, что «перед завершающим вызовом будет сделан хотя бы один вызов», вторая строка может быть удалена для сохранения 6 байтов.
источник
Юлия 0,5 , 18 байт
Попробуйте онлайн!
источник
R, 40 байт
0 действует как стоп-значение здесь. Еще два байта мы можем опустить.
Проблема в том, что R не хватает краткой встроенной лямбды. Но если мы добавим один , мы можем получить код до 26 байтов :
(Да, это действительно R. Это просто нужно импортировать.)
источник
PHP, 44 байта
Идея от @ user63956
Завершение вызова
0
Онлайн версия
Прекращение вызова с
NULL
необходимостью гипса[$i]
в[+$i]
PHP, 47 байт
Онлайн версия
PHP, 52 байта
Завершение вызова
NULL
или любое другое значение, которое является ложным в PHPесли программа должна завершиться после выхода, заменить
print$s
наdie("$s")
+ 2 байтаОнлайн версия
источник
$s
. так что вы могли бы сделать что-то вродеreturn$i?f:$s
в концеfunction f($i){return[$_GET[0]+=$i][$i]?:f;}
.PowerShell, 86 байт
Попробуйте онлайн!
Тестовый код:
Выход: 20
источник
$n="$args"
вместо$n=$args[0]
. Однако с другой стороны это не сработает$args[0]
, потому что тогда вы получите конкатенацию строк, а не сложение.Python 3 , 63 байта
Попробуйте онлайн!
Завершается 0
источник
Python, 69 байт
источник
Октава, 39 байт
* Аргументом завершения вызова является 0.
Попробуйте онлайн!
*
endfunction
требуется добавить некоторые другие коды.источник
R,
5452 байтаБлагодаря MickyT сэкономлено 2 байта!
Похоже на один из ответов питона. Ungolfed:
Работает как
источник
f=function(x){g=function(y='')'if'(y>'',f(x+y),x);g}
return
.return
в R это не то же самое, что в других языках, он выполняет преждевременную отмену. Не использоватьreturn
это идиоматично. С другой стороны, в вашей версии без гольфа все еще есть гольфif
.if
был лень, ноreturn
только для удобства чтения - он дает тот же результат с или безreturn
.return
снижает читабельность, поскольку сигнализирует о неправильной вещи (преждевременный выход) и является примером программирования культового груза .C ++ (gcc) ,
9591 байтПопробуйте онлайн!
источник