기능적 프로그래밍 패러다임 구현


21

회사가 막 프로젝트를 시작했으며 처음으로 함수형 프로그래밍 코드 스타일을 사용하기로 결정했습니다. 그러나 상사는 정말 어리 석고 내장 함수를 사용하고 싶지 않으며 주요 기능을 구현해야합니다. 특히이 기능을 쓸 필요가 : Map, Nest, Apply, Range, FoldTable당신의 선택의 언어이다. 사장님은 정말 바빠서 프로그램을 최대한 짧게 만들고 싶어서 독서 시간을 낭비하지 않습니다. 또한 루프를 사용하지 않기를 원하므로 루프를 사용하지 않으면 바이트 수를 10 % 줄일 수 있습니다.

기능의 자세한 요구 사항은 다음과 같습니다.

지도

Map함수는 두 개의 매개 변수 : flist여기서 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함수는 두 개의 매개 변수 : fargs여기서 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)

테이블 함수는 function fiterator형식으로 호출되는 매개 변수를 가져야합니다 . {iMin, iMax}where iMiniMax정수입니다. 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

감사합니다! 예 오타였습니다, 그러나 나는 내가 그것을 밖으로 얻을 수 있다고 생각 상징적 한 feauture로 사용 티카에 대한 참조로 X를 왼쪽
WizardOfMenlo

질문 하나 더 : 함수 이름을 어떻게 지정합니까? 그들에게 똑같은 이름을 주어야합니까? 한 글자?
kirbyfan64sos

@ kirbyfan64sos 코드 골프이기 때문에 단일 문자 이름을 사용할 수 있지만 귀하의 답변에 각 함수 위에 표제를 두어 어떤 함수인지 알 수 있습니다. 또한 충돌하는 문자를 사용하지 마십시오.
WizardOfMenlo

루프로 간주되는 항목에 대해 더 구체적으로 설명해 주시겠습니까?
xnor

답변:


9

하스켈, 많은 이전 바이트 수 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]

?폴드입니다 : ((+) ? 0) [1,2,3,4]->10

%테이블입니다 : (*2) % (2,4)->[4,6,8]

주석이 달린 ungolfed 버전을 요청했습니다. 참고 &?전화 또는 패턴이 일치 할 때 추가 괄호를 필요로 삼항 중위 연산자이다.

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에게 감사드립니다.


나는 haskell을 처음 사용하는데 꽤 좋아 보이지만,하고있는 일에 대한 설명을 추가해 주시겠습니까?
WizardOfMenlo

1
@WizardOfMenlo : 일부 의견을 추가
nimi

Haskell이 얼마나 우아한 지 깨달았습니다.
WizardOfMenlo

1
무한 목록과 효율성을 무시합니다 m#q=reverse$f((:).m)[]q. 이것은 당신과 같은 길이이지만 읽기가 훨씬 어렵습니다.
dfeuer

!연산자 대신 이름을 지정하여 단축 할 수 있습니다 i f=f..
dfeuer

5

파이썬 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람다에서하는 방법 은 높이 평가되므로 어떤 기능도 수행 할 필요가 없습니다 (Shudder.).

설명 :

  • 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 (a))[1:-1].replace(",","-1],a[")+"-1])")
    • range 함수를 사용하여 인덱스 1-len (list)을 가져옵니다. 목록의 올바른 색인을 얻는 방법으로 문자열 화 된 목록의 쉼표를 바꿉니다 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들은 그들에게 for 루프가 그렇게 나쁘지 않은 것을 보여주기 위해 더 필요합니다 :)
Blue

하아! 다른 버전을 사용하는 e=eval:r=lambda i:e("r(i-1)+"*(i>1)+"[i]")
Zgarb

보너스를 60 % 보너스에서 10 %로 변경할 수 있습니까? 나는 그래서 더 공정하게, 질문 사양을 수정
WizardOfMenlo

5

자바 스크립트 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)) :

0으로 감소 할 f때까지 재귀 적으로 적용하십시오 n.

적용 ( A=(f,l)=>f(...l)) :

spread ( ...) 연산자를 사용하여 에 적용 l합니다 f.

사거리 ( R=n=>n--?[...R(n),n+1]:[]) :

0으로 감소 할 때까지 범위의n 재귀 호출에 연결 합니다 .n

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

의 재귀 호출 적용 폴드n의 '번째 요소를 lf까지 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 및 아이 맥스 destructuring을 (사용하는 [n,x]=i) 다음 사용 범위 IMAX로 IMIN의 값의 테이블을 구성한다. f그런 다음 Map을 사용하여 테이블 위에 적용되고 결과가 반환됩니다.


내 철학을 알고 싶어? "싸면 산다." 스펙에서는 내장을 사용할 수 없다고 말하지 않으므로 사용하십시오!
Mama Fun Roll 1

4

파이썬 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적용, 0이 될 때까지 되풀이 f. 끝에있는 if 절은 어색한 느낌입니다. 아마도 재귀를 끝내는 더 좋은 방법이있을 것입니다.

기능 적용 T

T=lambda f,x:f(*x)
파이썬에는 멋진 확장 연산자가있어 무거운 작업을 모두 수행합니다.

범위 기능 H

H=lambda f,x=0:(H(f-1)if~-f else[])+[f]
이것은 내가 예상했던 것보다 더 힘들었다. 재귀적인 접근을하게되었습니다. 다시 말하지만 if-else 구성은 많은 바이트를 차지하며 개선 될 수 있다고 생각합니다. 왜 더미가 x=0있습니까? 을 사용하여 압축 할 때 just 대신 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)) 일종의 구성에 했지만 많은 성공을 거두지 못했습니다. 레인지 함수와 유사한 점을 공유 하는 끔찍한 재귀 접근 방식을 사용했습니다.

모든 람다는 바이트 수를 크게 줄이기 위해 execa replace로 싸여 있습니다.


나는 [f(_)for _ in x]짧아 질 수 있다고 언급하려고 map(f,x)했지만 그 도전이 무엇인지 기억했다
Cyoce

4

줄리아, 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에 익숙한 경우 꽤 읽을 수 있어야합니다. ( q(quote) 및 i(if)를 제외하고 대부분의 tinylisp 내장의 별칭을 지정했습니다 .)

(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단항 함수에 (따옴표)를 사용 하고 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 바이트 (10 % 할인 전 449 바이트)

골프 답변 :

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

이 질문은 재미있었습니다. 나는 파이썬 등가물을 사용하지 않고 함수를 작성하기로 결정했지만 (유효한 허점 일 수도 있었지만) 파이썬이 꼬리 재귀를 지원하는 것처럼 함수를 작성하기로 결정했습니다. 이 작업을 수행하기 위해 필요한 호출이 계속 작동하도록하는 많은 선택적 매개 변수를 사용했습니다.

아래에는 각 기능에 대한 골프화 목록이 있습니다.

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

그것은 미적 감각이 왜곡 된 것처럼 보인다. ) 필자가 읽은 첫 번째 파이썬 책이 파이썬이 가독성을 강화하는 방법에 대해 이야기 한 이래로 항상 골프를 친 파이썬을 보는 것이 재미 있다는 것을 알았습니다.
sadakatsu

나는 실제로 미적 감각이 왜곡되어 있습니다. :)
WizardOfMenlo

나는 다른 사람들의 점수에 혼란을 느낍니다. 루프를 사용하지 않은 필수 함수 각각의 점수의 10 % (모두 해당)를 사용했지만 다른 사람들은 루프를 사용하지 않는 각 함수에 대해 전체 점수의 10 %를 가졌습니다 ( 최대 60 % 할인). 올바른 방법은 무엇입니까?
sadakatsu

당신이 갈 수있는 올바른 방법이다, 나는 비현실적인 기대를 가지고 그래서 처음에 나는 마음 60 %의 접근 방식에 있었지만, 지금은 10 %가 자극 더 될 것이라고 생각하고 둘 사이의 righter
WizardOfMenlo

2

실론, 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]])];

실제로 두 개의 함수 ( tf) 만 실제로 실제로 재귀를 사용하고 (각각 목록 및 정수), 다른 함수 는 이들을 기반으로합니다. (적용은 약간 이상치이며 실제로 다른 것과 관련이 없습니다.)

나는 "List"를 Ceylon의 Sequential 타입으로 해석하는데, 이것은 불변의 순서가 붙은 (아마도 비어있는) 요소들의 시퀀스입니다. 어떤 [R*]의미에서 Sequential<R>우리는 또한 그것을 쓸 수 있습니다R[] 있는데 이는 1 바이트 더 짧다.

함수 타입은이며 Callable<R, A>, 여기서 A인자에 대한 튜플 타입은 [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으로 지정하면 더 짧아 질 수 있습니다 . 부정 행위처럼 보입니다.)

경우 ..허용되지 않습니다, 우리는 다시 구현해야합니다. 우리는 이러한 구현을 사용할 수 있습니다 rt합니다 (로 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

그루비 (146 바이트) (146 * 90 % = 131.4)

추신 : 나는이 맥락에서 당신이 '루프'로 간주하는 것을 모른다 .OP에 의해 의견을 들었을 때만 보너스를 적용했으며 2-3 명의 추가 사용자가 이러한 수집 기능과 반복자를 말하면 제거합니다. 루프이며 보너스를받을 자격이 없습니다. 또한, 1..it 사용시 저를 불러내려면 다시 작업하고 바이트 수를 업데이트하십시오.

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.