Napisz funkcję, f
która przyjmuje dodatnią liczbę całkowitą i zwraca funkcję.
Nowa zwrócona funkcja powinna być identyczna z f
. Jednak gdy nastąpi „wywołanie zakończenia”, f
zamiast tego należy zwrócić sumę wszystkich przekazanych liczb całkowitych.
Na przykład g=f(4)
(jeśli f
jest to pierwsza funkcja) należy ustawić g
na inną funkcję. h=g(3)
zrobi to samo. Jednak gdy wywołujesz h
bez argumentów (szczegóły poniżej), powinien on wypisać 7, ponieważ jest to suma poprzednich argumentów funkcji. Innymi słowy, f(3)(4)() == 7
.
Pamiętaj, że to nie to samo co f(3,4)()
.
„Połączenie kończące połączenie” to jedna z następujących opcji (do wyboru):
- wywołanie bez argumentów
- zerowy jako argument
- wszelkie wartości dodatnie
Należy obsłużyć dowolną liczbę wywołań funkcji, nie ma z góry określonego limitu.
Gwarantujemy, że całkowita suma nie będzie większa niż 1 000.
Możemy założyć, że przed „połączeniem kończącym” wykonano co najmniej jedno połączenie.
Twój kod nie powinien używać statycznych zmiennych dla poszczególnych programów, więc powinno być możliwe przeprowadzenie eksperymentu wiele razy w tym samym środowisku wykonawczym i obserwowanie dokładnie tego samego zachowania.
Przykłady:
f(1)() == 1
f(4)(2)(7)() == 13
f(4)(2)(7)(5)(2)() == 20
źródło
f(4)
zwraca nową funkcję. Jeśli ta nowa funkcja zostanie wywołana bez argumentów, zwróci4
, ale jeśli zostanie wywołana z innym argumentem, ponownie zwróci nową funkcję z tą samą semantyką, ale z dodanym nowym argumentem4
i tak dalej.q = f(2)(3); b = f(1)(2)(3); q(); b()
?Odpowiedzi:
JavaScript (ES6), 18 bajtów
Przekaż wartość fałszowania, aby pobrać sumę. Zero można dopuścić za koszt 2 bajtów.
Wypróbuj online
Nie golfowany:
źródło
Haskell (GHC), 118 bajtów
Jest to 98 bajtów dla kodu i 20 bajtów dla flagi kompilatora GHC
-XFlexibleInstances
, co umożliwia rozszerzenie systemu typów.Definiuje to „funkcję”
f
, którą można wywołać z dowolną liczbą liczb całkowitych()
, po której następuje jednostka , po czym zwraca liczbę całkowitą. Wpisz adnotacje są wymagane. Wypróbuj online!Wyjaśnienie
Zmuszenie ścisłego systemu typów Haskell do umożliwienia tego wymaga pewnej magii, a mianowicie umożliwienia rozszerzenia GHC dla elastycznych instancji typu czcionki. Jak to działa,
f
jest to parametrycznie polimorficzna funkcja ograniczona przez ograniczenie klasy typu: jej typ toF a => Int -> a
. Oznacza to, żef
przyjmuje liczbę całkowitą i zwraca wartość typua
dla każdego typua
należącego do klasyF
.F
jest tylko nazwą klasy, która udostępnia tę funkcjęf
; jest zadeklarowany w pierwszym wierszu.Następne dwa wiersze to dwa wystąpienia
F
różnych typówa
. Drugi wiersz mówi, że należy do typu funkcji od()
do liczb całkowitychF
(gdzie()
jest typ jednostki, którego jedynym elementem jest wartość()
), a implementacja tof n () = n
; funkcja zwraca swój pierwszy argument. Ostatni wiersz mówi, że jeślia
należyF
, to także rodzaj funkcji od liczb całkowitych doa
: z funkcjif :: Int -> a
możemy wygenerować inną funkcjęf :: Int -> Int -> a
. Implementacja jestf m n = f (m+n)
(kod używa kombinatorów, aby ją skrócić), gdzief
po lewej stronie jest nowy, af
po prawej stronie stary. To zasadniczo dajef
nowy argument liczby całkowitej, który jest dodawany do następnego. Wiele argumentów jest sumowanych w następujący sposób:W
f
każdej linii jest inny typ.Funkcje Haskell są automatycznie curry, więc jeśli podasz
f
tylko liczby całkowite, otrzymasz funkcję.źródło
f
, a nie pojedynczą funkcję wykonującą zadanie. Jest to jednak tak blisko, jak to tylko możliwe w Haskell. Nie sądzę, że możliwe jest rozwiązanie zadania za pomocą jednej funkcji ze względu na ścisły system typów.f
, ale nieskończenie wiele wywoływanych funkcjif
. (Jeden na każdą możliwą liczbę argumentów.) Funkcje te (z tej nieskończonej rodziny) mają dwa rodzaje definicji, jeden rodzaj, gdy liczba argumentów wynosi zero, a drugi, gdy nie jest.f n()=n
if=(f.).(+)
tak bym nazwać definiowania dwie funkcje.g 0 = 1
ag n = g (n-1) * n
tam, gdzie są dwie definicje, ale tylko jedna funkcja. Mamy tutaj dwie definicje, ale nieskończenie wiele funkcji. (Każdy z innego rodzaju.)ghci
załaduj powyższe i spróbuj:t f
- powief :: F a => Int -> a
(co oznacza, że jeślia
jest instancją klasyf
, tof
jest funkcjąInt -> a
). Moglibyśmy więc uznać to za jedną funkcję lub za nieskończenie wiele, ale chociaż ma ona dwa rodzaje definicji (podobnie jak funkcja silnia), nie widzę żadnej dobrej podstawy do uznania jej za dwie funkcje.Python 2,
424136 bajtówTo rozwiązanie nigdy nie będzie przepełnione, ponieważ Python obsługuje liczby całkowite o dowolnej dokładności. Zero to „wartość specjalna”.
Wypróbuj online
Nie golfowany:
źródło
C,
6258 bajtów, konkurencja na granicyZaoszczędź 4 bajty dzięki Kevinowi! (Wciąż nie usuwa typedef, ponieważ jest to coś, co jest potrzebne do wywołania).
Funkcja do wywołania to
f
; przestajesz to nazywać i otrzymujesz wynik, dzwoniąc na nie dodatni numer, taki jak0
. Wypróbuj uprząż testową online!Tak więc, o ile mogę stwierdzić, jedynym sposobem na „curry” funkcje, które mają wiele typów zwrotów, jest wykonanie jednej z następujących czynności:
union
/struct
typ który maint
podtypy i funkcja / autoreferencyjne.Próbowałem zrobić (2), ale wydawało mi się to trochę sprzeczne z duchem pytania i, szczerze mówiąc, prawie niemożliwe. Tak więc, zgodnie z duchem wyzwania, wybrałem opcję (1). Wymaga to rzutowania każdej zwróconej funkcji do funkcji, aby można było jej użyć.
Ta składnia „curry” wygląda nieco dziwnie, ale jest dość podobna. Aby naśladować
f(21)(1)
, trzeba by pisać((B)((B)f(21))(1))(0)
. ZdefiniowałemB
typ jako funkcję, która przyjmuje liczbę całkowitą i zwraca wskaźnik do funkcji, która przyjmuje liczbę całkowitą. Po rozwinięciu wygląda to następująco:źródło
q;f(x){return x?(q+=x,f):q;}
.q
po każdym uruchomieniu, funkcja nie byłaby już użytecznaMathematica, 25 bajtów
Wypróbuj online! (Korzystanie z matematyki.)
Można zrobić trzy bajty mniej, przenosząc odpowiedź JavaScript, ale chciałem przedstawić bardziej idiomatyczne rozwiązanie Mathematica. To
@
tylko odrobina cukru syntaktycznego, co sprawia, że rozwiązanie jest równoważne z:Więc tak, pomysł polega na tym, że w Mathematica nie można po prostu zdefiniować funkcji,
f[x_]
ale można bezpośrednio dołączyć wartość do bardziej skomplikowanego wyrażenia zawierającegof
np.f[x_]
Przekazany inny argument. Ustawiając dwie definicje, możemy uzyskać pożądane zachowanie:f[x][y]
wywołanief[x+y]
, zużywając w ten sposób jedno „wywołanie” i sumując znajdujące się w nim argumenty. Ta zasada obowiązuje, dopóki nie zostaniemyf[sum][]
.sum
.źródło
C ++, 72 bajty
Definiuje typ,
F
który działa jako żądana funkcja, oraz zmiennąf
tego typu do wywołania. Jest ważny od C ++ 11 i działa z wersjami online GCC, clang, icc i VC ++.Stosowanie:
Wyjaśnienie:
Po wstępnym przetworzeniu i ponownym sformatowaniu wygląda następująco:
Zwykle byłoby to napisane:
return a;
ireturn {+a};
zrób to samo, ponieważ unary+
nie zmienia wartości, a nadmiarowe nawiasy klamrowe wokół wartości zwracanej są dozwolone.int m
iint(m)
zrobić to samo, ponieważ dozwolone są nadmiarowe nawiasy wokół nazwy zmiennej, w tym parametry funkcji.return {m+a};
ireturn {int(m)+a};
rób to samo, ponieważ rzut zm
odint
naint
nie zmienia swojej wartości. Zmiany teoperator()
zbliżają dwa przeciążenia w składni, umożliwiając dwukrotne wywołanie definicji jednego makra. Wybór odpowiedniej kolejności dla trzech elementów umożliwia uwzględnienie również pierwszego słowa następnego wiersza (int
) w definicji makra.źródło
operator()
aby ta praca była szczególnie fajna.Rubinowy, 23 bajty
Stosowanie:
źródło
C,
10496 bajtówUżywa metody z linku udostępnionego przez @JulianWolf. Ostatni argument musi wynosić 0.
Wypróbuj online!
źródło
Math.JS, 38 bajtów
Zadzwoń za pomocą
f(number_a)(number_b)(...)(negative_number)
Jeśli wolno nam określić początkowe wywołanie,
f(x)=i(x,0)\n
można usunąć 12 bajtów ( ) i można je wywołać za pomocąi(number_one,0)(number_two)(...)(negative_number)
Spróbuj!
Wyjaśnienie
Jak pokazano w powyższym LaTex,
f(x)
po prostu wywołujei(x,0)
, a następniei(x,y)
zwraca wartośćy
ifx
jest mniejsza niż 0 lub funkcjęj(z)=i(z,x+y)
, która pobiera jeden argument, który zapętla się. Zwiększenie wartościy
.źródło
C,
232206 bajtówPrawdopodobnie można to znacznie pograć w golfa, ale powinno to służyć jako dowód na to, że można używać C bez żadnych rozszerzeń języka *, aby rozwiązać ten problem, wywołując bez argumentów, a nie z magiczną wartością.
* @hvd zauważył, że chociaż działa to od razu przy użyciu gcc, niektóre zachowania nie są zdefiniowane w standardzie C, co oznacza, że może nie być przenośne. Używaj na własne ryzyko!
Nie golfowany:
Kompilowanie i uruchamianie z
gcc arbitrary-length-currying.c -o arbitrary-length-currying && ./arbitrary-length-currying
wyjściami (po ostrzeżeniach)źródło
g
ih
kontynuacji łańcucha wywołań makr będzie działać, ponieważ nie jest określone, czy następneg
pojawi się w kontekście rozszerzenia pierwszegog
. C11 dodaje przykład do 6.10.3.4, aby przeliterować, że nie jest określony. (IIRC, preprocesor TenDRA to taki, który nie rozwinąłby go tak, jak chcesz.) Poza tym żadna wersja języka nie obsługuje zarówno pustych argumentów makr, jak i domyślnej int, więc prawidłowy program C nie może używać obu. :) Mimo to fajna odpowiedź. Czy chcesz dalej grać w golfa?*s
zamiaststrlen(s)
. Ciągi C mają długość niejawną, zakończonąchar
wartością0
. Fajny hack makr, który pozwala na rozmowy z / bez arg!Kod maszynowy 8086, 27 bajtów
Ten kod maszynowy musi mieć adres 0x100 i zakłada model małego kodu (cs = ds = es = ss). Lokalizacja funkcji może być jednak zmieniona bez dodatkowych kosztów. Ustawienie go w pozycji offset
0
spowoduje zapisanie bajtu (xor si,si
zamiastmov si, 0x100
)Wymagana konwencja połączeń
Zakłada się, że dzwoniący wstępnie przydzielił co najmniej 27 bajtów na stosie. Pobiera liczbę
ax
i zwraca wskaźnik funkcjibx
. Wywołanie tego wskaźnika zax=0
kończy łańcuch i zwraca sumębx
.Więc dla pierwszego połączenia:
Następnie dla każdego kolejnego połączenia:
Aby zakończyć:
Unngolfed (skomentował demontaż kodu maszynowego):
Po wywołaniu tego niezerowym AX,
bx = sp
a bufor jest wypełniony zmodyfikowaną kopią kodu maszynowego zfunction
. 16-bitowy natychmiast w pierwszej instrukcji zawiera sumę. (Jest napisany przez ostatnią instrukcję przedret
.)push di
/pop bx
można zastąpićmov bx, di
(przedrep movsb
), dzięki czemu jest to prostsze, ale nie ma oszczędności.Wymaganie od dzwoniącego przekazania wskaźnika do bufora dst w
di
zaoszczędziłoby 4 bajty w porównaniu do obliczenia go względemsp
.Ustawienie adresu początkowego funkcji na taki sam jak rozmiar funkcji pozwoliłoby zaoszczędzić bajt (
mov cx, si
).źródło
objdump -b binary
zamiasthexdump -C
di
(4 bajty). Ustaw adres początkowy funkcji = rozmiar:mov cx, si
zamiastmov cx, 0x1b
.C #, 62 bajty
Aby zakończyć połączenie, podaj liczbę ujemną, np
źródło
null
parametry lub nie kończąc żadnych parametrów. Jednak wszystkie sposoby próbowałem były o wiele dłużej!m
zamiastm<0
i przekazaćnull
lub0
jako ostatni parametr?Boolean
może być użyte jakoBoolean
... Próbowałem z,null
ale właśnie się wydłużyło. Chciałem użyć,??
co oznacza, że jeśli LHS ma wartość zerową, to RHS, ale ponieważ potrzebuję, jeśli LHS nie jest zerowe, zrób to inaczej RHS, czego nie mogłem.Scala, 58 znaków
Wypróbuj online
Nie golfowany:
Wyjaśnienie:
Ten kod definiuje
case class
nazwany f z konstruktorem przyjmującym wartość int. Zdefiniuj klasę przypadków, która wygeneruje metody equals, hashcode, toString i copy oraz obiekt towarzyszący o tej samej nazwie, aby umożliwić tworzenie obiektów beznew
słowa kluczowego.Ta klasa ma przeciążoną metodę zastosuj: jedna bierze kolejną liczbę całkowitą, aby dodać i tworzy nowy obiekt ze zaktualizowaną sumą, a druga bez argumentów, aby uzyskać sumę.
W Scali każdy obiekt z metodą zastosuj można nazwać jak metodę, czyli
o.apply(x)
można ją zapisać jakoo(x)
. Jest to używane w standardowej bibliotece dla tablic, list, map iFunction1
cechy implementowanej przez funkcje anonimoweźródło
Pyth, 19 bajtów
Wypróbuj online!
Jestem pod wrażeniem, że JavaScript pokonuje Pytha, ale z drugiej strony Pyth nie jest zaprojektowany do przekazywania funkcji.
źródło
Perl 5, 36 bajtów
źródło
-M5.016
? Wygląda na to, że powinieneś być w stanie upuścić,-M5.016
a następnie upuścićmy
i zapisać kilka bajtów. Jeśli taksay
, możesz-E
zamiast tego użyć flagi , która się nie aktywujeuse strict
, więc nadal możesz upuścićmy
.__SUB__
), ale zmieniłem to przed przesłaniem i nie usunąłem trochę o 5.16. Usunę to. Nie sądzę jednak, aby upuszczaniemy
było poprawne.say
jako część kodu, to tylko w celach ilustracyjnych)my
bezuse strict
,$n
jest to domyślnie zmienna globalna. Jest to zła forma w odpowiednich skryptach perla, ale jest dość powszechna w liniowcach i wydaje się, że tutaj działa.Brain-Flak , 6 bajtów
Właśnie zauważyłem, że skoro ToS jest poprawnym formatem zwrotnym, wyskakiwanie 0 nie jest tak naprawdę potrzebne, co pozwala zaoszczędzić 2 bajty:
Wypróbuj online!
Oryginalne zgłoszenia, 8 bajtów
Wykorzystuje
0
jako specjalną wartość:Wypróbuj online!
Wyjaśnienie
Biorąc pod uwagę argumenty u 1 , 2 , ..., n , 0 stos początkowo wygląda następująco:
a n
⋮
a 2
a 1
0
Następnie kod jest długa, co pojawia się I , gromadzi je zdejmuje 0 dodaje je i odkłada wynik:
Alternatywne rozwiązania, 8 bajtów
Zamiast wstawiać 0 i dodawać je do sumy, możemy również zamieniać stosy, ponieważ prawy jest początkowo pusty:
Wypróbuj online!
Używając
-r
flagi, 0 znajduje się na górze stosu, więc możemy ją najpierw wstawić:Wypróbuj online!
Wypróbuj online!
źródło
C (GCC), 83 bajty
Mój pierwszy golf C! Istnieje kilka innych rozwiązań C, ale to jest trochę inne. Zastosowanie preprocesora jest czysto kosmetyczne. To podejście zostało po raz pierwszy omówione w odpowiedzi Conora O'Briena tutaj .
Wartość końcowa wynosi zero. Zwracana wartość to unia, więc aby wywołać wynik, użyć pola
f
i uzyskać dostęp do wartości końcowej, użyj polav
, npWypróbuj online
Ograniczenia
Zmienna globalna zawiera bieżącą sumę. Chociaż jest to wyraźnie zabronione, przesyłanie obsługuje wielokrotne wywołania (suma jest resetowana w wywołaniu terminalu), co wydaje się być przyczyną zakazu stanu globalnego.
Wskaźnik do
f
jest przechowywany w zwrócony związek za pośrednictwemint
elementu, więc najwyraźniej nie jest przenośny. Nie jestem pewien, czy to działa w GCC na wszystkich platformach, czy tylko na Linuksie, czy tylko na x86, czy tylko z ELF lub ... Jeśli ktoś zna jakieś szczegóły na ten temat, proszę o komentarz lub wiadomość!źródło
APL (Dyalog Classic) ,
48474644 32 bajtyWypróbuj online!
Kończy się, przekazując zero. Składnia wywołania:
((0 f 1) 2) 0
-15 bajtów dzięki @ngn
Wymaga
⎕IO←0
Wszelkie wskazówki dotyczące gry w golfa są mile widziane!
źródło
:If x<0
, aby:If×x
i zamienić „jeśli” i „else” klauzuler←⍎condition⊃'else' 'then'
Perl 6 , 31 bajtów
źródło
Dyvil , 34 bajty
Zastosowanie :
Końcowe
()
można pominąć.Wyjaśnienie :
Definiuje operator zestawienia, który pobiera dwie liczby int i dodaje je. Ten parametr
j
ma wartość domyślną0
do obsługi połączenia bez argumentów. W0
powyższych przykładach nie jest to nazwa, ale dosłownie.źródło
Julia v0.5 +, 52 bajty
Zadzwoń jako
F
. Prawdopodobnie można by to znacznie skrócić, przyjmując mniej OO, ale zawsze lubię mieć możliwość korzystania z tego idiomu.Jeśli można założyć, że „co najmniej jedno połączenie zostanie wykonane przed połączeniem kończącym”, drugą linię można usunąć, aby zaoszczędzić 6 bajtów.
źródło
Julia 0,5 , 18 bajtów
Wypróbuj online!
źródło
R, 40 bajtów
0 działa tutaj jako wartość stop. W przypadku dwóch kolejnych bajtów możemy to pominąć.
Problem polega na tym, że R nie ma zwięzłej wbudowanej lambda. Ale jeśli dodamy jeden , możemy uzyskać kod do 26 bajtów :
(Tak, to jest poprawne R. Wystarczy importować.)
źródło
PHP, 44 bajty
Pomysł od @ user63956
Zakończenie połączenia
0
Wersja online
Zakończenie połączenia z
NULL
potrzebują oddanych[$i]
do[+$i]
PHP, 47 bajtów
Wersja online
PHP, 52 bajty
Wywołanie zakończenia
NULL
lub dowolna inna wartość fałszywa w PHPjeśli program musi zakończyć po wyjściu zastąpić
print$s
zdie("$s")
+ 2 bajtyWersja online
źródło
$s
. żebyś mógł zrobić coś takiego jakreturn$i?f:$s
na końcufunction f($i){return[$_GET[0]+=$i][$i]?:f;}
.PowerShell, 86 bajtów
Wypróbuj online!
Kod testowy:
Wyjście: 20
źródło
$n="$args"
zamiast$n=$args[0]
. To jednak nie będzie działać na drugim$args[0]
, ponieważ wtedy uzyskasz konkatenację łańcuchów zamiast dodawania.Python 3 , 63 bajty
Wypróbuj online!
Kończy się na 0
źródło
Python, 69 bajtów
źródło
Oktawa, 39 bajtów
* Argumentem zakończenia połączenia jest 0.
Wypróbuj online!
*
endfunction
wymagane, aby dodać kilka innych kodów.źródło
R,
5452 bajtówZaoszczędź 2 bajty dzięki MickyT!
Podobne do jednej z odpowiedzi na python. Nie golfowany:
Działa jako
źródło
f=function(x){g=function(y='')'if'(y>'',f(x+y),x);g}
return
.return
w R nie jest taki sam jak w innych językach, wykonuje przedwczesne przerwanie. Nieużywaniereturn
jest idiomatyczne. Z drugiej strony twoja nie golfowa wersja wciąż ma golfaif
.if
lenistwo, alereturn
jest tylko dla czytelności - daje ten sam wynik z lub bezreturn
.return
zmniejsza czytelność, ponieważ sygnalizuje niewłaściwą rzecz (przedwczesne wyjście) i jest przykładem programowania kultowego ładunku .C ++ (gcc) ,
9591 bajtówWypróbuj online!
źródło