İşlevsel programlama paradigmalarını uygulamak


21

Şirketiniz henüz yeni bir projeye başlıyor ve ilk defa fonksiyonel bir programlama kodu stili kullanmaya karar verdiniz. Bununla birlikte, patronunuz gerçekten çok farklı ve yerleşik işlevleri kullanmak istemiyor ve kendinize ana işlevleri uygulamanızı istiyor. Özellikle sen fonksiyonlarını yazmak gerekir: Map, Nest, Apply, Range, FoldveTable seçimi ile ilgili bir dilde. Patron gerçekten meşgul bir adam ve programları olabildiğince kısa yapmak istiyor, bu yüzden zamanını boşa harcamıyor. Ayrıca döngü kullanmamanızı istiyor, bu nedenle döngü kullanmadığınız için bayt sayısında% 10'luk bir düşüşe sahip olacaksınız.

İşlevlerin ayrıntılı gereksinimleri aşağıdadır:

harita

Mapİşlevi, iki parametre alır: fve listnerede fbir fonksiyondur ve listdeğerlerin bir listesidir. fUygulamayı her elemanına geri döndürmelidir list. Dolayısıyla bu şekilde çalışacak:

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

döner

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

ve

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

döner

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

yuva

Nest: İşlev de üç parametre alır f, arg, timesnerede f, bir işlevdir argonun başlangıç argümanı ve timesfonksiyon uygulanır kaç katıdır. fUygulanan timessüreleri olan bir ifade döndürmelidir arg. Dolayısıyla bu şekilde çalışacak:

Nest(f, x, 3)

döner

f(f(f(x)))

ve

Nest(f, {a,b}, 3)

döner

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

Uygulamak

Applyİşlevi, iki parametre alır: fve argsnerede fbir fonksiyonu ve olan argsbir liste. Bu başvurmalıdır fiçin args. Bu nedenle:

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

döner

f(a,b,c)

menzil

RangeFonksiyonu tek tamsayı alır rve o numaraya kadar tamsayılar çıkarır. Bu nedenle:

Range(5)

döner

{ 1, 2, 3, 4, 5}

Kat

FoldFonksiyon üç parametre alır f, arg, othersnerede fbir fonksiyondur, argbasit parametre ve olan othersbir liste. Bu şekilde çalışacak:

Fold(f, x, {a, b, c, d})

döner

f(f(f(f(x,a),b),c),d)

tablo

Tablo işlevleri bir işlev fve iteratorbiçim olarak adlandırılan bir parametre almalıdır : {iMin, iMax}where iMinve iMaxinteger. fBelirtilen aralıkta başvurmalısınız . Bu nedenle:

Table(f, {0, 5})

döner

{f(0), f(1), f(2), f(3), f(4), f(5)}

Bu fonksiyonların tanımını Mathematica fonksiyonel programlama sayfasından kullandım , bu nedenle daha fazla rehberliğe ihtiyacınız olursa oraya gidin. Bu sayfada gösterilen fonksiyonların tüm versiyonlarını uygulamanıza gerek kalmayacağına, sadece bu yazıya yazılanlara dikkat edin.

Standart Loopholes'a her zamanki gibi izin verilmez.

Dilinizin işlevlerin argüman olarak iletilmesine izin vermemesi durumunda, bu özelliği uygulamanız ve cevabınıza eklemeniz gerekir. Bununla birlikte, bu işlemin bayt sayısı topluma eklenmeyecektir.

Bu kod golf yani en kısa kod kazanır. İyi şanslar!!!


Bu harika! +1 Ancak, Tableburada nasıl çalıştığını gerçekten anlamadım . Örneğiniz Table(f, {x, 0, 5})mi olmalı ? Ayrıca x, işlevi yalnızca aralığa uyguladığı için de hiçbir amaç elde edemiyorum .
kirbyfan64sos

@ kirbyfan64sos Teşekkürler! Evet bu bir yazım hatası oldu, x'i, onu sembolik özellik olarak kullanan matematiğe referans olarak bıraktım, ancak çıkartabileceğimi düşünüyorum
WizardOfMenlo 24/15

Bir soru daha: fonksiyonları nasıl isimlendiririz? Onlara aynı isimleri vermek zorunda mıyız? Tek harfli?
kirbyfan64sos

@ kirbyfan64sos Kod golf olduğundan, tek harfli adlara izin vereceğim, ancak cevabınızda her bir fonksiyona bir başlık koyarız, böylece hangisinin olduğunu öğreniriz. Ayrıca çarpışan harfler kullanmayın.
WizardOfMenlo 24:15

Döngü olarak neyin önemli olduğu konusunda daha spesifik olabilir misiniz?
xnor

Yanıtlar:


9

Haskell, önceki birçok bayt, 127 * 0.9 = 114.3 bayt sayıyor

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)

Döngü yok, sadece özyineleme.

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

&yuva: ((*2) & 3) 4->48

igeçerlidir: i (*2) 7->14

raralık: r 4->[1,2,3,4]

?katlanır: ((+) ? 0) [1,2,3,4]->10

%tablodur: (*2) % (2,4)->[4,6,8]

İsteği gibi yorumlar ile ungolfed versiyonu. Not &ve ?çağrıldığında veya desen eşlendiğinde ek parantez gerektiren üçlü ek işleç operatörleridir.

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

Bazı yararlı ipuçları için @ dfeuer ve @ Zgarb'a teşekkürler


Ben haskell için yeniyim, oldukça iyi görünüyor, ancak ne yaptığınıza bir açıklama ekler misiniz?
WizardOfMenlo 24:15

1
@WizardOfMenlo: bazı yorumlar ekledi
nimi

Haskell'in ne kadar zarif olduğunu farkettim, gerçekten iyi!
WizardOfMenlo 24:15

1
Sonsuz listeleri ve verimliliği gözardı etmek m#q=reverse$f((:).m)[]q,. Bu sizinkiyle aynı uzunluktadır ancak okunması daha zordur.
dfeuer

Sen kısaltabilir !bir operatörün yerine bir isim yaparak: i f=f.
dfeuer

5

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

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(")

Genişletildiğinde, eşdeğer:

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]+")]")

Döngü yok!

Pekala, çok fazla evaliniş yapıyor ve eğer patronunuz döngülere dayanamıyorsa, o zaman HATE değerlendirmesinden nefret edecekler. Ama buna katlanmak zorunda kalacaklar

Bir rangelambda yapmanın bir yolu takdir edildiğinden herhangi bir fonksiyon yapmam gerekmiyor (Shudder.).

açıklamalar:

  • m=lambda f,l:eval("["+"f(l.pop()),"*len(l)+"][::-1]")
    • Listedeki öğeleri açan bir dize oluşturun, listeye kaydırın, ters çevirin ve sonunda değerlendirin!
  • n=lambda f,x,l:eval("f("*l+"*x"+")"*l)
    • İç içe yerleştirme ile dizeyi el ile oluşturun ve değerlendirin!
  • r=lambda i:e("r(i-1)+"*(i>1)+"[i]")
    • evalEd olduğunda [0]önceki sonuçları elde etmek için özyinelemeyi geri döndüren veya kullanan ve geçerli dizini listeye ekleyen bir dize oluşturun . Onu değerlendirir.
  • a=lambda f,a:eval("f(a["+R (len (a)),[1:-1].replace(",","-1],a[")+"-1])")
    • İndeksleri 1-len (list) almak için range işlevini kullanır. Doğru dizini listedeki virgül ile listenin doğru dizinini almak için değiştirir a. Değerlendirir!
  • f=lambda f,x,l:eval("f("*len(l)+"x,["+R (len (I))[1:-1].replace(",","-1]),l[")+"-1])")
    • Kapatma parantezleri, virgüller ve liste dizinini başlatma ile virgül yerine koyma hariç, aynısı geçerlidir.
  • t=lambda f,n,x:eval("[f("+R (x) [N-1:].replace(",","),f(")[1:-1]+")]")
    • Uygula ve kapat ile aynı, işlevi sonlandırıp yenisini çağırmak yerine değiştirir. Değerlendirir!

Harita, yuva, aralık, uygulama, katlama, tablo.

Menzil için lambda için teşekkürler @ Zgarb!


Patronum kafamın masasında olacak :) Kısa bir açıklama ekler misiniz lütfen?
WizardOfMenlo

Ne dersiniz r=lambda i:[]if i<1 else r(i-1)+[i]? Döngü yok, sadece özyineleme.
Zgarb 24:15

1
Tabii ki, bunu şimdilik alacağım ama patronların evalnasıl döngülerin o kadar da kötü olmadığını gösterebilmeleri için daha fazlasına ihtiyacı var :)
Blue

Ha! Başka bir sürüm kullanarak e=eval:r=lambda i:e("r(i-1)+"*(i>1)+"[i]")
Zgarb 24:15 '

Lütfen% 60 bonusdan% 10'a değiştirebilir misiniz? Soru şartnamesini gözden geçirdim, bu yüzden daha adil hale getirmek için
WizardOfMenlo 24:15

5

Javascript ES6, 197 * 0.9 = 177.3 bayt

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)))

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

Kullanımları katlayın sonuçlarını Concat için fher üyesi uygulanan lboş bir listeye üzerine. Yerleşik işlevlerin M=(f,l)=>l.map(f)kullanılması bunu azaltır (ucuz göründüğü için kullanmadın mı…?).

Yuva ( N=(f,x,n)=>f(--n?N(f,x,n):x)):

0'a findirilinceye kadar ntekrarlı olarak uygulayın .

Uygula ( A=(f,l)=>f(...l)):

Yayılma (Kullanımları ...uygulamak için) operatörü lüzerine f.

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

Concat nözyinelemeli çağrısına Range kadarn 0 .

Kat ( F=(f,x,l,n=l.length)=>n--?f(F(f,x,l,n),l[n]):x):

Recursive çağrıyı uygular Katlama ve niçinde 'inci elemanı liçin fkadar nyerleşik işlevleri için bu azaltır kullanma 0'a indirildiğiF=(f,x,l)=>l.reduce(f,x) (yine ucuz görünüyordu ...).

tablo ( T=(f,i)=>([n,x]=i,M(q=>f(q+n-1),R(x-n+1)))):

Öncelikle nve xiMin ve iMax'ı destructuring ( [n,x]=i) kullanarak başlatır , ardından iMin'den iMax'a kadar olan değerler tablosunu oluşturmak için Range kullanır . fDaha sonra Harita kullanılarak masanın üzerine uygulanır ve sonuç döndürülür.


Felsefemi bilmek ister misin? "Ucuzsa, satın al." Teknik özelliklerde (henüz) yerleşik yapamayacağınız söylenmiyor, öyleyse onları kullanın!
Mama Fun Roll

4

Python 3, 218 bayt

Okunamayan sürüm:

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"))

(Daha fazla) okunabilir versiyonu:

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])]

Her seferinde bir lambda olsa da:

Harita fonksiyonu P

P=lambda f,x:[f(_)for _ in x]
Sadece basit bir yineleyici. Burada söylenecek fazla bir şey yok.

Yuva fonksiyonu Y

Y=lambda f,x,z:Y(f,f(x),z-1)if z else x
Her seferinde zuygulayarak sıfıra kadar tekrarlar f. Sonunda if cümlesi tıkalı hissediyor; Belki de özyinelemeye son vermenin daha iyi bir yolu var.

Uygulama fonksiyonu T

T=lambda f,x:f(*x)
Python'un tüm ağır yükleri benim için yapması için hoş bir genişleme operatörü bulunuyor.

Menzil işlevi H

H=lambda f,x=0:(H(f-1)if~-f else[])+[f]
Bu beklediğimden daha zordu. Özyinelemeli bir yaklaşımla sona erdi. Yine, if-else inşası çok fazla bayt alır ve geliştirilebileceğini düşünüyorum. Neden bir kukla x=0var soruyorsun? Öyle sıkıştığımda exec, yerini alabilirim=lambda f,x onun yerine sadece=lambda f .

Kat fonksiyonu O

O=lambda f,x,z:O(f,f(x,z[0]),z[1:])if z else x
Bununla çok mutluyum. Sadece tekrar başladığında dizinin ilk elemanını bırakıp hiçbir şey kalmayacak.

Masa fonksiyonu N

N=lambda f,x:(N(f,[x[0],x[1]-1])if x[1]-x[0]else[])+[f(x[1])]
Bu korkunç ve iyileştirilmesi için yer olduğuna eminim. Daha önce bir map(f,range(x,y))çeşit inşaat için tanımlanmış aralık ve harita işlevlerini kullanmaya çalıştım , ancak çok başarılı olmadı. Çok korkunç bir şey yapıyorRange işleviyle benzerliği paylaşan özyinelemeli yaklaşım .

Tüm lambdalar byte sayısını önemli ölçüde kısaltmak için execa ile sarılır replace.


Bunun [f(_)for _ in x]kısaltılabileceği konusunda yorum yapmak üzereydim map(f,x), ama daha sonra zorluğun ne olduğunu hatırladım
Cyoce

4

Julia, 181 bayt

Benim için bonus yok; Döngüleri liberal olarak kullandım. Üzgünüm patron, ama Julia'daki döngüler verimli!

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]]

Bir argümandan sonra elipsleri bir işleve eklemek bir diziyi, diziyi ya da normal işlev argümanlarına neyin girdiğini kırar. Aksi taktirde, işlev bir dizi (veya demet vb.) İletmeye çalıştığınızı düşünecektir. Tek bağımsız değişkenler için bir etkisi yoktur.

İşlev isimleri:

  • Harita: M
  • Nest: N
  • Uygulamak: A
  • aralık: R
  • Kat: F
  • Tablo: T

4

tinylisp , 325 * 0.9 = 292.5

Dil sorudan daha yeni, ancak yine de kazanamayacak.

(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))))

A(Uygula), M(harita), N(yuva), R(aralık) fonksiyonlarını tanımlar.TFBir çift yardımcı işlevle birlikte (tablo) ve (katla) .Tikinci argümanı için iki tamsayı listesi bekler.

Tinylisp'in hiçbir döngü yapısı bile yoktur; her şey özyineleme kullanılarak gerçekleştirilir. Bu işlevlerin birçoğu değil özyinelemeli , bu nedenle büyük listelerde çağırırsanız büyük olasılıkla çağrı yığınını patlatacaktır. Hepsi kuyruk özyinelemeli olarak uygulanabilirdi ... ama daha fazla bayt alacaktı ve bu kod golf.

İşte Lisp ile aşina olmanız durumunda oldukça okunaklı olması gereken beyaz boşluklu ve isimler için gerçek kelimeleri olan genişletilmiş bir sürümü. ( q(Alıntı) ve i(eğer) hariç, tinylisp yapılarının çoğunu diğer adlarıyla değiştirdim )

(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)))

Talep üzerine daha fazla açıklama yapılabilir.

Örnek çıktı

Referans uygulamamdan REPL ortamını kullanır. Kullandığım qtekli işlevi hem de (tırnak) sBu örnekler için, ikili bir fonksiyona, hem de fonksiyonu olarak (çıkarma) @bağımsız değişkenler bir listesini verir (bu kodunda tanımlanan).

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 bayt (% 10 indirimden önce 493 bayt)

Golf cevap:

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

Bu soru eğlenceliydi. İşlevlerimi Python eşdeğerlerini kullanmadan yazmaya (bu geçerli bir boşluk olmasına rağmen) ve işlevleri Python'un kuyruk özyinelemesini destekliyormuş gibi yazmaya karar verdim. Bu işi yapmak için, gerekli çağrıların hala çalışmasına izin veren birçok isteğe bağlı parametre kullandım.

Aşağıda her işlev için listelenen ilanlar var.

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

Bu işlevin, iletilmenin functiondeğişken olarak birden fazla argümanı temsil etmesini gerektirdiğini unutmayın . Başka bir yaklaşım, işlevin her zaman tek bir liste almasını zorunlu kılmaktı, ancak bu, iletilen işlevlerin argüman listelerini yorumlayabilmesini gerektirecekti. Her iki şekilde de varsayımlar vardı, bu yüzden sistemin geri kalanına daha uygun olanı seçtim.

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

Aşağıdaki yardımcı fonksiyonları kullanarak örnek çıktı:

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'

Vay, çok iyi görünüyor!
WizardOfMenlo 24:15

Bu, çarpık bir estetik duygusu gibi görünüyor; (Python'un okunabilirliği nasıl yürüttüğü hakkında konuştuktan sonra okuduğum ilk Python kitabından beri) golfe atılmış Python'u görmek beni her zaman eğlenceli bulur.
sadakatsu

Gerçekten
eğrilmiş bir

Diğer insanların puanlarıyla kafam karıştı. Bir döngü kullanmayan gerekli fonksiyonların her birinin puanının% 10'unu aldım (hepsiydi), fakat diğer insanlar bir döngü kullanmayan her fonksiyon için tüm puanın% 10'unu aldı (ki bu olabilir ki). % 60'a kadar indirim). Doğru yaklaşım hangisi?
sadakatsu

Sizinki doğru yol, doğru olmayan bir beklentim vardı ve başlangıçta% 60 yaklaşımı aklımdaydı, ama şimdi% 10 daha uyarıcı olacağını ve ikisinin arasında daha hafif olacağını düşünüyorum
WizardOfMenlo

2

Seylan, 370 * 0.9 = 333 364 * 0.9 = 327.4

Bu işlevlerin çoğu zaten Seylan'ın dil paketinde (bazen biraz farklı bir imzaya sahip olsa da) mevcuttur, ancak bunları burada sorulduğu gibi tanımlıyoruz.

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]])];

Aslında sadece iki işlevden ( tvef ) gerçekte özyinelemeyi kullanıyor (sırasıyla listelerde ve tamsayılarda), diğeri bunlara dayanıyor. (Uygula biraz bir aykırıdır, başkaları ile gerçekten ilişkili değildir.)

"List" i Ceylon’un Sıralı türü olarak yorumluyorum (değişmez bir düzenlenmiş (muhtemelen boş) eleman dizisi. [R*]kısaltmalar Sequential<R>- bir nedenden dolayı biz de yazabilirizR[] bir byte kısa olanı .

Bir fonksiyon türü Callable<R, A>burada, Agibi bağımsız değişkenler için bir demet türüdür [X, Y, Z](yani, bir alt-tip Anything[]). Kısayol olarak R(X,Y,Z)yerine yazabiliriz .Callable<R,[X,Y,Z]> .

Bazı baytları kurtarmak için takma ad Integerkullandım I.

İşte biçimlendirilmiş (ve biraz yorum yapılan) bir sürüm:

// 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]])];

"Döngüler" kullanma

Tablo ve Harita, döngüler kullanılarak daha kısa bir şekilde uygulanabilir (aslında, bir dizi anlama):

// 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]);

..Operatörün tamsayı aralığı için kullanılmasının yerleşik bir işlev olarak sayılıp sayılmadığından emin değilim . Eğer buna izin verilirse, sonuçta ortaya çıkan kod şudur, uzunluk 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]);

(Tanımlayarak daha da kısaltılabilir r(I i) => 1..i, skor 301'e ulaşabilir.

Eğer ..izin verilmez, tekrar uygulamak gerekir. Bu uygulamaları aşağıdakiler için kullanabiliriz ( rve bunlarla tbirlikte m):

// 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]));

Bu, tamamen özyinelemeli sürümden daha iyi, ancak bonusu uyguladıktan sonra değil, 348 baytla sonuçlanır.


0

Groovy (146 Bayt) (146 * 90% = 131.4)

PS Bu bağlamda neyin “döngü” olduğunu düşündüğünüzü bilmiyorum, bonusu yalnızca OP tarafından yapılan yorumlarda söylendikten sonra uyguladım ve 2-3 ek kullanıcı bu koleksiyon işlevlerini ve yineleyicileri söylerse kaldırır. döngüler ve bonusu haketmiyorum. Ayrıca, beni 1..it kullanımımdan çağırmak istiyorsanız, lütfen bunu yapın ve elden geçirin / bytecount'umu güncelleyeceğim.

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

Örnek Giriş / Çıkış

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)

Çıktı

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]

Kendiniz deneyin: https://groovyconsole.appspot.com/edit/5203951758606336


Bu teknik olarak döngüler kullanmaz, bu yüzden bonusu unutmayın! Başka, harika cevap!
WizardOfMenlo

Teknik olarak döngüler yok ?! Gerçekten mi?! .each {} .times {} .collect {} yineleyicidir.
Magic Octopus Urn
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.