Ninja, małpy i niedźwiedzie, ojej!

37

Wyzwanie to jest nagrodą NinjaBearMonkey za wygraną w moje stada robotów Block Building! wyzwanie z poddaniem się Czarnego Rycerza . Gratulacje NinjaBearMonkey!

Wyzwanie tutaj jest dość proste, ale ma wiele możliwych podejść. Historia głosi, że w świecie Isometric Illusions istnieje 6 różnych rodzajów stworzeń:

  1. Ninja, w skrócie N
  2. Niedźwiedzie, w skrócie B
  3. Małpy, w skrócie M
  4. NinjaBears, w skrócie NB
  5. BearMonkeys, w skrócie BM
  6. NinjaBearMonkeys, w skrócie NBM

( NinjaBearMonkey jest oczywiście ostatnim, najpotężniejszym typem.)

Twoim zadaniem jest wykonanie spisu tych stworzeń, gdy są one ustawione obok siebie, tj. Kiedy ich łańcuchy skrótów są połączone. Zastrzeżenie polega na tym, że musisz uważać, aby nie przeliczyć części niektórych stworzeń jako osobnych stworzeń, które wyglądają podobnie. Stworzenia ustawią się tak, że:

  • Każde wystąpienie NBMto 1 NinjaBearMonkey i 0 innych stworzeń.
  • Każde wystąpienie, po którym NBnie następuje, Mto 1 NinjaBear i 0 innych stworzeń.
  • Każda instancja, której BMnie poprzedza, Nto 1 BearMonkey i 0 innych stworzeń.
  • W przeciwnym razie przypadki N, Bi Msą to pojedyncze Ninjas, niedźwiedzie, małpy i odpowiednio.

Linia jest odczytywana od lewej do prawej.

Na przykład w linii stworzeń NBMMBNBNBMjest 0 Ninja, 1 Niedźwiedź, 1 Małpa, 1 NinjaBear, 0 BearMonkeys i 2 NinjaBearMonkeys.

Wyzwanie

Napisz program lub funkcję, która pobiera ciąg znaków N, Boraz M, i wypisuje lub zwraca liczbę każdego z 6 typów stworzeń w nim obecnych.

Dane wyjściowe powinny mieć formę

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

z odpowiednią liczbą stworzeń zastępujących każdy #znak. Wszystkie 6 liczb musi być pokazanych, oddzielonych spacjami, nawet gdy są one równe 0. Jednak mogą być w dowolnej kolejności (np. #NBMMogą być pierwsze).

Również:

  • Ciąg wejściowy będzie zawierać tylko znaki N, Bi M.
  • Jeśli wprowadzony zostanie pusty ciąg, wszystkie liczby będą wynosić 0.
  • Dane wyjściowe mogą opcjonalnie zawierać pojedyncze początkowe i / lub końcowe spacje i / lub pojedyncze końcowe znaki.

Najkrótsze przesłanie w bajtach wygrywa.

Przykłady

Wejście: NB
Wyjście:0N 0B 0M 1NB 0BM 0NBM

Wejście: NBM
Wyjście:0N 0B 0M 0NB 0BM 1NBM

Dane wejściowe: NBMMBNBNBM(przykład z góry) Dane
wyjściowe:0N 1B 1M 1NB 0BM 2NBM

Wejście: MBNNBBMNBM
Wyjście:1N 1B 1M 1NB 1BM 1NBM

Wejście: NNNMNBMMBMMBMMMNBMNNMNNNBNNNBNBBNBNMMNBBNBMMBBMBMBBBNNMBMBMMNNNNNMMBMMBM
Wyjście:17N 6B 14M 5NB 8BM 3NBM

Hobby Calvina
źródło
53
Akceptuję to wyzwanie.
NinjaBearMonkey
Tylko dla potwierdzenia: jeśli wszystko, co miałeś, to 2 NinjaBearMonkeys, nie możesz utworzyć linii? Ponieważ nie mogą stać obok siebie?
Alan Campbell,
3
@AlanCampbell No. NBMNBMbyłoby całkowicie poprawnym wejściem. Czytając go od lewej do prawej, wyraźnie widać 2 NinjaBearMonkeys.
Calvin's Hobbies

Odpowiedzi:

20

Pyth, 22 bajty

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

Dość hackerski sposób na zaoszczędzenie 1 bajtu dzięki @Jakube.


Pyth, 23 bajty

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

Demonstracja.

Drukuje w odwrotnej kolejności, z końcową spacją i bez nowej linii.

.:"NBM")jest wszystkimi podciągami, _ustawia je we właściwej kolejności, /zNliczy wystąpienia i =:zNdzastępuje w miejscu każde wystąpienie danego ciągu spacją.

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
źródło
23

JavaScript ES6, 86 bajtów

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

(Musiałem tylko na to odpowiedzieć.) Przechodzi przez każdy podciąg NBM, zaczynając od dłuższych, które mają wyższy priorytet. Wyszukuje każde wystąpienie tego konkretnego ciągu i usuwa go (w tym przypadku zastępuje go bieżącą liczbą, aby nie było ponownie dopasowane). W końcu zastępuje każdy podciąg liczbą i łańcuchem.

Ten fragment kodu jest zapisany w odpowiedniku powyższego kodu w ES5, aby ułatwić testowanie z dowolnej przeglądarki. Jest to również nieznacznie zmieniony kod. Interfejs użytkownika aktualizuje się za każdym naciśnięciem klawisza.

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
źródło
Czy możesz zmienić część wyrażenia regularnego na 'NBM<newline>BM<newline>...<newline>N'.replace(/./g, ...)', gdzie <newline>s to dosłowne znaki nowej linii, a 's odwrotne, tworząc ciąg szablonu ES6? Zapisuje dwa bajty w wyrażeniu regularnym ( .nie pasuje do nowego wiersza).
wchargin
@WChargin Niestety nie, ponieważ dane wyjściowe muszą być rozdzielone spacjami.
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,

Wariant odpowiedzi Vioz . Zabawa z reprezentacjami ciągów Python 2!

Zlicza występowanie podciągów pośrednio, dzieląc je, zliczając części i odejmując 1. Zamiast zastępowania podciągów symbolem wypełniacza, zastępuje ciąg przez utworzoną listę split. Następnie, gdy weźmiemy reprezentację ciągu, części są oddzielone spacjami i przecinkami.

xnor
źródło
5
To jest szalone! Doskonale szalony, ale wciąż szalony.
Sp3000,
Dobra robota! Nie myślałem o tym :)
Kade
14

Rubin, 166 80 72 68 znaków

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

Wyjaśnienie:

  • Liczenie odbywa się w odwrotnej kolejności. Jest tak, ponieważ dłuższe ninje, niedźwiedzie i małpy mają pierwszeństwo przed krótszymi.

  • Dla NBM, BMi NB, sekwencje są gsub!poza oryginalnym ciągiem z blokiem, aby policzyć, ile z tych sekwencji istnieje (tak, funkcja modyfikuje swój argument).

    • Jednak nie można zastąpić niczym, gdyż w przeciwnym razie BNBMMbyłyby liczone jako NBMi BMzamiast B, NBMi M(bo gdy NBMzostaną usunięte, to umieścić Bi Mrazem i nie byłoby sposobem na to rozróżnienie). Pierwotnie zwróciłem ciąg jednego znaku ( .gsub!('NBM'){c+=1;?|}), ale zdałem sobie sprawę, że mogę po prostu zwrócić wynik +=(który jest liczbą, więc nie może to być żaden N B M).
  • Dla M, Bi N, mogę po prostu countokreślić, ile z nich jest w ciągu (nie trzeba ich usuwać przez gsub!). Teraz jest pętla (nie wiem, dlaczego nie pomyślałem o tym w pierwszej kolejności), więc są wykonywane w ten sam sposób.


Podobne rozwiązanie w Strusiu , 54 51 znaków :

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

Niestety nie jest to poprawne rozwiązanie, ponieważ w obecnej wersji strusia występuje błąd (który został już naprawiony, ale po opublikowaniu tego wyzwania).

Klamka
źródło
Możesz zapisać 3 znaki używając notacji tablicowej %w(NBM BM NB M B N)i usuwając podział.
DickieBoy,
@DickieBoy To właściwie 4 znaki; dzięki!
Klamka
Ach tak, kropka!
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],".");}

I z kilkoma podziałami linii:

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],".");
}

Działa to po prostu. Wystarczy zapętlić tokeny, zamieniając je kropkami i licząc, dopóki dane wejściowe zawierają niektóre. Najpierw liczą się te duże, więc maluchy się nie psują.

Początkowo próbowałem zastąpić wszystko naraz i licząc różnicę długości, ale w ten sposób zabrało to kilka znaków :(

Geobity
źródło
2
Jako programista Java chcę to skrócić i zobaczyć, jak Java wygrywa. Po wpatrzeniu się w nią przez jakiś czas muszę znaleźć sposób, aby ją skrócić.
DeadChex,
1
Cóż, zdecydowanie nie wygra ogólnie. Obecny lider ma 22 bajty i po prostu nie ma sposobu, aby zrobić coś znaczącego w Javie w tym rozmiarze. Moje printlnsamo oświadczenie jest większe. Jestem z tego jednak zadowolony: D
Geobits
1
Jestem trochę spóźniony, ale znalazłem sposób ... zmienić String q[]=naString[]q=
DeadChex
1
Miły! Nie mogę uwierzyć, że mi tego brakowało, jest na mojej standardowej liście rzeczy do obejrzenia :)
Geobits
Odkryłem to dopiero po próbie wejścia do Code Golf jako JavaDev, jestem zaskoczony niektórymi rzeczami, które możesz zrobić
DeadChex
11

CJam, 36 32 31 bajtów

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

Dzięki @Optimizer za grę w golfa z 1 bajtu.

Wypróbuj online w interpretatorze CJam .

Jak to działa

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
źródło
N*-> `powinno wystarczyć.
Optymalizator
@Optimize: To działa dobrze. Dzięki.
Dennis
7

R, 153 134 118

Trwało to naprawdę szybko, ale mam nadzieję, że uda mi się ogolić kilka. Wejście to STDIN i wyjście do STDOUT.

Edytuj Zmiana tack. Pozbyłem się podzielonego sznurka i liczenia części. Teraz zastępuję części sznurkiem o jeden krótszym niż część. Różnica między długościami łańcuchów jest zbierana dla danych wyjściowych.

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

Wyjaśnienie

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

Testowe uruchomienie

> 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
źródło
7

Pyth, 19 bajtów

jd+Ltl=zc`zd_.:"NBM

Jest to połączenie rozwiązania Pyth @ isaacg i niesamowitej sztuczki Python @ xnor.

Wypróbuj online: Demonstracja lub Uprząż testowa

Wyjaśnienie

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
źródło
6

Julia, 106 97 bajtów

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

Tworzy to nienazwaną funkcję, która pobiera ciąg jako dane wejściowe i drukuje wynik do STDOUT z pojedynczym końcowym odstępem i bez końcowego znaku nowej linii. Aby to nazwać, nadaj mu nazwę, np f=b->....

Niegolfowane + wyjaśnienie:

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

Przykłady:

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

julia> f("NNNMNBMMBMMBMMMNBMNNMNNNBNNNBNBBNBNMMNBBNBMMBBMBMBBBNNMBMBMMNNNNNMMBMMBM")
3NBM 8BM 5NB 14M 6B 17N 
Alex A.
źródło
4

Python 2, 93 88 89 84 bajtów

Przyjmując proste podejście.

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

Zadzwoń tak:

f("NBMMBNBNBM")

Dane wyjściowe są takie:

2NBM 0BM 1NB 1M 1B 0N
Kade
źródło
Możesz usunąć spację później in.
isaacg
W Pythonie 2 możesz przekonwertować na ciąg znaków za pomocą `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;

Użycie (dodano 7 bajtów dla 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

lub

%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;

Stosowanie:

data;%f(NNNMNBMMBMMBMMMNBMNNMNNNBNNNBNBBNBNMMNBBNBMMBBMBMBBBNNMBMBMMNNNNNMMBMMBM)

Wynik:

3NBM 5NB 8BM 17N 6B 14M
Jajko sadzone
źródło
Możesz zapisać kilka bajtów cats('s/',z,'/x/')zamiast 's/'||strip(z)||'/x/'.
Alex A.
1
Fajnie, to była niezła podróż powrotna do 139 :)
Fried Egg
1
126 bajtów: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;. Ponieważ już czytasz sysparm, możesz równie dobrze uruchomić go jako krok danych. A jeśli działasz wsadowo, nie potrzebujesz run;.
Alex A.
1
Ale możesz uzyskać 129, używając makra w stylu nowoczesnym, który nie odczytuje argumentu z wiersza poleceń:%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 bajty

Nie najkrótszy, ale czego jeszcze można oczekiwać od PHP?

Aby z niego skorzystać, ustaw klucz w COOKIE, POST, GET, SESSION ...

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

Apporach jest prosty:

  • Podziel ciąg na nazwy stworzeń
  • Policz, ile jest elementów
  • Odejmij 1 (pusty ciąg da tablicę z 1 elementem)
  • Podaj liczbę i nazwę stworzenia
  • Połącz to wszystko razem, używając pustego sznurka (który zmniejszy sznur i usunie ostatnie stworzenie)

Łatwe, prawda?

Ismael Miguel
źródło
2

JavaScript, 108 116 bajtów

Proste podejście, nic szczególnego

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
źródło
1
Nie działa: All 6 counts must be shown, separated by spaces, even when they are 0.. Przypadek testowy:N
edc65
@ edc65 Woah. Właśnie tęskniłem za tą częścią. Dzięki za zwrócenie na to uwagi. Naprawiono to za koszt 8 znaków
C5H8NNaO4
2

Perl, 46

#!perl -p
$_="NBM BM NB M B N"=~s/\w+/~~s!$&!x!g.$&/ger
nutki
źródło
Wyjaśnienie, jak to działa?
Cain
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$

Stosuje to samo podejście, co wiele innych. Wiersz 4 ciągle zapętla ciąg (od największego), zastępuje go, jeśli zostanie znaleziony.

SpecBAS ma kilka miłych akcentów w stosunku do oryginalnego ZX / Sinclair BASIC (przewijanie list, znajdowanie postaci), którego wciąż szukam.

Brian
źródło
1

C, 205 186 184 bajtów

Trochę inne podejście oparte na maszynie stanu. gdzie tjest państwo.

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

Rozszerzony

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

Funkcja testowa

#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]);
}
jakiś użytkownik
źródło
Czy nie użyłbyś for(;;*s++){...}zamiast do{...}while(*s++);zapisywać niektóre bajty? Ponadto nie potrzebujesz znaku nowej linii w printf.
Spikatrix,
Myślę, że miałeś na myśli for(;*s;s++). Ale musiałem zapętlić się z tym ostatnim znakiem zerowym. Dobre wezwanie do oszczędzania \n, które nie jest wymagane.
jakiś użytkownik
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
źródło
1

Haskell - 177 bajtów (bez importu)

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

(Przepraszam za nekromancję internetową tutaj.)

Platforma Haskell nie ma wyszukiwania ciągów bez importu, a ja chciałem pochwalić się i wykorzystać fakt, że wszystkie wyszukiwane ciągi są podciągami jednego (bez powtórzeń), aby można było grupować znaki, identyfikując pary, które mogą podążajcie za sobą, co ftutaj się dzieje.

Nadal potrzebuję pełnej listy, laby sprawdzić równość i wyświetlić dokładnie tak, jak jest to wymagane, ale nie zrobiłbym tego, gdyby wyzwaniem było tylko zgłoszenie liczby możliwych zdarzeń wordsw dowolnej kolejności.

Leif Willerts
źródło
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\ ;}

Przekaż ciąg jako pierwszy argument.

bash nmb.sh MBNNBBMNBM 

Wyjaśniono trochę:

# 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
źródło
0

rs , 275 bajtów

(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
 #/

Demo i testy na żywo.

Działania są proste, ale trochę dziwne:

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

To twórczo wykorzystuje grupy do zmiany danych wejściowych takich jak:

NBMBM

w

aNBMbcdeBMfghijkl

Następna linia:

[A-Z]+/_

Zastępuje to ciągi wielkich liter podkreśleniami.

#

To po prostu wstawia znak funta na początku linii.

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

To początek fajna część. Zasadniczo pobiera sekwencje małych liter i znaków podkreślenia, konwertuje je na wielkie litery, grupuje je razem i umieszcza przed wstawionym funtem. Celem funta jest zarządzanie sekwencjami, które zostały już przetworzone.

#

Funt jest ponownie wstawiany na początku wiersza.

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

Wielkie litery są zastępowane ich odpowiednikami tekstowymi z odpowiednimi liczbami. Z powodu błędu w rs (nie chciałem ryzykować jego naprawy i dyskwalifikacji), puste sekwencje są konwertowane na (^^), które są zastępowane przez 0 w wierszu od ostatniego do ostatniego. Ostatnia linia po prostu usuwa funta.

kirbyfan64sos
źródło
0

KDB (Q), 76 bajtów

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

Wyjaśnienie

                                                   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

Test

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
źródło
0

Haskell: 244 bajty

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
Lista Jeremy
źródło
Kilka sugestii: używasz pi stylko raz, więc nie musisz nadawać jej nazwy (-> a#[]=[]:a#"NBM", to samo dla p). BTW: words"N B M NB BM NBM"zamiast listy ciągów zapisuje dodatkowe bajty. importJest tylko dla intercalate, to krótsze te re-wdrożyć go: ...putStrLn.tail.((' ':)=<<)$map...i pozbyć import. Umieść wszystkich strażników |w definicji #w jednym wierszu i użyj 1<2zamiast True: ...#(b:m)|a==b=...l#m|1<2=[]......
nimi
... ?mogą być zdefiniowane krótszy z listowego: c?t=sum[1|x<-c,x==t]. Znowu używasz ?tylko raz, więc należy używać ciała bezpośrednio: ...show(sum[1|x<-l#[],x==t]).
nimi