ใช้กระบวนทัศน์การเขียนโปรแกรมการทำงาน


21

บริษัท ของคุณเพิ่งเริ่มต้นโครงการและเป็นครั้งแรกที่คุณตัดสินใจที่จะใช้การเขียนโปรแกรมแบบใช้งานได้ อย่างไรก็ตามเจ้านายของคุณมีความแตกต่างและไม่ต้องการใช้ฟังก์ชันในตัวและต้องการให้คุณใช้งานฟังก์ชั่นหลัก โดยเฉพาะอย่างยิ่งที่คุณต้องเขียนฟังก์ชั่น: Map, Nest, Apply, Range, FoldและTableในภาษาที่คุณเลือก เจ้านายเป็นคนที่ยุ่งมากและเขาต้องการให้รายการสั้นที่สุดเท่าที่จะเป็นไปได้ดังนั้นเขาจึงไม่ต้องเสียเวลาอ่าน เขาไม่ต้องการให้คุณใช้ลูปดังนั้นคุณจะมีการลดลง 10% สำหรับจำนวนไบต์ที่ไม่ได้ใช้ลูป

ข้อกำหนดรายละเอียดของฟังก์ชั่นอยู่ด้านล่าง:

แผนที่

Mapฟังก์ชั่นใช้เวลาสองพารามิเตอร์fและlistที่fเป็นฟังก์ชั่นและlistเป็นรายการค่า มันควรกลับนำไปใช้กับองค์ประกอบของแต่ละf listดังนั้นมันจะทำงานเช่น:

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

ผลตอบแทน

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

และ

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

ผลตอบแทน

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

รัง

Nestฟังก์ชั่นใช้เวลาสามพารามิเตอร์เช่นกัน: f, arg, timesที่fเป็นฟังก์ชั่นargคือการเริ่มต้นการโต้แย้งของตนและtimesเป็นวิธีการที่หลายต่อหลายครั้งฟังก์ชั่นที่มีการใช้ มันควรจะกลับแสดงออกที่มีfนำมาใช้ครั้งเพื่อtimes argดังนั้นมันจะทำงานเช่น:

Nest(f, x, 3)

ผลตอบแทน

f(f(f(x)))

และ

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

ผลตอบแทน

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

ใช้

Applyฟังก์ชั่นใช้เวลาสองพารามิเตอร์fและargsที่fเป็นฟังก์ชั่นและargsรายการ มันควรจะใช้กับf argsดังนั้น:

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

ผลตอบแทน

f(a,b,c)

พิสัย

Rangeฟังก์ชั่นใช้เวลาหนึ่งจำนวนเต็มrและผลจำนวนเต็มขึ้นไปยังหมายเลขที่ ดังนั้น:

Range(5)

ผลตอบแทน

{ 1, 2, 3, 4, 5}

พับ

Foldฟังก์ชั่นใช้เวลาสามพารามิเตอร์f, arg, othersที่fเป็นฟังก์ชั่นargเป็นพารามิเตอร์ที่ง่ายและothersรายการ มันจะทำงานเช่น:

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

ผลตอบแทน

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

ตาราง

ฟังก์ชั่นตารางควรใช้ฟังก์ชั่นfและพารามิเตอร์ที่เรียกว่าiteratorในรูปแบบ: {iMin, iMax}ที่ไหนiMinและiMaxเป็นจำนวนเต็ม คุณควรใช้fในช่วงที่ระบุ ดังนั้น:

Table(f, {0, 5})

ผลตอบแทน

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

ฉันใช้นิยามของฟังก์ชั่นเหล่านี้จากหน้าการเขียนโปรแกรมฟังก์ชั่น Mathematicaดังนั้นมุ่งไปที่นั่นหากคุณต้องการคำแนะนำเพิ่มเติม โปรดทราบว่าคุณไม่จำเป็นต้องใช้ฟังก์ชั่นทุกรุ่นที่แสดงในหน้านั้น แต่จะมีเฉพาะฟังก์ชันที่เขียนในโพสต์นี้เท่านั้น

ช่องโหว่มาตรฐานไม่อนุญาตตามปกติ

ในกรณีที่ภาษาของคุณไม่อนุญาตให้ส่งผ่านฟังก์ชั่นเป็นอาร์กิวเมนต์คุณต้องใช้ความสามารถนี้และเพิ่มเข้าไปในคำตอบของคุณ อย่างไรก็ตามจำนวนไบต์ของการดำเนินการนี้จะไม่ถูกเพิ่มไปยังผลรวม

นี่คือรหัสกอล์ฟเพื่อให้รหัสที่สั้นที่สุดชนะ โชคดี!!!


นี่มันเจ๋งมาก! +1 อย่างไรก็ตามฉันไม่เข้าใจวิธีการTableทำงานที่นี่ ตัวอย่างของคุณควรจะเป็นTable(f, {x, 0, 5})อย่างไร ฉันยังไม่ได้รับวัตถุประสงค์xเลยเพราะมันใช้ฟังก์ชันกับช่วงเท่านั้น
kirbyfan64sos

@ kirbyfan64sos ขอบคุณ! ใช่นั่นคือการพิมพ์ผิดฉันทิ้ง x ไว้เพื่ออ้างอิงถึง mathematica ซึ่งใช้มันเป็นสัญลักษณ์ feauture แต่ฉันคิดว่าฉันสามารถเอามันออกได้
WizardOfMenlo

อีกหนึ่งคำถาม: เราจะตั้งชื่อฟังก์ชั่นได้อย่างไร เราต้องให้ชื่อเดียวกันกับพวกเขาเหรอ? ตัวอักษรเดียว?
kirbyfan64sos

@ kirbyfan64sos เนื่องจากเป็น code-golf ฉันจะอนุญาตให้ใช้ชื่อตัวอักษรเดียว แต่ในคำตอบของคุณให้มุ่งหน้าไปยังแต่ละฟังก์ชั่นเพื่อที่เราจะได้รู้ว่าอันไหนเป็น อย่าใช้ตัวอักษรที่ขัดแย้งกัน
WizardOfMenlo

คุณจะเจาะจงมากขึ้นเกี่ยวกับสิ่งที่นับเป็นวนซ้ำได้ไหม
xnor

คำตอบ:


9

Haskell ไบต์ก่อนหน้าจำนวนมากนับ 127 * 0.9 = 114.3 ไบต์

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)

ไม่มีลูปเพียงแค่เรียกซ้ำ

#คือแผนที่: (*2) # [1,2,3]->[2,4,6]

&คือรัง: ((*2) & 3) 4->48

iใช้: i (*2) 7->14

rคือช่วง: r 4->[1,2,3,4]

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

%คือตาราง: (*2) % (2,4)->[4,6,8]

ตามที่ร้องขอในเวอร์ชันที่ไม่ได้ดูพร้อมความคิดเห็น หมายเหตุ&และ?เป็นผู้ประกอบการมัดสามส่วนซึ่งต้องใช้วงเล็บเพิ่มเติมเมื่อเรียกหรือจับคู่รูปแบบ

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

ขอบคุณ @dfeuer และ @Zgarb สำหรับคำแนะนำที่เป็นประโยชน์


ฉันใหม่สำหรับฮาเซลมันดูค่อนข้างดี แต่คุณช่วยเพิ่มคำอธิบายให้กับสิ่งที่คุณกำลังทำอยู่ได้ไหม?
WizardOfMenlo

1
@WizardOfMenlo: เพิ่มความคิดเห็น
nimi

เพิ่งรู้ว่า Haskell สง่างามเพียงใดดีจริง!
WizardOfMenlo

1
ไม่สนใจรายการและประสิทธิภาพที่ไม่มีที่สิ้นสุด, m#q=reverse$f((:).m)[]q. นี่คือความยาวเท่ากันกับคุณ แต่อ่านยากกว่ามาก
dfeuer

คุณสามารถลดได้โดยการทำให้มันชื่อแทนการดำเนินการ:! i f=f
dfeuer

5

Python 2, 305.1 ไบต์ (-10% 376 369 366 349 339 ไบต์)

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

เมื่อขยายแล้วเทียบเท่ากับ:

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

ไม่มีลูป!

มันทำได้ดีมากevalและถ้าเจ้านายของคุณไม่สามารถยืนได้ลูปพวกเขาจะเกลียดการประเมิน แต่พวกเขาจะต้องทนกับมัน

วิธีการทำrangeแลมบ์ดานั้นได้รับการชื่นชมดังนั้นฉันไม่จำเป็นต้องทำหน้าที่ใด ๆ (ตัวสั่น)

คำอธิบาย:

  • 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]")
    • สร้างสตริงที่เมื่อevaled จะส่งคืน[0]หรือใช้การเรียกซ้ำเพื่อรับผลลัพธ์ก่อนหน้าและเพิ่มดัชนีปัจจุบันลงในรายการ ประเมินมัน
  • a=lambda f,a:eval("f(a["+R (len (ก))[1:-1].replace(",","-1],a[")+"-1])")
    • ใช้ฟังก์ชัน range เพื่อรับดัชนี 1-len (รายการ) แทนที่เครื่องหมายจุลภาคในรายการ stringified aกับวิธีที่จะได้รับดัชนีที่ถูกต้องของรายการ ประเมินมัน!
  • 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]+")]")
    • เหมือนกับใช้และพับยกเว้นแทนที่ด้วยการสิ้นสุดฟังก์ชันและเรียกใช้ฟังก์ชันใหม่ ประเมินมัน!

แผนที่, รัง, ช่วง, ใช้, พับ, ตาราง

ขอบคุณ @Zgarb สำหรับแลมบ์ดาในช่วง!


หัวหน้าของฉันจะเอาหัววางบนโต๊ะของเขา :) คุณช่วยเพิ่มคำอธิบายสั้น ๆ ได้มั้ย
WizardOfMenlo

แล้วไงr=lambda i:[]if i<1 else r(i-1)+[i]ล่ะ ไม่มีลูปเรียกซ้ำเท่านั้น
Zgarb

1
แน่นอนว่าฉันจะรับมันไว้ตอนนี้ แต่หัวหน้าต้องการมากกว่านั้นevalเพื่อแสดงให้พวกเขาเห็นว่าลูปไม่ได้แย่ขนาดนั้นหรอก :)
บลู

ฮา! รุ่นอื่นที่ใช้e=eval:r=lambda i:e("r(i-1)+"*(i>1)+"[i]")
Zgarb

คุณสามารถเปลี่ยนจากโบนัส 60% เป็น 10% ได้ไหม? ฉันแก้ไขข้อกำหนดคำถามดังนั้นเพื่อให้เป็นธรรม
WizardOfMenlo

5

Javascript ES6, 197 * 0.9 = 177.3 ไบต์

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

แผนที่ ( M=(f,l)=>F((a,b)=>[...a,f(b)],[],l)):

ใช้การพับเพื่อเชื่อมผลลัพธ์ของfสมาชิกทุกคนของlรายการที่ว่าง การใช้ฟังก์ชั่นในตัวช่วยลดสิ่งนี้เป็นM=(f,l)=>l.map(f)(ไม่ได้ใช้เพราะดูเหมือนว่าราคาถูก ... ?)

ทำรัง ( N=(f,x,n)=>f(--n?N(f,x,n):x)):

ใช้fซ้ำจนกว่าnจะลดลงเหลือ 0

ใช้ ( A=(f,l)=>f(...l)):

ใช้การแพร่กระจาย ( ...) ผู้ประกอบการเพื่อนำไปใช้บนlf

ช่วง ( R=n=>n--?[...R(n),n+1]:[]):

เชื่อมnต่อเพื่อเรียกการเรียกซ้ำของRangeจนกระทั่งnลดลงเป็น 0

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

ใช้การเรียกซ้ำของFoldและnองค์ประกอบ 'ของlถึงfจนnลดลงเป็น 0 การใช้ฟังก์ชันในตัวจะลดสิ่งนี้เป็นF=(f,x,l)=>l.reduce(f,x)(อีกครั้งดูเหมือนจะถูก ... )

ตาราง ( T=(f,i)=>([n,x]=i,M(q=>f(q+n-1),R(x-n+1)))):

เริ่มต้นnและxiMin และ iMax โดยใช้ destructuring ( [n,x]=i) จากนั้นใช้Rangeเพื่อสร้างตารางค่าจาก iMin ถึง iMax fจะถูกนำไปใช้กับตารางโดยใช้แผนที่และผลลัพธ์จะถูกส่งคืน


อยากรู้ว่าปรัชญาของฉัน? "ถ้ามันราคาถูกซื้อได้" ไม่ได้บอกในสเป็คที่คุณไม่สามารถใช้ builtins (ยัง) ดังนั้นใช้พวกเขา!
Mama Fun Roll

4

Python 3, 218 ไบต์

รุ่นที่อ่านไม่ได้:

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

รุ่น (อ่านเพิ่มเติม) ที่อ่านได้:

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

แม้ว่ามันจะเป็นหนึ่งแลมบ์ดาในเวลา:

ฟังก์ชั่นแผนที่ P

P=lambda f,x:[f(_)for _ in x]
เป็นตัววนซ้ำที่เรียบง่าย ไม่มากที่จะพูดที่นี่

ฟังก์ชั่นรัง Y

Y=lambda f,x,z:Y(f,f(x),z-1)if z else x
วนซ้ำจนกว่าจะถึงzศูนย์ใช้fทุกครั้ง ถ้าประโยคที่ท้ายรู้สึก clunky; อาจมีวิธีที่ดีกว่าในการยุติการสอบถามซ้ำ

ใช้ฟังก์ชั่น T

T=lambda f,x:f(*x)
Python มีผู้ให้บริการเสริมที่ดีในการยกของหนักสำหรับฉัน

ฟังก์ชั่นช่วง H

H=lambda f,x=0:(H(f-1)if~-f else[])+[f]
อันนี้ยากกว่าที่ฉันคาดไว้ ลงเอยด้วยวิธีแบบเรียกซ้ำ อีกครั้งการก่อสร้าง if-else ใช้เวลามากในการไบต์และฉันรู้สึกว่ามันสามารถปรับปรุงได้ ทำไมถึงมีหุ่นx=0คุณถาม? มันเพื่อที่เมื่อฉันบีบอัดมันด้วยexec, ฉันสามารถเปลี่ยน=lambda f,xแทน=lambda fได้

ฟังก์ชั่นพับ O

O=lambda f,x,z:O(f,f(x,z[0]),z[1:])if z else x
ค่อนข้างมีความสุขกับอันนี้ เพียงแค่กระโดดออกองค์ประกอบแรกของอาร์เรย์ทุกครั้งที่มันเกิดขึ้นอีกจนกว่าจะไม่มีอะไรเหลือ

ฟังก์ชั่นตาราง N

N=lambda f,x:(N(f,[x[0],x[1]-1])if x[1]-x[0]else[])+[f(x[1])]
อันนี้น่ากลัวและฉันแน่ใจว่ามีห้องพักสำหรับการปรับปรุง พยายามใช้ช่วงและฟังก์ชั่นแผนที่ที่กำหนดไว้ก่อนหน้านี้สำหรับการmap(f,range(x,y))ก่อสร้าง แต่ไม่ประสบความสำเร็จมากนัก จบลงด้วยการทำที่น่ากลัววิธี recursive ซึ่งหุ้นคล้ายคลึงกันบางฟังก์ชั่นช่วง

แกะทั้งหมดนั้นถูกห่อหุ้มexecด้วยreplaceเพื่อให้สั้นลงจำนวนไบต์อย่างมีนัยสำคัญ


ฉันกำลังจะแสดงความคิดเห็นที่[f(_)for _ in x]สามารถย่อให้สั้นmap(f,x)แต่แล้วฉันจำได้ว่าความท้าทายคืออะไร
Cyoce

4

Julia, 181 ไบต์

ไม่มีโบนัสสำหรับฉัน ฉันใช้ลูปอย่างอิสระ ขออภัยเจ้านาย แต่ลูปในจูเลียนั้นมีประสิทธิภาพ!

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

การเพิ่มจุดไข่ปลาหลังจากข้อโต้แย้งไปยังฟังก์ชั่นแบ่งอาร์เรย์, ทูเปิลหรือสิ่งที่คุณได้เป็นข้อโต้แย้งฟังก์ชั่นปกติ มิฉะนั้นฟังก์ชั่นจะคิดว่าคุณกำลังพยายามผ่านอาร์เรย์ (หรือทูเปิล ฯลฯ ) ไม่มีผลสำหรับอาร์กิวเมนต์เดี่ยว

ชื่อฟังก์ชั่น:

  • แผนที่: M
  • รัง: N
  • สมัคร: A
  • พิสัย: R
  • พับ: F
  • ตาราง: T

4

tinylisp , 325 * 0.9 = 292.5

ภาษานี้ใหม่กว่าคำถาม แต่จะไม่ชนะต่อไป

(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(นำไปใช้), M(แผนที่), N(รัง), R(ช่วง), T(ตาราง) และF(พับ) พร้อมกับฟังก์ชั่นผู้ช่วยคู่ Tต้องการรายการจำนวนเต็มสองรายการสำหรับอาร์กิวเมนต์ที่สอง

Tinylisp ไม่มีแม้แต่โครงสร้างวนซ้ำ ทุกอย่างทำได้โดยใช้การเรียกซ้ำ หลายฟังก์ชั่นเหล่านี้ไม่ได้เรียกซ้ำโดยอัตโนมัติดังนั้นหากคุณเรียกพวกมันในรายการขนาดใหญ่ พวกเขาทั้งหมดสามารถนำไปใช้กับการเรียกซ้ำหาง ... แต่มันจะใช้เวลามากขึ้นไบต์และนี่คือรหัสกอล์ฟ

ต่อไปนี้เป็นเวอร์ชันขยายที่มีช่องว่างและคำจริงสำหรับชื่อซึ่งควรอ่านได้ง่ายหากคุณคุ้นเคยกับ Lisp (ฉันได้สร้างนามแฝงของ tinylisp บิวอินส่วนใหญ่แล้วยกเว้นq(quote) และi(ถ้า))

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

คำอธิบายเพิ่มเติมตามคำขอ

ตัวอย่างผลลัพธ์

ใช้สภาพแวดล้อม REPL จากการใช้การอ้างอิงของฉัน ฉันใช้q(quote) สำหรับฟังก์ชัน unary และs(ลบ) เป็นฟังก์ชันเลขฐานสองสำหรับตัวอย่างเหล่านี้รวมถึงฟังก์ชั่น@(กำหนดไว้ในรหัสนี้) ซึ่งส่งกลับรายการอาร์กิวเมนต์ของมัน

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 ไบต์ (493 ไบต์ก่อนส่วนลด 10%)

คำตอบกอล์ฟ:

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

คำถามนี้สนุกมาก ฉันตัดสินใจที่จะเขียนฟังก์ชั่นของฉันโดยไม่ใช้ Python ที่เทียบเท่ากัน (แม้ว่ามันอาจจะเป็นช่องโหว่ที่ถูกต้องก็ตาม) และเพื่อเขียนฟังก์ชั่นราวกับว่า Python รองรับการเรียกซ้ำแบบหาง ในการทำให้งานนี้ฉันใช้พารามิเตอร์ตัวเลือกมากมายที่อนุญาตให้การโทรที่ต้องการยังคงทำงานได้

ด้านล่างฉันมีรายชื่อที่ไม่ดีสำหรับแต่ละฟังก์ชัน

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

โปรดทราบว่าฟังก์ชั่นนี้ต้องการให้การส่งผ่านfunctionสามารถแสดงอาร์กิวเมนต์หลาย ๆ ตัวแปรได้ อีกวิธีหนึ่งคือการบังคับให้ฟังก์ชั่นได้รับรายการเดียวเสมอ แต่นั่นก็จำเป็นที่ฟังก์ชั่นที่ส่งผ่านจะสามารถตีความรายการอาร์กิวเมนต์ได้ มีข้อสมมติฐานสองทางดังนั้นฉันเลือกหนึ่งที่เหมาะสมกับระบบที่เหลือดีกว่า

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

นี่คือเอาต์พุตตัวอย่างโดยใช้ฟังก์ชันตัวช่วยต่อไปนี้:

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'

ว้าวดูดีจริงๆ!
WizardOfMenlo

มันดูเหมือนความรู้สึกที่บิดเบือนไป ) ฉันมักจะพบว่ามันน่าสนุกที่ได้เห็น Python golfed ตั้งแต่หนังสือ Python เล่มแรกที่ฉันอ่านได้พูดคุยเกี่ยวกับวิธีที่ Python บังคับให้อ่านง่าย
sadakatsu

แน่นอนฉันมีความรู้สึกเบ้ของความสวยงาม :)
WizardOfMenlo

ฉันสับสนกับคะแนนของคนอื่น ฉันใช้คะแนน 10% ของแต่ละฟังก์ชั่นที่ต้องการซึ่งไม่ได้ใช้ลูป (ซึ่งเป็นทั้งหมดของพวกเขา) แต่คนอื่น ๆ ใช้คะแนน 10% ของคะแนนทั้งหมดสำหรับแต่ละฟังก์ชั่นที่ไม่ได้ใช้ลูป (ซึ่งสามารถ มากถึง 60%) วิธีใดที่ถูกต้อง
sadakatsu

คุณเป็นวิธีที่ถูกต้องที่จะไปผมก็มีความคาดหวังที่ไม่สมจริงและอื่น ๆ ตอนแรกผมคิดวิธีการที่ 60% แต่ตอนนี้ผมคิดว่า 10% จะมีมากขึ้นและกระตุ้น righter ระหว่างสอง
WizardOfMenlo

2

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

ฟังก์ชั่นส่วนใหญ่นั้นมีอยู่แล้วในแพ็คเกจภาษาของ Ceylon (แต่บางครั้งก็มีลายเซ็นที่แตกต่างออกไปเล็กน้อย) แต่เรากำหนดไว้ที่นี่เหมือนที่ร้องขอในคำถาม

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

จริงๆแล้วมีเพียงสองฟังก์ชัน ( tและf) เท่านั้นที่ใช้การเรียกซ้ำ (ตามรายการและจำนวนเต็มตามลำดับ) ส่วนอีกอันนั้นใช้ฟังก์ชันเหล่านี้ (ใช้เป็นบิตของค่าผิดปกติมันไม่เกี่ยวข้องกับคนอื่น ๆ จริงๆ)

ฉันตีความ "List" เป็น Ceylon's Sequential Type ซึ่งเป็นลำดับที่ไม่เปลี่ยนรูปขององค์ประกอบ [R*]ย่อมาจากSequential<R>- ด้วยเหตุผลบางอย่างที่เราสามารถเขียนR[]ซึ่งสั้นกว่าหนึ่งไบต์

ประเภทฟังก์ชั่นคือCallable<R, A>โดยที่Aเป็นประเภท tuple สำหรับการขัดแย้งเช่น[X, Y, Z](เช่นบางประเภทย่อยของAnything[]) เป็นทางลัดเราสามารถเขียนแทนR(X,Y,Z)Callable<R,[X,Y,Z]>

ฉันใช้นามแฝงIntegerว่าIบันทึกไบต์

นี่คือเวอร์ชันที่จัดรูปแบบ (และแสดงความคิดเห็นเล็กน้อย):

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

ใช้ "ลูป"

ตารางและแผนที่สามารถนำมาใช้ให้สั้นลงโดยใช้ลูป (จริง ๆ แล้วเป็นความเข้าใจลำดับ):

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

แม้ว่าฉันจะไม่แน่ใจว่าการใช้..โอเปอเรเตอร์สำหรับช่วงจำนวนเต็มนับว่าเป็นการใช้ฟังก์ชั่นในตัวหรือไม่ หากได้รับอนุญาตรหัสที่ได้คือนี่ยาว 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]);

(อาจทำให้สั้นลงได้โดยการกำหนดr(I i) => 1..iส่งผลให้คะแนน 301 แม้ว่ามันจะดูเหมือนโกงมากขึ้น)

หาก..ไม่ได้รับอนุญาตเราจะต้องดำเนินการอีกครั้ง เราสามารถใช้การใช้งานเหล่านี้สำหรับrและt(กับ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]));

ผลลัพธ์นี้มีขนาด 348 ไบต์ดีกว่าเวอร์ชันแบบเรียกซ้ำโดยสมบูรณ์ แต่ไม่หลังจากใช้โบนัส


0

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

ป.ล. ฉันไม่ทราบว่าสิ่งที่คุณกำลังพิจารณาว่าเป็น 'วน' ในบริบทนี้ฉันใช้โบนัสหลังจากที่ฉันได้รับคำสั่งในความคิดเห็นโดย OP และจะลบหากผู้ใช้เพิ่มเติม 2-3 คนพูดว่าฟังก์ชั่นการรวบรวมและตัววนซ้ำเหล่านี้ เป็นลูปและฉันไม่สมควรได้รับโบนัส นอกจากนี้หากคุณต้องการโทรหาฉันเมื่อฉันใช้งาน 1..it โปรดทำเช่นนั้นและฉันจะทำใหม่ / อัปเดต bytecount ของฉัน

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

ตัวอย่างอินพุต / เอาท์พุต

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)

เอาท์พุต

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]

ลองด้วยตัวคุณเอง: https://groovyconsole.appspot.com/edit/5203951758606336


เทคนิคนี้ไม่ใช้ลูปดังนั้นให้จำโบนัสไว้! มิฉะนั้นคำตอบที่ดี!
WizardOfMenlo

ในทางเทคนิคไม่มีลูป! จริงๆ?! .each {} .times {} .collect {} เป็นตัววนซ้ำ
Magic Octopus Urn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.