Комбінатор з фіксованою точкою для гольфу


9

Напишіть комбінатор з фіксованою точкою якомога менше символів мовою, яку ви обрали.

  • вільна форма ( тобто найкоротша версія): вся програма, фактична функція, фрагмент коду
  • ви не можете використовувати вашу стандартну бібліотеку, якщо вона має її
  • Ви можете, однак, витягнути його з інших функцій високого рівня, але це краще зробити, ніж побудувати з баз

Будь ласка, додайте рекурсивний факторіал або Фібоначчі, який використовує його як демонстраційну версію.

У цьому питанні самопосилання є прийнятною, мета полягає виключно в тому, щоб вилучити її з рекурсивної функції, до якої вона застосовуватиметься.


Чи все в порядку ледачої мови? (Чи прийняли б ви (define Y(lambda(f)(f(Y f))))?)
Ельвакс

Будь-яка реалізація, яку ви можете продемонструвати одним із запитуваних прикладів, добре.
JB

1
Якщо я не помиляюсь, строго кажучи, термін "Y комбінатор" стосується конкретно комбінатора єдиної точки фіксації, виявленого Haskell Curry, λf. (Λx.f (xx)) (λx.f (xx)).
Joey Adams

@Eelvex: Очевидно, що обидві відповіді поки що (включаючи власну відповідь ОП) використовують спосіб обману, так що, я думаю, це робить нормально. :-P Особисто я б скоріше пішов із підходом @ Joey і скажу, що тільки справжній (нереференційний) комбінатор Y зробить. ;-)
Кріс Єстер-Янг

@Chris: О, мій. Це я мав на увазі спочатку, а потім я по дорозі забув. Зараз це занадто пізно, щоб змінитись, нам доведеться відкрити ще одне питання.
JB

Відповіді:


13

Haskell: 10 символів

y f=f$y f

Приклад використання для створення рекурсивних визначень факторіального або n-го-Фібоначчі:

> map ( y(\f n->if n <= 1 then 1 else n*f(n-1)) ) [1..10]
[1,2,6,24,120,720,5040,40320,362880,3628800]

> map ( y(\f n->if n <= 1 then 1 else f(n-1)+f(n-2)) ) [0..10]
[1,1,2,3,5,8,13,21,34,55,89]

Хоча більш поширеним способом використання yбуло б генерування цих послідовностей безпосередньо, а не як функції:

> take 10 $ y(\p->1:zipWith (*) [2..] p)
[1,2,6,24,120,720,5040,40320,362880,3628800]

> take 11 $ y(\f->1:1:zipWith (+) f (tail f))
[1,1,2,3,5,8,13,21,34,55,89]

Звичайно, з Haskell це трохи схоже на стрільбу риби в бочку! Data.FunctionБібліотека має цю функцію, яка називається fix, хоча реалізується кілька більш докладно.


4

Перл, 37

sub f{my$s=$_[0];sub{$s->(f($s),@_)}}

Факторна демонстрація:

sub fact {
  my ($r, $n) = @_;
  return 1 if $n < 2;
  return $n * $r->($n-1);
}
print "Factorial $_ is ", f(\&fact)->($_), "\n" for 0..10;

Демонстрація Фібоначчі:

sub fib {
  my ($r, $n) = @_;
  return 1 if $n < 2;
  return $r->($n-1) + $r->($n-2);
}
print "Fibonacci number $_ is ", f(\&fib)->($_), "\n" for 0..10;

3

GNU C - 89 символів

#define fix(f,z)({typeof(f)__f=(f);typeof(__f(0,z))x(typeof(z)n){return __f(x,n);}x(z);})

Приклад:

#define lambda2(arg1, arg2, expr) ({arg1;arg2;typeof(expr)__f(arg1,arg2){return(expr);};__f;})

int main(void)
{
    /* 3628800 */
    printf("%ld\n", fix(lambda2(
        long factorial(int n), int n, 
            n < 2 ? 1 : n * factorial(n-1)
        ), 10));

    /* 89 */
    printf("%ld\n", fix(lambda2(
        long fibonacci(int n), int n, 
            n < 2 ? 1 : fibonacci(n-1) + fibonacci(n-2)
        ), 10));

    return 0;
}

1

k2, 12 char

Очевидна самореференційна реалізація є найкоротшою. Це ознака гарного мовного дизайну. На жаль, K не лінивий, тому ми можемо керувати лише за замовчуванням.

Y:{x[Y[x]]y}

Це визначення також має працювати без проблем у k4 та q, хоча я припускаю k2 для наведених нижче прикладів.

  Y:{x[Y[x]]y}
  fac: {[f;arg] :[arg>0; arg*f[arg-1]; 1]}
  Y[fac] 5
120
  fib: {[f;arg] :[arg>1; f[arg-1] + f[arg-2]; arg]}
  Y[fib]' !10
0 1 1 2 3 5 8 13 21 34

Більш скромний 18 символів дозволяє нам точно переписати (λx. x x) (λxyz. y (x x y) z)на К.

{x[x]}{y[x[x;y]]z}

Можливо, колись (k7?) Це могло виглядати так Y:{x Y x}.


0

Пітон 3, 30 байт

Y=lambda f:lambda a:f(Y(f))(a)

Демонстрація:

Y=lambda f:lambda a:f(Y(f))(a)
quicksort = Y(
lambda f:
    lambda x: (
        f([item for item in x if item < x[0]])
        + [y for y in x if x[0] == y]
        + f([item for item in x if item > x[0]])
    ) if x
    else []
)
print(quicksort([1, 3, 5, 4, 1, 3, 2]))

Кредити: https://gist.github.com/WoLpH/17552c9508753044e44f


У Python 3 є фільтр. Також мені шкода, що я знехтував позначити цей коментар як жарт
Cyoce

Фільтр Python 3 повертає об'єкт фільтра, а не список. Використовувати фільтр було б менш читабельним чи пітонічним.
Лабо

це було б менш пітонічно, але більше в руслі було функціональне програмування , що було моєю точкою
Cyoce
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.