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.


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.


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;

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;
}

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}.


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


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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.