Menerapkan paradigma pemrograman fungsional


21

Perusahaan Anda baru saja memulai suatu proyek, dan untuk pertama kalinya Anda memutuskan untuk menggunakan gaya pemrograman kode fungsional. Namun bos Anda benar-benar malu-malu dan tidak ingin menggunakan fungsi bawaan, dan mengharuskan Anda untuk menerapkan sendiri fungsi-fungsi utama. Secara khusus Anda perlu menulis fungsi: Map, Nest, Apply, Range, Folddan Tabledalam bahasa pada pilihan Anda. Bosnya orang yang sangat sibuk, dan dia ingin programnya sesingkat mungkin, jadi dia tidak membuang waktu untuk membaca. Dia juga ingin agar Anda tidak menggunakan loop, oleh karena itu Anda akan memiliki pengurangan 10% pada jumlah byte karena tidak menggunakan loop.

Persyaratan rinci fungsi di bawah ini:

Peta

The MapFungsi mengambil dua parameter: fdan listdi mana fadalah fungsi dan listmerupakan daftar nilai. Ini harus mengembalikan fditerapkan ke setiap elemen list. Karena itu akan berfungsi seperti itu:

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

kembali

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

dan

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

kembali

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

Sarang

The NestFungsi mengambil tiga parameter juga: f, arg, timesdi mana fadalah fungsi, argadalah argumen mulai, dan timesadalah berapa kali fungsi ini diterapkan. Itu harus mengembalikan ekspresi dengan waktu yang fditerapkan timeske arg. Karena itu akan berfungsi seperti itu:

Nest(f, x, 3)

kembali

f(f(f(x)))

dan

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

kembali

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

Menerapkan

The ApplyFungsi mengambil dua parameter: fdan argsdi mana fadalah fungsi dan argsdaftar. Itu harus berlaku funtuk args. Karena itu:

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

kembali

f(a,b,c)

Jarak

The RangeFungsi mengambil satu bilangan bulat rdan output bilangan bulat hingga jumlah itu. Karena itu:

Range(5)

kembali

{ 1, 2, 3, 4, 5}

Melipat

The FoldFungsi mengambil tiga parameter f, arg, othersdi mana fadalah fungsi, argadalah parameter sederhana, dan othersdaftar. Ini akan berfungsi seperti itu:

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

kembali

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

Meja

Fungsi-fungsi tabel harus mengambil fungsi f, dan parameter yang disebut iteratordalam bentuk: {iMin, iMax}where iMinand iMaxinteger. Anda harus menerapkan frentang yang ditentukan. Karena itu:

Table(f, {0, 5})

kembali

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

Saya telah menggunakan definisi fungsi-fungsi ini dari halaman pemrograman fungsional Mathematica , jadi pergilah ke sana jika Anda memerlukan panduan lebih lanjut. Perhatikan bahwa Anda tidak perlu mengimplementasikan semua versi fungsi yang ditampilkan di halaman itu, tetapi hanya yang ditulis dalam posting ini.

Celah Standar tidak diizinkan seperti biasa.

Jika bahasa Anda tidak memungkinkan fungsi untuk diteruskan sebagai argumen, Anda perlu menerapkan kemampuan ini, dan menambahkannya ke dalam jawaban Anda. Namun byte-count dari operasi ini tidak akan ditambahkan ke total.

Ini adalah kode golf sehingga kode terpendek menang. Semoga berhasil!!!


Ini luar biasa! +1 Namun, saya tidak begitu mengerti cara Tablekerjanya di sini. Apakah teladan Anda seharusnya Table(f, {x, 0, 5})? Saya juga tidak mendapatkan tujuan xsama sekali, karena itu hanya menerapkan fungsi ke kisaran.
kirbyfan64sos

@ kirbyfan64sos Terima kasih! Ya itu salah ketik, saya meninggalkan x sebagai referensi untuk Mathematica, yang menggunakannya sebagai simbol feauture, namun saya pikir saya bisa mengeluarkannya
WizardOfMenlo

Satu pertanyaan lagi: bagaimana kita memberi nama fungsinya? Apakah kita harus memberi mereka nama yang sama persis? Huruf tunggal?
kirbyfan64sos

@ kirbyfan64sos Karena ini adalah kode-golf, saya akan mengizinkan satu nama huruf, namun dalam jawaban Anda letakkan tajuk di atas setiap fungsi sehingga kita tahu yang mana. Juga jangan gunakan huruf bertabrakan.
WizardOfMenlo

Bisakah Anda lebih spesifik tentang apa yang dianggap sebagai loop?
xnor

Jawaban:


9

Haskell, banyak byte sebelumnya menghitung 127 * 0,9 = 114,3 byte

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)

Tidak ada loop, hanya rekursi.

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

&adalah sarang: ((*2) & 3) 4->48

iberlaku: i (*2) 7->14

rkisaran: r 4->[1,2,3,4]

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

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

Seperti yang diminta versi yang ungolfed dengan komentar. Catatan, &dan ?merupakan operator infix ternary, yang membutuhkan tanda kurung tambahan saat dipanggil atau pola cocok.

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

Terima kasih kepada @dfeuer dan @Zgarb untuk beberapa petunjuk bermanfaat


Saya baru mengenal haskell, tampilannya cukup bagus, tetapi bisakah Anda menambahkan penjelasan pada apa yang Anda lakukan?
WizardOfMenlo

1
@WizardOfMenlo: menambahkan beberapa komentar
nimi

Baru menyadari betapa elegannya Haskell, sungguh bagus!
WizardOfMenlo

1
Mengabaikan daftar dan efisiensi tanpa batas m#q=reverse$f((:).m)[]q,. Panjangnya sama dengan milik Anda, tetapi jauh lebih sulit untuk dibaca.
dfeuer

Anda dapat mempersingkat !dengan membuat nama bukan operator: i f=f.
dfeuer

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

Saat diperluas, setara dengan:

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

Tidak ada loop!

Ya, itu sangat sulit evaldan jika bos Anda tidak tahan, maka mereka akan BENCI eval. Tapi, mereka harus tahan dengan itu

Cara melakukannya rangedi lambda dihargai jadi saya tidak harus melakukan fungsi apa pun (Shudder.).

Penjelasan:

  • m=lambda f,l:eval("["+"f(l.pop()),"*len(l)+"][::-1]")
    • Buat string yang muncul elemen dari daftar, bungkus ke dalam daftar, balikkan dan akhirnya eval!
  • n=lambda f,x,l:eval("f("*l+"*x"+")"*l)
    • Secara manual buat string dengan sarang, dan evaluasi!
  • r=lambda i:e("r(i-1)+"*(i>1)+"[i]")
    • Buat string yang saat evaled, baik kembali [0]atau menggunakan rekursi untuk mendapatkan hasil sebelumnya dan menambahkan indeks saat ini ke daftar. Benarkah?
  • a=lambda f,a:eval("f(a["+r (len (a))[1:-1].replace(",","-1],a[")+"-1])")
    • Menggunakan fungsi rentang untuk mendapatkan indeks 1-len (daftar). Mengganti koma dalam daftar yang dirangkai dengan cara untuk mendapatkan indeks daftar yang benar a. Benarkah itu!
  • f=lambda f,x,l:eval("f("*len(l)+"x,["+r (len (l))[1:-1].replace(",","-1]),l[")+"-1])")
    • Sama seperti yang berlaku kecuali mengganti koma dengan tanda kurung penutup, koma dan memulai indeks daftar.
  • t=lambda f,n,x:eval("[f("+r (x) [n-1:].replace(",","),f(")[1:-1]+")]")
    • Sama seperti berlaku dan lipat kecuali mengganti dengan mengakhiri fungsi dan memanggil yang baru. Benarkah itu!

Peta, sarang, jangkauan, terapkan, lipat, tabel.

Terima kasih @Zgarb untuk lambda untuk jangkauannya!


Bos saya akan menempatkan kepala saya di mejanya :) Bisakah Anda menambahkan penjelasan singkat juga?
WizardOfMenlo

Bagaimana dengan r=lambda i:[]if i<1 else r(i-1)+[i]? Tidak ada loop, hanya rekursi.
Zgarb

1
Tentu, saya akan mengambilnya untuk saat ini tetapi bos membutuhkan lebih banyak evaluntuk menunjukkan kepada mereka bagaimana agar loop tidak terlalu buruk :)
Blue

Ha! Versi lain menggunakan e=eval:r=lambda i:e("r(i-1)+"*(i>1)+"[i]")
Zgarb

dapatkah Anda mengubahnya dari bonus 60% menjadi 10%? Saya merevisi spesifikasi pertanyaan, sehingga membuatnya lebih adil
WizardOfMenlo

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

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

Penggunaan Lipat untuk menggabungkan hasil yang fditerapkan ke setiap anggota lke daftar kosong. Menggunakan fungsi bawaan mengurangi ini ke M=(f,l)=>l.map(f)(tidak menggunakannya karena tampaknya murah ...?).

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

Terapkan fsecara berulang sampai ndikurangi menjadi 0.

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

Menggunakan penyebaran ( ...) operator untuk menerapkan lke f.

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

Concat npanggilan rekursif dari Rentang sampai ndecremented ke 0.

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

Menerapkan panggilan rekursif dari Fold dan nelemen lke fhingga ndikurangi menjadi 0. Menggunakan fungsi bawaan mengurangi ini menjadi F=(f,x,l)=>l.reduce(f,x)(sekali lagi, tampak murah ...).

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

Pertama menginisialisasi ndan xke iMin dan iMax menggunakan destructure ( [n,x]=i), kemudian menggunakan Range untuk membangun tabel nilai dari iMin ke iMax. fkemudian diterapkan di atas tabel menggunakan Peta dan hasilnya dikembalikan.


Ingin tahu filosofi saya? "Kalau murah, beli saja." Tidak disebutkan dalam spesifikasi bahwa Anda tidak dapat menggunakan builtin (belum), jadi gunakanlah!
Mama Fun Roll

4

Python 3, 218 byte

Versi tidak terbaca:

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

Versi (lebih) dapat dibaca:

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

Meskipun hanya satu lambda sekaligus:

Fungsi peta P

P=lambda f,x:[f(_)for _ in x]
Hanya iterator sederhana. Tidak banyak bicara di sini.

Fungsi sarang Y

Y=lambda f,x,z:Y(f,f(x),z-1)if z else x
Berulang hingga zmencapai angka nol, terapkan fsetiap saat. Klausa if pada akhirnya terasa kikuk; mungkin ada cara yang lebih baik untuk mengakhiri rekursi.

Terapkan fungsi T

T=lambda f,x:f(*x)
Python memiliki operator ekspansi yang bagus untuk melakukan semua pekerjaan berat untuk saya.

Fungsi rentang H

H=lambda f,x=0:(H(f-1)if~-f else[])+[f]
Yang ini lebih sulit daripada yang saya harapkan. Akhirnya mengambil pendekatan rekursif. Sekali lagi, konstruksi if-else membutuhkan banyak byte, dan saya rasa ini dapat ditingkatkan. Mengapa ia memiliki boneka x=0, Anda bertanya? Itu sehingga ketika saya kompres dengan exec, saya bisa mengganti =lambda f,xbukan hanya =lambda f.

Fungsi lipat O

O=lambda f,x,z:O(f,f(x,z[0]),z[1:])if z else x
Cukup senang dengan yang ini. Hanya memotong elemen pertama dari array setiap kali berulang, sampai tidak ada yang tersisa.

Fungsi tabel N

N=lambda f,x:(N(f,[x[0],x[1]-1])if x[1]-x[0]else[])+[f(x[1])]
Yang ini mengerikan dan saya yakin ada ruang untuk perbaikan. Mencoba menggunakan rentang dan fungsi peta yang sebelumnya ditentukan untuk map(f,range(x,y))semacam konstruksi, tetapi tanpa banyak keberhasilan. Akhirnya melakukan pendekatan rekursif yang mengerikan yang memiliki kesamaan dengan fungsi rentang.

Semua lambda dibungkus execdengan dengan replaceuntuk mempersingkat jumlah byte secara signifikan.


Saya hendak berkomentar yang [f(_)for _ in x]dapat disingkat menjadi map(f,x), tetapi kemudian saya ingat apa tantangannya
Cyoce

4

Julia, 181 byte

Tidak ada bonus untuk saya; Saya menggunakan loop secara bebas. Maaf bos, tetapi loop di Julia efisien!

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

Menambahkan elips setelah argumen ke suatu fungsi memecah array, tuple, atau apa yang Anda miliki ke dalam argumen fungsi biasa. Kalau tidak, fungsi akan berpikir Anda mencoba untuk melewatkan array (atau tuple, dll.). Tidak ada efek untuk argumen tunggal.

Nama fungsi:

  • Peta: M
  • Sarang: N
  • Menerapkan: A
  • Jarak: R
  • Melipat: F
  • Meja: T

4

tinylisp , 325 * 0,9 = 292,5

Bahasa lebih baru dari pertanyaan, tetapi tidak akan menang.

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

Menentukan fungsi A(berlaku), M(peta), N(sarang), R(rentang), T(tabel), dan F(lipat), bersama dengan fungsi pasangan pembantu. Tmengharapkan daftar dua bilangan bulat untuk argumen keduanya.

Tinylisp bahkan tidak memiliki konstruksi loop; semuanya dilakukan dengan menggunakan rekursi. Beberapa fungsi-fungsi ini tidak berulang , jadi jika Anda memanggil mereka pada daftar besar mereka mungkin akan meniup tumpukan panggilan. Mereka semua dapat diimplementasikan dengan rekursi ekor ... tetapi akan membutuhkan lebih banyak byte, dan ini adalah kode golf.

Berikut adalah versi yang diperluas dengan spasi putih dan kata-kata nyata untuk nama, yang seharusnya cukup mudah dibaca jika Anda terbiasa dengan Lisp. (Saya telah alias sebagian besar builtinisp builtin kecuali untuk q(kutipan) dan i(jika).)

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

Penjelasan lebih lanjut tersedia atas permintaan.

Output sampel

Menggunakan lingkungan REPL dari implementasi referensi saya. Saya menggunakan q(kutipan) untuk fungsi unary dan s(kurangi) sebagai fungsi biner untuk contoh-contoh ini, serta fungsi @(didefinisikan dalam kode ini) yang mengembalikan daftar argumennya.

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 byte (493 byte sebelum diskon 10%)

Jawaban golf:

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

Pertanyaan ini menyenangkan. Saya memutuskan untuk menulis fungsi saya tanpa menggunakan padanan Python (meskipun itu mungkin merupakan celah yang valid) dan untuk menulis fungsi seolah-olah Python mendukung rekursi ekor. Untuk membuat ini berfungsi, saya menggunakan banyak parameter opsional yang memungkinkan panggilan yang diperlukan masih berfungsi.

Di bawah ini saya memiliki daftar yang tidak dipisahkan untuk setiap fungsi.

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

Perhatikan bahwa fungsi ini mensyaratkan bahwa yang lulus functiondapat mewakili beberapa argumen secara beragam. Pendekatan lain adalah untuk menegakkan bahwa fungsi selalu menerima satu daftar, tetapi itu akan mengharuskan fungsi yang berlalu dapat menafsirkan daftar argumen. Ada beberapa asumsi, jadi saya memilih yang paling sesuai dengan sistem.

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

Berikut ini contoh keluaran menggunakan fungsi pembantu berikut:

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, terlihat sangat bagus!
WizardOfMenlo

Tampaknya seperti estetika yang condong; ) Saya selalu merasa senang melihat golf Python sejak buku Python pertama yang saya baca berbicara tentang bagaimana Python memaksakan keterbacaan.
sadakatsu

Saya memang memiliki rasa estetika yang condong :)
WizardOfMenlo

Saya bingung dengan skor orang lain. Saya mengambil 10% dari skor masing-masing fungsi yang diperlukan yang tidak menggunakan loop (yang semuanya), tetapi orang lain mengambil 10% dari seluruh skor untuk setiap fungsi yang tidak menggunakan loop (yang bisa berupa hingga 60% off). Mana pendekatan yang benar?
sadakatsu

Milikmu adalah cara yang tepat untuk pergi, aku punya harapan yang tidak realistis dan awalnya aku memikirkan pendekatan 60%, tapi sekarang aku pikir 10% akan lebih menstimulasi dan lebih baik antara keduanya
WizardOfMenlo

2

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

Sebagian besar fungsi tersebut sudah tersedia dalam paket bahasa Ceylon (meskipun terkadang dengan tanda tangan yang sedikit berbeda), tetapi kami mendefinisikannya di sini seperti yang diminta dalam pertanyaan.

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

Sebenarnya hanya dua fungsi ( tdan f) yang benar-benar menggunakan rekursi (masing-masing daftar dan bilangan bulat), yang lain didasarkan pada ini. (Aplikasi sedikit outlier, itu tidak benar-benar berhubungan dengan yang lain.)

Saya menafsirkan "Daftar" sebagai tipe Sequential Ceylon, yang merupakan urutan elemen (mungkin kosong) yang tidak dapat diubah. [R*]singkatan Sequential<R>- untuk beberapa alasan kita juga dapat menulisnya R[], yang lebih pendek satu byte.

Tipe fungsi adalah Callable<R, A>, di mana Aadalah tipe tuple untuk argumen, seperti [X, Y, Z](yaitu beberapa subtipe Anything[]). Sebagai jalan pintas kita dapat menulis R(X,Y,Z)bukan Callable<R,[X,Y,Z]>.

Aku alias Integersebagai Iuntuk menyimpan beberapa byte.

Ini adalah versi yang diformat (dan sedikit dikomentari):

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

Menggunakan "loop"

Tabel dan Peta dapat diimplementasikan lebih pendek menggunakan loop (sebenarnya, pemahaman urutan):

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

Meskipun saya tidak yakin apakah penggunaan ..operator untuk rentang bilangan bulat dianggap sebagai menggunakan fungsi bawaan. Jika ini dibolehkan, kode yang dihasilkan ada di sini, panjang 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]);

(Itu bisa dibuat lebih pendek dengan mendefinisikan r(I i) => 1..i, menghasilkan skor 301. Meskipun itu terlihat lebih seperti curang.)

Jika ..tidak diizinkan, kami harus menerapkannya lagi. Kita dapat menggunakan implementasi ini untuk rdan t(dengan yang di matas):

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

Ini menghasilkan 348 byte, lebih baik daripada versi yang sepenuhnya rekursif, tetapi tidak setelah menerapkan bonus.


0

Groovy (146 Bytes) (146 * 90% = 131,4)

PS Saya tidak tahu apa yang Anda pertimbangkan sebagai 'loop' dalam konteks ini, saya hanya menerapkan bonus setelah saya diberitahu dalam komentar oleh OP dan akan menghapus jika 2-3 pengguna tambahan mengatakan fungsi dan iterator pengumpulan ini. adalah loop dan saya tidak pantas mendapatkan bonus. Juga, jika Anda ingin memanggil saya untuk menggunakan 1..it, silakan lakukan dan saya akan memperbaikinya / memperbarui bytecount saya.

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

Contoh Input / Output

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)

Keluaran

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]

Cobalah sendiri: https://groovyconsole.appspot.com/edit/5203951758606336


Ini secara teknis tidak menggunakan loop, jadi ingat bonusnya! Lain, jawaban yang bagus!
WizardOfMenlo

Secara teknis tidak ada loop ?! Sangat?! .each {} .tim {} .collect {} adalah iterator.
Magic Octopus Urn
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.