Domanda

Ho creato l'ultimo generatore di risate usando queste regole. Puoi implementarlo nella tua lingua preferita in modo intelligente?

Regole:

Ad ogni iterazione, si verificano le seguenti trasformazioni.

H   -> AH
A   -> HA
AA  -> HA
HH  -> AH
AAH -> HA
HAA -> AH

n = 0 |  H
n = 1 |  AH
n = 2 |  HAAH
n = 3 |  AHAH
n = 4 |  HAAHHAAH
n = 5 |  AHAHHA
n = 6 |  HAAHHAAHHA
n = 7 |  AHAHHAAHHA
n = 8 |  HAAHHAAHHAAHHA
n = 9 |  AHAHHAAHAHHA
n = ...
È stato utile?

Soluzione

MATLAB (v7.8.0):

73 caratteri (esclusi i caratteri di formattazione utilizzati per renderlo leggibile)

Questo script (" haha.m ") presuppone che tu abbia già definito la variabile n :

s = 'H';
for i = 1:n,
  s = regexprep(s,'(H)(H|AA)?|(A)(AH)?','${[137-$1 $1]}');
end

... ed ecco la versione di una riga:

s='H';for i=1:n,s = regexprep(s,'(H)(H|AA)?|(A)(AH)?','${[137-$1 $1]}');end

Prova:

>> for n=0:10, haha; disp([num2str(n) ': ' s]); end
0: H
1: AH
2: HAAH
3: AHAH
4: HAAHHAAH
5: AHAHHA
6: HAAHHAAHHA
7: AHAHHAAHHA
8: HAAHHAAHHAAHHA
9: AHAHHAAHAHHA
10: HAAHHAAHHAHAAHHA

Altri suggerimenti

Lex / Flex

69 caratteri. Nel testo qui, ho cambiato le schede in 8 spazi in modo che appaia giusto, ma tutti quegli spazi consecutivi dovrebbero essere schede e le schede sono importanti, quindi arriva a 69 caratteri.

        #include <stdio.h>
%%
HAA|HH|H        printf("AH");
AAH|AA|A        printf("HA");

Per quello che vale, il lex.yy.c generato è di 42736 caratteri, ma non credo che conta davvero. Posso (e presto) scrivere una versione in puro C che sarà molto più breve e farà la stessa cosa, ma penso che probabilmente dovrebbe essere una voce separata.

Modifica

Ecco una voce Lex / Flex più legittima (302 caratteri):

        char*c,*t;
        #define s(a) t=c?realloc(c,strlen(c)+3):calloc(3,1);if(t)c=t,strcat(c,#a);
%%
        free(c);c=NULL;
HAA|HH|H        s(AH)
AAH|AA|A        s(HA)
%%
int main(void){c=calloc(2,1);if(!c)return 1;*c='H';for(int n=0;n<10;n++)printf("n = %d |  %s\n",n,c),yy_scan_string(c),yylex();return 0;}int yywrap(){return 1;}

Questo fa più iterazioni (a differenza dell'ultima, che ha fatto solo una iterazione e ha dovuto essere seminata manualmente ogni volta, ma ha prodotto i risultati corretti) e ha il vantaggio di essere un codice dall'aspetto estremamente orribile. Uso una macro di funzione, l'operatore di stringa e due variabili globali. Se vuoi una versione ancora più disordinata che non controlli nemmeno l'errore malloc () , sembra così (282 caratteri):

        char*c,*t;
        #define s(a) t=c?realloc(c,strlen(c)+3):calloc(3,1);c=t;strcat(c,#a);
%%
        free(c);c=NULL;
HAA|HH|H        s(AH)
AAH|AA|A        s(HA)
%%
int main(void){c=calloc(2,1);*c='H';for(int n=0;n<10;n++)printf("n = %d |  %s\n",n,c),yy_scan_string(c),yylex();return 0;}int yywrap(){return 1;}

Una versione ancora peggiore potrebbe essere inventata dove c è un array nello stack, e gli diamo solo un MAX_BUFFER_SIZE di qualche tipo, ma sento che sta prendendo questo troppo lontano.

... Sto solo scherzando. 207 caratteri se prendiamo i " 99 caratteri sempre sarà sufficiente " mentalità:

        char c[99]="H";
%%
        c[0]=0;
HAA|HH|H    strcat(c, "AH");
AAH|AA|A    strcat(c, "HA");
%%
int main(void){for(int n=0;n<10;n++)printf("n = %d |  %s\n",n,c),yy_scan_string(c),yylex();return 0;}int yywrap(){return 1;}

La mia preferenza è per quella che funziona meglio (cioè la prima che può iterare fino a quando la memoria si esaurisce e controlla i suoi errori), ma questo è il golf del codice.

Per compilare il primo, digitare:

flex golf.l
gcc -ll lex.yy.c

(Se hai lex invece di flex , cambia flex in lex . Dovrebbero essere compatibili .)

Per compilare gli altri, digitare:

flex golf.l
gcc -std=c99 lex.yy.c

Altrimenti GCC si lamenterà di & # 8216; per & # 8217; dichiarazione iniziale in loop utilizzata al di fuori della modalità C99 e altre cazzate.

Risposta in puro C in arrivo.

Una semplice traduzione in Haskell:

grammar = iterate step
    where
        step ('H':'A':'A':xs) = 'A':'H':step xs
        step ('A':'A':'H':xs) = 'H':'A':step xs
        step ('A':'A':xs) = 'H':'A':step xs
        step ('H':'H':xs) = 'A':'H':step xs
        step ('H':xs) = 'A':'H':step xs
        step ('A':xs) = 'H':'A':step xs
        step [] = []

E una versione più breve (122 caratteri, ottimizzata fino a tre regole di derivazione + caso base):

grammar=iterate s where{i 'H'='A';i 'A'='H';s(n:'A':m:x)|n/=m=m:n:s x;s(n:m:x)|n==m=(i n):n:s x;s(n:x)=(i n):n:s x;s[]=[]}

E una traduzione in C ++ (182 caratteri, esegue una sola iterazione, invoca con lo stato iniziale sulla riga di comando):

#include<cstdio>
#define o putchar
int main(int,char**v){char*p=v[1];while(*p){p[1]==65&&~*p&p[2]?o(p[2]),o(*p),p+=3:*p==p[1]?o(137-*p++),o(*p++),p:(o(137-*p),o(*p++),p);}return 0;}

JavaScript:

120 stripping di spazi bianchi e lo sto lasciando da solo ora!

function f(n,s){s='H';while(n--){s=s.replace(/HAA|AAH|HH?|AA?/g,function(a){return a.match(/^H/)?'AH':'HA'});};return s}

Expanded:

function f(n,s)
{
    s = 'H';
    while (n--)
    {
        s = s.replace(/HAA|AAH|HH?|AA?/g, function(a) { return a.match(/^H/) ? 'AH' : 'HA' } );
    };
    return s
}

quel sostituto è costoso!

Ecco un esempio in C #, che arriva a 321 byte se riduco gli spazi bianchi a uno spazio tra ogni elemento.

Modifica : in risposta al @Johannes R & # 246; ssel commento, Ho rimosso i generici dalla soluzione per eliminare qualche byte in più.

Modifica : un'altra modifica, ho eliminato tutte le variabili temporanee.

public static String E(String i)
{
    return new Regex("HAA|AAH|HH|AA|A|H").Replace(i, 
        m => (String)new Hashtable {
            { "H", "AH" },
            { "A", "HA" },
            { "AA", "HA" },
            { "HH", "AH" },
            { "AAH", "HA" },
            { "HAA", "AH" }
        }[m.Value]);
}

La soluzione riscritta con meno spazi bianchi, che viene comunque compilata, è di 158 caratteri:

return new Regex("HAA|AAH|HH|AA|A|H").Replace(i,m =>(String)new Hashtable{{"H","AH"},{"A","HA"},{"AA","HA"},{"HH","AH"},{"AAH","HA"},{"HAA","AH"}}[m.Value]);

Per una soluzione completa di codice sorgente per Visual Studio 2008, di seguito è disponibile un repository di sovversione con il codice necessario, inclusi i test unitari.

Il repository è qui , nome utente e password sono entrambe "guest", senza virgolette.

Rubino

Questo codice golf non è molto ben specificato - ho assunto che la funzione che restituisce n - la stringa di iterazione sia il modo migliore per risolverlo. Ha 80 caratteri.

def f n
a='h'
n.times{a.gsub!(/(h(h|aa)?)|(a(ah?)?)/){$1.nil?? "ha":"ah"}}
a
end

Stampa del codice n prime stringhe (71 caratteri):

a='h';n.times{puts a.gsub!(/(h(h|aa)?)|(a(ah?)?)/){$1.nil?? "ha":"ah"}}

Erlang

241 byte e pronto per l'esecuzione:

> erl -noshell -s g i -s init stop
AHAHHAAHAHHA

-module(g).
-export([i/0]).
c("HAA"++T)->"AH"++c(T);
c("AAH"++T)->"HA"++c(T);
c("HH"++T)->"AH"++c(T);
c("AA"++T)->"HA"++c(T);
c("A"++T)->"HA"++c(T);
c("H"++T)->"AH"++c(T);
c([])->[].
i(0,L)->L;
i(N,L)->i(N-1,c(L)).
i()->io:format(i(9,"H"))

Probabilmente potrebbe essere migliorato.

Perl 168 caratteri.

(senza contare le nuove righe non necessarie)

perl -E'
($s,%m)=qw[H H AH A HA AA HA HH AH AAH HA HAA AH];
sub p{say qq[n = 

Perl 168 caratteri.

(senza contare le nuove righe non necessarie)

use strict;
use warnings;
use 5.010;

my $str = 'H';

my %map = (
    H => 'AH',
    A => 'HA',
   AA => 'HA',
   HH => 'AH',
  AAH => 'HA',
  HAA => 'AH'
);

sub prn{
 my( $n, $str ) = @_;
 say "n = $n |  $str"
}

prn( 0, $str );

for my $i ( 1..9 ){
  $str =~ s(
    (
      H(?:AA|H)? # HAA | HH | H
    |
      A(?:AH?)?  # AAH | AA | A
    )
  ){
    $map{$1}
  }xge;

  prn( $i, $str );
}

say 'n = ...';

De-offuscato:

perl -E'
$s="H";
sub p{say qq[n = 

Perl 168 caratteri.

(senza contare le nuove righe non necessarie)

perl -E'
($s,%m)=qw[H H AH A HA AA HA HH AH AAH HA HAA AH];
sub p{say qq[n = 

Perl 168 caratteri.

(senza contare le nuove righe non necessarie)

use strict;
use warnings;
use 5.010;

my $str = 'H';

my %map = (
    H => 'AH',
    A => 'HA',
   AA => 'HA',
   HH => 'AH',
  AAH => 'HA',
  HAA => 'AH'
);

sub prn{
 my( $n, $str ) = @_;
 say "n = $n |  $str"
}

prn( 0, $str );

for my $i ( 1..9 ){
  $str =~ s(
    (
      H(?:AA|H)? # HAA | HH | H
    |
      A(?:AH?)?  # AAH | AA | A
    )
  ){
    $map{$1}
  }xge;

  prn( $i, $str );
}

say 'n = ...';

De-offuscato:

#! /usr/bin/env perl
use strict;
use warnings;
use 5.010;

my $str = 'H';

sub prn{
 my( $n, $str ) = @_;
 say "n = $n |  $str"
}

prn( 0, $str );

for my $i ( 1..9 ){
  $str =~ s{(?|
        (H)(?:AA|H)? # HAA | HH | H
      |
        (A)(?:AH?)?  # AAH | AA | A
    )}{
      ( 'H' eq $1 ?'A' :'H' ).$1
    }egx;
  prn( $i, $str );
}

say 'n = ...';

Perl 150 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato

<*>[0] |

Perl 168 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato:

<*>

Perl 150 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato

<*>[1]]};p(0,$s); for(1..9){$s=~s/(H(AA|H)?|A(AH?)?)/$m{$1}/g;p(

Perl 168 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato:

<*>

Perl 150 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato

<*>,$s)} say q[n = ...]'

De-offuscato:

<*>

Perl 150 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato

<*>[0] |

Perl 168 caratteri.

(senza contare le nuove righe non necessarie)

perl -E'
($s,%m)=qw[H H AH A HA AA HA HH AH AAH HA HAA AH];
sub p{say qq[n = 

Perl 168 caratteri.

(senza contare le nuove righe non necessarie)

use strict;
use warnings;
use 5.010;

my $str = 'H';

my %map = (
    H => 'AH',
    A => 'HA',
   AA => 'HA',
   HH => 'AH',
  AAH => 'HA',
  HAA => 'AH'
);

sub prn{
 my( $n, $str ) = @_;
 say "n = $n |  $str"
}

prn( 0, $str );

for my $i ( 1..9 ){
  $str =~ s(
    (
      H(?:AA|H)? # HAA | HH | H
    |
      A(?:AH?)?  # AAH | AA | A
    )
  ){
    $map{$1}
  }xge;

  prn( $i, $str );
}

say 'n = ...';

De-offuscato:

<*>

Perl 150 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato

<*>[0] |

Perl 168 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato:

<*>

Perl 150 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato

<*>[1]]};p(0,$s); for(1..9){$s=~s/(H(AA|H)?|A(AH?)?)/$m{$1}/g;p(

Perl 168 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato:

<*>

Perl 150 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato

<*>,$s)} say q[n = ...]'

De-offuscato:

<*>

Perl 150 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato

<*>[1]]};p(0,$s); for(1..9){$s=~s/(?|(H)(?:AA|H)?|(A)(?:AH?)?)/("H"eq$1?"A":"H").$1/eg;p(

Perl 168 caratteri.

(senza contare le nuove righe non necessarie)

perl -E'
($s,%m)=qw[H H AH A HA AA HA HH AH AAH HA HAA AH];
sub p{say qq[n = 

Perl 168 caratteri.

(senza contare le nuove righe non necessarie)

use strict;
use warnings;
use 5.010;

my $str = 'H';

my %map = (
    H => 'AH',
    A => 'HA',
   AA => 'HA',
   HH => 'AH',
  AAH => 'HA',
  HAA => 'AH'
);

sub prn{
 my( $n, $str ) = @_;
 say "n = $n |  $str"
}

prn( 0, $str );

for my $i ( 1..9 ){
  $str =~ s(
    (
      H(?:AA|H)? # HAA | HH | H
    |
      A(?:AH?)?  # AAH | AA | A
    )
  ){
    $map{$1}
  }xge;

  prn( $i, $str );
}

say 'n = ...';

De-offuscato:

<*>

Perl 150 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato

<*>[0] |

Perl 168 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato:

<*>

Perl 150 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato

<*>[1]]};p(0,$s); for(1..9){$s=~s/(H(AA|H)?|A(AH?)?)/$m{$1}/g;p(

Perl 168 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato:

<*>

Perl 150 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato

<*>,$s)} say q[n = ...]'

De-offuscato:

<*>

Perl 150 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato

<*>,$s)} say q[n = ...]'

Perl 150 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato

<*>[0] |

Perl 168 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato:

<*>

Perl 150 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato

<*>[1]]};p(0,$s); for(1..9){$s=~s/(H(AA|H)?|A(AH?)?)/$m{$1}/g;p(

Perl 168 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato:

<*>

Perl 150 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato

<*>,$s)} say q[n = ...]'

De-offuscato:

<*>

Perl 150 caratteri.

(senza contare le nuove righe non necessarie)

<*>

De-offuscato

<*>

Python (150 byte)

import re
N = 10
s = "H"
for n in range(N):
    print "n = %d |"% n, s
    s = re.sub("(HAA|HH|H)|AAH|AA|A", lambda m: m.group(1) and "AH" or "HA",s)

uscita
n = 0 | H
n = 1 | AH
n = 2 | HAAH
n = 3 | AHAH
n = 4 | HAAHHAAH
n = 5 | AHAHHA
n = 6 | HAAHHAAHHA
n = 7 | AHAHHAAHHA
n = 8 | HAAHHAAHHAAHHA
n = 9 | AHAHHAAHAHHA

Ecco una versione C ++ molto semplice:

#include <iostream>
#include <sstream>
using namespace std;

#define LINES 10

#define put(t) s << t; cout << t

#define r1(o,a,c0) \
    if(c[0]==c0) {put(o); s.unget(); s.unget(); a; continue;}
#define r2(o,a,c0,c1) \
    if(c[0]==c0 && c[1]==c1) {put(o); s.unget(); a; continue;}
#define r3(o,a,c0,c1,c2) \
    if(c[0]==c0 && c[1]==c1 && c[2]==c2) {put(o); a; continue;}

int main() {
    char c[3];
    stringstream s;
    put("H\n\n");
    for(int i=2;i<LINES*2;) {
        s.read(c,3);
        r3("AH",,'H','A','A');
        r3("HA",,'A','A','H');
        r2("AH",,'H','H');
        r2("HA",,'A','A');
        r1("HA",,'A');
        r1("AH",,'H');
        r1("\n",i++,'\n');
    }
}

Non è esattamente code-golf (potrebbe essere molto più breve), ma funziona. Cambia LINES per quante righe vuoi stampare (nota: non funzionerà per 0 ). Stampa l'output in questo modo:

H

AH

HAAH

AHAH

HAAHHAAH

AHAHHA

HAAHHAAHHA

AHAHHAAHHA

HAAHHAAHHAAHHA

AHAHHAAHAHHA

ANSI C99

Entra in un brutale 306 personaggi:

#include <stdio.h>
#include <string.h>
char s[99]="H",t[99]={0};int main(){for(int n=0;n<10;n++){int i=0,j=strlen(s);printf("n = %u |  %s\n",n,s);strcpy(t,s);s[0]=0;for(;i<j;){if(t[i++]=='H'){t[i]=='H'?i++:t[i+1]=='A'?i+=2:1;strcat(s,"AH");}else{t[i]=='A'?i+=1+(t[i+1]=='H'):1;strcat(s,"HA");}}}return 0;}

Ci sono troppi if nidificati e operatori condizionali per poterlo ridurre efficacemente con le macro. Credimi, ci ho provato. Versione leggibile:

#include <stdio.h>
#include <string.h>
char s[99] = "H", t[99] = {0};
int main()
{
    for(int n = 0; n < 10; n++)
      {
        int i = 0, j = strlen(s);
        printf("n = %u |  %s\n", n, s);
        strcpy(t, s);
        s[0] = 0;
        /*
         * This was originally just a while() loop.
         * I tried to make it shorter by making it a for() loop.
         * I failed.
         * I kept the for() loop because it looked uglier than a while() loop.
         * This is code golf.
         */
        for(;i<j;)
          {
            if(t[i++] == 'H' )
              {
                // t[i] == 'H' ? i++ : t[i+1] == 'A' ? i+=2 : 1;
                // Oh, ternary ?:, how do I love thee?
                if(t[i] == 'H')
                    i++;
                else if(t[i+1] == 'A')
                    i+= 2;
                strcat(s, "AH");
              }
            else
              {
                // t[i] == 'A' ? i += 1 + (t[i + 1] == 'H') : 1;
                if(t[i] == 'A')
                    if(t[++i] == 'H')
                        i++;
                strcat(s, "HA");
              }
          }
      }
    return 0;
}

Potrei riuscire a realizzare una versione più breve con strncmp () in futuro, ma chi lo sa? Vedremo cosa succede.

In python:

def l(s):
 H=['HAA','HH','H','AAH','AA','A']
 L=['AH']*3+['HA']*3
 for i in [3,2,1]:
  if s[:i] in H: return L[H.index(s[:i])]+l(s[i:])
 return s

def a(n,s='H'):
 return s*(n<1)or a(n-1,l(s))

for i in xrange(0,10):
 print '%d: %s'%(i,a(i))

Primo tentativo: 198 caratteri di codice, sono sicuro che può ridursi: D

REBOL, 150 caratteri. Sfortunatamente REBOL non è un linguaggio favorevole al codice golf, ma 150 caratteri non sono troppo squallidi, come dice Adam Sandler.

Ciò presuppone che la variabile di ciclo m sia già stata definita.

s: "H" r: "" z:[some[["HAA"|"HH"|"H"](append r "AH")|["AAH"|"AA"|"A"](append r "HA")]to end]repeat n m[clear r parse s z print["n =" n "|" s: copy r]]

Ed eccolo con un layout migliore:

s: "H"
r: ""
z: [
    some [
        [ "HAA" | "HH" | "H" ] (append r "AH")
    |   [ "AAH" | "AA" | "A" ] (append r "HA")
    ]
    to end
]

repeat n m [
    clear r
    parse s z
    print ["n =" n "|" s: copy r]
]

F #: 184 caratteri

Sembra mappare abbastanza chiaramente su F #:

type grammar = H | A
let rec laugh = function
    | 0,l -> l
    | n,l ->
        let rec loop = function
            |H::A::A::x|H::H::x|H::x->A::H::loop x
            |A::A::H::x|A::A::x|A::x->H::A::loop x
            |x->x
        laugh(n-1,loop l)

Ecco una corsa in fsi:

> [for a in 0 .. 9 -> a, laugh(a, [H])] |> Seq.iter (fun (a, b) -> printfn "n = %i: %A" a b);;
n = 0: [H]
n = 1: [A; H]
n = 2: [H; A; A; H]
n = 3: [A; H; A; H]
n = 4: [H; A; A; H; H; A; A; H]
n = 5: [A; H; A; H; H; A]
n = 6: [H; A; A; H; H; A; A; H; H; A]
n = 7: [A; H; A; H; H; A; A; H; H; A]
n = 8: [H; A; A; H; H; A; A; H; H; A; A; H; H; A]
n = 9: [A; H; A; H; H; A; A; H; A; H; H; A]
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top