Le coupeur gourmand

27

iBug a récemment obtenu une longue barre en matériaux composites, mais précieux. La barre est si longue qu'iBug ne peut pas facilement la vendre pour des crédits, donc il veut la couper. La barre est faite de matériaux si fragiles et magiques que, si une pièce est cassée, toutes les parties de la barre faites du même matériau se briseront également, ce qui rendra difficile la coupe arbitraire.

iBug veut couper la barre en autant de morceaux que possible. Il aime également les programmes très courts et le golf de code, il a donc fait une analyse abstraite de son problème.

La barre magique d'iBug est représentée sous la forme d'une chaîne (ou d'un tableau ou d'une séquence de caractères si vous préférez), comme ceci:

aaabbccccccbbbaaacccccaabbbaaaaa

Chaque lettre de la chaîne représente un matériau magique. La barre correspond toujours au RegEx ^\w*$, il peut donc y avoir jusqu'à 63 matériaux dans la barre. Une "partie" est une séquence consécutive de tous les caractères qui ne sont pas séparés par des espaces.

iBug veut que vous écriviez un programme qui calcule le maximum de parties qu'il pourrait obtenir, si zéro ou plusieurs jeux de caractères sont complètement supprimés (remplacés par des espaces), et dites à iBug ce nombre.


Exemple 1:

In:  aaabbccccccbbbaaacccccaabbbaaaaa
Out: 4

Description: S'il best complètement retiré de la barre, iBug pourrait obtenir 4 parties. Il peut également obtenir 4 parties en retirant bet c, comme indiqué ci-dessous

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

Et c'est le nombre maximum de pièces que iBug peut obtenir de cette barre

Exemple 2:

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

Description: en supprimant uniquement le trait de soulignement, iBug peut obtenir 6 parties de la barre et c'est le maximum.

Exemple 3:

In:  __________
Out: 1

Description: Quoi? Tu veux couper ça? Il n'est possible d'obtenir 1 partie que si vous ne la coupez pas du tout.

Exemple 4:

In:  
Out: 0

Description: Il n'y a rien à couper, donc zéro.


Il y a aussi quelques règles auxquelles iBug veut que les programmes obéissent:

  1. iBug n'aime pas les failles standard et elles sont interdites.

  2. Tant qu'il fonctionne, il n'est pas nécessaire que ce soit un programme complet. Une fonction qui prend l'entrée d'un paramètre et donne une sortie via une valeur de retour est également acceptée.

  3. Les entrées et sorties flexibles sont autorisées. Votre programme ou fonction peut prendre une chaîne, un tableau de caractères ou tout ce que vous trouvez le plus facile à gérer. Vous pouvez donner la sortie en imprimant le numéro ou en le renvoyant.


Exemples de cas de test (mais sans s'y limiter)

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

Puisqu'il s'agit d'un , le programme le plus court (en octets) dans chaque langue gagne!


Supplémentaire

iBug apprécie grandement si vous pouvez fournir une explication pour votre programme, même si cela n'affecte pas votre score (il est toujours en octets).

iBug
la source
2
Comment 123456789donne 5? Et comment aaabcccdedaaabefdadonne 6? J'obtiens respectivement 2 et 4 pour ces deux cas de test.
M. Xcoder
@ Mr.Xcoder pour le premier, supprimez 2468, pour le second, supprimez bd.
Martin Ender
@MartinEnder Oh donc toute sous- séquence peut être supprimée? si l'un des caractères est entièrement supprimé, suggérez le contraire.
M. Xcoder
1
@ Mr.Xcoder, si j'ai bien compris le défi, vous supprimez 2,4,6,8du premier et b,d,fdu second.
Shaggy
2
@ Mr.Xcoder, cela signifie supprimer toutes les copies de tout jeu de caractères. Je pense que l'exemple travaillé le montre assez bien.
Martin Ender

Réponses:

8

Haskell , 73 71 70 octets

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

Merci à Laikoni d' avoir économisé 1 octet!

Essayez-le en ligne!

Cristian Lupascu
la source
1
maximum$(length$words x):peut être raccourci maximum$length(words x):.
Laikoni
6

JavaScript (ES6), 109 90 octets

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

Un peu lent sur le 123456789cas de test. La réponse précédente de 109 octets ne se limitait pas à !/\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
la source
@AsoneTuhid Oh, je n'ai pas vu la restriction sur le jeu de caractères; mon code fonctionne pour n'importe quelle chaîne.
Neil
Le seul personnage pour lequel il n'a pas à travailler est l'espace, n'est-ce pas?
Asone Tuhid
@AsoneTuhid Votre port ne fonctionne que pour exactement les caractères pour lesquels il doit travailler; votre original semble fonctionner pour tout sauf les espaces.
Neil
Quels caractères votre réponse originale fonctionne-t-elle pour que la nouvelle ne fonctionne pas?
Asone Tuhid
4

Python 2 , 111 93 72 octets

-21 octets merci Kirill L.

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

Essayez-le en ligne!

ovs
la source
Il semble que l'approche actuellement utilisée par JS et Ruby fonctionne également très bien pour Python: 73 octets
Kirill L.
@KirillL. merci pour la recommandation
ovs
3

Gelée ,  13  11 octets

Trop d'instructions 2 octets
-2 grâce à Zgarb (utilisez le produit externe rapidementþ>. <)

eþŒPŒr¬S€ṀḢ

Un lien monadique acceptant une liste de caractères et renvoyant un entier non négatif.

Essayez-le en ligne!

Comment?

Pour chaque sous-séquence de l'entrée (les ensembles que nous pouvons supprimer, plus les équivalents redondants) obtient une liste d'existence pour identifier ceux qui sont supprimés, puis trouve efficacement le nombre de séries de zéros restant et donne le maximum. La dernière partie fonctionne de manière un peu étrange depuis que je l'ai trouvé plus golfeur que des alternatives plus naïves - elle trouve les pistes par [element, count]paires, nie pour identifier les zéros comme des uns, les sommes trouvent le maximum puis prennent la tête (la somme des éléments plutôt que des comptes) ).

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
la source
Je pense que c'est €Đ€possible þ.
Zgarb
3

Rubis , 98 89 75 64 61 octets

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

Essayez-le en ligne!

plus petit et plus lent qu'auparavant!

Fondamentalement, un portage de la réponse Javascript de @ Neil

Non golfé et annoté

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

Essayez-le en ligne!

Asone Tuhid
la source
2

Husk , 12 11 octets

▲mȯ#€0gM€¹Ṗ

Essayez-le en ligne! Cela fonctionne par force brute et est assez lent. Ajoutez uà l'extrémité droite pour le faire fonctionner plus rapidement, sans changer la sémantique.

Explication

▲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
la source
2

Perl 5 , (versions plus anciennes), -p -I., 52 49 43 octets

Comptage à l'ancienne: +3pour -p: 46octets (car il doit être dans un programme, il ne peut pas être exécuté en utilisant -e)

barsplit.pl:

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

Exécutez avec la chaîne sur STDIN:

echo aaabcccdedaaabefda | ./barsplit.pl; echo

Essayez-le en ligne!

L' -I.option est là pour que cela fonctionne également sur les perles récentes où, par défaut, il .n'y en a plus @INC. Dans les anciennes versions de perl, cette option n'est pas nécessaire. J'ai testé cela sur une machine plus ancienne qui en avait encore perl 5.20, donc le score est basé sur cela (sinon je devrais aussi compter l' .argument -I)

Version rapide ( 49octets):

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