Implementieren Sie funktionale Programmierparadigmen


21

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, Foldund Tablein 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 MapFunktion akzeptiert zwei Parameter: fund listwo fist eine Funktion und listist eine Liste von Werten. Es sollte das fauf 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 NestFunktion nimmt drei Parameter als auch: f, arg, timeswobei feine Funktion ist, argist sein Ausgangsargument, und timesist , wie oft die Funktion angewandt wird. Es sollte einen Ausdruck mit fangewendeten timesZeiten 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 ApplyFunktion akzeptiert zwei Parameter: fund argswo fist eine Funktion und argseine Liste. Es sollte gelten , fum die args. Deshalb:

Apply(f, {a,b,c})

kehrt zurück

f(a,b,c)

Reichweite

Die RangeFunktion nimmt eine ganze Zahl rund gibt die ganzen Zahlen bis zu dieser Zahl aus. Deshalb:

Range(5)

kehrt zurück

{ 1, 2, 3, 4, 5}

Falten

Die FoldFunktion nimmt drei Parameter f, arg, otherswo feine Funktion ist, argist einfach Parameter und otherseine 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 fund einen Parameter enthalten, die iteratorin der folgenden Form aufgerufen werden: {iMin, iMax}where iMinund iMaxare integer. Sie sollten sich finnerhalb 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!!!


Das ist fantastisch! +1 Allerdings verstehe ich nicht wirklich, wie Tabledas hier funktioniert. Soll Ihr Beispiel sein Table(f, {x, 0, 5})? Ich verstehe auch überhaupt nicht den Zweck x, da es nur die Funktion auf den Bereich anwendet.
kirbyfan64sos

@ kirbyfan64sos Danke! Ja, das war ein Tippfehler, ich habe x in als Referenz zu mathematica belassen, das es als symbolische Schönheit verwendet, aber ich denke, ich kann es
rausholen

Noch eine Frage: Wie benennen wir die Funktionen? Müssen wir ihnen exakt dieselben Namen geben? Einzelner Buchstabe?
kirbyfan64sos

@ kirbyfan64sos Da es sich um Code-Golf handelt, erlaube ich Namen mit einem Buchstaben. In Ihrer Antwort setzen Sie jedoch eine Überschrift über jede Funktion, damit wir wissen, um welche es sich handelt. Verwenden Sie auch keine kollidierenden Buchstaben.
WizardOfMenlo

Könnten Sie genauer festlegen, was als Schleife gilt?
24.

Antworten:


9

Haskell, viele frühere Bytes zählen 127 * 0,9 = 114,3 Bytes

f#(a:b)=f a:f#b;f#x=x
(f&x)0=x;(f&x)i=f$f&x$i-1
i=id
r x=i%(1,x)
(g?x)(a:b)=g(g?x$b)a;(g?x)y=x
f%(a,b)|a>b=[]|1<2=f a:f%(a+1,b)

Keine Schleifen, nur Rekursion.

#ist karte: (*2) # [1,2,3]->[2,4,6]

&ist nest: ((*2) & 3) 4->48

iist zutreffend: i (*2) 7->14

ris 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.

f # (a:b) = f a : f#b        -- map on a list (a->head, b->tail) is f a in front of mapping f to b
f # x     = x                -- map on the empty list is the empty list
                             -- (non empty lists are caught in the line before) 

(f & x) 0 = x                -- nesting zero times is x
(f & x) i = f $ f&x $ i-1    -- nesting i times is f (nesting one time less)

i=id                         -- apply in Haskell is just the identity function 

r x = i % (1,x)              -- defined via the "table" of the identity function from 1 to x

(g ? x) (a:b) = g (g?x$b) a  -- folding g into a list (a->head, b->tail) is g applied to (folding g into b) and a
(g ? x) y     = x             -- folding the empty list is x
                             --  again, y must be the empty list, else it would have been handled by the previous line

f % (a,b)                    
  |a>b       = []                -- if iMin is greater than iMax, the table is empty
  |otherwise = f a : f%(a+1,b)   --  otherwise f a in front of the table with iMin increased by one

Vielen Dank an @dfeuer und @Zgarb für einige nützliche Hinweise


Ich bin neu bei haskell, es sieht ganz gut aus. Könntest du bitte eine Erklärung zu dem hinzufügen, was du tust?
WizardOfMenlo

1
@WizardOfMenlo: Einige Kommentare hinzugefügt
nimi

Ich habe gerade gemerkt, wie elegant Haskell ist, wirklich gut!
WizardOfMenlo

1
Unendliche Listen und Effizienz ignorieren m#q=reverse$f((:).m)[]q. Dies ist die gleiche Länge wie Ihre, aber viel schwerer zu lesen.
Dienstag,

Sie können verkürzen , !indem sie einen Namen anstelle eines Operators: i f=f.
Dienstag,

5

Python 2, 305,1 Byte (-10% 376 369 366 349 339 Byte)

exec'e=eval;q=len;m=@,l:e("["+"f(l.pop()),"*q(l)+"][::-1]");n=@,x,l:e("f("*l+"*x"+")"*l);r=@:e("r(f-1)+"*(f>1)+"[f]");a=@,a:e("f(a["+`r(q(a))`[1:-1]$",","-1],a[")+"-1])");f=@,x,l:e("f("*q(l)+"x,["+`r(q(l))`[1:-1]$",","-1]),l[")+"-1])");t=@,n,x:e("[f("+`r(x)[n-1:]`$",","),f(")[1:-1]+")]")'.replace("@","lambda f").replace("$",".replace(")

Wenn erweitert, äquivalent zu:

e=eval;q=len
m=lambda f,l:e("["+"f(l.pop()),"*q(l)+"][::-1]")
n=lambda f,x,l:e("f("*l+"*x"+")"*l)
r=lambda i:e("r(i-1)+"*(i>1)+"[i]")
a=lambda f,a:e("f(a["+`r(q(a))`[1:-1].replace(",","-1],a[")+"-1])")
f=lambda f,x,l:e("f("*q(l)+"x,["+`r(q(l))`[1:-1].replace(",","-1]),l[")+"-1])")
t=lambda f,n,x:e("[f("+`r(x)[n-1:]`.replace(",","),f(")[1:-1]+")]")

Keine Schleifen!

Nun, es macht eine Menge evalund wenn Ihr Chef Schleifen nicht aushält, dann werden sie EVALUIEREN. Aber sie werden sich damit abfinden müssen

Ein Weg, rangein 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]")
    • Erstellen Sie einen String, der Elemente aus der Liste aufnimmt, in eine Liste einwickelt, umkehrt und schließlich auswertet!
  • n=lambda f,x,l:eval("f("*l+"*x"+")"*l)
    • Erstellen Sie die Zeichenfolge mit der Verschachtelung manuell und bewerten Sie sie!
  • r=lambda i:e("r(i-1)+"*(i>1)+"[i]")
    • Erstellen Sie eine Zeichenfolge, die bei Bearbeitung die vorherigen Ergebnisse evalzurü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])")
    • Verwendet die Bereichsfunktion, um die Indizes 1-len (Liste) abzurufen. Ersetzt die Kommas in der Liste durch eine Methode, um den korrekten Index der Liste zu erhalten a. Bewerte es!
  • f=lambda f,x,l:eval("f("*len(l)+"x,["+r (len (l))[1:-1].replace(",","-1]),l[")+"-1])")
    • Das Gleiche gilt, außer dass die Kommas durch schließende Klammern und Kommas ersetzt werden und der Listenindex gestartet wird.
  • t=lambda f,n,x:eval("[f("+r (x) [n-1:].replace(",","),f(")[1:-1]+")]")
    • Entspricht apply und fold, ersetzt jedoch durch Beenden der Funktion und Aufrufen der neuen Funktion. Bewerte es!

Map, nest, range, apply, fold, table.

Danke @Zgarb für ein Lambda für Reichweite!


Mein Chef wird meinen Kopf auf seinem Schreibtisch haben :) Könnten Sie bitte auch eine kurze Erklärung hinzufügen?
WizardOfMenlo

Wie wäre es r=lambda i:[]if i<1 else r(i-1)+[i]? Keine Schleifen, nur Rekursion.
Zgarb,

1
Klar, ich nehme das erstmal an, aber der Chef braucht mehr eval, um ihnen zu zeigen, dass Schleifen nicht so schlimm sind :)
Blau

Ha! Eine andere Version mit e=eval:r=lambda i:e("r(i-1)+"*(i>1)+"[i]")
Zgarb

Können Sie den Bonus von 60% auf 10% ändern? Ich habe die
Fragenspezifikation

5

Javascript ES6, 197 * 0,9 = 177,3 Byte

M=(f,l)=>F((a,b)=>[...a,f(b)],[],l)
N=(f,x,n)=>f(--n?N(f,x,n):x)
A=(f,l)=>f(...l)
R=n=>n--?[...R(n),n+1]:[]
F=(f,x,l,n=l.length)=>n--?f(F(f,x,l,n),l[n]):x
T=(f,i)=>([n,x]=i,M(q=>f(q+n-1),R(x-n+1)))

Karte ( M=(f,l)=>F((a,b)=>[...a,f(b)],[],l)):

Mit Fold können Sie die fauf jedes Mitglied von angewendeten Ergebnisse lauf eine leere Liste setzen. Die Verwendung von eingebauten Funktionen reduziert dies auf M=(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)):

fRekursiv anwenden, bis nauf 0 dekrementiert wird.

Übernehmen ( A=(f,l)=>f(...l)):

Verwendet den ...Operator spread ( ), auf den langewendet werden soll f.

Bereich ( R=n=>n--?[...R(n),n+1]:[]):

Konzentrieren Sie sich nauf den rekursiven Aufruf von Range, bis nauf 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 von lto funtil nwird auf 0 dekrementiert. Die Verwendung integrierter Funktionen reduziert dies auf F=(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 nund xauf Imin und Imax Verwendung Destrukturierung ( [n,x]=i), verwendet Bereich die Tabelle der Werte von Imin bis Imax zu konstruieren. fwird dann mit Map auf die Tabelle angewendet und das Ergebnis zurückgegeben.


Willst du meine Philosophie kennen? "Wenn es billig ist, kauf es." In den technischen Daten steht nicht, dass Sie Builtins (noch) nicht verwenden können, also verwenden Sie sie!
Mama Fun Roll

4

Python 3, 218 Bytes

Die unlesbare Version:

exec("P!:[f(_)for _ in x];Y!,z:Y(f,f(x),z-1)if z else x;T!:f(*x);H!=0:(H(f-1)if~-f else[])+[f];O!,z:O(f,f(x,z[0]),z[1:])if z else x;N!:(N(f,[x[0],x[1]-1])if x[1]-x[0]else[])+[f(x[1])]".replace("!","=lambda f,x"))

Die (mehr) lesbare Version:

P=lambda f,x:[f(_)for _ in x]
Y=lambda f,x,z:Y(f,f(x),z-1)if z else x
T=lambda f,x:f(*x)
H=lambda f,x=0:(H(f-1)if~-f else[])+[f]
O=lambda f,x,z:O(f,f(x,z[0]),z[1:])if z else x
N=lambda f,x:(N(f,[x[0],x[1]-1])if x[1]-x[0]else[])+[f(x[1])]

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 zNull erreicht ist f. 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 komprimiere exec, ersetzen kann, =lambda f,xanstatt 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 execmit einem umhüllt replace, um die Byteanzahl deutlich zu verkürzen.


Ich wollte gerade einen Kommentar [f(_)for _ in x]map(f,x)
abgeben

4

Julia, 181 Bytes

Kein Bonus für mich; Ich habe großzügig mit Loops gearbeitet. Sorry Boss, aber Loops in Julia sind effizient!

M(f,x)=[f(i...)for i=x]
N(f,x,n)=(for i=1:n x=f(x...)end;x)
A(f,x)=f(x...)
R(n)=(i=0;x={};while i<n push!(x,i+=1)end;x)
F(f,x,a)=(for b=a x=f(x,b)end;x)
T(f,i)=[f(j)for j=i[1]:i[2]]

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:

  • Karte: M
  • Nest: N
  • Sich bewerben: A
  • Reichweite: R
  • Falten: F
  • Tabelle: T

4

Tinylisp , 325 × 0,9 = 292,5

Die Sprache ist neuer als die Frage, aber sie wird trotzdem nicht gewinnen.

(d @(q(a a)))(d Q(q((l)(i l(c(@(q q)(h l))(Q(t l)))l))))(d A(q((f a)(v(c(q f)(Q a))))))(d M(q((f l)(i l(c(A f(@(h l)))(M f(t l)))l))))(d N(q((f a x)(i x(A f(@(N f a(s x 1))))a))))(d ,(q((m a b)(i(l b a)m(,(c b m)a(s b 1))))))(d R(q((a)(,()1 a))))(d T(q((f r)(M f(A ,(c()r))))))(d F(q((f a l)(i l(F f(A f(@ a(h l)))(t l))a))))

Definiert die Funktionen A(Apply), M(Map), N(Nest), R(Range), T(Table) und F(Fold) sowie einige Hilfsfunktionen. Terwartet 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) und i(if) als Alias ​​verwendet .)

(d define d)
(define cons c)
(define car h)
(define cdr t)
(define subtract s)
(define less l)
(define eval v)

(define lambda
  (q (()
      (arglist expr)
      (list arglist expr))))

(define list (lambda args args))

(define quote-all
  (lambda (lyst)
    (i lyst
       (cons
         (list (q q) (car lyst))
         (quote-all (cdr lyst)))
       lyst)))

(define Apply
  (lambda (func arglist)
    (eval (cons (q func) (quote-all arglist)))))

(define Map
  (lambda (func lyst)
    (i lyst
       (cons
         (Apply func (list (car lyst)))
         (Map func (cdr lyst)))
       lyst)))

(define Nest
  (lambda (func arg times)
    (i times
       (Apply func
              (list (Nest func arg (subtract times 1))))
       arg)))

(define range*
  (lambda (accumulator a b)
    (i (less b a)
       accumulator
       (range* (cons b accumulator) a (subtract b 1)))))

(define Range
  (lambda (x)
    (range* 1 x)))

(define Table
  (lambda (func iterator)
    (Map func
         (Apply range* (cons () iterator)))))

(define Fold
  (lambda (func arg lyst)
    (i lyst
       (Fold func
             (Apply func (list arg (car lyst)))
             (cdr lyst))
       arg)))

Weitere Erläuterungen auf Anfrage.

Beispielausgabe

Verwendet die REPL-Umgebung aus meiner Referenzimplementierung. Ich habe q(quote) für die unäre Funktion und s(subtrahieren) als binäre Funktion für diese Beispiele sowie die Funktion @(in diesem Code definiert) verwendet, die eine Liste ihrer Argumente zurückgibt.

tl> [line of definitions goes here]
@
Q
A
M
N
,
R
T
F
tl> (A s (@ 10 7))
3
tl> (M q (@ 1 2 3 4))
((q 1) (q 2) (q 3) (q 4))
tl> (N q 123 4)
(q (q (q (q 123))))
tl> (R 5)
(1 2 3 4 5)
tl> (T q (@ 3 7))
((q 3) (q 4) (q 5) (q 6) (q 7))
tl> (F s 10 (@ 4 3 2))
1

2

Python 2.x: 450,6 Bytes (493 Bytes vor 10% Rabatt)

Golf Antwort:

y=len
z=lambda a,b:a.append(b)
_=lambda a:a if a is not None else[]
def M(a,b,c=None):
 c=_(c);d=y(b)
 if d:z(c,A(a,b[0]))
 return M(a,b[1:],c)if d else c
def N(a,b,c):d=A(a,b);return N(a,d,c-1)if c>1 else d
A=lambda a,b:a(*b)if type(b)is list else a(b)
def R(a,b=None):b=_(b);b.insert(0,a);return b if a<=1 else R(a-1,b)
def F(a,b,c):d=a(b,c[0]);return F(a,d,c[1:])if y(c)>1 else d
def T(a,b,c=None,d=None):
 if c is None:c=b[0];d=[]
 z(d,a(c));return T(a,b,c+1,d)if c<b[1]else d

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:

A = lambda function, arguments: function(*arguments) if type(arguments) is list else function(arguments)

Map:

def M(function, arguments, result=None):
    result = result if result is not None else []
    length = len(arguments)
    if length != 0:
        result.append(A(function, arguments[0]))
    return M(function, arguments[1:], result) if length != 0 else result

Nest:

def N(function, arguments, times):
    result = A(function, arguments)
    return N(function, result, times - 1) if times > 1 else result

Beachten Sie, dass diese Funktion erfordert, dass das übergebene functionArgument 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:

def R(ceiling, result=None):
    result = result if result is not None else []
    result.insert(0, ceiling)
    return result if ceiling <= 1 else R(ceiling - 1, result)

Fold:

def F(function, initial, rest):
    result = function(initial, rest[0])
    return F(function, result, rest[1:] if len(rest) > 1 else result

Table:

def T(function, iterator, current=None, result=None):
    if current is None:
        current = iterator[0]
        result = []
    result.append(function(current))
    return T(function, iterator, current + 1, result) if current < iterator[1] else result

Hier ist eine Beispielausgabe mit den folgenden Hilfsfunktionen:

square = lambda x: x * x
def add(*args):
    addTwo = lambda a, b: a + b
    if len(args) == 1 and type(args[0]) is list:
        return F(addTwo, 0, args[0])
    else:
        return F(addTwo, 0, args)

>>> M(square, R(10))
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> M(add, [R(i) for i in R(10)])
[1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
>>> T(square, [0, 10])
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> N(square, 2, 4)
65536
>>> N(lambda *args: F(lambda a, b: a * b, 1, args) if len(args) > 1 else str(args[0]) + 'a', R(5), 10)
'120aaaaaaaaa'

Wow, sieht echt gut aus!
WizardOfMenlo

Das scheint ein verzerrter Sinn für Ästhetik zu sein. Ich finde es immer amüsant, Golf-Python zu sehen, seit das erste Python-Buch, das ich las, darüber sprach, wie Python die Lesbarkeit erzwingt.
Sadakatsu

Ich habe in der Tat einen verzerrten Sinn für Ästhetik :)
WizardOfMenlo

Die Ergebnisse anderer Leute verwirren mich. Ich habe 10% der Punktzahl für jede der erforderlichen Funktionen genommen, bei denen keine Schleife verwendet wurde (das war alles), aber andere Leute haben 10% der Gesamtpunktzahl für jede Funktion genommen, bei der keine Schleife verwendet wurde (das kann sein) bis zu 60% Rabatt). Welches ist der richtige Ansatz?
Sadakatsu

Ihr Weg ist der richtige, ich hatte eine unrealistische Erwartung und so dachte ich anfangs an den 60% -Ansatz, aber jetzt denke ich, dass die 10% anregender und der bessere Abstand zwischen den beiden sind
WizardOfMenlo,

2

Ceylon, 370 · 0,9 = 333, 364 · 0,9 = 327,4

Die 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.

alias I=>Integer;R[]m<A,R>(R(A)g,A[]l)=>f((R[]x,A y)=>x.append([g(y)]),[],l);A n<A>(A(A)g,A a,I t)=>f((A x,I y)=>g(x),a,r(t));R y<A,R>(Callable<R,A>g,A v)given A satisfies Anything[]=>g(*v);I[]r(I i)=>t((j)=>j,[1,i]);A f<A,O>(A(A,O)g,A a,O[]o)=>if(nonempty o)then f(g,g(a,o[0]),o.rest)else a;R[]t<R>(R(I)g,[I,I]i)=>i[1]<i[0]then[]else[g(i[0]),*t(g,[i[0]+1,i[1]])];

Tatsächlich verwenden nur zwei der Funktionen ( tund f) 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ür Sequential<R>- aus irgendeinem Grund können wir es auch schreiben R[], was ein Byte kürzer ist.

Ein Funktionstyp ist Callable<R, A>, wo Aist ein Tupeltyp für die Argumente, wie [X, Y, Z](dh ein Subtyp von Anything[]). Als Abkürzung können wir R(X,Y,Z)statt schreiben Callable<R,[X,Y,Z]>.

Ich aliased Integerals Izu speichern einige Bytes.

Hier ist eine formatierte (und leicht kommentierte) Version:

// implement functional paradigms
//
// Question: http://codegolf.stackexchange.com/q/58588/2338
// My Answer: http://codegolf.stackexchange.com/a/64515/2338

alias I => Integer;

// map – based on fold.
R[] m<A, R>(R(A) g, A[] l) =>
        f((R[]x,A y) => x.append([g(y)]), [], l);

// nest – based on fold + range, throwing away the second
//        argument in a proxy function.
A n<A>(A(A) g, A a, I t) =>
        f((A x, I y) => g(x), a, r(t));

// apply – this looks quite heavy due to type safety.
//         This uses the "spread operator" *.
R y<A, R>(Callable<R,A> g, A v)
        given A satisfies Anything[] =>
        g(*v);

// range – based on table (using the identity function)
I[] r(I i) =>
        t((j) => j, [1, i]);

// fold – a plain list recursion.
A f<A, O>(A(A, O) g, A a, O[] o) =>
        if (nonempty o) then f(g, g(a, o[0]), o.rest) else a;

// table – an integer recursion.
//        (Not sure why the min/max parameters need
//         to be passed in one argument.)
R[] t<R>(R(I) g, [I, I] i) =>
        i[1] < i[0] then [] else [g(i[0]), *t(g, [i[0] + 1, i[1]])];

Verwenden von "Schleifen"

Tabelle und Map können mit Schleifen kürzer implementiert werden (eigentlich ein Sequenzverständnis):

// map – using a sequence comprehension:
R[] m<A, R>(R(A) g, A[] l) =>
        [for(a in l) g(a)];

// table – map with an integer range.
//        (Not sure why the min/max parameters need
//         to be passed in one argument.)
R[] t<R>(R(I) g, [I, I] i) =>
        m(g, i[0]..i[1]);

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:

alias I=>Integer;R[]m<A,R>(R(A)g,A[]l)=>[for(a in l)g(a)];A n<A>(A(A)g,A a,I t)=>f((A x,I y)=>g(x),a,r(t));R y<A,R>(Callable<R,A>g,A v)given A satisfies Anything[]=>g(*v);I[]r(I i)=>t((j)=>j,[1,i]);A f<A,O>(A(A,O)g,A a,O[]o)=>if(nonempty o)then f(g,g(a,o[0]),o.rest)else a;R[]t<R>(R(I)g,[I,I]i)=>m(g,i[0]..i[1]);

(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ür rund t(mit den moben genannten) verwenden:

// range – based two-limit range 
I[] r(I i) =>
        q(1, i);

// two-limit range implemented recursively
I[] q(I i, I j) =>
        j < i then [] else [i, *q(i + 1, j)];


// table – map with an integer range.
//        (Not sure why the min/max parameters need
//         to be passed in one argument.)
R[] t<R>(R(I) g, [I, I] i) =>
        m(g, q(i[0], i[1]));

Dies ergibt 348 Bytes, besser als die vollständig rekursive Version, jedoch nicht nach Anwendung des Bonus.


0

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.

m={f,l->l.collect{f(it)}}            // Map
n={f,x,n->n.times{x=f(x)};x}         // Nest
a={f,l->f(l)}                        // Apply
r={1..it}                            // Range (Is this cheating?)
f={f,x,l->l.each{x=f(x,it)};x}       // Fold
t={f,l->(l[0]..l[1]).collect{f(it)}} // Table

Beispiel Eingabe / Ausgabe

f1={2*it}
f2={a,b,c,d,e->a*b*c*d*e}
f3={a,b->a*b}
l=[1,2,3,4,5]
l2=[1,9]
y=5
x=1
println m(f1,l)
println n(f1,x,y)
println a(f2,l)
println r(y)
println f(f3,x,l)
println t(f1,l2)

Ausgabe

MAP:   [2, 4, 6, 8, 10]
NEST:  32
APPLY: 120
RANGE: [1, 2, 3, 4, 5]
FOLD:  120
TABLE: [2, 4, 6, 8, 10, 12, 14, 16, 18]

Probieren Sie es selbst aus: https://groovyconsole.appspot.com/edit/5203951758606336


Dies verwendet technisch gesehen keine Schleifen, denken Sie also an den Bonus! Sonst tolle Antwort!
WizardOfMenlo

Technisch keine Schleifen ?! Ja wirklich?! .each {} .times {} .collect {} sind Iteratoren.
Magic Octopus Urn
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.