Combinateur de points fixes golf

9

Écrivez un combinateur à virgule fixe en aussi peu de caractères que possible, dans la langue de votre choix.

  • forme libre ( c'est-à - dire ce qui est le plus court): programme entier, fonction réelle, extrait de code
  • vous ne pouvez pas utiliser votre bibliothèque standard si elle en a une
  • vous pouvez cependant l'extraire d'autres fonctions de haut niveau si vous préférez le faire plutôt que de le construire à partir des bases

Veuillez inclure une factorielle récursive ou Fibonacci qui l'utilise comme démo.

Dans cette question, l'auto-référence est acceptable, le but est uniquement de la retirer de la fonction récursive à laquelle elle s'appliquera.

JB
la source
Une implémentation en langage paresseux est-elle correcte? (Accepteriez-vous (define Y(lambda(f)(f(Y f))))?)
Eelvex
Toute implémentation que vous pouvez démontrer avec l'un des exemples demandés est correcte.
JB
1
Si je ne me trompe pas à proprement parler, le terme "combinateur Y" se réfère spécifiquement à un combinateur à point fixe unique découvert par Haskell Curry, λf. (Λx.f (xx)) (λx.f (xx)).
Joey Adams
@Eelvex: De toute évidence, les deux réponses jusqu'à présent (y compris la propre réponse de l'OP) utilisent la façon de tricher, donc, je suppose que cela va bien. :-P Personnellement, je préfère aller avec l'approche de @ Joey et dire que seul le combinateur Y réel (non auto-référentiel) fera l'affaire. ;-)
Chris Jester-Young
@Chris: Oh mon Dieu. C'est ce que j'avais en tête au départ, puis j'ai ... oublié en cours de route. Il est un peu trop tard pour changer maintenant, nous allons devoir ouvrir une autre question.
JB

Réponses:

13

Haskell: 10 caractères

y f=f$y f

Exemple d'utilisation pour créer des définitions récursives de factorielle ou nième-Fibonacci:

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

Cependant, une façon plus courante d'utiliser yserait de générer ces séquences directement, plutôt qu'en tant que fonctions:

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

Bien sûr, avec Haskell, c'est un peu comme tirer du poisson dans un tonneau! La Data.Functionbibliothèque a cette fonction, appelée fix, bien que mise en œuvre un peu plus verbalement.

MtnViewMark
la source
4

Perl, 37

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

Démonstration factorielle:

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

Démonstration de Fibonacci:

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
la source
3

GNU C - 89 caractères

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

Exemple:

#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
la source
1

k2, 12 caractères

La mise en œuvre autoréférentielle évidente est la plus courte. C'est un signe de bonne conception du langage. Malheureusement, K n'est pas paresseux, nous ne pouvons donc gérer que les appels par valeur.

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

Cette définition devrait également fonctionner en k4 et q sans problème, bien que je suppose que k2 pour les exemples ci-dessous.

  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

Un 18 caractères plus modestes nous permet de transcrire exactement (λx. x x) (λxyz. y (x x y) z)en K.

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

Peut-être qu'un jour (k7?), Cela pourrait ressembler Y:{x Y x}.

algorithmshark
la source
0

Python 3, 30 octets

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

Démo:

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

Crédits: https://gist.github.com/WoLpH/17552c9508753044e44f

Labo
la source
Python 3 a un filtre. Aussi, je suis désolé d'avoir négligé de marquer ce commentaire comme une blague
Cyoce
Le filtre de Python 3 renvoie un objet filtre et non une liste. Il serait moins lisible ou pythonique d'utiliser le filtre.
Labo
ce serait moins Pythonic, mais plus en ligne était la programmation fonctionnelle , ce qui était mon point
Cyoce