Ninjas et singes et ours, oh mon dieu!

37

Ce défi est le prix de NinjaBearMonkey pour avoir gagné mes troupeaux de bots! contester avec la soumission Black Knight . Félicitations NinjaBearMonkey!

Le défi ici est assez simple, mais a une variété d’approches possibles. L'histoire raconte que dans le monde des illusions isométriques , il existe 6 types de créatures différentes:

  1. Ninjas, abrégés N
  2. Ours, abrégé B
  3. Singes, abrégés M
  4. NinjaBears, abrégé NB
  5. BearMonkeys, en abrégé BM
  6. NinjaBearMonkeys, en abrégé NBM

( NinjaBearMonkey est, bien sûr, le dernier type le plus puissant.)

Votre tâche consiste à recenser ces créatures lorsqu'elles sont alignées côte à côte, c'est-à-dire lorsque leurs chaînes d'abréviations sont concaténées. La mise en garde est que vous devez vous assurer de ne pas trop compter les parties de certaines créatures en tant que créatures distinctes qui se ressemblent. Les créatures s'aligneront de telle sorte que:

  • Toute instance de NBM1 NinjaBearMonkey et 0 autre créature.
  • Toute instance NBnon suivie de Mest 1 NinjaBear et 0 autre créature.
  • Toute instance BMnon précédée de Nest 1 BearMonkey et 0 autre créature.
  • Sinon, les instances de N, Bet Msont respectivement des ninjas, des ours et des singes isolés.

La ligne se lit de gauche à droite.

Ainsi, par exemple, dans la lignée des créatures NBMMBNBNBM, il y a 0 Ninja, 1 Ours, 1 Singe, 1 NinjaBear, 0 BearMonkeys et 2 NinjaBearMonkeys.

Défi

Ecrivez un programme ou une fonction qui prend une chaîne de caractères N, Bet M, et imprime ou retourne le nombre de chacun des 6 types de créatures qu'il contient.

La sortie devrait avoir la forme

#N #B #M #NB #BM #NBM

avec le nombre de créatures respectives remplaçant chaque #signe. Tous les 6 comptes doivent être affichés, séparés par des espaces, même lorsqu'ils sont 0. Cependant, ils peuvent être dans n'importe quel ordre (par exemple, ils #NBMpourraient venir en premier).

Également:

  • La chaîne d'entrée ne contiendra que les caractères N, Bet M.
  • Si la chaîne vide est entrée, tous les comptages sont 0.
  • La sortie peut éventuellement contenir un seul espace de début et / ou de fin et / ou une nouvelle ligne de fin.

La soumission la plus courte en octets l'emporte.

Exemples

Entrée: NB
sortie:0N 0B 0M 1NB 0BM 0NBM

Entrée: NBM
sortie:0N 0B 0M 0NB 0BM 1NBM

Entrée: NBMMBNBNBM(exemple d'en haut)
Sortie:0N 1B 1M 1NB 0BM 2NBM

Entrée: MBNNBBMNBM
sortie:1N 1B 1M 1NB 1BM 1NBM

Entrée: NNNMNBMMBMMBMMMNBMNNMNNNBNNNBNBBNBNMMNBBNBMMBBMBMBBBNNMBMBMMNNNNNMMBMMBM
sortie:17N 6B 14M 5NB 8BM 3NBM

Les passe-temps de Calvin
la source
53
J'approuve ce défi.
NinjaBearMonkey
Juste pour confirmer: si tout ce que vous aviez était 2 NinjaBearMonkeys, vous ne pouvez pas former de ligne? Parce qu'ils ne peuvent pas rester l'un à côté de l'autre?
Alan Campbell
3
@AlanCampbell No. NBMNBMserait une entrée parfaitement valide. En le lisant de gauche à droite, il y a clairement 2 NinjaBearMonkeys.
Les passe-temps de Calvin

Réponses:

20

Pyth, 22 octets

 f|pd+/zTT=:zTd_.:"NBM

Un moyen assez astucieux de sauvegarder 1 octet, grâce à @Jakube.


Pyth, 23 octets

FN_.:"NBM")pd+/zNN=:zNd

Manifestation.

Imprime dans l’ordre inverse, avec un espace de fin et pas de nouvelle ligne.

.:"NBM")est toutes les sous-chaînes, les _met dans le bon ordre, /zNcompte les occurrences et =:zNdremplace sur place chaque occurrence de la chaîne en question par un espace.

FN_.:"NBM")pd+/zNN=:zNd
FN                         for N in                            :
  _                                 reversed(                 )
   .:     )                                  substrings(     )
     "NBM"                                              "NBM"
           pd              print, with a space at the end,
              /zN          z.count(N)
             +   N                    + N
                  =:zNd    replace N by ' ' in z.
isaacg
la source
23

JavaScript ES6, 86 octets

f=s=>'NBM BM NB M B N'.replace(/\S+/g,e=>(i=0,s=s.replace(RegExp(e,'g'),_=>++i))&&i+e)

(Je viens juste de répondre à cela.) Il passe par chaque sous-chaîne de NBM, en commençant par les plus longues, qui ont une priorité plus élevée. Il recherche chaque occurrence de cette chaîne particulière et la supprime (dans ce cas, la remplace par le nombre actuel afin qu'elle ne corresponde plus). Il remplace finalement chaque sous-chaîne par le compte + la chaîne.

Cet extrait de pile est écrit dans l'équivalent ES5 du code ci-dessus pour faciliter le test à partir de n'importe quel navigateur. C'est aussi un code légèrement non-golfé. L'interface utilisateur est mise à jour à chaque frappe.

f=function(s){
  return'NBM BM NB M B N'.replace(/\S+/g,function(e){
    i=0
    s=s.replace(RegExp(e,'g'),function(){
      return++i
    })
    return i+e
  })
}

run=function(){document.getElementById('output').innerHTML=f(document.getElementById('input').value)};document.getElementById('input').onkeyup=run;run()
<input type="text" id="input" value="NBMMBNBNBM" /><br /><samp id="output"></samp>

NinjaBearMonkey
la source
Pourriez-vous changer la partie regex en 'NBM<newline>BM<newline>...<newline>N'.replace(/./g, ...)', où les <newline>s sont des sauts de ligne littéraux et les 's sont des backticks, formant une chaîne de template ES6? Enregistre deux octets dans l'expression régulière ( .ne correspond pas aux nouvelles lignes).
wchargin
@WChargin Malheureusement non, car la sortie doit être séparée de l'espace.
NinjaBearMonkey
17

Python 2, 78

n=input()
for x in"NBM BM NB M B N".split():n=`n`.split(x);print`len(n)-1`+x,

Une variante de la réponse de Vioz . Amusez-vous avec les représentations de chaînes Python 2!

Compte indirectement les occurrences de la sous-chaîne en y coupant, en comptant les parties et en soustrayant 1. Au lieu de remplacer les sous-chaînes par un symbole de remplissage, remplace la chaîne par la liste splitproduite. Ensuite, lorsque nous prenons sa représentation sous forme de chaîne, les parties sont séparées par des espaces et des virgules.

Xnor
la source
5
C'est dingue! Excellemment fou, mais toujours fou.
Sp3000
Bon travail! Je n'ai pas pensé à ça :)
Kade
14

Ruby, 166 80 72 68 caractères

f=->s{%w(NBM BM NB M B N).map{|t|c=0;s.gsub!(t){c+=1};c.to_s+t}*' '}

Explication:

  • Le comptage se fait en sens inverse. En effet, les ninjas, ours et singes les plus longs priment les plus petits.

  • Pour NBM, BMet NB, les séquences gsub!sortent de la chaîne d'origine avec un bloc pour compter le nombre de ces séquences existantes (oui, la fonction modifie son argument).

    • Cependant, ils ne peuvent être remplacés par rien, car sinon, BNBMMils seraient comptés comme NBMet BMau lieu de B, NBMet M(parce que lorsque le NBMserait supprimé, il serait mis le Bet Mensemble et il n'y aurait pas moyen de le distinguer). À l'origine, j'avais renvoyé une chaîne de caractères unique ( .gsub!('NBM'){c+=1;?|}), mais je me suis rendu compte que je pouvais simplement renvoyer le résultat de +=(qui est un nombre, donc il ne peut en être aucun N B M).
  • Pour M, Bet N, je peux juste countcombien il y en a dans la chaîne (pas besoin de les enlever via gsub!). Maintenant, c'est une boucle (je ne sais pas pourquoi je n'y avais pas pensé en premier lieu), donc cela se fait de la même manière.


Solution similaire en autruche , 54 51 caractères :

:s;`NBM BM NB M B N`" /{:t0:n;s\{;n):n}X:s;nt+}%" *

Malheureusement, ce n’est pas une solution valable, car il existe un bogue dans la version actuelle d’Ostrich (qui est maintenant corrigé, mais après la publication de ce défi).

Poignée de porte
la source
Vous pouvez enregistrer 3 caractères en utilisant la notation de tableau %w(NBM BM NB M B N)et en supprimant la division.
DickieBoy
@ DickieBoy C'est en fait 4 caractères; Merci!
Poignée de porte
Ah oui, le point!
DickieBoy
14

Java, 166 162

void f(String a){String[]q="NBM-NB-BM-N-B-M".split("-");for(int i=0,c;i<6;System.out.print(c+q[i++]+" "))for(c=0;a.contains(q[i]);c++)a=a.replaceFirst(q[i],".");}

Et avec quelques sauts de ligne:

void f(String a){
    String[]q="NBM-NB-BM-N-B-M".split("-");
    for(int i=0,c;i<6;System.out.print(c+q[i++]+" "))
        for(c=0;a.contains(q[i]);c++)
            a=a.replaceFirst(q[i],".");
}

Cela fonctionne assez simplement. Bouclez simplement les jetons, remplacez-les par des points et comptez tant que l'entrée en contient. Commence par compter les plus gros, pour que les plus petits ne le gâchent pas.

Au départ, j'ai essayé de tout remplacer en même temps et de compter la différence de longueur, mais il a fallu quelques caractères supplémentaires de cette façon :(

Géobits
la source
2
En tant que développeur Java, je souhaite raccourcir ce processus et voir Java gagner. Après l'avoir regardé pendant un moment, je n'ai pas encore trouvé le moyen de le raccourcir.
DeadChex
1
Eh bien, il ne va certainement pas gagner en général. Le leader actuel est de 22 octets et il n'y a aucun moyen de faire quelque chose de significatif en Java de cette taille. Ma printlnseule déclaration est plus grande que cela. J'en suis cependant satisfait: D
Geobits
1
Je suis un peu en retard mais j'ai trouvé un moyen ... changer String q[]=pourString[]q=
DeadChex
1
Agréable! Vous ne pouvez pas croire que j'ai raté ça, c'est sur ma liste standard de choses à regarder :)
Geobits
Je ne l'ai découvert qu'après avoir essayé d'entrer dans Code Golf en tant que JavaDev. Je suis assez surpris de ce que vous pouvez faire
DeadChex
11

CJam, 36 32 31 octets

l[ZYX]"NBM"few:+{A/_,(A+S@`}fA;

Merci à @Optimizer pour le golf de 1 octet.

Essayez-le en ligne dans l' interprète CJam .

Comment ça marche

l                                e# Read a line L from STDIN.
 [ZYX]"NBM"                      e# Push [3 2 1] and "NBM".
           few                   e# Chop "NBM" into slices of length 3 to 1.
              :+                 e# Concatenate the resulting arrays of slices.
                {          }fA   e# For each slice A:
                 A/              e#   Split L at occurrences of A.
                   _,(           e#   Push the numbers of resulting chunks minus 1.
                      A+         e#   Append A.
                        S        e#   Push a space.
                         @`      e#   Push a string representation of the split L.
                              ;  e# Discard L.
Dennis
la source
N*-> `devrait suffire.
Optimiseur
@Optimize: Cela fonctionne bien. Merci.
Dennis
7

R, 153 134 118

Cela a pris beaucoup de temps, mais j'espère pouvoir en raser quelques-uns. L'entrée est STDIN et la sortie sur STDOUT.

Edit Changement de virement de bord. Je me suis débarrassé de la chaîne fendue et du comptage des pièces. Maintenant, je remplace les pièces par une chaîne plus courte que la pièce. La différence entre les longueurs de chaîne est collectée pour la sortie.

N=nchar;i=scan(,'');for(s in scan(,'',t='NBM BM NB M B N'))cat(paste0(N(i)-N(i<-gsub(s,strtrim('  ',N(s)-1),i)),s),'')

Explication

N=nchar;
i=scan(,'');                     # Get input from STDIN
for(s in scan(,'',t='NBM BM NB M B N'))  # Loop through patterns
  cat(                           # output
    paste0(                      # Paste together
      N(i) -                     # length of i minus
      N(i<-gsub(                 # length of i with substitution of
        s,                       # s
        strtrim('  ',N(s)-1)     # with a space string 1 shorter than s
        ,i)                      # in i
      ),
      s)                         # split string
  ,'')

Essai

> N=nchar;i=scan(,'');for(s in scan(,'',t='NBM BM NB M B N'))cat(paste0(N(i)-N(i<-gsub(s,strtrim('  ',N(s)-1),i)),s),'')
1: NNNMNBMMBMMBMMMNBMNNMNNNBNNNBNBBNBNMMNBBNBMMBBMBMBBBNNMBMBMMNNNNNMMBMMBM
2: 
Read 1 item
Read 6 items
3NBM 8BM 5NB 14M 6B 17N 
> N=nchar;i=scan(,'');for(s in scan(,'',t='NBM BM NB M B N'))cat(paste0(N(i)-N(i<-gsub(s,strtrim('  ',N(s)-1),i)),s),'')
1: NBMMBNBNBM
2: 
Read 1 item
Read 6 items
2NBM 0BM 1NB 1M 1B 0N 
> 
MickyT
la source
7

Pyth, 19 octets

jd+Ltl=zc`zd_.:"NBM

Ceci est un mélange de la solution Pyth @ isaacg et de l'incroyable tour Python de @ xnor.

Essayez-le en ligne: démonstration ou test de harnais

Explication

jd+Ltl=zc`zd_.:"NBM   implicit: z = input string
             .:"NBM   generate all substrings of "NBM"
            _         invert the order
  +L                  add left to each d in ^ the following:
         `z             convert z to a string
        c  d            split at d
      =z                assign the resulting list to z
    tl                  length - 1
jd                    join by spaces and implicit print
Jakube
la source
6

Julia, 106 97 octets

b->for s=split("NBM BM NB M B N") print(length(matchall(Regex(s),b)),s," ");b=replace(b,s,".")end

Cela crée une fonction non nommée qui prend une chaîne en tant qu'entrée et affiche le résultat dans STDOUT avec un seul espace de fin et sans nouvelle ligne. Pour l'appeler, donnez-lui un nom, par exemple f=b->....

Ungolfed + explication:

function f(b)
    # Loop over the creatures, biggest first
    for s = split("NBM BM NB M B N")

        # Get the number of creatures as the count of regex matches
        n = length(matchall(Regex(s), b))

        # Print the number, creature, and a space
        print(n, s, " ")

        # Remove the creature from captivity, replacing with .
        b = replace(b, s, ".")
    end
end

Exemples:

julia> f("NBMMBNBNBM")
2NBM 0BM 1NB 1M 1B 0N 

julia> f("NNNMNBMMBMMBMMMNBMNNMNNNBNNNBNBBNBNMMNBBNBMMBBMBMBBBNNMBMBMMNNNNNMMBMMBM")
3NBM 8BM 5NB 14M 6B 17N 
Alex A.
la source
4

Python 2, 93 88 89 84 octets

Prenant l'approche simple.

def f(n):
 for x in"NBM BM NB M B N".split():print`n.count(x)`+x,;n=n.replace(x,"+")

Appelle comme ça:

f("NBMMBNBNBM")

La sortie est comme ça:

2NBM 0BM 1NB 1M 1B 0N
Kade
la source
Vous pouvez supprimer l'espace après in.
isaacg
En Python 2, vous pouvez convertir une représentation sous forme de chaîne avec `x`.
xnor
4

SAS, 144 142 139 129

data;i="&sysparm";do z='NBM','NB','BM','N','B','M';a=count(i,z,'t');i=prxchange(cats('s/',z,'/x/'),-1,i);put a+(-1)z@;end;

Utilisation (7 octets ajoutés pour sysparm):

$ sas -stdio -sysparm NNNMNBMMBMMBMMMNBMNNMNNNBNNNBNBBNBNMMNBBNBMMBBMBMBBBNNMBMBMMNNNNNMMBMMBM << _S
data;i="&sysparm";do z='NBM','NB','BM','N','B','M';a=count(i,z,'t');i=prxchange(cats('s/',z,'/x/'),-1,i);put a+(-1)z@;end;
_S

ou

%macro f(i);i="&i";do z='NBM','NB','BM','N','B','M';a=count(i,z,'t');i=prxchange(cats('s/',z,'/x/'),-1‌​,i);put a+(-1)z@;end;%mend;

Usage:

data;%f(NNNMNBMMBMMBMMMNBMNNMNNNBNNNBNBBNBNMMNBBNBMMBBMBMBBBNNMBMBMMNNNNNMMBMMBM)

Résultat:

3NBM 5NB 8BM 17N 6B 14M
Oeuf frit
la source
Vous pouvez enregistrer quelques octets en utilisant cats('s/',z,'/x/')à la place de 's/'||strip(z)||'/x/'.
Alex A.
1
Bien, ça a été tout un voyage de retour à 139 :)
Œuf sur le plat
1
126 octets:macro a i="&sysparm";do z='NBM','NB','BM','N','B','M';a=count(i,z,'t');i=prxchange(cats('s/',z,'/x/'),-1,i);put a+(-1)z@;end;%
Alex A.
1
122: data;i="&sysparm";do z='NBM','NB','BM','N','B','M';a=count(i,z,'t');i=prxchange(cats('s/',z,'/x/'),-1,i);put a+(-1)z@;end;. Puisque vous lisez déjà de sysparm, vous pouvez aussi bien l’exécuter comme une étape de données. Et si vous travaillez en batch, vous n’avez pas besoin run;.
Alex A.
1
Mais vous pourriez obtenir 129 en utilisant une macro de style moderne qui ne lit pas l'argument en ligne de commande:%macro a(i);i="&i";do z='NBM','NB','BM','N','B','M';a=count(i,z,'t');i=prxchange(cats('s/',z,'/x/'),-1,i);put a+(-1)z@;end;%mend;
Alex A.
3

PHP4.1, 92 octets

Pas le plus court, mais qu'attendez-vous de plus de PHP?

Pour l'utiliser, définissez une clé sur un cookie, post, obtenir, session ...

<?foreach(split(o,NBMoNBoBMoMoBoN)as$a){echo count($T=split($a,$S))-1,"$a ";$S=join('',$T);}

L'approach est basique:

  • Diviser la chaîne en noms de créatures
  • Comptez combien d'éléments il y a
  • Soustraire 1 (une chaîne vide donnerait un tableau avec 1 élément)
  • Affiche le compte et le nom de la créature
  • Joignez le tout ensemble, en utilisant une chaîne vide (ce qui réduira la chaîne et supprimera la dernière créature)

Facile, non?

Ismael Miguel
la source
2

JavaScript, 108 116 octets

Juste une approche simple, rien d'extraordinaire

o="";r=/NBM|NB|BM|[NMB]/g;g={};for(k in d=(r+prompt()).match(r))g[d[k]]=~-g[d[k]];for(k in g)o+=~g[k]+k+" ";alert(o);
C5H8NNaO4
la source
1
Ne fonctionne pas: All 6 counts must be shown, separated by spaces, even when they are 0.. Cas de test:N
edc65
@ edc65 Woah. Je viens de manquer cette partie. Merci d'avoir fait remarquer cela. Corrigé pour le coût de 8chars
C5H8NNaO4
2

Perl, 46

#!perl -p
$_="NBM BM NB M B N"=~s/\w+/~~s!$&!x!g.$&/ger
nutki
la source
Explication sur comment cela fonctionne?
Caïn
1

SpecBAS - 164

1 INPUT s$
2 FOR EACH a$ IN ["NBM","BM","NB","M","B","N"]
3 LET n=0
4 IF POS(a$,s$)>0 THEN INC n: LET s$=REPLACE$(s$,a$,"-"): GO TO 4: END IF
5 PRINT n;a$;" ";
6 NEXT a$

Utilise la même approche que beaucoup d'autres. La ligne 4 continue de passer en boucle sur la chaîne (en commençant par la plus grande), la remplace si elle est trouvée.

SpecBAS a quelques petites touches par rapport à l’original ZX / Sinclair BASIC (lecture en boucle des listes, recherche de personnages), que je découvre encore.

Brian
la source
1

C, 205 186 184 octets

Une approche légèrement différente basée sur la machine à états. où test l'état

a[7],t,i;c(char*s){do{i=0;t=*s==78?i=t,1:*s-66?*s-77?t:t-4?t-2?i=t,3:5:6:t-1?i=t,2:4;i=*s?i:t;a[i]++;}while(*s++);printf("%dN %dB %dM %dNB %dBM %dNBM",a[1],a[2],a[3],a[4],a[5],a[6]);}

Étendu

int a[7],t,i;

void c(char *s)
{
    do {
        i = 0;
        if (*s == 'N') {
            i=t; t=1;
        }
        if (*s == 'B') {
            if (t==1) {
                t=4;
            } else {
                i=t;
                t=2;
            }
        }
        if (*s == 'M') {
            if (t==4) {
                t=6;
            } else if (t==2) {
                t=5;
            } else {
                i=t;
                t=3;
            }
        }
        if (!*s)
            i = t;
        a[i]++;
    } while (*s++);
    printf("%dN %dB %dM %dNB %dBM %dNBM",a[1],a[2],a[3],a[4],a[5],a[6]);
}

Fonction de test

#include <stdio.h>
#include <stdlib.h>

/*
 * 0 : nothing
 * 1 : N
 * 2 : B
 * 3 : M
 * 4 : NB
 * 5 : BM
 * 6 : NBM
 */
#include "nbm-func.c"

int main(int argc, char **argv)
{
    c(argv[1]);
}
un utilisateur
la source
Ne pas utiliser for(;;*s++){...}au lieu de do{...}while(*s++);sauver quelques octets? En outre, vous n'avez pas besoin du caractère de nouvelle ligne dans le fichier printf.
Spikatrix
Je pense que tu voulais dire for(;*s;s++). Mais je devais boucler avec ce dernier caractère nul. Bon appel à sauver le \n, ce qui n'est pas nécessaire.
certains utilisateurs
1

C, 146

f(char*s)
{
  char*p,*q="NBM\0NB\0BM\0N\0B\0M",i=0,a=2;
  for(;i<6;q+=a+2,a=i++<2)
  {
    int n=0;
    for(;p=strstr(s,q);++n)*p=p[a>1]=p[a]=1;
    printf("%d%s ",n,q);
  }
}

// Main function, just for testing
main(c,a)char**a;{
  f(a[1]);
}  
edc65
la source
1

Haskell - 177 octets (sans importations)

n s=c$map(\x->(show$length$filter(==x)(words$c$zipWith(:)s([f(a:[b])|(a,b)<-zip s(tail s)]++[" "])))++x++" ")l
f"NB"=""
f"BM"=""
f p=" "
l=["N","B","M","NB","BM","NBM"]
c=concat

(Désolé pour la nécromancie Internet ici.)

La plate-forme Haskell ne permet pas la recherche de chaînes sans importations et je voulais montrer et exploiter le fait que les chaînes recherchées sont toutes des sous-chaînes d'une chaîne (sans répétitions), afin de pouvoir regrouper les caractères en identifiant les paires autorisées à se suivent, c'est quoi f fait ici.

J'ai toujours besoin de la liste complète là la fin pour vérifier l'égalité et afficher exactement ce qui est requis, mais ce ne serait pas le cas si le seul défi était de signaler le nombre d'occurrences possibles wordsdans n'importe quel ordre.

Leif Willerts
la source
0

Bash - 101

I=$1
for p in NBM BM NB M B N;{ c=;while [[ $I =~ $p ]];do I=${I/$p/ };c+=1;done;echo -n ${#c}$p\ ;}

Passez la chaîne comme premier argument.

bash nmb.sh MBNNBBMNBM 

Expliqué un peu:

# We have to save the input into a variable since we modify it.
I=$1

# For each pattern (p) in order of precedence
for p in NBM BM NB M B N;do
    # Reset c to an empty string
    c=

    # Regexp search for pattern in string
    while [[ $I =~ $p ]];do
        # Replace first occurance of pattern with a space
        I=${I/$p/ }
        # Append to string c. the 1 is not special it could be any other
        # single character
        c+=1
    done

    # -n Suppress's newlines while echoing
    # ${#c} is the length on the string c
    # Use a backslash escape to put a space in the string.
    # Not using quotes in the golfed version saves a byte.
    echo -n "${#c}$p\ "
done
Daniel Wakefield
la source
0

rs , 275 octets

(NBM)|(NB)|(BM)|(N)|(B)|(M)/a\1bc\2de\3fg\4hi\5jk\6l
[A-Z]+/_
#
+(#.*?)a_b/A\1
+(#.*?)c_d/B\1
+(#.*?)e_f/C\1
+(#.*?)g_h/D\1
+(#.*?)i_j/E\1
+(#.*?)k_l/F\1
#.*/
#
#(A*)/(^^\1)NBM #
#(B*)/(^^\1)NB #
#(C*)/(^^\1)BM #
#(D*)/(^^\1)N #
#(E*)/(^^\1)B #
#(F*)/(^^\1)M #
\(\^\^\)/0
 #/

Démo en direct et tests.

Les rouages ​​sont simples mais un peu bizarres:

(NBM)|(NB)|(BM)|(N)|(B)|(M)/a\1bc\2de\3fg\4hi\5jk\6l

Cela utilise de manière créative des groupes pour transformer les entrées de la manière suivante:

NBMBM

dans

aNBMbcdeBMfghijkl

La ligne suivante:

[A-Z]+/_

Ceci remplace les séquences de lettres majuscules par des traits de soulignement.

#

Cela insère simplement un signe dièse au début de la ligne.

+(#.*?)a_b/A\1
+(#.*?)c_d/B\1
+(#.*?)e_f/C\1
+(#.*?)g_h/D\1
+(#.*?)i_j/E\1
+(#.*?)k_l/F\1
#.*/

C'est la partie cool du début. Il prend essentiellement les séquences de lettres minuscules et des caractères de soulignement, les convertit en lettres majuscules, les regroupe et les place avant la livre insérée. Le but de la fourrière est de gérer les séquences déjà traitées.

#

La livre est réinsérée au début de la ligne.

#(A*)/(^^\1)NBM #
#(B*)/(^^\1)NB #
#(C*)/(^^\1)BM #
#(D*)/(^^\1)N #
#(E*)/(^^\1)B #
#(F*)/(^^\1)M #
\(\^\^\)/0
 #/

Les lettres majuscules sont remplacées par leurs équivalents textuels avec les nombres associés. À cause d'un bogue dans rs (je ne voulais pas risquer de le réparer et d'être disqualifié), les séquences vides sont converties en (^^), qui sont remplacées par un 0 dans l'avant-dernière ligne. La toute dernière ligne supprime simplement la livre.

kirbyfan64sos
la source
0

KDB (Q), 76 octets

{" "sv string[-1+count@'enlist[x]{y vs" "sv x}\l],'l:" "vs"NBM NB BM N B M"}

Explication

                                                   l:" "vs"NBM NB BM N B M"     / substrings
                        enlist[x]{y vs" "sv x}\l                                / replace previous substring with space and cut
              -1+count@'                                                        / counter occurrence
       string[                                  ],'                             / string the count and join to substrings
{" "sv                                                                     }    / concatenate with space, put in lambda

Tester

q){" "sv string[-1+count@'enlist[x]{y vs" "sv x}\l],'l:" "vs"NBM NB BM N B M"}"NNNMNBMMBMMBMMMNBMNNMNNNBNNNBNBBNBNMMNBBNBMMBBMBMBBBNNMBMBMMNNNNNMMBMMBM"
"3NBM 5NB 8BM 17N 6B 14M"
q){" "sv string[-1+count@'enlist[x]{y vs" "sv x}\l],'l:" "vs"NBM NB BM N B M"}""
"0NBM 0NB 0BM 0N 0B 0M"
WooiKent Lee
la source
0

Haskell: 244 octets

import Data.List
s="NBM"
[]#_=[[]]
a#[]=[]:a#s
l@(a:r)#(b:m)
 |a==b=let(x:y)=r#m in((a:x):y)
 |True=[]:l#m
c?t=length$filter(==t)c
p=["N","B","M","NB","BM","NBM"]
main=getLine>>= \l->putStrLn.intercalate " "$map(\t->show((l#[])?t)++t)p
Jeremy List
la source
Quelques suggestions: Vous utilisez pet une sseule fois, il n'y a donc pas besoin de lui donner un nom (-> a#[]=[]:a#"NBM", même pour p). BTW: words"N B M NB BM NBM"au lieu de la liste des chaînes, vous enregistrez des octets supplémentaires. C’est importseulement pour intercalate, c’est plus court pour le ré-implémenter: ...putStrLn.tail.((' ':)=<<)$map...et vous en débarrasser import. Mettez tous les gardes |dans la définition de #dans une seule ligne et utilisez à la 1<2place de True: ...#(b:m)|a==b=...l#m|1<2=[]......
nimi
... ?peut être défini plus court avec une compréhension de la liste: c?t=sum[1|x<-c,x==t]. Encore une fois, vous utilisez une ?seule fois, utilisez donc le corps directement: ...show(sum[1|x<-l#[],x==t]).
nimi