Zmniejsz HTML do n znaków, zachowując formatowanie

11

Prawie każdy język ma wbudowaną funkcję, która może rozdzielać łańcuch w danej pozycji. Jednak gdy tylko w tagu znajdą się tagi html, wbudowana funkcja nie będzie działać poprawnie.

Twoim zadaniem jest napisanie programu lub funkcji, która dzieli ciąg na n-ty znak, ale nie liczy znaków tagów HTML i wyświetli prawidłowy HTML. Program musi zachować formatowanie. Miejsca poza znacznikami html mogą być liczone lub nie być zliczane, jak chcesz, ale muszą zostać zachowane. Możesz jednak zamienić wiele kolejnych spacji w jedną spację.

Wejście:

  1. ciąg
  2. pozycja do podziału w (na podstawie 0)

Można je traktować jako argumenty programu lub funkcji lub można je odczytać ze standardowego wejścia.

Dane wyjściowe: podzielony ciąg znaków, który można zwrócić lub zapisać na standardowym wyjściu.

Dane wejściowe będą poprawne w formacie HTML, nie będą zawierać żadnych elementów (takich jak  ). Tagi otwierane po limicie znaków należy pominąć w danych wyjściowych (patrz ostatni przykład).

Przykład:

Wejście:, <i>test</i>3
Wyjście:<i>tes</i>

Wejście:, <strong><i>more</i> <span style="color: red">complicated</span></strong>7
Wyjście:<strong><i>more</i> <span style="color: red">co</span></strong>

Wejście:, no html2
Wyjście:no

Wejście:, <b>no</b> <i>html root</i>5
Wyjście:<b>no</b> <i>ht</i>

Wejście:, <b>no img</b><img src="test.png" />more text6
Wyjście:<b>no img</b>

Możesz użyć dowolnego języka i standardowej biblioteki danego języka. To jest kod golfowy, wygrywa najkrótszy program. Baw się dobrze!

David Frank
źródło
1
czy dane wejściowe mogą zawierać „<” i „>”, które nie są częścią znacznika HTML?
xem
Należy użyć &lt;i &gt;zamiast <>, więc nie ( &lt;lub też &gt;nie będzie).
David Frank
Czy możesz podać przykład, w którym po węźle tekstowym, w którym następuje podział, jest znacznik ? Jak <i>ab</i><b>cd</b> 1?
Martin Ender
Czy są jakieś inne opcje niż <i>a</i>?
David Frank
@DavidFrank <i>a</i><b></b>(Co ma sens, jeśli weźmiesz pod uwagę, że bmoże to być divlub img.)
Martin Ender

Odpowiedzi:

2

Ta odpowiedź nie jest już aktualna w przypadku najnowszej reguły.

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

Nie golfowany:

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
źródło
Czy możesz podać kod bez golfa, a może po prostu wyjaśnienie, co i dlaczego kod działa? Obecnie jest trochę trudny do uchwycenia. Dzięki!
Gaurang Tandon
@GaurangTandon dodał nieoznakowany kod z komentarzami
nderscore
2

Rebol - 252 znaków

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

Niegolfowany z komentarzami:

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

Przykłady w konsoli 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
źródło
Ponownie łamie to ostatnią zasadę: tagi, które są otwierane po limicie znaków, powinny zostać pominięte w danych wyjściowych (patrz ostatni przykład). W ostatnim przykładzie tagi span i b powinny zostać pominięte. Ta zasada sprawia, że ​​wyzwanie jest prawie niemożliwe.
edc65,
@ edc65 - Niestety (@David Frank) nie skomentował ani nie zaktualizował swoich przykładów, więc nie jest jasne, czy chce tego zachowania, czy nie? Miałem nadzieję, że mój ostatni przykład coś poruszy! Wyjeżdżamy tak, jak jest, dopóki nie otrzymamy wyjaśnienia. W każdym razie zajęłoby to tylko 17 dodatkowych znaków, aby działało tak, jak sugerowałeś. Nie podoba mi się ten hack, więc zamiast tego przepisałem go tutaj (niegolfowany) - gist.github.com/draegtun/93682f5a07c40bd86e31
draegtun
0

Ruby ... Bardzo nieokrzesany z pętlami

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
użytkownik26900
źródło
To pytanie jest oznaczone jako codegolf, powinieneś zagrać w golfa w swojej odpowiedzi. Możesz zacząć od zamiany nazw zmiennych na nazwy jednoliterowe, używając krótszych nazw funkcji i usuwając białe
znaki
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}

Teraz czuję się brudny. Ale musisz zacząć usuwać wszystkie te znaki ...

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

Zrzeczenie się:

  • uruchom w konsoli IE
eithed
źródło
1
To łamie ostatnią (szaloną) zasadę: Tagi, które są otwierane po limicie znaków, powinny zostać pominięte w danych wyjściowych (wypróbuj mój przykład w komentarzach powyżej).
edc65,
@ edc65 mam nadzieję, że zaktualizowana wersja sprawdza wszystkie zasady
wyszła