Reduzca html a n caracteres mientras mantiene el formato

11

Casi todos los idiomas tienen una función incorporada que puede dividir una cadena en una posición determinada. Sin embargo, tan pronto como tenga etiquetas html en la cadena, la función incorporada no funcionará correctamente.

Su tarea es escribir un programa o función que divida una cadena en el enésimo carácter, pero no cuenta los caracteres de las etiquetas html y generará un html válido. El programa debe mantener el formato. Los espacios fuera de las etiquetas html pueden contarse o no, como desee, pero deben conservarse. Sin embargo, puede intercambiar múltiples espacios consecutivos en un solo espacio.

Entrada:

  1. la cuerda
  2. la posición para dividir en (basado en 0)

Estos pueden tomarse como argumentos de programa o función o pueden leerse desde la entrada estándar.

Salida: la cadena dividida que se puede devolver o escribir en la salida estándar.

La entrada será html válida, no contendrá ninguna entidad (como  ). Las etiquetas que se abren después del límite de caracteres deben omitirse de la salida (consulte el último ejemplo).

Ejemplo:

Entrada: <i>test</i>3
Salida:<i>tes</i>

Entrada: <strong><i>more</i> <span style="color: red">complicated</span></strong>7
Salida:<strong><i>more</i> <span style="color: red">co</span></strong>

Entrada: no html2
Salida:no

Entrada: <b>no</b> <i>html root</i>5
Salida:<b>no</b> <i>ht</i>

Entrada: <b>no img</b><img src="test.png" />more text6
Salida:<b>no img</b>

Puede usar cualquier idioma y la biblioteca estándar del idioma dado. Este es el código de golf, el programa más corto gana. ¡Que te diviertas!

David Frank
fuente
1
¿Puede la entrada contener "<" sy ">" s que no son parte de una etiqueta HTML?
xem
Uno debería usar &lt;y en &gt;lugar de <>, así que no ( &lt;o &gt;tampoco estará presente).
David Frank
¿Podría incluir un ejemplo donde haya un marcado después del nodo de texto donde se produce la división? Al igual que <i>ab</i><b>cd</b> 1?
Martin Ender
¿Hay alguna otra opción que <i>a</i>?
David Frank
@DavidFrank <i>a</i><b></b>(lo cual tiene sentido si consideras que btambién podría ser divo img.)
Martin Ender

Respuestas:

2

Esta respuesta ya no es válida con la última regla.

Javascript ( ES6 ) 94 91

f=(s,l)=>s.split(/(<[^>]+>)/).map(x=>x[0]=='<'?x:[l-->0?y:''for(y of x)].join('')).join('')
f('<strong><i>more</i> <span style="color: red">complicated</span></strong>', 7);
// '<strong><i>more</i> <span style="color: red">co</span></strong>'

Sin golf:

f=(s,l)=>
    s.split(/(<[^>]+>)/). // split string s by <*>, capture group is spliced into the array 
    map(x=> // map function to every item in the array
        x[0]=='<'? // if first character is a <
            x // don't modify the string
        : // else
            [ // array comprehension
                for(y of x) // for every character y in x
                    l-->0? // if l > 0 (and decrement l)
                        y // character y
                    : // else
                        '' // empty string 
            ].join('') // join characters in array
        ).
    join('') // join all strings in array
nderscore
fuente
¿Podría por favor proporcionar el código sin golf, o tal vez solo una explicación de qué y por qué lo hace el código? Actualmente es un poco difícil de entender. ¡Gracias!
Gaurang Tandon
@GaurangTandon agregó un código no reflejado con comentarios
nderscore
2

Rebol - 252 caracteres

c: complement charset"<>"f: func[s n][t: e: 0 to-string collect[parse s[any[(m: 0)copy w[["</"some c">"](-- t)|["<"some c"/>"]|["<"some c">"](++ t)| any c(m: 1)](if e = 0[if m = 1[w: copy/part w n n: n - length? w]keep w]if all[n <= 0 t = 0][e: 1])]]]]

Ungolfed con comentarios:

c: complement charset "<>"

f: func [s n] [
    t: e: 0             ;; tag level (nesting) & end output flag
    to-string collect [
        parse s [
            any [
                (m: 0)                            ;; tag mode
                copy w [
                      ["</" some c ">" ] (-- t)   ;; close tag
                    | ["<"  some c "/>"]          ;; self-closing / void elements
                    | ["<"  some c ">" ] (++ t)   ;; open tag
                    | any c (m: 1)                ;; text mode
                ] (
                    ;; flag not set so can still output
                    if e = 0 [
                        ;; in text mode - so trim text
                        if m = 1 [
                            w: copy/part w n
                            n: n - length? w
                        ]
                        keep w
                    ]

                    ; if all trimmed and returned to flat tag level then end future output
                    if all [n <= 0  t = 0] [e: 1]
                )
            ]
        ]
    ]
]

Ejemplos en la consola de Rebol:

>> f "<i>test</i>" 3
== "<i>tes</i>"

>> f {<strong><i>more</i> <span style="color: red">complicated</span></strong>} 7
== {<strong><i>more</i> <span style="color: red">co</span></strong>}

>> f {no html} 2
== "no"

>> f {<b>no</b> <i>html root</i>} 5
== "<b>no</b> <i>ht</i>"

>> f {<b>no img</b><img src="test.png" />more text} 6
== "<b>no img</b>"

>> f {<i>a</i><b></b>} 1
== "<i>a</i>"

>> f {<strong><i>even</i> <span style="color: red">more <b>difficult</b></span></strong>} 14
== {<strong><i>even</i> <span style="color: red">more <b>diff</b></span></strong>}

>> f {<strong><i>even</i> <span style="color: red">more <b>difficult</b></span></strong>} 3 
== {<strong><i>eve</i><span style="color: red"><b></b></span></strong>}
draegtun
fuente
Nuevamente, esto rompe la última regla: las etiquetas que se abren después del límite de caracteres deben omitirse de la salida (ver el último ejemplo). En el último ejemplo, se deben omitir las etiquetas span yb. Esta regla hace que el desafío sea casi imposible.
edc65
@ edc65 - Desafortunadamente (@David Frank) no ha comentado ni actualizado sus ejemplos, ¿no está claro si quiere este comportamiento o no? ¡Esperaba que mi último ejemplo agitara algo! Voy a salir como está hasta que obtengamos una aclaración. De todos modos, solo tomaría 17 caracteres adicionales para que funcione de la manera que ha sugerido. No me gustó el truco, así que en cambio lo reescribí aquí (sin golf) - gist.github.com/draegtun/93682f5a07c40bd86e31
draegtun
0

Ruby ... muy rubylike con bucles

def split(str,n)

  i = current = 0 
  return_str = ""

  while i < n
    if str[current] == "<"
      while str[current] != ">"
        return_str.concat str[current]
        current += 1
      end
      return_str.concat str[current]
      current += 1
    else
      return_str.concat str[current]
      i += 1
      current += 1
    end
  end

  while current < str.length
    if str[current] == "<"
      while str[current] != ">"
        return_str.concat str[current]
        current += 1
      end
      return_str.concat str[current]
      current += 1
    end
    current += 1
  end


  return_str + str[current..-1]
end
usuario26900
fuente
Esta pregunta está marcada como codegolf, debe responder su respuesta. Usted puede comenzar mediante la sustitución de los nombres de las variables a uno nombres de las letras, el uso de nombres de funciones más cortos y la eliminación de espacios en blanco siempre que sea posible
sagiksp
0

(IE) JS - 135

function f(t,n){b=document.body;b.innerHTML=t;r=b.createTextRange();r.moveStart("character",n);r.select();r.execCommand('cut');return b.innerHTML}

Ahora me siento sucio. Pero necesito comenzar a eliminar todos esos caracteres ...

function f(t,n)
{b=document.body;b.innerHTML=t;r=b.createTextRange();r.collapse();r.moveEnd("character",n);
r.select();return r.htmlText}

Descargo de responsabilidad:

  • ejecutar en la consola IE
eithed
fuente
1
Esto rompe la última regla (loca): las etiquetas que se abren después del límite de caracteres deben omitirse de la salida (pruebe mi ejemplo en los comentarios anteriores).
edc65
@ edc65 con suerte, la versión actualizada verifica todas las reglas
canceló el