Combinatore a punto fisso golfato


9

Scrivi un combinatore a virgola fissa nel minor numero di caratteri possibile, nella lingua che preferisci.

  • forma libera ( vale a dire , qualunque sia la più breve): intero programma, funzione effettiva, frammento di codice
  • non puoi usare la tua libreria standard se ne ha una
  • puoi comunque estrarlo da altre funzioni di alto livello, preferiresti farlo piuttosto che costruirlo dalle basi

Includi un fattoriale ricorsivo o Fibonacci che lo utilizza come demo.

In questa domanda, l'auto-riferimento è accettabile, lo scopo è solo quello di rimuoverlo dalla funzione ricorsiva a cui si applicherà.


Un'implementazione in linguaggio pigro va bene? (Accetteresti (define Y(lambda(f)(f(Y f))))?)
Eelvex,

Qualsiasi implementazione che puoi dimostrare con uno degli esempi richiesti è ok.
JB

1
Se non sbaglio, a rigor di termini, il termine "combinatore a Y" si riferisce specificamente a un singolo combinatore a punto fisso scoperto da Haskell Curry, λf. (Λx.f (xx)) (λx.f (xx)).
Joey Adams,

@Eelvex: ovviamente entrambe le risposte finora (compresa la risposta dell'OP) usano il modo di imbrogliare, quindi, suppongo che lo renda bene. :-P Personalmente, preferirei seguire l'approccio di @ Joey e dire che solo il vero combinatore Y (non autoreferenziale) lo farà. ;-)
Chris Jester-Young,

@ Chris: Oh mio. Questo è quello che avevo in mente inizialmente, e poi ... ho dimenticato lungo la strada. È un po 'troppo tardi per cambiare adesso, dovremo aprire un'altra domanda.
JB

Risposte:


13

Haskell: 10 personaggi

y f=f$y f

Esempio di utilizzo per creare definizioni ricorsive di fattoriale o n-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]

Tuttavia, un modo più comune di utilizzare ysarebbe generare queste sequenze direttamente, piuttosto che come funzioni:

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

Certo, con Haskell, è un po 'come sparare al pesce in una botte! La Data.Functionlibreria ha questa funzione, chiamata fix, sebbene implementata in modo un po 'più prolisso.


4

Perl, 37

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

Dimostrazione fattoriale:

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

Dimostrazione di 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 caratteri

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

Esempio:

#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 caratteri

L'ovvia implementazione autoreferenziale è la più breve. Questo è un segno di un buon design del linguaggio. Sfortunatamente, K non è pigro, quindi possiamo gestire solo chiamate per valore.

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

Questa definizione dovrebbe funzionare anche in k4 e q senza problemi, anche se presumo k2 per gli esempi seguenti.

  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 caratteri più modesti ci permette di trascrivere esattamente (λx. x x) (λxyz. y (x x y) z)in K.

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

Forse un giorno (k7?), Potrebbe sembrare Y:{x Y x}.


0

Python 3, 30 byte

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

Demo:

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

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


Python 3 ha un filtro. Inoltre mi dispiace di aver trascurato di contrassegnare quel commento come uno scherzo
Cyoce

Il filtro di Python 3 restituisce un oggetto filtro e non un elenco. Sarebbe meno leggibile o pythonic usare il filtro.
Labo,

sarebbe meno Pythonic, ma più in linea era la programmazione funzionale , che era il mio punto
Cyoce
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.