関数型プログラミングパラダイムを実装する


21

あなたの会社はプロジェクトを始めたばかりで、初めて関数型プログラミングコードスタイルを使用することに決めました。しかし、上司は本当に気が進まないため、組み込み関数を使用したくないため、メイン関数を自分で実装する必要があります。特に、あなたは関数を記述する必要があります:MapNestApplyRangeFoldTableお好みの言語で。上司は本当に忙しいので、プログラムをできるだけ短くしたいので、読書に時間を浪費しません。彼はまた、ループを使用しないことを望んでいるため、ループを使用しない場合のバイトカウントが10%削減されます。

機能の詳細な要件は以下のとおりです。

地図

Mapこの関数は2つのパラメータを取ります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機能は同様に3つのパラメータを取ります:fargtimesどこ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この関数は2つのパラメータを取りますfし、argsどこfの機能とあるargsリスト。に適用fする必要がありますargs。したがって:

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

返す

f(a,b,c)

範囲

このRange関数は1つの整数rを取り、その数までの整数を出力します。したがって:

Range(5)

返す

{ 1, 2, 3, 4, 5}

折ります

Foldこの関数は3つのパラメータを取りfargothersどこfの関数である、arg簡単なパラメータ、及びあるothersリスト。以下のように機能します:

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

返す

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

表関数は、function f、および次iteratorの形式で呼び出されるパラメーターを取る必要{iMin, iMax}iMinありiMaxます。where およびは整数です。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ありがとうございます!タイプミスだったことはい、私は、しかし、私はそれを得ることができると思い、象徴feautureとしてそれを使用してMathematicaに参照としてのXを左
WizardOfMenlo

もう1つの質問:関数にどのように名前を付けますか?まったく同じ名前を付ける必要がありますか?一文字?
kirbyfan64sos

@ kirbyfan64sosこれはコードゴルフなので、1文字の名前を許可しますが、答えでは各機能に見出しを付けて、どの機能であるかを確認します。また、衝突する文字を使用しないでください。
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]

?折り畳まれている:((+) ? 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に感謝


私はhaskellを初めて使用しますが、非常に良いように見えますが、あなたが何をしているのか説明を加えていただけますか?
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ラムダで行う方法があればいいので、関数を実行する必要はありません(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])")
    • 範囲関数を使用して、インデックス1-len(list)を取得します。文字列化されたリスト内のコンマを、リストの正しいインデックスを取得する方法に置き換えますa。それを評価します!
  • f=lambda f,x,l:eval("f("*len(l)+"x,["+r(len(l))[1:-1].replace(",","-1]),l[")+"-1])")
    • applyと同じですが、コンマを閉じ括弧、コンマで置き換え、リストインデックスを開始します。
  • t=lambda f,n,x:eval("[f("+r(x)[n-1:].replace(",","),f(")[1:-1]+")]")
    • 関数を終了して新しい関数を呼び出すことで置き換える以外は、applyおよびfoldと同じです。それを評価します!

マップ、ネスト、範囲、適用、折りたたみ、テーブル。

範囲のラムダを@Zgarbに感謝します!


私の上司は私の頭を私の机の上に置いてくれます:)簡単な説明もお願いします。
WizardOfMenlo

どうr=lambda i:[]if i<1 else r(i-1)+[i]?ループなし、再帰のみ。
ズガルブ

1
確かに、私は今のためにそれを取るだろうが、より多くの上司のニーズはeval:)それほど悪くはありませんどのようにループのそれらを表示する
ブルー

ハ!を使用する別のバージョンe=evalr=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)):

Foldを使用してf、すべてのメンバーに適用された結果をl空のリストに連結します。組み込み関数を使用すると、thisが減少します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(...)演算子を使用して適用lfます。

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

0に減分されるまでnRangeの再帰呼び出しに連結し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)))):

最初にデストラクタリング()を使用してiMinおよびiMaxを初期化nし、次にRangeを使用してiMinからiMaxへの値のテーブルを構築します。次に、Mapを使用してテーブルに適用され、結果が返されます。x[n,x]=if


私の哲学を知りたいですか?「安いなら買う。」スペックでは、(まだ)ビルトインを使用できないとは言っていないので、それらを使用してください!
ママファンロール

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

一度に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毎回適用されます。最後のif節は不格好な感じがします。おそらく、再帰を終了するより良い方法があります。

機能を適用 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があるのですか?で圧縮すると、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))一種の構築用に定義された範囲およびマップ関数を使用しようとしましたが、あまり成功しませんでした。範囲関数とある程度の類似性を共有するひどい再帰的アプローチを行うことになりました。

すべてのラムダは、バイトカウントを大幅に短縮するためにexecでラップされreplaceます。


私は[f(_)for _ in x]に短縮できるコメントをしようmap(f,x)としていましたが、その挑戦が何であったかを思い出しました
チョイス

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(apply)、M(map)、N(nest)、R(range)、T(table)、およびF(fold)を、いくつかのヘルパー関数とともに定義します。T2番目の引数には2つの整数のリストが必要です。

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%割引前の493バイト)

ゴルフの答え:

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の本はPythonが読みやすさをどのように強制するかについて話していたので、私はゴルフをしたPythonを見ることは常に面白いと思います。
貞勝

私は確かに美学の歪んだ感覚を持っています:)
WizardOfMenlo

私は他の人のスコアに混乱しています。私は、ループを使用しなかった必要な関数(すべて)のスコアの10%を取得しましたが、他の人はループを使用しなかった各関数のスコア全体の10%を取得しました(これは最大60%オフ)。正しいアプローチはどれですか?
貞勝

あなたが行くための正しい方法ですが、私は非現実的な期待を持っていたので、最初は、私は心の中で60%のアプローチを持っていたが、今は10%より多くの刺激と2の間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)のうち2つだけが実際に再帰を使用しています(それぞれリストと整数に対して)。他の関数はこれらに基づいています。(Applyは少し外れ値であり、実際には他のものとは関係ありません。)

「リスト」をCeylonのシーケンシャル型と解釈します。これは、要素の不変の順序付けられた(空の場合もある)シーケンスです。[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になります。それは不正行為のように見えますが。)

..許可されていない場合は、再度実装する必要があります。当社は、のために、これらの実装を使用することができます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バイト)(146 * 90%= 131.4)

PSこのコンテキストで「ループ」として何を考えているのかわかりません。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 {}はイテレータです。
魔法のタコUr
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.