El cortador codicioso

27

iBug recientemente recibió una barra larga hecha de materiales compuestos pero valiosos. La barra es tan larga que iBug no puede venderla fácilmente por créditos, por lo que quiere cortarla. La barra está hecha de materiales tan frágiles y mágicos que, si una parte se rompe, todas las partes de la barra hechas del mismo material también se romperán, lo que dificultará el corte arbitrario.

iBug quiere cortar la barra en tantas piezas como sea posible. También le encantan los programas muy cortos y el golf de código, por lo que hizo un análisis abstracto de su problema.

La barra mágica de iBug se representa como una cadena (o una matriz o una secuencia de caracteres si lo prefiere), así:

aaabbccccccbbbaaacccccaabbbaaaaa

Cada letra en la cadena representa un material mágico. La barra siempre coincide con el RegEx ^\w*$, por lo que puede haber hasta 63 materiales en la barra. Una "parte" es una secuencia consecutiva de cualquier carácter que no esté separado por espacios.

iBug quiere que escribas un programa que calcule las partes máximas que podría obtener, si cero o más juegos de caracteres se eliminan por completo (reemplazados por espacios), y le dices a iBug ese número.


Ejemplo 1:

In:  aaabbccccccbbbaaacccccaabbbaaaaa
Out: 4

Descripción: si bse elimina completamente de la barra, iBug podría obtener 4 partes. También puede obtener 4 partes quitando by c, como se muestra a continuación

aaabbccccccbbbaaacccccaabbbaaaaa  # Original string
aaa  cccccc   aaacccccaa   aaaaa  # Remove 'b'
aaa           aaa     aa   aaaaa  # Remove 'b' and 'c'

Y esa es la cantidad máxima de partes que iBug puede obtener de esta barra

Ejemplo 2

In:     111aa___9999____aaa99111__11_a_aa999
Result: 111aa   9999    aaa99111  11 a aa999
Out:    6

Descripción: Al eliminar solo el guión bajo, iBug puede obtener 6 partes de la barra y eso es lo máximo.

Ejemplo 3

In:  __________
Out: 1

Descripción: ¿Qué? ¿Quieres cortar esto? Solo es posible obtener 1 parte si no la corta en absoluto.

Ejemplo 4

In:  
Out: 0

Descripción: no hay nada que cortar, así que cero.


También hay algunas reglas que iBug quiere que los programas obedezcan:

  1. A iBug no le gustan las lagunas estándar y están prohibidas.

  2. Mientras funcione, no necesita ser un programa completo. También se acepta una función que toma la entrada de un parámetro y da salida a través del valor de retorno.

  3. Se permiten entradas y salidas flexibles. Su programa o función puede tomar una cadena, o una serie de caracteres, o lo que sea más fácil de manejar. Puede dar el resultado imprimiendo el número o devolviéndolo.


Ejemplos de casos de prueba (pero no limitados a estos)

aaabbbaaa           = 2
123456789           = 5
AaAaAaAa            = 4
aaabcccdedaaabefda  = 6
________            = 1
(empty)             = 0

Como se trata de un , ¡el programa más corto (en bytes) en cada idioma gana!


Extra

iBug aprecia mucho si puede proporcionar una explicación para su programa, a pesar de que no afecta su puntuación (todavía es la longitud en bytes).

iBug
fuente
2
¿Cómo 123456789rinde 5? ¿Y cómo aaabcccdedaaabefdarinde 6? Obtengo 2 y 4 respectivamente para estos dos casos de prueba.
Sr. Xcoder
@ Mr.Xcoder para el primero, eliminar 2468, para el segundo, eliminar bd.
Martin Ender
@MartinEnder Oh, ¿entonces se puede eliminar cualquier subsecuencia ? si alguno de los caracteres se elimina por completo, se sugiere lo contrario.
Sr. Xcoder
1
@ Mr.Xcoder, si he entendido el desafío correctamente, eliminas 2,4,6,8del primero y b,d,fdel segundo.
Shaggy
2
@ Mr.Xcoder significa eliminar todas las copias de cualquier conjunto de caracteres. Creo que el ejemplo trabajado lo muestra bastante bien.
Martin Ender

Respuestas:

8

Haskell , 73 71 70 bytes

x#z|z==x=' '|1<2=z
f x=maximum$length(words x):[f$(c#)<$>x|c<-x,c>' ']

¡Gracias a Laikoni por guardar 1 byte!

Pruébalo en línea!

Cristian Lupascu
fuente
1
maximum$(length$words x):se puede acortar a maximum$length(words x):.
Laikoni
6

JavaScript (ES6), 109 90 bytes

f=s=>Math.max((s.match(/\s+/g)||[]).length,...[...s].map(c=>c>` `&&f(s.split(c).join` `)))
<input oninput=o.textContent=/\s/.test(this.value)?``:f(this.value)><pre id=o>0

Algo lento en el 123456789caso de prueba. La respuesta anterior de 109 bytes no se limitó a !/\s/:

f=
s=>(g=a=>Math.max(a.filter(s=>s).length,...[...a.join``].map(c=>g([].concat(...a.map(s=>s.split(c)))))))([s])
<input oninput=o.textContent=f(this.value)><pre id=o>0

Neil
fuente
@AsoneTuhid Oh, no vi la restricción en el conjunto de caracteres; mi código funciona para cualquier cadena en absoluto.
Neil
El único personaje para el que no tiene que trabajar es el espacio, ¿no?
Asone Tuhid
@AsoneTuhid Su puerto solo funciona para exactamente aquellos caracteres para los que necesita trabajar; su original parece funcionar para cualquier cosa excepto espacios.
Neil
¿Para qué caracteres funciona tu respuesta original y la nueva no?
Asone Tuhid
4

Python 2 , 111 93 72 bytes

-21 bytes gracias Kirill L.

f=lambda s:max([len(s.split())]+[f(s.replace(c,' '))for c in s if'/'<c])

Pruébalo en línea!

ovs
fuente
Parece que el enfoque utilizado actualmente por JS y Ruby también funciona bastante bien para Python: 73 bytes
Kirill L.
@KirillL. gracias por la recomendación
ovs
3

Jalea ,  13  11 bytes

Demasiadas instrucciones de
2 bytes -2 gracias a Zgarb (use el producto externo rápidoþ>. <)

eþŒPŒr¬S€ṀḢ

Un enlace monádico que acepta una lista de caracteres y devuelve un entero no negativo.

Pruébalo en línea!

¿Cómo?

Para cada subsecuencia de la entrada (los conjuntos que podemos eliminar, más los equivalentes redundantes), se obtiene una lista de existencia para identificar cuáles se eliminan, luego encuentra efectivamente cuántas ejecuciones de ceros quedan y produce el máximo. La última parte funciona de una manera un tanto extraña, ya que me pareció más golfista que las alternativas más ingenuas: encuentra las carreras como [element, count]pares, niega identificar los ceros como unos, las sumas encuentran el máximo y luego toma la cabeza (la suma de elementos en lugar de contar) )

eþŒPŒr¬S€ṀḢ - Link: list of characters        e.g. "aabcde"
  ŒP        - power-set - gets all subsequences    ["","a","a","b",...,"bd",...,"aabcde"]
 þ          - outer-product with:
e           -   exists in?                         [[0,0,0,0,0,0],[1,1,0,0,0,0],[1,1,0,0,0,0],[0,0,1,0,0,0],..,[0,0,1,0,1,0]...,[1,1,1,1,1,1]]
    Œr      - run-length encode                    [[[0,6]],[[1,2],[0,4]],[[1,2],[0,4]],[[0,2],[1,1],[0,3]],...,[[0,2],[1,1],[0,1],[1,1],[0,1]],...,[[1,6]]]
      ¬     - NOT                                  [[[1,0]],[[0,0],[1,0]],[[0,0],[1,0]],[[1,0],[0,0],[1,0]],...,[[1,0],[0,0],[1,0],[0,0],[1,0]],...,[[0,0]]]
        €   - for €ach:
       S    -   sum                                [[1,0],[1,0],[1,0],[2,0],...,[3,0],...,[0,0]]
         Ṁ  - maximum                              [3,0]
          Ḣ - head                                 3
Jonathan Allan
fuente
Creo que €Đ€puede ser þ.
Zgarb
3

Ruby , 98 89 75 64 61 bytes

f=->s{[s.split.size,*s.scan(/\w/).map{|c|f[s.tr c,' ']}].max}

Pruébalo en línea!

más pequeño y más lento que antes!

Básicamente un puerto de la respuesta Javascript de @ Neil

Sin golf y anotado

def f(input_string)
    # splits by / +/ by default
    size0 = input_string.split.size
    # an array of all non-space characters in input_string
    characters = input_string.scan(/\w/)
    size1 = characters.map {|i|
        # all letters and digits and _ are "bigger" than /, space isn't
        if i > '/'
            # tr replaces every occurrence of i in input_string with space
            next_string = input_string.tr(i, ' ')
            f(next_string) # recursive call
        else
            0
        end
    }
    # max value between size0 and any element in size1
    return [size0, *size1].max
end

Pruébalo en línea!

Asone Tuhid
fuente
2

Casco , 12 11 bytes

▲mȯ#€0gM€¹Ṗ

Pruébalo en línea! Esto funciona por fuerza bruta y es bastante lento. Agregue ual extremo derecho para que funcione más rápido, sin cambiar la semántica.

Explicación

▲mȯ#€0gM€¹Ṗ  Implicit input, say S = "abddccbdcaab"
          Ṗ  Powerset of S: P = ["","a","b","ab","d","ad"...,"abddccbdcaab"]
 m           Map this function over P:
              Argument is a subsequence, say R = "acc"
       M ¹    Map over S
        €     index of first occurrence in R: [1,0,0,0,2,2,0,0,2,1,1,0]
      g       Group equal elements: [[1],[0,0,0],[2,2],[0,0],[2],[1,1],[0]]
  ȯ#          Count the number of groups
    €0        that contain 0: 3
▲            Take maximum of the results: 4
Zgarb
fuente
2

Perl 5 , (versiones anteriores) -p -I., 52 49 43 bytes

Conteo de estilo antiguo: +3para -p: 46bytes (porque debe estar en un programa, no se puede ejecutar usando -e)

barsplit.pl:

#!/usr/bin/perl -pI.
$G[split]+=s%\S%do$0for s/$&/ /rg%eg;$_=$#G

Ejecutar con la cadena en STDIN:

echo aaabcccdedaaabefda | ./barsplit.pl; echo

Pruébalo en línea!

La -I.opción está ahí para hacer que esto también funcione en perls recientes en los que, de forma predeterminada, .ya no hay más @INC. En versiones anteriores de perl esa opción no es necesaria. Probé eso en una máquina más antigua que todavía tenía perl 5.20, por lo que la puntuación se basa en eso (de lo contrario, también debería contar el .argumento para -I)

Versión rápida ( 49bytes):

#!/usr/bin/perl -pI.
$G[split]+=s%.%$$_++||do$0for s/$&/ /rg%eg;$_=$#G
Ton Hospel
fuente