Kombinator stałoprzecinkowy z golfem

9

Napisz kombinator punktów stałych z jak najmniejszą liczbą znaków, w wybranym języku.

  • dowolna forma ( tzn . najkrótsza): cały program, aktualna funkcja, fragment kodu
  • nie możesz używać swojej standardowej biblioteki, jeśli ma taką bibliotekę
  • możesz jednak wyodrębnić go z innych funkcji wysokiego poziomu, które wolisz to zrobić niż zbudować z podstaw

Podaj rekurencyjną silnię lub Fibonacciego, która używa jej jako wersji demonstracyjnej.

W tym pytaniu samo-odniesienie jest dopuszczalne, jego celem jest jedynie usunięcie go z funkcji rekurencyjnej, do której będzie się odnosił.

JB
źródło
Czy implementacja leniwego języka jest w porządku? (Czy zaakceptowałbyś (define Y(lambda(f)(f(Y f))))?)
Eelvex
Każda implementacja, którą możesz zademonstrować za pomocą jednego z wymaganych przykładów, jest w porządku.
JB
1
Jeśli się nie mylę, ściśle mówiąc, termin „kombinator Y” odnosi się konkretnie do pojedynczego kombinatora punktów stałych odkrytego przez Haskell Curry, λf. (Λx.f (xx)) (λx.f (xx)).
Joey Adams,
@Eelvex: Oczywiście obie dotychczasowe odpowiedzi (w tym odpowiedź OP) wykorzystują sposób oszukiwania, więc myślę, że to jest w porządku. :-P Osobiście wolałbym podejście @ Joeya i powiedziałbym, że zrobi to tylko prawdziwy (nie-referencyjny) kombinator Y. ;-)
Chris Jester-Young
@Chris: Oh my. Właśnie to miałem na myśli, a potem ... zapomniałem po drodze. Jest już trochę za późno na zmiany, będziemy musieli otworzyć kolejne pytanie.
JB

Odpowiedzi:

13

Haskell: 10 znaków

y f=f$y f

Przykład zastosowania do tworzenia rekurencyjnych definicji czynnikowych lub n-Fibonacciego:

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

Jednak bardziej powszechnym sposobem użycia ybyłoby wygenerowanie tych sekwencji bezpośrednio, a nie jako funkcji:

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

Oczywiście w przypadku Haskell jest to trochę jak strzelanie do ryb w beczce! Data.FunctionBiblioteka posiada tę funkcję, o nazwie fix, choć nieco bardziej realizowane --long.

MtnViewMark
źródło
4

Perl, 37

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

Demonstracja czynnikowa:

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

Demonstracja Fibonacciego:

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;
JB
źródło
3

GNU C - 89 znaków

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

Przykład:

#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;
}
Joey Adams
źródło
1

k2, 12 znaków

Oczywista implementacja autoreferencji jest najkrótsza. To znak dobrego projektowania języka. Niestety K nie jest leniwy, więc możemy zarządzać tylko wartością według wartości.

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

Ta definicja powinna również działać bez problemu w k4 i q, choć zakładam, że k2 dla poniższych przykładów.

  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

Bardziej skromne 18 znaków pozwala nam dokładnie zapisać się (λx. x x) (λxyz. y (x x y) z)na K.

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

Może kiedyś (k7?) Może to wyglądać Y:{x Y x}.

algorytmshark
źródło
0

Python 3, 30 bajtów

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

Próbny :

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

Kredyty: https://gist.github.com/WoLpH/17552c9508753044e44f

Labo
źródło
Python 3 ma filtr. Również przepraszam, że zaniedbałem oznaczyć ten komentarz jako żart
Cyoce
Filtr Python 3 zwraca obiekt filtru, a nie listę. Użycie filtru byłoby mniej czytelne lub pytoniczne.
Labo
byłoby mniej Pythońskie, ale bardziej zgodne było programowanie funkcjonalne , o co mi
chodziło