Rientra una stringa usando le parentesi indicate


16

Dato il seguente input al programma:

  1. Elenco dei caratteri di inizio blocco
  2. Elenco dei caratteri di fine blocco
  3. Una stringa da formattare

formattare la stringa con i blocchi delimitati dai due set di caratteri rientrati.

La formattazione viene eseguita con due spazi per livello e le parentesi vengono posizionate come mostrato nell'esempio seguente. Si può presumere che le serie di caratteri di apertura e chiusura siano disgiunte.

Ad esempio per {[(<e }])>come set di caratteri di apertura e chiusura e la seguente stringa:

abc{xyz{text[note{comment(t{ex}t)abc}]}}

ci si aspetterebbe il seguente risultato:

abc
{
  xyz
  {
    text
    [
      note
      {
        comment
        (
          t
          {
            ex
          }
          t
        )
        abc
      }
    ]
  }
}

Non è possibile codificare in modo casuale l'elenco dei caratteri "parentesi". Tuttavia, come viene fornito l'input non viene specificato; potrebbe trattarsi di argomenti da riga di comando o tramite input standard, come si desidera.


5
Possiamo supporre che per ogni parentesi ce ne sia una di chiusura, e nello stesso ordine?
Juan,

Il programma deve supportare caratteri tra parentesi indicati come argomenti? es. ./program 'p' 'q' <<< '1p23p45q67q8' O ha solo bisogno di supporto {[(<e }])>?
Joey Adams,

@Joey, immagino di no, anche se sarebbe tanto più impressionante.
Neil,

joey: input sono 1. apri i caratteri parentesi 2.cludi i caratteri parentesi 3. stringa da indentare. Juan: possiamo presumere che, sebbene il codice non debba basarsi su questo, ciò che intendo è se il delim fa parte dell'apertura dei caratteri parentesi, aumenta il rientro, altrimenti se parte dei caratteri della parentesi chiusa diminuisce il rientro.
Prashant Bhate,

1
@Phrasant Bhate: E nell'output?
Lowjacker,

Risposte:


6

Rubino, 106 101 96 95

s,e,i=$*
i.scan(/[#{z=Regexp.quote s+e}]|[^#{z}]*/){|l|puts'  '*(s[l]?~-$.+=1:e[l]?$.-=1:$.)+l}

L'input viene fornito tramite la riga di comando.


1
Puoi salvare 4 caratteri usando ~-j+=1invece di (j+=1;j-1). Inoltre, l'utilizzo $.dappertutto invece di jconsente di rimuovere il j=0, che salva un altro personaggio.
Ventero,

6

Perl - 131 96 94 caratteri

$i="";for$_(split/([\Q$ARGV[0]$ARGV[1]\E])/,$ARGV[2]){$i=~s/..// if/[\Q$ARGV[1]\E]/;print "$i$_\n"if$_;$i.='  'if/[\Q$ARGV[0]\E]/;}

Sembra che ci dovrebbe essere spazio per eliminare le espressioni comuni, almeno, ma è una rapida interpretazione che gestisce l'esempio, così come l'ipotetico Joey Adams sulle parentesi arbitrarie.


Vi era, in effetti, molto margine di miglioramento:

$_=pop;($s,$e)=map"[\Q$_\E]",@ARGV;for(split/($s|$e)/){print"  "x($i-=/$e/),"$_\n"if$_;$i+=/$s/}

... e ancora un po 'di più:

$_=pop;($s,$e)=map"[\Q$_\E]",@ARGV;map{print"  "x($i-=/$e/),"$_\n"if$_;$i+=/$s/}split/($s|$e)/

3

Mathematica (golf non di codice)

indent[str_String]:=Module[{ind,indent,f},
ind=0;
indent[i_]:="\n"<>Nest["    "<>ToString[#]&,"",i];
f[c_] :=  (indent[ind] <> c <> indent[++ind]) /; StringMatchQ["[({",___~~c~~___];
f[c_] := ( indent[--ind] <> c <>indent[ind])  /; StringMatchQ["])}",___~~c~~___];
f[c_] := (c <>indent[ind])       /; StringMatchQ[";,",___~~c~~___];
f[c_] := c  ;
f /@ Characters@ str//StringJoin
]

Test

indent["abc{xyz{text[note{comment(t{ex}t)abc}]}}"]
abc
{
    xyz
    {
        text
        [
            note
            {
                comment
                (
                    t
                    {
                        ex
                    }
                    t
                )
                abc
            }

        ]

    }

}

Come bonus, la seguente funzione può essere utilizzata per formattare l'espressione matematica

format[expr_] := indent[expr // FullForm // ToString]

EDIT (golf non di codice) Aggiornato con un controllo granulare fine sul modo in cui vengono visualizzate le nuove linee

indent[str_String, ob_String, cb_String, delim_String] := 
  Module[{ind, indent, f, tab}, ind = 0; tab = "    ";
   indent[i_, tab_, nl_] := nl <> Nest[tab <> ToString[#] &, "", i];
   f[c_] := (indent[ind, "", " "] <> c <> indent[++ind, tab, "\n"]) /;StringMatchQ[ob, ___ ~~ c ~~ ___];
   f[c_] := (indent[--ind, "", " "] <> c <> indent[ind, tab, "\n"]) /;StringMatchQ[cb, ___ ~~ c ~~ ___];
   f[c_] := (c <> indent[ind, tab, "\n"]) /;StringMatchQ[delim, ___ ~~ c ~~ ___];
   f[c_] := c;
   f /@ Characters@str // StringJoin];
format[expr_] := indent[expr // InputForm // ToString, "[({", "])}", ";"];

format[Hold@Module[{ind, indent, f, tab}, ind = 0; tab = "    ";
 indent[i_, tab_, nl_] := nl <> Nest[tab <> ToString[#] &, "", i];
 f[c_] := (indent[ind, "", " "] <> c <> indent[++ind, tab, "\n"]) /;StringMatchQ[ob, ___ ~~ c ~~ ___];
 f[c_] := (indent[--ind, "", " "] <> c <> indent[ind, tab, "\n"]) /;StringMatchQ[cb, ___ ~~ c ~~ ___];
 f[c_] := (c <> indent[ind, tab, "\n"]) /;StringMatchQ[delim, ___ ~~ c ~~ ___];
 f[c_] := c;
 f /@ Characters@str // StringJoin]]

Produzione

Hold [
    Module [
         {
            ind, indent, f, tab }
        , ind = 0;
         tab = "    ";
         indent [
            i_, tab_, nl_ ]
         := StringJoin [
            nl, Nest [
                StringJoin [
                    tab, ToString [
                        #1 ]
                     ]
                 & , "", i ]
             ]
        ;
         f [
            c_ ]
         := StringJoin [
            indent [
                ind, "", " " ]
            , c, indent [
                ++ind, tab, "\n" ]
             ]
         /;
         StringMatchQ [
            ob, ___~~c~~___ ]
        ;
         f [
            c_ ]
         := StringJoin [
            indent [
                --ind, "", " " ]
            , c, indent [
                ind, tab, "\n" ]
             ]
         /;
         StringMatchQ [
            cb, ___~~c~~___ ]
        ;
         f [
            c_ ]
         := StringJoin [
            c, indent [
                ind, tab, "\n" ]
             ]
         /;
         StringMatchQ [
            delim, ___~~c~~___ ]
        ;
         f [
            c_ ]
         := c;
         StringJoin [
            f / @
                 Characters [
                    str ]
                 ]
             ]
         ]

Questo è difficilmente un codice golf, con nomi multi-carattere come indent. Il tuo obiettivo è il codice o la leggibilità al massimo? Esistono diversi modi per ridurre questo codice, se questo è davvero il tuo obiettivo. Inoltre: "Non è possibile codificare a fondo l'elenco dei caratteri" parentesi "." ma non è esattamente quello che hai fatto qui? Comunque, mi dispiace di sembrare così negativo; mi sembra solo una strana risposta alla tua stessa sfida.
Mr.Wizard,

1
@ Mr.Wizard non è golf da codice, l'ho aggiunto per mio riferimento [aggiornato per chiarire]. Lo uso spesso per capire il codice matematico non formattato che si estende su una pagina più grande
Prashant Bhate,

3

JavaScript, 255 227 205 caratteri

Ehi, la sua lunghezza si adatta perfettamente in un byte! : D

function(s,e,t){R=eval.bind(0,"Array(n).join(' ')");for(i=n=0,b=r='';c=t[i++];)~s.indexOf(c)?(r+=b,b='\n'+R(++n)+c+'\n '+R(++n)):~e.indexOf(c)?b+='\n'+((n-=2)?R()+' ':'')+c+'\n'+(n?R()+' ':''):b+=c;return r+b}

È una funzione, passa i caratteri iniziali, i caratteri finali, quindi il testo.


Il tuo commento di modifica è stato usato contro di te. : D
Maniglia della porta

@Doorknob: io ... pensavo di non averlo mai fatto. D: Mi dispiace tanto. (Stavi cacciando?)
Ry,

@Doorknob: E grazie per avermelo ricordato; abbreviato :)
Ry

No, non stavo cacciando, mi sono imbattuto in questa domanda, ma ho deciso di farlo e ho trovato questo : O: P
Maniglia della porta

2

Python - 162 caratteri

i=f=0
s=""
l,r,z=[raw_input()for c in'   ']
o=lambda:s+("\n"+"  "*i)*f+c
for c in z:
 if c in l:f=1;s=o();i+=1
 elif c in r:i-=1;f=1;s=o()
 else:s=o();f=0
print s

Si noti che l'attività richiede che i due set di parentesi siano parte dell'input, non codificati.
Joey,

@Joey ha notato, mi occuperò di risolvere il problema tra un po '. Grazie
Juan,

2

Python 2.7.X - 136 caratteri

import sys
a,c=sys.argv,0
for i in a[3]:
 if not(i in a[2]):print ' '*c+i
 else:print ' '*(c-4)+i
 if i in a[1]:c+=4
 if i in a[2]:c-=4

Utilizzo : $ ./foo.py '(' ')' '(ab (cd (ef) gh) ij)'

Uscita risultante:

(
    a
    b
    (
        c
        d
        (
            e
            f
        )
        g
        h
    )
    i
    j
)

Hai bisogno degli spazi dopo le printdichiarazioni?
Zacharý,

2

C - 213 209

Odio gli stupidi errori ...>. <

#include<stdio.h>
#include<string.h>
int main(int i,char**s){for(char q,r,c,t,a=0;~(c=getchar());t=q|r){q=!!strchr(s[1],c);a-=r=!!strchr(s[2],c);for(i=0;t|q|r&&i<2*a+1;putchar(i++?' ':'\n'));a+=q;putchar(c);}}

Legge le parentesi sinistre dal primo argomento della riga di comando, le parentesi destre dal secondo argomento e immette il rientro su stdin.

Abbastanza stampato e commentato:

int main(int i, char **s) {
  for (char q, r, /* is left-paren? is right-paren? */
            c,    /* character read from input */
            t,    /* last char was a paren-char */
            a=0;  /* indentation */
       ~(c = getchar());
       t = q|r) {
         q = !!strchr(s[1],c);
    a -= r = !!strchr(s[2],c);
    for (i=0; t|q|r && i<2*a+1; putchar(i++? ' ' : '\n'));
    a += q;
    putchar(c);
  }
}

1

C ( 159 225 caratteri)

#define q(s,c)strchr(s,c)
#define p(i,j,k)printf("\n%*s%c%c%*s",i,"",*s,k,j,"")
g(char*b,char*e,char*s){int i;for(i=0;*s;s++)q(b,*s)?p(i-2,i+=2,'\n'):q(e,*s)?q(b,*(s+1))||q(e,*(s+1))?p(i-=2,i-2,0):p(i-=2,i-2,'\n'):putchar(*s);}

Mi è costato 66 caratteri extra solo per correggere il bug con le righe vuote :( Francamente, ho bisogno di un nuovo approccio, ma lo chiamerò un giorno per ora.

#define p(i,j)printf("\n%*s%c\n%*s",i,"",*s,j,"")
f(char*b,char*e,char*s){int i;for(i=0;*s;s++){strchr(b,*s)?p(i-2,i+=2):strchr(e,*s)?p(i-=2,i-2):putchar(*s);}}

Un approccio piuttosto rapido e sporco. Ha un bug nel produrre righe vuote tra parentesi di chiusura consecutive, ma per il resto fa il lavoro (o almeno così penso). Lo rivedrò per una soluzione migliore e più pulita, questa settimana.

char * b è il set di parentesi di apertura, char * e è il set di parentesi di chiusura e char * s è la stringa di input.


1

Perl - 69 byte

TMTOWTDI semplifica il codice

#!perl -p
s/([[{(<])|([]})>])|\w+/"  "x($1?$t++:$2?--$t:$t)."$&
"/ge

3
Dovresti prendere le parentesi come input, non codificarle.
Gareth,

1

Scala (2.9), 211 caratteri

object P extends App{def x(j:Int)={"\n"+"  "*j}
var(i,n)=(0,"")
for(c<-args(2)){if(args(0).exists(_==c)){print(x(i)+c)
i+=1
n=x(i)}else{if(args(1).exists(_==c)){i-=1
print(x(i)+c)
n=x(i)}else{print(n+c)
n=""}}}}

1

Perl - 89 85 byte

Una versione della risposta di Hojung Youn che accetta i caratteri di blocco tramite due argomenti.

#!perl -p
BEGIN{$b=pop;$a=pop}s/([$a])|([$b])|\w+/"  "x($1?$t++:$2?--$t:$t)."$&
"/ge

Chiamato come:

perl golf.pl<<<'abc{xyz{text[note{comment(t{ex}t)abc}]}}' '[{(<' ']})>'

Concetto molto bello, @Hojung e Sorpigal. È un po 'fragile, però. Ad esempio, scambiare] e} nell'argomento close-paren e] chiude la classe di caratteri, causando un errore di paren senza pari. Allo stesso modo, supponiamo che il set aperto inizi con ^, forse per abbinare v nel set vicino; otterrai il complemento della classe [$ a] prevista. Ecco perché ho usato \ Q ... \ E nella mia risposta. Il \ w + per i caratteri non-paren funziona nell'esempio, ma che dire dell'input come 'x (foo-bar) y' '(' ')'? Naturalmente, non è chiaro che il codice debba gestire qualcosa del genere.
DCharness

1

Python3, 184 182 caratteri

import sys
_,p,q,t=sys.argv
i,f,x=0,1,print
for e in t:
 if e in p:f or x();x(' '*i+e);i+=2;f=1
 elif e in q:f or x();i-=2;f=1;x(' '*i+e)
 else:not f or x(' '*i,end='');f=x(e,end='')

Esempio:

$ python3 ./a.py '{[(<' '}])>' 'abc{xyz{text[note{comment(t{ex}t)abc}]}}'
abc
{
  xyz
  {
    text
    [
      note
      {
        comment
        (
          t
          {
            ex
          }
          t
        )
        abc
      }
    ]
  }
}

heinrich5991 ha suggerito di salvare due personaggi cambiando la seconda riga in_,p,q,t=sys.argv
Peter Taylor

1

Groovy, 125

p=args;i=0;s={a,b->"\n"+"\t"*(b?i++:--i)+a+"\n"+"\t"*i};p[0].each{c->print p[1].contains(c)?s(c,1):p[2].contains(c)?s(c,0):c}

Puoi salvare lo script in un file indent.groovy e provarlo con:
groovy indent.groovy "abc {xyz {text [note {comment (t {ex} t) abc}]}}" "{[(" ") ]}"


Ho provato in giro per un'ora prima di vedere la tua risposta, ho usato un approccio simile, ma il mio è molto più lungo del tuo, quindi non mi prenderò nemmeno il disturbo di pubblicare .. Ottimo lavoro! :)
Fels l'

1

Python - 407

from sys import*;o=argv[1];c=argv[2];t=argv[3];p=0;n=False;a=lambda:h not in e;b=lambda s:print(s+(" "*p)+h);r="";e=o+c
for h in t:
 for k in o:
  if h==k:
   if(r in e)and(r!=""):b("")
   else:b("\n")
   p+=2;n=True;break
 for k in c:
  if h==k:
   p-=2
   if(r in e)and(r!=""):b("")
   else:b("\n")
   n=True;break
 if a()and n:print((" "*p)+h,end="");n=False
 elif a():print(h,end="")
 r=h

Una versione non controllata del programma:

import sys

open_set = sys.argv[1]
close_set = sys.argv[2]
text = sys.argv[3]
spaces = 0
newline = False
a = lambda : char not in b_set
b = lambda s: print(s + (" " * spaces) + char)
prev = ""
b_set = open_set + close_set

for char in text:
    for bracket in open_set:
        if char == bracket:
            if (prev in b_set) and (prev != ""):
                b("")
            else:
            b("\n")
        spaces += 2
        newline = True
        break
    for bracket in close_set:
        if char == bracket:
            spaces -= 2
            if (prev in b_set) and (prev != ""):
                b("")
            else:
                b("\n")
            newline = True
            break
    if a() and newline:
        print((" " * spaces) + char, end="")
        newline = False
    elif a():
        print(char, end="")
    prev = char

Gli argomenti del programma sono (in ordine): le parentesi di apertura, le parentesi di chiusura e il testo da indentare.

Esempio ($ è un prompt della riga di comando):

$ python indent.py "{[(<" "}])>" "abc{xyz{text[note{comment(t{ex}t)abc}]}}"
abc
{
  xyz
  {
    text
    [
      note
      {
        comment
        (
          t
          {
            ex
          }
          t
        )
        abc
      }
    ]
  }
}

0

D (300)

C[] i(C,S)(ref S s,C p){if(!*s)return[];static C[] w;w~=" ";C[] r;C c=s[0];while(c!=p){s=s[1..$];r~=(c=='{'||c=='['||c=='<'?"\n"~w~c~"\n"~i(s,cast(char)(c+2)):c=='('?"\n"~w~c~"\n"~i(s,')'):[c]);c=*s;}w=w[1..$];if(*s)s=s[1..$];c=*s;return" "~w~r~"\n"~w~(c=='}'||c==']'||c=='>'||c==')'?[p]:p~"\n"~w);}

necessita di una stringa terminata null per il controllo dei limiti (altrimenti è if(*s)necessario modificarla in if(s.length))


Si noti che l'attività richiede che i due set di parentesi siano parte dell'input, non codificati.
Joey,

0

Giava

Non codegolf version! Supponendo che abbiamo questa versione di split () che include delim,

public static String indent(String input, String openPars,
        String closingPars) {
    String re = "["
            + (openPars + closingPars).replace("[", "\\[").replace("]",
                    "\\]") + "]";
    String[] split = inclusiveSplit(input, re, 0);
    int indent = 0;
    StringBuilder sb = new StringBuilder();
    for (String string : split) {
        if (StringUtils.isEmpty(string))
            continue;
        if (closingPars.indexOf(string) != -1) {
            indent--;
        }
        sb.append(StringUtils.repeat(" ", indent * 2));
                    sb.append(string);
                    sb.append("\n");
        if (openPars.indexOf(string) != -1) {
            indent++;
        }
    }
    String string = sb.toString();
    return string;
}

2
StringUtilsnon fa parte del JDK standard.
via

0

C 284 Personaggi non bianchi

Non sono un fan dell'offuscamento ma bene ...

#include<cstdio>
#include<cstring>
#define g printf
#define j char
int main(int a,j**b){int c=0;for(j*f=b[3];*f!='\0';++f){if(strchr(b[1],*f)!=0){g("\n%*c\n%*c",c,*f,c+2,'\0');c+=2;}else if(strchr(b[2],*(f))!=0){c-=2;g("\n%*c",c,*f);if(strchr(b[2],*(f+1))==0)g("\n%*c",c,'\0');}else putchar(*f);}}

Utilizzo: ./program start_brackets end_brackets string_to_parse


0

php (187) (153)

function a($s,$o,$e){while(''!=$c=$s[$i++]){$a=strpbrk($c,$o)?2:0;$b=strpbrk($c,$e)?2:0;echo ($a+$b||$r)?"\n".str_pad('',$t-=$b):'',$c;$t+=$a;$r=$a+$b;}}

La funzione accetta la stringa, apre i delimitatori, termina i delimitatori come argomenti.


0

C, 256

parametri:

  • e è il carattere finale,
  • n è il rientro,
  • B le staffe di apertura,
  • d le parentesi quadre di chiusura.

Ho rotto il codice per evitare la barra di scorrimento orizzontale.

#define r char
#define P(c) putchar(c);
#define N P(x)
#define W printf("%*s",n,"");
r*s,x='\n';i(r e,int n,r*b,r*d){r*t=s,*p;int l=0;W while(*s!=e)    
{if(p=strchr(b,*s)){if(s!=t){N W}P(*s++)N i(d[p-b],n+2,b,d); N W 
P(*s++);l=1;}else{if(l){N W l=0;}P(*s++)}}}

Il programma completo è di 363 caratteri.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define r char
#define P(c) putchar(c);
#define N P(x)
#define W printf("%*s",n,"");
r*s,x='\n';i(r e,int n,r*b,r*d)
{r*t=s,*p;int l=0;W while(*s!=e)
{if(p=strchr(b,*s)){if(s!=t){N W}
P(*s++)N i(d[p-b],n+2,b,d); N W
P(*s++);l=1;}else{if(l){N W l=0;}
P(*s++)}}}main(int c,r*v[]){s =
v[3];i('\0',0,v[1],v[2]);}

0

VB.net (? C)

La lingua non è adatta al golf del codice, quindi ho usato un approccio non comune. Utilizzo di un listener di traccia per l'output sulla console.

Imports System.Diagnostics.Debug
Module Module1
  Sub Main(args() As String)
    IndentText(args(0), args(1), args(2)) 'openings, closings, text)
  End Sub
  Sub IndentText(o As String, e As String, t As String)
    Dim x = 0
    Listeners.Add(New Diagnostics.ConsoleTraceListener)
    IndentSize = 2
    For Each c In t
      If o.Contains(c) Then
        WriteLine("")
        WriteLine(c)
        Indent()
        x = 1
      ElseIf e.Contains(c) Then
        If x = 0 Then WriteLine("")
        Unindent()
        WriteLine(c)
        x = 1
      Else
        Write(c)
        x = 0
      End If
    Next
  End Sub
End Module

Utilizza args a riga di comando per l'input

args(0) is the indenting chars
args(1) is the undenting chars
args(2) is the text to be indented.

0

Powershell, 146 byte

param([char[]]$s,[char[]]$e,[char[]]$f)$f|%{}{if($_-in$s){$o;'  '*$i+$_;$o='  '*++$i;}elseif($_-in$e){$o;'  '*--$i+$_;$o='  '*$i}else{$o+=$_}}{$o}

Spiegazione Ungolfed

param([char[]]$start,             # Cast as array of Chars
      [char[]]$end,
      [char[]]$string)
$string | foreach-object { } {    # For every char in string. Empty Begin block
    if ( $_ -in $start ) {        # If char is in start
        $o                        # Print stack ($o)
        '  ' * $i + $_            # Newline, indent, insert start char
        $o = '  ' * ++$i          # Set stack to ident (incremented)
    } elseif ( $_ -in $end ) {    # If char is in end
        $o                        # Print stack
        '  ' * --$i + $_          # Newline, decrement indent, insert end char
        $o = '  ' * $i            # Set stack to indent
    } else {
        $o+ = $_                  # Otherwise add character to stack
    }
} { $o }                          # Print remaining stack (if any)

0

C, 181 caratteri

#define d(m,f)if(strchr(v[m],*s)){puts("");for(j=f;j--;)printf("  ");}
i;main(j,v,s)char**v,*s;{for(s=v[3];*s;s++){d(1,i++)d(2,--i)putchar(*s);d(1,i)if(!strchr(v[2],*(s+1)))d(2,i)}}

Praticamente l'approccio più semplice che si possa immaginare. Scorrere la stringa (v [3]), se è una parentesi graffa sinistra (come definita in v [1]), aumentare il livello di rientro, se è una parentesi graffa destra (come definito in v [2]), diminuire il livello di rientro .


-1

C, 114 121

main(i,x,s,c){while(~(c=getchar()))(s=x)|(x=2*!!strchr("(){}[]<>",c))?s=c-1&x,i-=x-2*s,printf("\n%*c",i-s,c):putchar(c);}

Non molto bella, ma una soluzione ... prima o dopo potrebbe apparire una riga vuota a seconda che l'input inizi / termini con una parentesi.

Con la nuova restrizione, questo approccio è quasi inutile per il golf.


Non indentifica abbastanza le parentesi di apertura e genera righe vuote tra quelle di chiusura consecutive.
Joey,

@joey fixed, grazie per il feedback!
esneider,

Codifica ancora le parentesi mentre dovrebbero far parte dell'input. Attualmente tutte le risposte non sono conformi alle specifiche.
Joey,
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.