Leggi la dichiarazione della variabile C.


42

sfondo

L'istruzione di dichiarazione delle variabili in C è composta da tre parti: il nome della variabile, il suo tipo di base e i modificatori del tipo .

Esistono tre tipi di modificatori di tipo:

  • Puntatore *(prefisso)
  • Array [N](postfix)
  • Funzione ()(postfisso)
    • Puoi specificare un elenco di argomenti di funzione all'interno delle parentesi, ma per il bene di questa sfida, ignoriamolo e usiamolo ()(che tecnicamente significa "la funzione può accettare qualsiasi tipo di argomento").

E un modo per leggere le notazioni è il seguente:

int i;             // i is an int
float *f;          // f is a pointer to a float
my_struct_t s[10]; // s is an array of 10 my_struct_t
int func();        // func is a function returning an int

Il problema è che possiamo mescolare tutti questi per formare un tipo più complicato, come un array di array o un array di puntatori a funzione o un puntatore a un array di puntatori :

int arr[3][4];
// arr is an array of 3 arrays of 4 ints

int (*fptrs[10])();
// fptrs is an array of 10 pointers to functions returning an int

float *(*p)[16];
// p is a pointer to an array of 16 pointers to float

Come ho letto queste dichiarazioni complicate?

  1. Inizia dal nome della variabile. (name) is ...
  2. Seleziona il modificatore con la precedenza più alta.
  3. Leggilo:
    • * -> pointer to ...
    • [N] -> array of N ...
    • () -> function returning ...
  4. Ripeti 2 e 3 fino ad esaurimento dei modificatori.
  5. Infine, leggi il tipo di base. ... (base type).

In C, gli operatori postfix hanno la precedenza sugli operatori prefissi e i modificatori di tipo non fanno eccezione. Pertanto, []e ()associare prima, quindi *. Qualsiasi cosa all'interno di una coppia di parentesi (...)(da non confondere con l'operatore di funzione) si lega prima di tutto a qualsiasi cosa all'esterno.

Esempio illustrato:

int (*fptrs[10])();
      fptrs           fptrs is ...
           [10]       array of 10 ... // [] takes precedence over *
    (*         )      pointer to ...
                ()    function returning ...
int                   int

Compito

Data una riga di dichiarazione di dichiarazione variabile scritta in C, genera l'espressione inglese che descrive la riga, usando il metodo mostrato sopra.

Ingresso

L'input è una singola istruzione C che include un singolo tipo di base, un singolo nome di variabile, zero o più modificatori di tipo e il punto e virgola finale. Devi implementare tutti gli elementi di sintassi descritti sopra, oltre a:

  • Sia il tipo di base che il nome della variabile corrispondono all'espressione regolare [A-Za-z_][A-Za-z0-9_]*.
  • Teoricamente, il tuo programma dovrebbe supportare un numero illimitato di modificatori di tipo.

È possibile semplificare altri elementi della sintassi C nei modi seguenti (è gradita anche l'implementazione completa):

  • Il tipo base è sempre una sola parola, per esempio int, float, uint32_t, myStruct. Qualcosa del genere unsigned long longnon verrà testato.
  • Per la notazione di matrice [N], il numero Nsarà sempre un unico numero intero positivo scritto in base 10. I cose simili int a[5+5], int a[SIZE]o int a[0x0f]non sarà testato.
  • Per la notazione della funzione (), nessun parametro verrà specificato affatto, come indicato sopra.
  • Per gli spazi bianchi, 0x20verrà utilizzato solo il carattere spazio . È possibile limitare il programma all'utilizzo specifico di spazi bianchi, ad es
    • Utilizzare solo uno spazio dopo il tipo di base
    • Usa uno spazio ovunque tra i token
  • Tuttavia, non è possibile utilizzare due o più spazi consecutivi per trasmettere più informazioni che essere un separatore di token.

Secondo la sintassi C, le seguenti tre combinazioni non sono valide e quindi non verranno testate:

  • f()() Funzione di ritorno alla funzione
  • f()[] Array di ritorno funzioni
  • a[]() Matrice di N funzioni

Gli sviluppatori C usano invece questi moduli equivalenti (e tutti questi sono trattati nei casi di test):

  • (*f())()Funzione che restituisce il puntatore alla funzione
  • *f()Funzione che restituisce il puntatore al primo elemento dell'array
  • (*a[])()Matrice di N puntatori per funzionare

Produzione

L'output è una singola frase inglese. Non è necessario (ma è possibile se lo si desidera) rispettare la grammatica inglese, ad esempio l'uso di a, an, theforme singolari / plurali e il punto finale (punto). Ogni parola deve essere separata da uno o più spazi bianchi (spazio, tabulazione, nuova riga) in modo che il risultato sia leggibile dall'uomo.

Ancora una volta, ecco il processo di conversione:

  1. Inizia dal nome della variabile. (name) is ...
  2. Seleziona il modificatore con la precedenza più alta.
  3. Leggilo:
    • * -> pointer to ...
    • [N] -> array of N ...
    • () -> function returning ...
  4. Ripeti 2 e 3 fino ad esaurimento dei modificatori.
  5. Infine, leggi il tipo di base. ... (base type).

Casi test

int i;              // i is int
float *f;           // f is pointer to float
my_struct_t s[10];  // s is array of 10 my_struct_t
int func();         // func is function returning int
int arr[3][4];      // arr is array of 3 array of 4 int
int (*fptrs[10])(); // fptrs is array of 10 pointer to function returning int
float *(*p)[16];    // p is pointer to array of 16 pointer to float

_RANdom_TYPE_123 (**(*_WTH_is_TH15)())[1234][567];
/* _WTH_is_TH15 is pointer to function returning pointer to pointer to array of
   1234 array of 567 _RANdom_TYPE_123 */

uint32_t **(*(**(*(***p)[2])())[123])[4][5];
/* p is pointer to pointer to pointer to array of 2 pointer to function returning
   pointer to pointer to array of 123 pointer to array of 4 array of 5 pointer to
   pointer to uint32_t */

uint32_t (**((*(**(((*(((**(*p)))[2]))())))[123])[4])[5]);
// Same as above, just more redundant parens

some_type (*(*(*(*(*curried_func())())())())())();
/* curried_func is function returning pointer to function returning pointer to
   function returning pointer to function returning pointer to
   function returning pointer to function returning some_type */

Punteggio e criterio di vincita

Questa è una sfida di . Vince il programma con il minor numero di byte.


9
Correlato: cdecl.org
user202729

int arr[3][4];è an array of 3 arrays of 4 ints(come dici tu), oppure an array of 4 arrays of 3 ints?
Charlie,

1
@Charlie Il primo è corretto. sizeof(arr[0]) == sizeof(int[4]), quindi un elemento di arrcontiene quattro ints.
Bubbler,

1
L'input contiene il ;alla fine della riga?
Black Owl Kai,

2
@KamilDrakari È il secondo. "array di puntatore a funzione" è essenzialmente "array di puntatore", che è perfettamente valido in C.
Bubbler

Risposte:


17

Python 3 , 331 312 294 261 240 byte

from re import*
class V(str):__pos__=lambda s:V(s+'pointer to ');__call__=lambda s:V(s+'function returning ');__getitem__=lambda s,i:V(s+'array of %i '%i)
t,e=input().split()
print(eval(sub('\*','+',sub('(\w+)',r'V("\1 is ")',e[:-1],1)))+t)

Provalo online!

-19 byte passando a Python 2 e inserendo la definizione della classe in un exec

-18 byte modificando la regex da [a-zA-Z_][a-zA-Z0-9_]*a \\w+, grazie a Kevin Cruijssen

-33 byte lavorando un po 'di definizione di classe e usando str, grazie a Lynn, tornando a Python 3

-21 byte unendo più regex, grazie a infmagic2047

Richiede che nell'input sia contenuto solo uno spazio (tra il tipo e l'espressione).

Penso che questo sia un approccio piuttosto singolare al problema. Ciò utilizza principalmente il fatto che Python stesso può valutare stringhe simili (**((*(**(((*(((**(*p)))[2]))())))[123])[4])[5])e ottenere la sequenza corretta di chiamate di funzione, indici di array e puntatori - e che l'utente può sovraccaricarle.


1
Bel approccio, +1 da parte mia! Puoi giocare [a-zA-Z_][A-Za-z0-9_]*a golf per [a-zA-Z_]\\w*risparmiare qualche byte. EDIT: In realtà, penso che puoi semplicemente usare al \\w+posto di [a-zA-Z_][A-Za-z0-9_]*.
Kevin Cruijssen,

Mi piace questo approccio :) eccolo qui in 253 byte
Lynn il

1
È un buon punto. 261 è allora.
Lynn,

1
È possibile utilizzare [0]anziché .group()da Python 3.6.
infmagic2047,


13

Retina 0.8.2 , 142 138 128 117 byte

(\w+) (.+);
($2) $1
\(\)
 function returning
\[(\d+)?]
 array of$#1$* $1
+`\((\**)(.+)\)
$2$1
\*
 pointer to
1` 
 is 

Provalo online! Il link include casi di test. Grammatica migliore . Modifica: salvato 10 21 byte eseguendo il porting della soluzione Pip di DLosc. Spiegazione:

(\w+) (.+);
($2) $1

Spostare il tipo alla fine e avvolgere il resto della dichiarazione in ()s nel caso contenga un esterno *.

\(\)
 function returning

Elabora qualsiasi funzione.

\[(\d+)?]
 array of$#1$* $1

Elaborare eventuali array.

+`\((\**)(.+)\)
$2$1

Spostare eventuali puntatori alla fine delle loro parentesi, ed eliminare le parentesi, lavorando ripetutamente dall'insieme più esterno di parentesi verso l'interno.

\*
 pointer to

Elabora tutti i puntatori.

1` 
 is 

Inserisci il is.


7

Java 11, 469 467 463 450 byte

s->{String r="",t,S[];for(s=s.replace("()","~");s.contains("(");s=s.replace(t,"").replace("()",""),r+=t+";")t=s.replaceAll(".*(\\([^()]+\\)).*","$1");S=s.split(" ");t=S[0];r+=r.isEmpty()?S[1]:s;S=r.split(";");r=S[0].replaceAll(".*?(\\w+).*","$1 is ");for(var p:S)r+=p.replaceAll("[A-Za-z_]+\\d+|[^\\[\\d]","").replaceAll("\\[(\\d+)","array of $1 ")+(p.contains("~")?"function returning ":"")+"pointer to ".repeat(p.split("\\*").length-1);return r+t;}

Provalo online.

Spiegazione:

s->{               // Method with String as both parameter and return-type
  String r="",     //  Result-String, starting empty
         t,        //  Temp-String, starting uninitialized
         S[];      //  Temp String-array, starting uninitialized
  for(s=s.replace("()","~");
                   //  Replace all "()" in the input `s` with "~"
      s.contains("(");
                   //  Loop as long as the input `s` still contains "("
      ;            //    After every iteration:
       s=s.replace(t,"")
                   //     Remove `t` from `s`
          .replace("()",""),
                   //     And also remove any redundant parenthesis groups
       r+=t+";")   //     Append `t` and a semi-colon to the result-String
    t=s.replaceAll(".*(\\([^()]+\\)).*","$1");
                   //   Set `t` to the inner-most group within parenthesis
  S=s.split(" ");  //  After the loop, split the remainder of `s` on the space
  t=S[0];          //  Set `t` to the first item (the type)
  r+=              //  Append the result-String with:
    r.isEmpty()?   //   If the result-String is empty
                   //   (so there were no parenthesis groups)
     S[1]          //    Set the result-String to the second item
    :              //   Else:
     s;            //    Simple append the remainder of `s`
  S=r.split(";");  //  Then split `r` on semi-colons
  r=S[0].replaceAll(".*?(\\w+).*",
                   //  Extract the variable name from the first item
     "$1 is ");    //  And set `r` to this name appended with " is "
  for(var p:S)     //  Loop over the parts split by semi-colons:
    r+=            //   Append the result-String with:
      p.replaceAll("[A-Za-z_]+\\d+
                   //    First remove the variable name (may contain digits)
         |[^\\[\\d]","")
                   //    And then keep only digits and "["
       .replaceAll("\\[(\\d+)",
                   //    Extract the number after "["
         "array of $1 ")
                   //    And append the result-String with "array of " and this nr
      +(p.contains("~")?
                   //    If the part contains "~"
         "function returning "
                   //     Append the result-String with "function returning "
       :           //    Else:
        "")        //     Leave the result-String the same
      +"pointer to ".repeat(
                   //    And append "pointer to " repeated
         p.split("\\*").length-1);
                   //    the amount of "*" in the part amount of time
  return r         //  Then return the result-String
          +t;}     //  appended with the temp-String (type)

Errore nel caso di test con parentesi ridondanti.
Bubbler,

@Bubbler Ah, non ho notato quel nuovo caso di test. Fortunatamente è una soluzione semplice.
Kevin Cruijssen,

6

Bash + cdecl + GNU sed, 180

cdeclè una venerabile utility Unix che fa la maggior parte di ciò che è richiesto qui, ma al fine di soddisfare i requisiti I / O, sono necessari alcuni sedpre e post-processing:

sed -r 's/^/explain struct /;s/struct (int|char double|float|void) /\1 /;s/\bfunc/_func/g'|cdecl|sed -r 's/^declare //;s/as/is/;s/struct //g;s/([0-9]+) of/of \1/g;s/\b_func/func/g'
  • Nessun tentativo fatto per correggere la grammatica.

sed Pre-elaborazione:

  • s/^/explain struct /- Aggiungi "spiega struct" all'inizio di ogni riga
  • s/struct (int|char double|float|void) /\1 /- Rimuovere structquando si tratta di tipi di linguaggio C.
  • s/\bfunc/_func/g - "func" è riconosciuto come una parola chiave da cdecl - sopprimilo

sed Post-elaborazione:

  • s/^declare // - rimuovere "dichiara" all'inizio della riga
  • s/as/is/ - autoesplicativo
  • s/struct //g - rimuovere tutte le parole chiave "struct"
  • s/([0-9]+) of/of \1/g - corretto ordinamento di "di"
  • s/\b_func/func/g - ripristina qualsiasi "_func" che è stato sostituito nella pre-elaborazione

In azione:

$ < cdecls.txt sed -r 's/^/explain struct /;s/struct (int|char double|float|void) /\1 /;s/\bfunc/_func/g'|cdecl|sed -r 's/^declare //;s/as/is/;s/struct //g;s/([0-9]+) of/of \1/g;s/\b_func/func/g'
i is int
f is pointer to float
s is array of 10 my_struct_t
func is function returning int
arr is array of 3 array of 4 int
fptrs is array of 10 pointer to function returning int
p is pointer to array of 16 pointer to float
_WTH_is_TH15 is pointer to function returning pointer to pointer to array of 1234 array of 567 _RANdom_TYPE_123
p is pointer to pointer to pointer to array of 2 pointer to function returning pointer to pointer to array of 123 pointer to array of 4 array of 5 pointer to pointer to uint32_t
p is pointer to pointer to pointer to array of 2 pointer to function returning pointer to pointer to array of 123 pointer to array of 4 array of 5 pointer to pointer to uint32_t
curried_func is function returning pointer to function returning pointer to function returning pointer to function returning pointer to function returning pointer to function returning some_type
$ 

Sarebbe sufficiente fare s/\bfu/_fu/ge salvare i byte della funcsostituzione completa ?
DLosc,

aspetta è una vera utility? Ho sempre pensato che fosse il nome del sito web
phuclv,

@phuclv cdecl è una vera utility e molto utile per controllare le dichiarazioni C.
Patricia Shanahan,


Non riesce per una variabile denominata as(+4 byte per gli spazi da correggere). Non ho accesso a, cdeclma penso che puoi salvare 64 byte usando sed -r 's/^(\w+)(\W+)/explain struct \1_\2_/'|cdecl|sed -r 's/^declare struct _|_$//;s/ as / is /;s/([0-9]+) of/of \1/g'.
Neil,

6

Pip -s , 152 150 148 139 137 126 125 123 byte

Terzo approccio!

YaRs" ("R';')R`\[(\d+)]`` array of \1`R"()"" function returning"L#aYyR`\((\**)(.+)\)`{c." pointer to"X#b}{[b"is"g@>2a]}Vy^s

Prende la dichiarazione come input da riga di comando. Provalo online!

Spiegazione

Il codice è suddiviso in tre parti: impostazione iniziale e gestione delle funzioni e degli array; un ciclo che gestisce parentesi e puntatori; e un riarrangiamento finale.

Setup, funzioni e array

Vogliamo che l'intera dichiarazione sia tra parentesi (questo aiuta con il ciclo in seguito), quindi cambiamo type ...;in type (...). Quindi, osserva che non viene eseguito alcun riordino con le descrizioni di funzioni e array, in modo da poter eseguire prima tutte quelle sostituzioni senza influire sull'output finale.

Y                         Yank into y variable...
 a                        The result of a (the cmdline arg)...
  R s                     Replace the space
   " ("                    with " ("
  R ';                    Replace the semicolon
   ')                      with a closing paren
  R `\[(\d+)]`            Replace digits in square brackets
   ` array of \1`          with " array of <digits>"
  R "()"                  Replace function parens
   " function returning"   with " function returning"

Se il nostro input originale fosse float *((*p()))[16];, ora abbiamo float (*((*p function returning)) array of 16).

Parentesi e puntatori

Eseguiamo un ciclo che sostituisce la coppia più esterna di parentesi e tutti gli asterischi che si trovano immediatamente all'interno della parentesi aperta.

L#a                   Loop len(a) times (enough to complete all replacements):
 Y                    Yank into y variable...
  y                   The result of y...
   R `\((\**)(.+)\)`  Replace open paren, 0 or more asterisks (group 1), 1 or more
                      characters (group 2), and close paren
    {                  with this callback function (b = group 1, c = group 2):
     c .               The stuff in the middle, concatenated to...
      " pointer to"    that string
       X #b            repeated len(asterisks) times
    }

Passaggi di esempio:

float (*((*p function returning)) array of 16)
float ((*p function returning)) array of 16 pointer to
float (*p function returning) array of 16 pointer to
float p function returning pointer to array of 16 pointer to

Pulire

L'unica cosa rimasta è spostare il tipo fino alla fine e aggiungere "è":

{[b"is"g@>2a]}Vy^s
               y^s  Split y on spaces
{            }V     Use the resulting list as arguments to this function:
 [          ]        Return a list of:
  b                   2nd argument (the variable name)
   "is"               That string
       g@>2           All arguments after the 2nd
           a          1st argument (the type)
                    The resulting list is printed, joining on spaces (-s flag)

Per definizioni come int x;, questo approccio si tradurrà in uno spazio extra, che è consentito dalla sfida.


5

JavaScript (ES6), 316 ... 268 253 byte

s=>(g=s=>[/\d+(?=])/,/\*/,/!/,/.+ /,/\w+/].some((r,i)=>(S=s.replace(r,s=>(O=[O+`array of ${s} `,O+'pointer to ','function returning '+O,O+s,s+' is '+O][i],'')))!=s)?g(S):'',F=s=>(O='',S=s.replace(/\(([^()]*)\)/,g))!=s?O+F(S):g(s)+O)(s.split`()`.join`!`)

Provalo online!

Commentate

Funzione di aiuto

g = s =>                             // s = expression to parse
  [                                  // look for the following patterns in s:
    /\d+(?=])/,                      //   array
    /\*/,                            //   pointer
    /!/,                             //   function
    /.+ /,                           //   type
    /\w+/                            //   variable name
  ].some((r, i) =>                   // for each pattern r at index i:
    ( S = s.replace(                 //   S = new string obtained by removing
      r,                             //       the pattern matching r from s
      s => (                         //     using the first match s and the index i,
        O = [                        //     update the output O:
          O + `array of ${s} `,      //       array
          O + 'pointer to ',         //       pointer
          'function returning ' + O, //       function
          O + s,                     //       type
          s + ' is ' + O             //       variable name
        ][i],                        //
        ''                           //     replace the match with an empty string
    )))                              //   end of replace()
    != s                             //   make some() succeed if S is not equal to s
  ) ?                                // end of some(); if truthy:
    g(S)                             //   do a recursive call with S
  :                                  // else:
    ''                               //   stop recursion and return an empty string

Parte principale

s => (                 // s = input
  g = …,               // define the helper function g (see above)
  F = s => (           // F = recursive function, taking a string s
    O = '',            //   O = iteration output, initialized to an empty string
    S = s.replace(     //   S = new string obtained by removing the next expression from s
      /\(([^()]*)\)/,  //     look for the deepest expression within parentheses
      g                //     and process it with the helper function g
    )                  //   end of replace()
  ) != s ?             // if S is not equal to s:
    O + F(S)           //   append O to the final output and do a recursive call with S
  :                    // else (we didn't find an expression within parentheses):
    g(s) + O           //   process the remaining expression with g and return O
)(s.split`()`.join`!`) // initial call to F with all strings '()' in s replaced with '!'

Mi chiedevo perché tu l'abbia usato [...s.split`()`.join`!`]invece che solo [...s.replace('()','!')], ma mi sono reso conto che è esattamente lo stesso byte-count .. :)
Kevin Cruijssen,

@KevinCruijssen Il motivo principale è che s.replace('()','!')sostituirebbe solo la prima occorrenza.
Arnauld,

Ah certo. La sostituzione di JS dimenticata non è la stessa di Java. In Java .replacesostituisce tutte le occorrenze e .replaceAllsostituisce tutte le occorrenze con regex abilitato. Ho sempre pensato che la denominazione fosse piuttosto negativa per questi due metodi in Java, come li avrei chiamati .replaceAlle .regexReplaceAllo qualcosa del genere, ma immagino che per codegolf sia più breve come .replacee .replaceAll.
Kevin Cruijssen,

1
A proposito, ho notato che stavi usando la stessa tecnica (con ~) subito dopo aver pubblicato la prima versione della mia risposta. Le grandi menti pensano allo stesso modo, suppongo. : p
Arnauld,

3

Pulito , 415 byte

import StdEnv,Text
$s#(b,[_:d])=span((<>)' ')(init s)
=join" "(?d++[""<+b])
?[]=[]
?['()':s]=["function returning": ?s]
?['*':s]= ?s++["pointer to"]
?['[':s]#(n,[_:t])=span((<>)']')s
=["array of "<+n: ?t]
?s=case@0s of(['(':h],t)= ?(init h)++ ?t;(h,t)|t>[]= ?h++ ?t=[h<+" is"]
~c=app2((++)[c],id)
@n[c:s]=case c of'('= ~c(@(n+1)s);')'|n>1= ~c(@(n-1)s)=([c],s);_|n>0= ~c(@n s)=span(\c=c<>'('&&c<>'[')[c:s]
@_ e=(e,e)

Provalo online!


3

R , 225 218 byte

g=gsub
"&"="@"=paste
"["=function(a,b)a&"array of"&b
"+"=function(a)a&"pointer to"
eval(parse(t=g('\\(\\)','@"function returning"',g('(\\w+) (.*?)([A-Za-z_]\\w*)(.*);','\\2"\\3 is"\\4&"\\1"',g('\\*','+',readline())))))

Provalo online!

Programma completo, racchiuso in una funzione su TIO per un comodo test di tutti i casi di test contemporaneamente.

Innanzitutto, utilizziamo Regex per convertire l'input del modulo type ...name...;in ..."name is"..."type". La notazione di funzione ()viene quindi convertita in testo con un operatore di concatenazione con precedenza elevata. Sfortunatamente, dobbiamo anche sostituire *con +il primo non accettabile come operatore unario. Il resto è fatto da R evalcon operatori sovraccarichi.


1
Soluzione intelligente!
J.Doe,

3

Perl 6 , 209 190 171 162 153 byte

{~({(.[1]Z'is'),.<e>.&?BLOCK,('array of'X .[2]),('function returning','pointer to'Zxx.[3,0])if $_}(m:g/(\*)*[(\w+)+|\(<e=~~>.][\[(\d+).]*(\(.)*/[1]),$0)}

Provalo online!

Approccio regex ricorsivo. Produce alcuni caratteri di spazio extra che possono essere evitati al costo di 3 byte .

Spiegazione

{     # Anonymous block
 ~(   # Convert list to string
   {  # Block converting a regex match to a nested list
     (.[1]            # Array of 0 or 1 variable names
       Z'is'),        # zipped with string "is"
     .<e>.&?BLOCK,    # Recursive call to block with subexpression
     ('array of'      # String "array of"
       X .[2]),       # prepended to each array size
     ('function returning',  # Strings "function returning"
      'pointer to'           # and "pointer to"
      Zxx             # zipped repetition with
      .[3,0])         # number of function and pointer matches
     if $_            # Only if there's an argument
   }
   (             # Call block
     m:g/        # Input matched against regex
      (\*)*      # Sequence of asterisks, stored in [0]
      [          # Either
       (\w+)+    # the variable name, stored as 1-element array in [1]
       |         # or
       \(        # literal (
         <e=~~>  # the same regex matched recursively, stored in <e>
       .         # )
      ]
      [\[(\d+).]*  # Sequence of "[n]" with sizes stored in [2]
      (\(.)*       # Sequence of "()" stored in [3]
     /
     [1]  # Second match
   ),
   $0     # First match (base type)
 )
}

2

JavaScript 250 byte [249?]

Questo utilizza 250 byte:

k=>(a=k.match(/\W|\w+/g),s=[v=j=r=""],f=y=>!j&!a[i+1]||(m=a[i],v?(r+=v=m=='['?`array of ${a[i+=3,i-2]} `:m<')'?(i+=2,"function returning "):s[j-1]=='*'?j--&&"pointer to ":""):m==')'?v=j--|i++:m<'+'?s[j++]=a[i++]:r+=a[v=i++]+" is ",f(),r+a[0]),f(i=2))

Spiegazione:

Fondamentalmente, sta leggendo da un buffer a, che è l'input tokenizzato. Sposta continuamente i token dal buffer aa uno stack s, fino all'attivazione della modalità di valutazione. La modalità di valutazione consumerà prima le operazioni postfix (), []dal buffer, e quindi utilizzerà l'operatore prefisso *dallo stack. La modalità di valutazione viene attivata quando lo stato è dove una parola sarebbe (o il nome tipografico viene trovato e consumato, oppure )viene trovata e rimossa una fine ). La modalità di valutazione viene disattivata quando non vengono trovati più operatori prefisso / postfisso.

k=>( // k is input
    a=k.match(/\W|\w+/g), // split by symbol or word
    s=[v=j=r=""], // j=0, v=false, r="", s=[]
    // s is the stack, r is the return string,
    // v is true if we're in evaluation mode (Consume (), [], *)
    // v is false if we're waiting to see a ) or token, which triggers evaluation
    // j is the index of the top of the stack (Stack pointer)
    f=y=>!j&!a[i+1]||( // !j means stack is empty, !a[i+1] means we're at the ;
        m=a[i], // Save a[i] in a variable
        v // Are we evaluating?
        ?(
        r+=v=
            m=='[' // Array
            ?`array of ${a[i+=3,i-2]} ` // Skip three tokens: "[", "10", "]"
                                        // a[i-2] is the "10"
            :m<')' // m == '('
                ?(i+=2,"function returning ") // Skip two tokens: "(", ")"
                :s[j-1]=='*' // Stack has a pointer
                    ?j--&&"pointer to " // Pop the stack
                    :"" // Set v to be false, r+=""
        )
        :m==')'
            ?v=j--|i++ // Pop the '(', skip over the ')', v = Evaluation mode
            :m<'+' // m == '*' || m == '('
                ?s[j++]=a[i++] // push(s, pop(a))
                :r+=a[v=i++]+" is " // Otherwise we have the token
        , f(), r+a[0] // Recurse f(), and return r+a[0]. a[0] is the type.
    ),
    f(i=2) // Set i=2, and call f(), which returns the final value r + type
    // a = ["type", " ", ...], so i=2 give the first real token
    // This soln assumes there is only one space, which is an allowed assumption
)

NOTA

Se capisco correttamente "Usa uno spazio ovunque tra i token":

k=>(a=k.split(" "),s=[v=j=r=""],f=y=>!j&!a[i+1]||(v?(r+=v=a[i]=='['?`array of ${a[i+=3,i-2]} `:a[i]<')'?(i+=2,"function returning "):s[j-1]=='*'?j--&&"pointer to ":""):a[i]==')'?v=j--|i++:a[i]<'+'?s[j++]=a[i++]:r+=a[v=i++]+" is ",f(),r+a[0]),f(i=1))

è tecnicamente valido e utilizza

249 byte

Supponendo che ci sia uno spazio tra ogni token.


2
Mi ci sono volute molte ore, nonostante sembrasse semplice. Probabilmente ho bussato 5-10 byte / ora, iniziando con 350 caratteri. Non ho davvero vita.
Nicholas Pipitone,

2
Ero a circa 325 quando ho pensato "Ho raggiunto l'ottimalità con il mio attuale algoritmo - rip", ma poi per qualche motivo ero ancora in grado di bussare 5-10 / ora, nonostante ogni bussata fosse seguita da "Okay, questo è sicuramente il risultato ottimale ". Colpire 250 è stato arbitrario poiché è stato il primo a battere il 253 in carica, quindi anche se continuo a dire "Okay, questo è sicuramente il risultato ottimale", potrebbe esserci ancora altro da ottimizzare.
Nicholas Pipitone,

1

Rosso , 418 410 byte

func[s][n: t:""a: charset[#"a"-#"z"#"A"-#"Z"#"0"-#"9""_"]parse s[remove[copy x thru" "(t: x)]to a
change[copy x[any a](n: x)]"#"]b: copy[]until[c: next find s"#"switch c/1[#"("[append
b"function returning"take/part c 2]#"["[parse c[remove[skip copy d to"]"(append b
reduce["array of"d])skip]]]#")"#";"[take c c: back back c while[#"*"= c/1][take c
c: back c append b"pointer to"]take c]]s =""]reduce[n"is"b t]]

Provalo online!

Spiegazione:

f: func [ s ] [
    n: t: 0                                         ; n is the name, t is the type
    a: charset [ #"a"-#"z" #"A"-#"Z" #"0"-#"9" "_" ]; characters set for parsing 
    parse s[                                        ; parse the input with the following rules
        remove [ copy x thru " " ](t: x)            ; find the type, save it to t and remove it from the string
        to a                                        ; skip to the next alphanumerical symbol
        change [ copy n [ any a ] (n: x) ] "#"      ; save it to n and replace it with '#'
    ]
    b: copy [ ]                                     ; block for the modifiers 
    until [                                         ; repeat 
       c: next find s "#"                           ; find the place of the name   
       switch c/1 [                                 ; and check what is the next symbol
           #"(" [ append b "function returning"     ; if it's a '('- it's a function - add the modifier       
                  take/part c 2                     ; and drop the "()"
                ]
           #"[" [ parse c [                         ; '[' - an array
                     remove [ skip copy d to "]"    ; save the number
                             (append b reduce [     ; and add the modifier 
                                  "array of" d
                              ] )                   
                             skip ]                 ; and remove it from the string
                     ]
                ]
           #")"                                     ; a closing bracket 
           #";" [ take c                            ; or ';' - drop it
                    c: back back c                  ; go to the left 
                    while [ #"*" = c/1 ]            ; and while there are '*'
                    [
                        take c                      ; drop them
                        c: back c                   ; go to the left
                        append b "pointer to"       ; add the modifier
                    ]
                    take c                          ; drop '(' (or space)
                 ]
       ]
       s = ""                                       ; until the string is exhausted
    ]
    reduce [ n "is" b t ]                     ; display the resul
]

0

APL (NARS), caratteri 625, byte 1250

CH←⎕D,⎕A,⎕a,'_'⋄tkn←nm←∆←''⋄in←⍬⋄⍙←lmt←lin←0
eb←{∊(1(0 1 0)(0 1)(1 0))[⍺⍺¨⍵]}
tb←{x←({⍵='[':3⋄⍵=']':4⋄⍵∊CH,' ':1⋄2}eb⍵)\⍵⋄(x≠' ')⊂x}

gt
tkn←''⋄→0×⍳⍙>lin⋄tkn←∊⍙⊃in⋄⍙+←1⋄→0×⍳(⍙>lin)∨'('≠↑tkn⋄→0×⍳')'≠↑⍙⊃in⋄tkn←tkn,⍙⊃in⋄⍙+←1

r←dcl;n
   n←0
B: gt⋄→D×⍳'*'≠↑tkn⋄n+←1⋄→B×⍳tkn≢''
D: r←ddcl⋄∆←∆,∊n⍴⊂'pointer to '

r←ddcl;q
   r←¯1⋄→0×⍳0>lmt-←1
   →A×⍳∼'('=↑tkn⋄q←dcl⋄→F×⍳')'=↑tkn⋄→0
A: →B×⍳∼(↑tkn)∊CH⋄nm←tkn⋄→F
B: r←¯2⋄→0
F: gt⋄→G×⍳∼tkn≡'()'⋄∆←∆,'function that return '⋄→F
G: →Z×⍳∼'['=↑tkn⋄∆←∆,'array of ',{''≡p←(¯1↓1↓tkn):''⋄p,' '}⋄→F
Z: r←0

r←f w;q
   nm←∆←''⋄in←tb w⋄⍙←1⋄lin←↑⍴in⋄lmt←150⋄gt⋄→A×⍳∼0>q←dcl⋄r←⍕q⋄→0
A: r←nm,' is a ',∆,1⊃in

questa è solo una traduzione dal linguaggio C all'APL dal codice nel libro: "Linguaggio C" di Brian W. Kerninghan e Dennis M. Ritchie capitolo 5.12. Non so come ridurre tutto ciò perché non avevo capito al 100% quel codice e perché non so troppo su APL ... La funzione per l'esercizio è f; penso che siano consentite solo 150 parentesi nidificate '(' ')' per errore restituire una stringa con un valore negativo in quella o la descrizione della stringa se tutto è ok. Sembra che questo non sia migliore dell'altra versione anche se meno caratteri perché l'altro vede meglio gli errori. Alcuni test:

  f 'int f()()'
f is a function that return function that return int
  f 'int a[]()'
a is a array of function that return int
  f 'int f()[]'
f is a function that return array of int
  f 'int i;'
i is a int
  f 'float *f;'
f is a pointer to float
  f 'my_struct_t s[10];'
s is a array of 10 my_struct_t
  f 'int func();'
func is a function that return int
  f 'int arr[3][4];'
arr is a array of 3 array of 4 int
  f 'int (*fptrs[10])();'
fptrs is a array of 10 pointer to function that return int
  f 'float *(*p)[16]; '
p is a pointer to array of 16 pointer to float
  f '_RANdom_TYPE_123 (**(*_WTH_is_TH15)())[1234][567];'
_WTH_is_TH15 is a pointer to function that return pointer to pointe
  r to array of 1234 array of 567 _RANdom_TYPE_123
  f 'uint32_t (**((*(**(((*(((**(*p)))[2]))())))[123])[4])[5]);'
p is a pointer to pointer to pointer to array of 2 pointer to funct
  ion that return pointer to pointer to array of 123 pointer to
   array of 4 array of 5 pointer to pointer to uint32_t
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.