Frage

Ich haben das Letzte lachen-generator anhand dieser Regeln.Können Sie es implementieren in Ihrer bevorzugten Sprache auf eine geschickte Art und Weise?

Regeln:

Bei jeder iteration werden die folgenden Transformationen auftreten.

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 = ...
War es hilfreich?

Lösung

MATLAB (V7.8.0):

73 Zeichen (ohne Formatierungszeichen verwendet, um es lesbar aussehen)

Dieses Skript ( "haha.m") setzt voraus, Sie haben bereits die Variable definiert n :

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

... und hier ist die einzeilige Version:

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

Test:

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

Andere Tipps

Lex / Flex

69 Zeichen. Im Text hier, änderte es Tabs 8 Leerzeichen so wäre es richtig aussehen, aber alle diese aufeinanderfolgenden Leerzeichen sollten Registerkarten sein, und die Laschen sind wichtig, damit es aus zu 69 Zeichen kommt.

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

Für das, was es wert ist, das erzeugte lex.yy.c ist 42.736 Zeichen, aber ich glaube nicht, dass wirklich zählt. Ich kann (und bald wird) schreibe eine reinen-C-Version, die viel kürzer sein und das gleiche tun, aber ich glaube, das sollte wohl ein eigener Eintrag sein.

EDIT:

Hier ist ein mehr legit Lex / Flex-Eintrag (302 Zeichen):

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

Dies macht mehrere Iterationen (im Gegensatz zu den letzten, die nur eine Iteration tat, und musste jedes Mal manuell ausgesät werden, aber produziert die richtigen Ergebnisse) und hat den Vorteil, dass sie extrem schrecklich aussehenden Code. Ich benutze eine Funktion Makro, den Zeichenfolgen Operator und zwei globale Variablen. Wenn Sie eine noch unordentlicher Version möchten, die nicht einmal für malloc() Ausfall nicht überprüft, sieht es wie folgt aus (282 Zeichen):

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

Eine noch schlechtere Version zusammengebraut werden könnte, wo c ein Array auf dem Stapel ist, und wir ihm nur ein MAX_BUFFER_SIZE irgendeine Art geben, aber ich fühle, dass diese Einnahme ist zu weit.

... Nur ein Scherz. 207 Zeichen, wenn wir nehmen die "99 Zeichen werden immer genug sein, um" Einstellung:

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

Meine Präferenz ist für die, die am besten (das heißt das erste, das laufen kann, bis die Speicherkapazität erschöpft und überprüft seine Fehler) funktioniert, aber das ist Code Golf.

die erste zu kompilieren, geben Sie:

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

(Wenn Sie statt lex flex haben, nur flex zu lex ändern. Sie sollten kompatibel sein.)

, die andere zu kompilieren, geben Sie:

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

Oder GCC wird jammern über ‘for’ loop initial declaration used outside C99 mode und anderen Mist.

Pure-C-Antwort zu finden.

Eine einfache Übersetzung 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 [] = []

Und eine kürzere Version (122 Zeichen, optimiert auf drei Ableitungsregeln + Basisfall):

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[]=[]}

Und eine Übersetzung C ++ (182 Zeichen, nicht nur eine Iteration, rufen Sie mit Anfangszustand in der Befehlszeile):

#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 Leerzeichen Strippen und ich verlasse es jetzt allein!

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}

Erweitert:

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
}

, dass replacer ist teuer!

Hier ist ein C# - Beispiel, kommen bei 321 bytes, wenn ich die Leerzeichen um ein Leerzeichen zwischen jedem Element.

Bearbeiten:In Antwort auf @Johannes Rössel Kommentar habe ich entfernt Generika aus der Lösung zu suchen sich ein paar bytes mehr.

Bearbeiten:Eine weitere änderung, losgeworden alle temporären Variablen.

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

Der neu geschriebene Lösung mit weniger Leerraum, der noch kompiliert, 158 Zeichen:

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

Für eine vollständige source-code-Lösung für Visual Studio 2008, ein subversion-repository mit den erforderlichen code, unit-tests, finden Sie unten.

Repository ist hier, Benutzername und Passwort sind sowohl für "Gast", ohne die Anführungszeichen.

Rubin

Dieser Code Golf ist nicht sehr gut angegeben - ging ich davon aus, dass die Funktion der Rückkehr n -te Iteration String ist bester Weg, es zu lösen. Es hat 80 Zeichen.

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

Code-Ausdrucke n erste Strings (71 Zeichen):

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

Erlang

241 Bytes und bereit zu laufen:

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

Könnte wahrscheinlich verbessert werden.

Perl 168 Zeichen.

(nicht unnötig neue Zeilen zu zählen)

perl -E'
($s,%m)=qw[H H AH A HA AA HA HH AH AAH HA HAA AH];
sub p{say qq[n = $_[0] |  $_[1]]};p(0,$s);
for(1..9){$s=~s/(H(AA|H)?|A(AH?)?)/$m{$1}/g;p($_,$s)}
say q[n = ...]'

De-verschleiert:

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 = ...';

Perl 150 Zeichen.

(nicht unnötig neue Zeilen zu zählen)

perl -E'
$s="H";
sub p{say qq[n = $_[0] |  $_[1]]};p(0,$s);
for(1..9){$s=~s/(?|(H)(?:AA|H)?|(A)(?:AH?)?)/("H"eq$1?"A":"H").$1/eg;p($_,$s)}
say q[n = ...]'

De-verschleierte

#! /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 = ...';

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)

Output

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

Hier ist eine sehr einfache C ++ Version:

#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');
    }
}

Es ist nicht gerade Code-Golf (es viel kürzer gemacht werden könnte), aber es funktioniert. Ändern LINES auf wie viele Zeilen, die Sie gedruckt werden sollen (Anmerkung: es wird nicht für 0 arbeiten). Es wird eine Ausgabe wie diese gedruckt werden:

H

AH

HAAH

AHAH

HAAHHAAH

AHAHHA

HAAHHAAHHA

AHAHHAAHHA

HAAHHAAHHAAHHA

AHAHHAAHAHHA

ANSI C99

Kommen bei einem brutalen 306 Zeichen in:

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

Es gibt zu viele verschachtelten ifs und bedingte Operatoren für mich effektiv zu reduzieren, dies mit Makros. Glauben Sie mir, ich versuchte. Lesbare Version:

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

Vielleicht kann ich eine kürzere Version mit strncmp() in der Zukunft machen, aber wer weiß? Wir werden sehen, was passiert.

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

Erster Versuch: 198 Zeichen von Code, ich bin sicher, es kann kleiner werden: D

REBOL, 150 Zeichen. REBOL ist keine Sprache förderlich Code Golf Leider aber 150 Zeichen ist nicht zu schäbig, wie Adam Sandler sagt.

Dies setzt der Schleifenvariable m bereits definiert wurde.

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

Und hier ist es mit einem besseren Layout:

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 Zeichen

Scheint ziemlich sauber zu F # zur Karte:

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)

Hier ist ein Lauf 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]
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top