Ihr Unternehmen ist gerade dabei, ein Projekt zu starten, und Sie haben sich zum ersten Mal dafür entschieden, einen funktionalen Programmcode zu verwenden. Ihr Chef ist jedoch sehr zurückhaltend und möchte keine eingebauten Funktionen verwenden. Sie müssen die Hauptfunktionen selbst implementieren. Insbesondere müssen Sie die Funktionen schreiben: Map
, Nest
, Apply
, Range
, Fold
und Table
in einer Sprache auf Ihrer Wahl. Der Chef ist sehr beschäftigt und möchte die Programme so kurz wie möglich halten, damit er keine Zeit mit Lesen verschwendet. Er möchte auch, dass Sie keine Schleifen verwenden. Daher wird die Anzahl der Bytes um 10% reduziert, wenn Sie keine Schleifen verwenden.
Die detaillierten Anforderungen der Funktionen sind nachfolgend aufgeführt:
Karte
Die Map
Funktion akzeptiert zwei Parameter: f
und list
wo f
ist eine Funktion und list
ist eine Liste von Werten. Es sollte das f
auf jedes Element angewendete von zurückgeben list
. Daher wird es als solches funktionieren:
Map(f,{a,b,c})
kehrt zurück
{ f(a), f(b), f(c) }
und
Map(f, {{a,b},{b,c}})
kehrt zurück
{ f({a,b}), f({b,c})}
Nest
Die Nest
Funktion nimmt drei Parameter als auch: f
, arg
, times
wobei f
eine Funktion ist, arg
ist sein Ausgangsargument, und times
ist , wie oft die Funktion angewandt wird. Es sollte einen Ausdruck mit f
angewendeten times
Zeiten an zurückgeben arg
. Daher wird es als solches funktionieren:
Nest(f, x, 3)
kehrt zurück
f(f(f(x)))
und
Nest(f, {a,b}, 3)
kehrt zurück
f(f(f({a,b})))
Sich bewerben
Die Apply
Funktion akzeptiert zwei Parameter: f
und args
wo f
ist eine Funktion und args
eine Liste. Es sollte gelten , f
um die args
. Deshalb:
Apply(f, {a,b,c})
kehrt zurück
f(a,b,c)
Reichweite
Die Range
Funktion nimmt eine ganze Zahl r
und gibt die ganzen Zahlen bis zu dieser Zahl aus. Deshalb:
Range(5)
kehrt zurück
{ 1, 2, 3, 4, 5}
Falten
Die Fold
Funktion nimmt drei Parameter f
, arg
, others
wo f
eine Funktion ist, arg
ist einfach Parameter und others
eine Liste. Es wird so funktionieren:
Fold(f, x, {a, b, c, d})
kehrt zurück
f(f(f(f(x,a),b),c),d)
Tabelle
Die Tabellenfunktionen sollten eine Funktion f
und einen Parameter enthalten, die iterator
in der folgenden Form aufgerufen werden: {iMin, iMax}
where iMin
und iMax
are integer. Sie sollten sich f
innerhalb des angegebenen Bereichs bewerben . Deshalb:
Table(f, {0, 5})
kehrt zurück
{f(0), f(1), f(2), f(3), f(4), f(5)}
Ich habe die Definition dieser Funktionen von der Seite zur funktionalen Programmierung in Mathematica übernommen. Gehen Sie also dorthin, wenn Sie weitere Anleitungen benötigen. Beachten Sie, dass Sie nicht alle auf dieser Seite gezeigten Funktionen implementieren müssen, sondern nur die in diesem Beitrag beschriebenen.
Standard-Regelungslücken sind wie gewohnt unzulässig.
Falls Ihre Sprache nicht zulässt, dass Funktionen als Argumente übergeben werden, müssen Sie diese Funktion implementieren und in Ihre Antwort einfügen. Die Byteanzahl dieser Operation wird jedoch nicht zur Gesamtsumme addiert.
Dies ist Codegolf, also gewinnt der kürzeste Code. Viel Glück!!!
quelle
Table
das hier funktioniert. Soll Ihr Beispiel seinTable(f, {x, 0, 5})
? Ich verstehe auch überhaupt nicht den Zweckx
, da es nur die Funktion auf den Bereich anwendet.Antworten:
Haskell,
viele frühere Bytes zählen127 * 0,9 = 114,3 BytesKeine Schleifen, nur Rekursion.
#
ist karte:(*2) # [1,2,3]
->[2,4,6]
&
ist nest:((*2) & 3) 4
->48
i
ist zutreffend:i (*2) 7
->14
r
is range:r 4
->[1,2,3,4]
?
is fold:((+) ? 0) [1,2,3,4]
->10
%
ist Tisch:(*2) % (2,4)
->[4,6,8]
Auf Wunsch eine unbenutzte Version mit Kommentaren. Beachten Sie
&
und?
sind ternäre Infix-Operatoren, für die beim Aufruf oder bei der Musterübereinstimmung zusätzliche Klammern erforderlich sind.Vielen Dank an @dfeuer und @Zgarb für einige nützliche Hinweise
quelle
m#q=reverse$f((:).m)[]q
. Dies ist die gleiche Länge wie Ihre, aber viel schwerer zu lesen.!
indem sie einen Namen anstelle eines Operators:i f=f
.Python 2, 305,1 Byte (-10%
376369366349339 Byte)Wenn erweitert, äquivalent zu:
Keine Schleifen!
Nun, es macht eine Menge
eval
und wenn Ihr Chef Schleifen nicht aushält, dann werden sie EVALUIEREN. Aber sie werden sich damit abfinden müssenEin Weg,
range
in einem Lambda zu tun, wird geschätzt, damit ich keine Funktionen ausführen muss (Shudder.).Erklärungen:
m=lambda f,l:eval("["+"f(l.pop()),"*len(l)+"][::-1]")
n=lambda f,x,l:eval("f("*l+"*x"+")"*l)
r=lambda i:e("r(i-1)+"*(i>1)+"[i]")
eval
zurückgibt[0]
oder mithilfe der Rekursion abruft und den aktuellen Index zur Liste hinzufügt. Bewerte es.a=lambda f,a:eval("f(a["+
r (len (a))[1:-1].replace(",","-1],a[")+"-1])")
a
. Bewerte es!f=lambda f,x,l:eval("f("*len(l)+"x,["+
r (len (l))[1:-1].replace(",","-1]),l[")+"-1])")
t=lambda f,n,x:eval("[f("+
r (x) [n-1:].replace(",","),f(")[1:-1]+")]")
Map, nest, range, apply, fold, table.
Danke @Zgarb für ein Lambda für Reichweite!
quelle
r=lambda i:[]if i<1 else r(i-1)+[i]
? Keine Schleifen, nur Rekursion.eval
, um ihnen zu zeigen, dass Schleifen nicht so schlimm sind :)e=eval
:r=lambda i:e("r(i-1)+"*(i>1)+"[i]")
Javascript ES6, 197 * 0,9 = 177,3 Byte
Karte (
M=(f,l)=>F((a,b)=>[...a,f(b)],[],l)
):Mit Fold können Sie die
f
auf jedes Mitglied von angewendeten Ergebnissel
auf eine leere Liste setzen. Die Verwendung von eingebauten Funktionen reduziert dies aufM=(f,l)=>l.map(f)
(hat es nicht verwendet, weil es billig erscheint ...?).Nest (
N=(f,x,n)=>f(--n?N(f,x,n):x)
):f
Rekursiv anwenden, bisn
auf 0 dekrementiert wird.Übernehmen (
A=(f,l)=>f(...l)
):Verwendet den
...
Operator spread ( ), auf denl
angewendet werden sollf
.Bereich (
R=n=>n--?[...R(n),n+1]:[]
):Konzentrieren Sie sich
n
auf den rekursiven Aufruf von Range, bisn
auf 0 dekrementiert wird.Falten (
F=(f,x,l,n=l.length)=>n--?f(F(f,x,l,n),l[n]):x
):Wendet den rekursiven Aufruf von Fold an und das
n
'te Element vonl
tof
untiln
wird auf 0 dekrementiert. Die Verwendung integrierter Funktionen reduziert dies aufF=(f,x,l)=>l.reduce(f,x)
(wieder schien es billig ...).Tabelle (
T=(f,i)=>([n,x]=i,M(q=>f(q+n-1),R(x-n+1)))
):Zuerst initialisiert
n
undx
auf Imin und Imax Verwendung Destrukturierung ([n,x]=i
), verwendet Bereich die Tabelle der Werte von Imin bis Imax zu konstruieren.f
wird dann mit Map auf die Tabelle angewendet und das Ergebnis zurückgegeben.quelle
Python 3, 218 Bytes
Die unlesbare Version:
Die (mehr) lesbare Version:
Gehen Sie es ein Lambda nach dem anderen:
Kartenfunktion
P
P=lambda f,x:[f(_)for _ in x]
Nur ein einfacher Iterator. Hier gibt es nicht viel zu sagen.
Nest-Funktion
Y
Y=lambda f,x,z:Y(f,f(x),z-1)if z else x
Wird solange wiederholt, bis
z
Null erreicht istf
. Wird jedes Mal angewendet . Die if-Klausel am Ende fühlt sich klobig an; Vielleicht gibt es einen besseren Weg, um die Rekursion zu beenden.Funktion anwenden
T
T=lambda f,x:f(*x)
Python hat einen netten Expansionsoperator, der das ganze schwere Heben für mich erledigt.
Range-Funktion
H
H=lambda f,x=0:(H(f-1)if~-f else[])+[f]
Dieser war schwieriger als ich erwartet hatte. Endete mit einem rekursiven Ansatz. Auch hier nimmt die if-else-Konstruktion viele Bytes in Anspruch, und ich bin der Meinung, dass sie verbessert werden kann. Warum hat es einen Dummy
x=0
, fragst du? Es ist so, dass ich, wenn ich es mit dem komprimiereexec
, ersetzen kann,=lambda f,x
anstatt nur=lambda f
.Falzfunktion
O
O=lambda f,x,z:O(f,f(x,z[0]),z[1:])if z else x
Ziemlich zufrieden mit diesem. Hüpft einfach jedes Mal vom ersten Element des Arrays, wenn es wiederholt wird, bis nichts mehr übrig ist.
Tabellenfunktion
N
N=lambda f,x:(N(f,[x[0],x[1]-1])if x[1]-x[0]else[])+[f(x[1])]
Dieser ist schrecklich und ich bin sicher, dass es Raum für Verbesserungen gibt. Versucht, die zuvor für eine
map(f,range(x,y))
Art Konstruktion definierten Entfernungs- und Kartenfunktionen zu verwenden, jedoch ohne großen Erfolg. Endete mit einem furchtbaren rekursiven Ansatz, der Ähnlichkeiten mit der Bereichsfunktion aufweist.Alle Lambdas sind
exec
mit einem umhülltreplace
, um die Byteanzahl deutlich zu verkürzen.quelle
[f(_)for _ in x]
map(f,x)
Julia, 181 Bytes
Kein Bonus für mich; Ich habe großzügig mit Loops gearbeitet. Sorry Boss, aber Loops in Julia sind effizient!
Wenn Sie die Ellipsen nach einem Argument zu einer Funktion hinzufügen, wird ein Array, ein Tupel oder was Sie haben, in reguläre Funktionsargumente aufgeteilt. Andernfalls wird die Funktion denken, dass Sie versuchen, ein Array (oder Tupel usw.) zu übergeben. Es hat keine Auswirkung auf einzelne Argumente.
Funktionsnamen:
M
N
A
R
F
T
quelle
Tinylisp , 325 × 0,9 = 292,5
Die Sprache ist neuer als die Frage, aber sie wird trotzdem nicht gewinnen.
Definiert die Funktionen
A
(Apply),M
(Map),N
(Nest),R
(Range),T
(Table) undF
(Fold) sowie einige Hilfsfunktionen.T
erwartet eine Liste mit zwei ganzen Zahlen für das zweite Argument.Tinylisp hat nicht einmal Loop-Konstrukte. Alles wird durch Rekursion erreicht. Einige dieser Funktionen sind nicht rekursiv . Wenn Sie sie also in großen Listen aufrufen, werden sie wahrscheinlich den Aufrufstapel sprengen. Sie könnten alle mit Schwanzrekursion implementiert werden ... aber es würde mehr Bytes benötigen, und dies ist Codegolf.
Hier ist eine erweiterte Version mit Leerzeichen und echten Wörtern für Namen, die ziemlich gut lesbar sein sollten, wenn Sie mit Lisp vertraut sind. (Ich habe die meisten Tinylisp-Builtins mit Ausnahme von
q
(quote) undi
(if) als Alias verwendet .)Weitere Erläuterungen auf Anfrage.
Beispielausgabe
Verwendet die REPL-Umgebung aus meiner Referenzimplementierung. Ich habe
q
(quote) für die unäre Funktion unds
(subtrahieren) als binäre Funktion für diese Beispiele sowie die Funktion@
(in diesem Code definiert) verwendet, die eine Liste ihrer Argumente zurückgibt.quelle
Python 2.x: 450,6 Bytes (493 Bytes vor 10% Rabatt)
Golf Antwort:
Diese Frage hat Spaß gemacht. Ich beschloss, meine Funktionen ohne die Python-Entsprechungen zu schreiben (obwohl dies eine gültige Lücke gewesen sein könnte) und die Funktionen so zu schreiben, als ob Python die Schwanzrekursion unterstützt. Damit dies funktioniert, habe ich viele optionale Parameter verwendet, mit denen die erforderlichen Aufrufe weiterhin ausgeführt werden können.
Nachstehend habe ich für jede Funktion unbenutzte Listen.
Apply
:Map
:Nest
:Beachten Sie, dass diese Funktion erfordert, dass das übergebene
function
Argument mehrere Argumente variabel darstellen kann. Ein anderer Ansatz wäre gewesen, zu erzwingen, dass die Funktion immer eine einzige Liste empfängt, aber dazu müssten die übergebenen Funktionen in der Lage sein, Argumentlisten zu interpretieren. In beiden Fällen gab es Annahmen, daher habe ich die ausgewählt, die besser zum Rest des Systems passt.Range
:Fold
:Table
:Hier ist eine Beispielausgabe mit den folgenden Hilfsfunktionen:
quelle
Ceylon,
370 · 0,9 = 333,364 · 0,9 = 327,4Die meisten dieser Funktionen sind bereits in Ceylons Sprachpaket verfügbar (wenn auch manchmal mit einer etwas anderen Signatur), aber wir definieren sie hier wie in der Frage gefordert.
Tatsächlich verwenden nur zwei der Funktionen (
t
undf
) eine Rekursion (über Listen bzw. Ganzzahlen), die anderen basieren auf diesen. (Bewerben ist ein Ausreißer, es hat nichts mit den anderen zu tun.)Ich interpretiere "Liste" als Ceylons sequentiellen Typ, der eine unveränderlich geordnete (möglicherweise leere) Folge von Elementen ist.
[R*]
steht fürSequential<R>
- aus irgendeinem Grund können wir es auch schreibenR[]
, was ein Byte kürzer ist.Ein Funktionstyp ist
Callable<R, A>
, woA
ist ein Tupeltyp für die Argumente, wie[X, Y, Z]
(dh ein Subtyp vonAnything[]
). Als Abkürzung können wirR(X,Y,Z)
statt schreibenCallable<R,[X,Y,Z]>
.Ich aliased
Integer
alsI
zu speichern einige Bytes.Hier ist eine formatierte (und leicht kommentierte) Version:
Verwenden von "Schleifen"
Tabelle und Map können mit Schleifen kürzer implementiert werden (eigentlich ein Sequenzverständnis):
Ich bin mir jedoch nicht sicher, ob die Verwendung des
..
Operators für den Ganzzahlbereich als Verwendung einer integrierten Funktion gilt. Wenn dies zulässig ist, lautet der resultierende Code hier, Länge 312:(Es könnte noch kürzer gemacht werden, indem definiert wird
r(I i) => 1..i
, was zu Punktzahl 301 führt. Das sieht jedoch noch mehr nach Betrug aus.)Wenn dies
..
nicht erlaubt ist, müssen wir es erneut implementieren. Wir können diese Implementierungen fürr
undt
(mit denm
oben genannten) verwenden:Dies ergibt 348 Bytes, besser als die vollständig rekursive Version, jedoch nicht nach Anwendung des Bonus.
quelle
Groovy (146 Bytes) (146 * 90% = 131,4)
PS Ich weiß nicht, was Sie in diesem Zusammenhang als "Schleife" betrachten. Ich habe den Bonus erst angewendet, nachdem ich in den Kommentaren von OP darauf hingewiesen wurde, und werde entfernen, wenn 2-3 zusätzliche Benutzer diese Sammlungsfunktionen und Iteratoren angeben sind Schleifen und das verdiene ich nicht den Bonus. Wenn Sie mich auf meine Verwendung von 1..it aufmerksam machen möchten, tun Sie dies bitte und ich werde es überarbeiten / meinen bytecount aktualisieren.
Beispiel Eingabe / Ausgabe
Ausgabe
Probieren Sie es selbst aus: https://groovyconsole.appspot.com/edit/5203951758606336
quelle