Justifica y separa completamente un bloque de texto


26
Given  a width  and  a block  of
text containing possible hyphen-
ation points,  format it  fully-
justified (in monospace).

Totalmente justificado significa que está alineado a la izquierda y a la derecha, y se logra aumentando el espacio entre las palabras hasta que encaje cada línea.

Relacionado:

Entrada

Puede tomar la entrada en cualquier formato que desee. Se le dará:

  • Un ancho objetivo (en caracteres), en el rango de 5-100 (inclusive);
  • Un bloque de texto que contiene palabras posiblemente con guiones. Esto podría ser una cadena separada por espacios, un conjunto de palabras o un conjunto de conjuntos de fragmentos de palabras (o cualquier otra representación de datos que desee).

Una entrada típica podría ser:

Width: 25
Text:  There's no bu-si-ne-ss lik-e s-h-o-w busine-ss, n-o bus-iness I know.

Donde los guiones denotan posibles puntos de separación de sílabas, y los espacios denotan límites de palabras. Una posible representación alternativa del texto:

[["There's"], ["no"], ["bu", "si", "ne", "ss"], ["lik", "e"], (etc.)]

Salida

El texto de entrada con espacios agregados entre palabras, líneas nuevas en el ancho de la columna y puntos de separación silábica elegidos para justificarlo completamente al ancho de la columna. Para las funciones, se puede devolver una matriz de cadenas (una para cada línea) en lugar de usar la separación de nueva línea.

Una posible salida para la entrada anterior podría ser:

There's no  business like
show  business,  no  bus-
iness I know.

Tenga en cuenta que todos los guiones se han eliminado, excepto el que está en el "bus-iness" final, que se mantiene para mostrar que la palabra se ajusta a la siguiente línea y se eligió para garantizar que la segunda línea contenga la mayor cantidad de texto posible.

Reglas

  • Dentro de cada línea, el número de espacios entre las palabras no puede variar en más de 1, pero el lugar donde inserte los espacios adicionales depende de usted:

    hello hi foo     bar    <-- not permitted (1,1,5)
    hello  hi foo    bar    <-- not permitted (2,1,4)
    hello  hi  foo   bar    <-- OK (2,2,3)
    hello  hi   foo  bar    <-- OK (2,3,2)
    hello   hi  foo  bar    <-- OK (3,2,2)
    
  • Ninguna línea puede comenzar o terminar con espacios (excepto la última línea, que puede terminar con espacios).

  • La última línea debe dejarse justificada, conteniendo espacios individuales entre cada palabra. Puede ir seguido de espacios en blanco arbitrarios / una nueva línea si lo desea, pero esto no es obligatorio.

  • Las palabras consistirán en AZ, az, 0-9 y puntuación simple ( .,'()&)

  • Puede suponer que ningún fragmento de palabra será más largo que el ancho objetivo, y siempre será posible llenar líneas de acuerdo con las reglas (es decir, habrá al menos 2 fragmentos de palabra en cada línea, o un fragmento de 1 palabra que llene la línea perfectamente)

  • Debe elegir puntos de separación silábica que maximicen el número de caracteres de palabras en líneas anteriores (es decir, las palabras deben consumirse con avidez por líneas), por ejemplo:

    This is an input stri-ng with hyph-en-at-ion poi-nts.
    
    This     is     an     input    stri-      <-- not permitted
    ng with hyphenation points.
    
    This  is an  input string  with hyph-      <-- not permitted
    enation points.
    
    This is an input  string with hyphen-      <-- OK
    ation points.
    
  • El código más corto en bytes gana

Ejemplos

Width: 20
Text:  The q-uick brown fox ju-mp-s ove-r t-h-e lazy dog.

The quick  brown fox
jumps over the  lazy
dog.

Width: 32
Text: Given a width and a block of text cont-ain-ing pos-sible hyphen-ation points, for-mat it ful-ly-just-ified (in mono-space).

Given  a width  and  a block  of
text containing possible hyphen-
ation points,  format it  fully-
justified (in monospace).

Width: 80
Text:  Pro-gram-ming Puz-zles & Code Golf is a ques-tion and ans-wer site for pro-gram-ming puz-zle enth-usi-asts and code golf-ers. It's built and run by you as part of the St-ack Exch-ange net-work of Q&A sites. With your help, we're work-ing to-g-et-her to build a lib-rary of pro-gram-ming puz-zles and their sol-ut-ions.

Programming Puzzles &  Code Golf  is a question and answer  site for programming
puzzle enthusiasts  and code golfers.  It's built and run  by you as part of the
Stack Exchange network  of Q&A sites. With your help,  we're working together to
build a library of programming puzzles and their solutions.

Width: 20
Text:  Pro-gram-ming Puz-zles & Code Golf is a ques-tion and ans-wer site for pro-gram-ming puz-zle enth-usi-asts and code golf-ers. It's built and run by you as part of the St-ack Exch-ange net-work of Q&A sites. With your help, we're work-ing to-g-et-her to build a lib-rary of pro-gram-ming puz-zles and their sol-ut-ions.

Programming  Puzzles
&  Code  Golf  is  a
question and  answer
site for programming
puzzle   enthusiasts
and  code   golfers.
It's  built  and run
by  you  as  part of
the  Stack  Exchange
network    of    Q&A
sites.   With   your
help,  we're working
together to  build a
library of  program-
ming   puzzles   and
their solutions.

Width: 5
Text:  a b c d e f g h i j k l mm nn oo p-p qq rr ss t u vv ww x yy z

a b c
d e f
g h i
j k l
mm nn
oo pp
qq rr
ss  t
u  vv
ww  x
yy z

Width: 10
Text:  It's the bl-ack be-ast of Araghhhhh-hhh-h-hhh-h-h-h-hh!

It's   the
black  be-
ast     of
Araghhhhh-
hhhhhhhhh-
hhh!

Sí, finalmente otro desafío de tipografía (basado en texto) :-)
ETHproductions

1
@ Adám sí a los builtins: no hay restricciones de código, y el código más corto gana. Aunque, por supuesto, ¡podría ser una respuesta aburrida! En cuanto a las bibliotecas, puede hacerlo siempre que la biblioteca esté disponible libremente y marque su respuesta como "idioma + biblioteca". Además, la versión de la biblioteca debe ser anterior a este desafío.
Dave

1
En el caso de que una línea pueda terminar con un guión o un solo carácter, por ejemplo, anybod-ycon un ancho de 7, ¿podemos elegir la salida de anybodyo anybod-\ny?
darrylyeo

1
@JonathanAllan sí; lo siento, lo arreglaré
Dave

3
@darrylyeo no, en ese caso, debe emitir la palabra completa, ya que debe tener la mayor cantidad de caracteres posibles en cada línea.
Dave

Respuestas:


7

JavaScript (ES6), 218 bytes

w=>s=>s.map((c,i)=>c.map((p,j)=>(k+p)[l="length"]-w-(b=!i|j>0)+(j<c[l]-1)<0?k+=b?p:" "+p:(Array(w-k[l]-b).fill(h=k.split` `).map((_,i)=>h[i%(h[l]-1)]+=" "),o.push(h.join` `+(b?"-":"")),k=p)),o=[],k="")&&o.join`
`+`
`+k

Toma argumentos en sintaxis de curry ( f(width)(text)) y la entrada de texto está en el formato de matriz doble descrito en el desafío. Las cadenas se convierten a ese formato a través de .split` `.map(a=>a.split`-`)). Además, las nuevas líneas son nuevas líneas literales dentro de las cadenas de plantilla.

Sin golf y reorganizado

width=>string=> {
    out=[];
    line="";
    string.map((word,i)=> {
        word.map((part,j)=> {

            noSpaceBefore = i==0 || j>0;
            if ((line+part).length - width - noSpaceBefore + (j<word.length-1) < 0) {
                line += noSpaceBefore ? part : " "+part;
            }
            else {
                words=line.split` `;
                Array(width - line.length - noSpaceBefore).fill()
                    .map((_,i) => words[i % (words.length-1)] += " ");
                out.push(words.join(" ") + (noSpaceBefore? "-" : ""));
                line=part;
            }
        });
    });
    return out.join("\n") + "\n"+line
}

La idea aquí era pasar por cada parte de la cadena completa y construir cada línea una parte a la vez. Una vez que se completa una línea, aumenta el espacio entre palabras de izquierda a derecha hasta que se colocan todos los espacios adicionales.

Fragmento de prueba

f=
w=>s=>s.map((c,i)=>c.map((p,j)=>(k+p)[l="length"]-w-(b=!i|j>0)+(j<c[l]-1)<0?k+=b?p:" "+p:(Array(w-k[l]-b).fill(h=k.split` `).map((_,i)=>h[i%(h[l]-1)]+=" "),o.push(h.join` `+(b?"-":"")),k=p)),o=[],k="")&&o.join`
`+`
`+k
<style>*{font-family:Consolas,monospace;}</style>
<div oninput="O.innerHTML=f(+W.value)(S.value.split` `.map(a=>a.split`-`))">
Width: <input type="number" size="3" min="5" max="100" id="W">
Tests: <select id="T" style="width:20em" oninput="let x=T.value.indexOf(','),s=T.value;W.value=s.slice(0,x);S.value=s.slice(x+2)"><option></option><option>20, The q-uick brown fox ju-mp-s ove-r t-h-e lazy dog.</option><option>32, Given a width and a block of text cont-ain-ing pos-sible hyphen-ation points, for-mat it ful-ly-just-ified (in mono-space).</option><option>80, Pro-gram-ming Puz-zles & Code Golf is a ques-tion and ans-wer site for pro-gram-ming puz-zle enth-usi-asts and code golf-ers. It's built and run by you as part of the St-ack Exch-ange net-work of Q&A sites. With your help, we're work-ing to-g-et-her to build a lib-rary of pro-gram-ming puz-zles and their sol-ut-ions.</option><option>20, Pro-gram-ming Puz-zles & Code Golf is a ques-tion and ans-wer site for pro-gram-ming puz-zle enth-usi-asts and code golf-ers. It's built and run by you as part of the St-ack Exch-ange net-work of Q&A sites. With your help, we're work-ing to-g-et-her to build a lib-rary of pro-gram-ming puz-zles and their sol-ut-ions.</option><option>5, a b c d e f g h i j k l mm nn oo p-p qq rr ss t u vv ww x yy z</option><option>10, It's the bl-ack be-ast of Araghhhhh-hhh-h-hhh-h-h-h-hh</option></select><br>
Text: &nbsp;<textarea id="S" cols="55" rows="4"></textarea>
</div>
<pre id="O" style="border: 1px solid black;display:inline-block;"></pre>


8

GNU sed -r, 621 bytes

Toma la entrada como dos líneas: el ancho como un número unario primero y la cadena como segundo.

Estoy seguro de que esto se podría jugar mucho más, pero ya le he dedicado demasiado tiempo.

x;N
G
s/\n/!@/
:
/@\n/bZ
s/-!(.*)@ /\1 !@/
s/!(.*[- ])(@.*1)$/\1!\2/
s/@(.)(.*)1$/\1@\2/
s/-!(.*-)(@.*)\n$/\1!\2\n1/
s/(\n!@) /\1/
s/-!(.* )(@.*)\n$/\1!\2\n1/
s/-!(.*-)(@.*1)$/\1!\21/
s/!(.*)-@([^ ]) /\1\2!@ /
t
s/ !@(.*)\n$/\n!@\1#/
s/!(.*-)@(.*)\n$/\1\n!@\2#/
s/!(.*)(@ | @)(.*)\n$/\1\n!@\3#/
s/-!(.*[^-])@([^ ]) (.*)\n$/\1\2\n!@\3#/
s/!(.+)@([^ ].*)\n$/\n!@\1\2#/
/#|!@.*\n$/{s/#|\n$//;G;b}
:Z
s/-?!|@.*//g
s/ \n/\n/g
s/^/%/
:B
G
/%.*\n.+\n/!bQ
:C
s/%([^\n])(.*)1$/\1%\2/
tC
s/([^\n]+)%\n/%\1\n/
:D
s/%([^ \n]* )(.*)1$/\1 %\2/
tD
s/(^|\n)([^\n]+)%(.*1)$/\1%\2\3/
tD
s/%([^\n]*)\n(.*)\n$/\1\n%\2/
tB
:Q
s/%(.*)\n1*$/\1/

Pruébalo en línea!

Explicación

El programa funciona en dos fases: 1. Dividir y 2. Justificar. Para lo siguiente, supongamos que nuestra entrada es:

111111111111
I re-mem-ber a time of cha-os, ru-ined dreams, this was-ted land.

Preparar

Primero leemos la entrada, moviendo la primera línea (el ancho como un número unario) al espacio de espera ( x), luego agregamos la siguiente línea ( N) y luego una copia del ancho del espacio de espera ( G) al espacio del patrón. Como Nnos dejó con un líder, \nlo reemplazamos !@, que usaremos como cursores en la Fase 1.

x;N
G
s/\n/!@/

Ahora el contenido del espacio de retención es 1111111111111(y no cambiará de ahora en adelante) y el espacio del patrón es (en el formato del lcomando "imprimir sin ambigüedades" de sed ):

!@I re-mem-ber a time of cha-os, ru-ined dreams, this was-ted land.\n111111111111$

Fase 1

En la Fase 1, el @cursor principal avanza un carácter a la vez, y para cada personaje 1se elimina un "contador" al final del espacio del patrón. En otras palabras, @foo\n111$, f@oo\n11$, fo@o\n1$, etc.

El !cursor se arrastra detrás del @cursor, marcando lugares que podríamos romper si el contador llega a 0 en el medio de la línea. Un par de rondas se vería así:

!@I re-mem-ber a time of cha-os, ru-ined dreams, this was-ted land.\n111111111111$
!I@ re-mem-ber a time of cha-os, ru-ined dreams, this was-ted land.\n11111111111$
!I @re-mem-ber a time of cha-os, ru-ined dreams, this was-ted land.\n1111111111$

Aquí hay un patrón que reconocemos: un espacio seguido inmediatamente por el @cursor. Como el contador es mayor que 0, avanzamos el marcador de ruptura, luego seguimos avanzando el cursor principal:

I !@re-mem-ber a time of cha-os, ru-ined dreams, this was-ted land.\n1111111111$
I !r@e-mem-ber a time of cha-os, ru-ined dreams, this was-ted land.\n111111111$
I !re@-mem-ber a time of cha-os, ru-ined dreams, this was-ted land.\n11111111$
I !re-@mem-ber a time of cha-os, ru-ined dreams, this was-ted land.\n1111111$

Aquí hay otro patrón: -@y todavía tenemos 7 en el contador, así que avanzamos el cursor de nuevo y seguimos avanzando:

I re-!mem-@ber a time of cha-os, ru-ined dreams, this was-ted land.\n111$

Aquí hay un patrón diferente: un guión que precede inmediatamente al cursor de ruptura y otro que precede al cursor principal. Eliminamos el primer guión, avanzamos el cursor de ruptura y, como eliminamos un carácter, agregamos 1 al contador.

I remem-!@ber a time of cha-os, ru-ined dreams, this was-ted land.\n1111$

Seguimos avanzando el cursor principal:

I remem-!ber@ a time of cha-os, ru-ined dreams, this was-ted land.\n1$

Similar a antes, pero esta vez el cursor principal precede a un espacio en lugar de seguir un guión. Eliminamos el guión, pero como también avanzamos el cursor principal, tampoco incrementamos ni disminuimos el contador.

I remember !@a time of cha-os, ru-ined dreams, this was-ted land.\n1$
I remember !a@ time of cha-os, ru-ined dreams, this was-ted land.\n$

Finalmente, nuestro contador ha llegado a cero. Como el carácter después del cursor principal es un espacio, insertamos una nueva línea y colocamos ambos cursores inmediatamente después. Luego reponemos el contador ( G) y comenzamos de nuevo.

I remember a\n!@ time of cha-os, ru-ined dreams, this was-ted land.\n111111111111$

La fase 1 continúa, avanzando los cursores y haciendo coincidir varios patrones, hasta que el @cursor llega al final de la cadena.

# Phase 1
:
  # End of string; branch to :Z (end of phase 1)
  /@\n/bZ

  # Match -!.*@_
  s/-!(.*)@ /\1 !@/

  # Match [-_]@ and >0
  s/!(.*[- ])(@.*1)$/\1!\2/

  # Advance cursor
  s/@(.)(.*)1$/\1@\2/

  # Match -!.*-@ and 0; add 1
  s/-!(.*-)(@.*)\n$/\1!\2\n1/

  # Match \n!@_
  s/(\n!@) /\1/

  # Match -!.*_@ and 0; add 1
  s/-!(.* )(@.*)\n$/\1!\2\n1/

  # Match -!.*-@ and >0; add 1
  s/-!(.*-)(@.*1)$/\1!\21/

  # Match -@[^_]_
  s/!(.*)-@([^ ]) /\1\2!@ /

  # If there were any matches, branch to `:`
  t

  # Match _!@ and 0
  s/ !@(.*)\n$/\n!@\1#/

  # Match -@ and 0
  s/!(.*-)@(.*)\n$/\1\n!@\2#/

  # Match @_|_@ and 0
  s/!(.*)(@ | @)(.*)\n$/\1\n!@\3#/

  # Match -!.*[^-]@[^_]_ and 0
  s/-!(.*[^-])@([^ ]) (.*)\n$/\1\2\n!@\3#/

  # Match !.+@[^_] and 0
  s/!(.+)@([^ ].*)\n$/\n!@\1\2#/

  # Match marked line (#) or !@ and 0
  /#|!@.*\n$/{
    # Remove mark; append width and branch to `:`
    s/#|\n$//
    G
    b
  }

:Z

# Cleanup
s/-?!|@.*//g
s/ \n/\n/g

Al final de la Fase 1, nuestro espacio de patrón se ve así:

I remember a\ntime of cha-\nos, ruined\ndreams, this\nwasted land.

O:

I remember a
time of cha-
os, ruined
dreams, this
wasted land.

Fase 2

En la Fase 2 usamos %como cursor y usamos el contador de manera similar, comenzando así:

%I remember a\ntime of cha-\nos, ruined\ndreams, this\nwasted land.\n111111111111$

Primero, contamos los caracteres en la primera línea avanzando el cursor y eliminando 1s del contador, después de lo cual tenemos;

I remember a%\ntime of cha-\nos, ruined\ndreams, this\nwasted land.\n$

Como el contador es 0, no hacemos nada más en esta línea. La segunda línea también tiene el mismo número de caracteres que el contador, así que pasemos a la tercera línea:

I remember a\ntime of cha-\nos, ruined%\ndreams, this\nwasted land.\n11$

El contador es mayor que 0, por lo que movemos el cursor de regreso al comienzo de la línea. Luego encontramos la primera serie de espacios y agregamos un espacio, decrementando el contador.

I remember a\ntime of cha-\nos, % ruined\ndreams, this\nwasted land.\n1$

El contador es mayor que 0; dado que el cursor ya está en la última (única) ejecución de espacios en la línea, lo movemos de regreso al comienzo de la línea y lo hacemos nuevamente:

I remember a\ntime of cha-\nos,  % ruined\ndreams, this\nwasted land.\n$

Ahora el contador es 0, entonces movemos el cursor al comienzo de la siguiente línea. Repetimos esto para cada línea excepto la última. ¡Ese es el final de la fase 2 y el final del programa! El resultado final es:

I remember a
time of cha-
os,   ruined
dreams, this
wasted land.
# Phase 2
# Insert cursor
s/^/%/
:B
  # Append counter from hold space
  G
  # This is the last line; branch to :Q (end of phase 1)
  /%.*\n.+\n/!bQ

  :C
    # Count characters
    s/%([^\n])(.*)1$/\1%\2/
    tC

  # Move cursor to beginning of line
  s/([^\n]+)%\n/%\1\n/

  :D
    # Add one to each space on the line as long as counter is >0
    s/%([^ \n]* )(.*)1$/\1 %\2/
    tD

    # Counter is still >0; go back to beginning of line
    s/(^|\n)([^\n]+)%(.*1)$/\1%\2\3/
    tD

    # Counter is 0; move cursor to next line and branch to :B
    s/%([^\n]*)\n(.*)\n$/\1\n%\2/
    tB

:Q

# Remove cursor, any remaining 1s
s/%(.*)\n1*$/\1/

Esto es increíble, pero cuando lo ejecuto usando gsed (GNU sed) 4.4me sale gsed: -e expression #1, char 16: ":" lacks a label. ¿Puedes agregar una nota sobre exactamente cómo lo estás invocando? (Estoy usando printf "%s\n%s" "$1" "$2" | gsed -r '<code here>';)
Dave

@Dave Eso me funciona en GNU sed 4.2. Aquí hay una idea general : gist.github.com/jrunning/91a7584d95fe10ef6b036d1c82bd385c Tenga en cuenta que la página sed de TiO no parece respetar la -rbandera, por lo que el enlace de TiO anterior va a la página bash.
Jordan

Ah, no había notado el enlace de TiO. Eso me servirá; tener un +1! Sin embargo, hay 2 pequeños errores en el último ejemplo (el de la "bestia negra"): imprime el penúltimo renglón de un carácter corto y omite el final !(aunque como me perdí !de la lista de posibles caracteres especiales, yo no sostendrá eso contra eso).
Dave

5

JavaScript (ES6), 147 bytes

Toma entrada como (width)(text).

w=>F=(s,p=S=' ')=>(g=([c,...b],o='',h=c=='-')=>c?o[w-1]?c==S&&o+`
`+F(b):o[w+~h]?o+c+`
`+F(b):c>S?g(b,h?o:o+c):g(b,o+p)||g(b,o+p+c):o)(s)||F(s,p+S)

Pruébalo en línea!

Comentado

w =>                              // w = requested width
  F = (                           // F is a recursive function taking:
    s,                            //   s = either the input string (first iteration) or an
                                  //       array of remaining characters (next iterations)
    p =                           //   p = current space padding
    S = ' '                       //   S = space character
  ) => (                          //
    g = (                         // g is a recursive function taking:
      [c,                         //   c   = next character
          ...b],                  //   b[] = array of remaining characters
      o = '',                     //   o   = output for the current line
      h = c == '-'                //   h   = flag set if c is a hyphen
    ) =>                          //
      c ?                         // if c is defined:
        o[w - 1] ?                //   if the line is full:
          c == S &&               //     fail if c is not a space
          o + `\n` + F(b)         //     otherwise, append o + a linefeed and process the
                                  //     next line
        :                         //   else:
          o[w + ~h] ?             //     if this is the last character and c is a hyphen:
            o + c + `\n` + F(b)   //       append o + c + a linefeed and process the next
                                  //       line
          :                       //     else, we process the next character:
            c > S ?               //       if c is not a space:
              g(b, h ? o : o + c) //         append c if it's not a hyphen
            :                     //       else:
              g(b, o + p) ||      //         append either the current space padding
              g(b, o + p + c)     //         or the current padding and one extra space
      :                           // else:
        o                         //   success: return o
  )(s)                            // initial call to g() with s
  || F(s, p + S)                  // in case of failure, try again with a larger padding

4

APL (Dyalog Unicode) , 129 123 121 118 111 109 107 104 100 95 bytes SBCS

{⊃⌽m←⍺≥-⌿c⍪+\⊢c' -'∘.≠⍵:⊂⍵/⍨⊢⌿c⋄(⊂∊ll[(⍺-≢l)⍴⍸' '=l],←⊃0l←⍵/⍨n×⊣⌿c⊖⍨1n),⍺∇⍵/⍨~n←⌽∨\⌽m>×⌿c}

Pruébalo en línea!



1

Python 2 , 343 bytes

W,T=input()
T+=' '
L,l=[],len
while T:
 p,r=0,''
 for i in range(l(T)):
  s=T[:i].replace('-','')
  if'-'==T[i]:s+='-'
  if T[i]in' -'and W-l(s)>=0:p,r=i,s
 R=r.split()
 if R:
  d,k=W-l(''.join(R)),0
  for j in range(d):
   R[k]+=' '
   k+=1
   if k==l(R)-1:k=0
  L+=[''.join(R)]
  T=T[p+1:]
print'\n'.join(L[:-1])
print' '.join(L[-1].split())

Pruébalo en línea!

The  input  is a block of text
containing possibly hyphenated
words.  For  each space/hyphen
position  p  the code computes
l(p)  the  length  of the line
induced  by  slipping the text
to this space/hyphen. Then the
code choses the position p for
which  the  length l(p) is the
closest  to  the given width W
(and  l(p)<=W).  If l(p)<W the
code  adds spaces  fairly  in-
between  the  words to achieve
the length W.

Aunque la entrada puede estar en cualquier formato que desee, aún debe provenir de STDIN o parámetros. Ver los valores predeterminados de E / S . Generalmente no permitimos que la "entrada" provenga de variables preasignadas.
mbomb007

Puede guardar un byte haciendo en print'\n'.join(L[:-1])lugar defor e in L[:-1]:print e
mbomb007

@ mbomb007 ok, sí, haré los cambios necesarios para respetar la E / S
mdahmoune
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.