Ninja dan Monyet dan Beruang, Ya ampun!

37

Tantangan ini adalah hadiah NinjaBearMonkey untuk memenangkan Kawanan Blok Bangunan Bot saya! menantang dengan pengajuan Black Knight . Selamat, NinjaBearMonkey!

Tantangannya di sini cukup sederhana, tetapi memiliki berbagai pendekatan yang mungkin. Ceritanya bahwa di dunia Ilusi Isometrik , ada 6 jenis makhluk:

  1. Ninja, disingkat N
  2. Beruang, disingkat B
  3. Monyet, disingkat M
  4. NinjaBears, disingkat NB
  5. BearMonkeys, disingkat BM
  6. NinjaBearMonkeys, disingkat NBM

( NinjaBearMonkey , tentu saja, tipe terakhir, yang paling kuat.)

Tugas Anda adalah mengambil sensus makhluk-makhluk ini ketika mereka berbaris berdampingan, yaitu ketika string singkatan mereka digabungkan. Peringatannya adalah bahwa Anda perlu memastikan untuk tidak terlalu menghitung bagian-bagian dari beberapa makhluk sebagai makhluk terpisah yang kebetulan terlihat serupa. Makhluk itu akan berbaris sedemikian rupa sehingga:

  • Instance dari NBMadalah 1 NinjaBearMonkey dan 0 makhluk lainnya.
  • Contoh yang NBtidak diikuti Madalah 1 NinjaBear dan 0 makhluk lainnya.
  • Contoh yang BMtidak didahului oleh Nadalah 1 BearMonkey dan 0 makhluk lainnya.
  • Kalau tidak, contoh dari N,, Bdan MNinjas, Beruang, dan Monyet masing-masing.

Baris dibaca dari kiri ke kanan.

Jadi, misalnya, di garis makhluk NBMMBNBNBM, ada 0 Ninja, 1 Beruang, 1 Monyet, 1 NinjaBear, 0 BearMonkeys, dan 2 NinjaBearMonkeys.

Tantangan

Tulis program atau fungsi yang mengambil string karakter N,, Bdan M, dan cetak atau kembalikan berapa banyak dari masing-masing dari 6 jenis makhluk yang ada di dalamnya.

Keluaran harus memiliki formulir

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

dengan jumlah makhluk masing-masing menggantikan setiap #tanda. Semua 6 hitungan harus ditunjukkan, dipisahkan oleh spasi, bahkan ketika mereka 0. Namun, mereka mungkin dalam urutan apa pun (misalnya #NBMbisa didahulukan).

Juga:

  • Input string hanya akan berisi karakter N, Bdan M.
  • Jika string kosong dimasukkan, maka semua jumlah adalah 0.
  • Output secara opsional dapat berisi satu spasi awal dan / atau trailing, dan / atau baris baru trailing tunggal.

Pengajuan terpendek dalam byte menang.

Contohnya

Input: NB
Keluaran:0N 0B 0M 1NB 0BM 0NBM

Input: NBM
Keluaran:0N 0B 0M 0NB 0BM 1NBM

Input: NBMMBNBNBM(contoh dari atas)
Output:0N 1B 1M 1NB 0BM 2NBM

Input: MBNNBBMNBM
Keluaran:1N 1B 1M 1NB 1BM 1NBM

Input: NNNMNBMMBMMBMMMNBMNNMNNNBNNNBNBBNBNMMNBBNBMMBBMBMBBBNNMBMBMMNNNNNMMBMMBM
Keluaran:17N 6B 14M 5NB 8BM 3NBM

Hobi Calvin
sumber
53
Saya menyetujui tantangan ini.
NinjaBearMonkey
Hanya untuk mengonfirmasi: jika yang Anda miliki hanyalah 2 NinjaBearMonkeys, Anda tidak dapat membentuk garis? Karena mereka tidak bisa berdiri berdampingan?
Alan Campbell
3
@AlanCampbell No. NBMNBMakan menjadi input yang benar-benar valid. Membaca dari kiri ke kanan jelas ada 2 NinjaBearMonkeys.
Hobi Calvin

Jawaban:

20

Pyth, 22 byte

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

Cara cukup hack untuk menyimpan 1 byte, terima kasih kepada @ Jakube.


Pyth, 23 byte

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

Demonstrasi.

Mencetak dalam urutan terbalik, dengan spasi tambahan dan tanpa tambahan baris baru.

.:"NBM")adalah semua substring, _menempatkannya dalam urutan yang benar, /zNmenghitung kejadian, dan =:zNdmenggantikan setiap kemunculan string yang dipertanyakan dengan spasi.

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
sumber
23

JavaScript ES6, 86 byte

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

(Saya hanya harus menjawab ini.) Ia melewati setiap substring NBM, mulai dari substring yang lebih panjang, yang mengambil prioritas lebih tinggi. Ia mencari setiap kemunculan string tertentu dan menghapusnya (dalam hal ini menggantinya dengan jumlah saat ini sehingga tidak akan cocok lagi). Akhirnya menggantikan setiap substring dengan jumlah + string.

Cuplikan Stack ini ditulis dalam ES5 yang setara dengan kode di atas untuk membuatnya lebih mudah untuk diuji dari browser apa pun. Ini juga kode yang sedikit tidak diubah. UI diperbarui dengan setiap penekanan tombol.

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
sumber
Bisakah Anda mengubah bagian regex ke 'NBM<newline>BM<newline>...<newline>N'.replace(/./g, ...)', di mana <newline>s adalah baris baru literal dan 's adalah backticks, membentuk string template ES6? Menghemat dua byte di regex ( .tidak cocok dengan baris baru).
wchargin
@WChargin Sayangnya, tidak, karena output harus dipisahkan oleh ruang.
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,

Varian dari jawaban Vioz- . Bersenang-senang dengan representasi string Python 2!

Menghitung kemunculan substring secara tidak langsung dengan membelahnya, menghitung bagian-bagian, dan mengurangi 1. Alih-alih mengganti substring dengan simbol filler, ganti string dengan daftar yang splitdihasilkan. Kemudian, ketika kita mengambil representasi stringnya, bagian-bagian dipisahkan oleh spasi dan koma.

Tidak
sumber
5
Itu gila! Sangat gila, tapi masih gila.
Sp3000
Kerja bagus! Tidak memikirkan itu :)
Kade
14

Ruby, 166 80 72 68 karakter

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

Penjelasan:

  • Penghitungan dilakukan secara terbalik. Ini karena semakin lama ninja, beruang, dan monyet lebih diutamakan daripada yang lebih pendek.

  • Untuk NBM,, BMdan NB, urutannya akan gsub!keluar dari string asli dengan blok untuk menghitung berapa banyak urutan ini ada (ya, fungsi memodifikasi argumennya).

    • Namun, mereka tidak dapat diganti dengan apa pun, karena jika BNBMMtidak akan dihitung sebagai NBMdan BMbukanB , NBMdan M(karena ketika NBMakan dihapus, itu akan menempatkan Bdan Mbersama-sama dan tidak akan ada cara untuk membedakannya). Awalnya saya mengembalikan string karakter tunggal ( .gsub!('NBM'){c+=1;?|}), tetapi saya menyadari saya hanya bisa mengembalikan hasil dari +=(yang merupakan angka, jadi tidak bisa apa-apa N B M).
  • Untuk M,, Bdan N, saya bisa hanya countberapa banyak dari mereka yang ada di string (tidak perlu menghapusnya melalui gsub!). Sekarang ini adalah pengulangan (tidak tahu mengapa saya tidak memikirkan hal itu sejak awal), jadi ini dilakukan dengan cara yang sama.


Solusi serupa di Ostrich , 54 51 karakter :

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

Sayangnya bukan solusi yang valid, karena ada bug dalam versi Ostrich saat ini (yang sekarang sudah diperbaiki, tetapi setelah tantangan ini diposting).

Gagang pintu
sumber
Anda dapat menyimpan 3 karakter dengan menggunakan notasi array %w(NBM BM NB M B N)dan menghapus pemisahan.
DickieBoy
@DickieBoy Itu sebenarnya 4 karakter; Terima kasih!
Gagang Pintu
Ah ya, titik!
DickieBoy
14

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

Dan dengan beberapa jeda baris:

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

Ini bekerja sangat sederhana. Lingkarkan token, ganti dengan titik dan hitung selama input mengandung beberapa. Hitung yang besar dulu, jadi yang kecil tidak mengacaukannya.

Saya awalnya mencoba mengganti sekaligus dan menghitung perbedaan panjangnya, tetapi butuh beberapa karakter seperti itu :(

Geobit
sumber
2
Sebagai seorang pengembang Java, saya ingin mempersingkat ini dan melihat Java menang untuk suatu perubahan. Setelah menatapnya sebentar, saya belum menemukan cara untuk membuatnya lebih pendek.
DeadChex
1
Yah itu pasti tidak akan menang secara keseluruhan. Pemimpin saat ini adalah 22 byte dan tidak ada cara untuk melakukan sesuatu yang bermakna di Jawa dalam ukuran itu. printlnPernyataan saya sendiri lebih besar dari itu. Saya puas dengan itu: D
Geobits
1
Saya agak terlambat tetapi saya menemukan cara ... ubah String q[]=keString[]q=
DeadChex
1
Bagus! Tidak percaya saya melewatkan itu, itu ada dalam daftar standar saya untuk dilihat :)
Geobits
Saya hanya menemukannya setelah mencoba masuk ke Code Golf sebagai JavaDev, saya cukup terkejut dengan beberapa hal yang dapat Anda lakukan
DeadChex
11

CJam, 36 32 31 byte

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

Terima kasih kepada @Optimizer untuk bermain golf 1 byte.

Cobalah online di juru bahasa CJam .

Bagaimana itu bekerja

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
sumber
N*-> `sudah cukup.
Pengoptimal
@Optimasi: Itu bekerja dengan baik. Terima kasih.
Dennis
7

R, 153 134 118

Ini menjadi lebih lama dengan sangat cepat, tapi semoga saya bisa mencukurnya. Input adalah STDIN dan output ke STDOUT.

Edit Perubahan taktik. Singkirkan string perpecahan dan penghitungan bagian. Sekarang saya mengganti bagian-bagian dengan string yang lebih pendek daripada bagian. Perbedaan antara panjang string dikumpulkan untuk output.

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

Penjelasan

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

Uji coba

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

Pyth, 19 byte

jd+Ltl=zc`zd_.:"NBM

Ini adalah campuran dari solusi Pyth @ isaacg dan trik Python @ xnor yang luar biasa.

Cobalah secara online: Demonstrasi atau Uji harness

Penjelasan

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
sumber
6

Julia, 106 97 byte

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

Ini menciptakan fungsi tanpa nama yang mengambil string sebagai input dan mencetak hasilnya ke STDOUT dengan satu spasi tambahan dan tanpa tambahan baris baru. Untuk menyebutnya, berikan nama, mis f=b->....

Penjelasan + tidak dikumpulkan:

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

Contoh:

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

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

Python 2, 93 88 89 84 Bytes

Mengambil pendekatan langsung.

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

Sebut seperti ini:

f("NBMMBNBNBM")

Outputnya seperti ini:

2NBM 0BM 1NB 1M 1B 0N
Kade
sumber
Anda dapat menghapus ruang setelah in.
isaacg
Dalam Python 2, Anda bisa mengonversi ke representasi string dengan `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;

Penggunaan (7 byte ditambahkan untuk 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

atau

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

Pemakaian:

data;%f(NNNMNBMMBMMBMMMNBMNNMNNNBNNNBNBBNBNMMNBBNBMMBBMBMBBBNNMBMBMMNNNNNMMBMMBM)

Hasil:

3NBM 5NB 8BM 17N 6B 14M
Telor goreng
sumber
Anda dapat menyimpan beberapa byte menggunakan cats('s/',z,'/x/')di tempat 's/'||strip(z)||'/x/'.
Alex A.
1
Bagus, itu cukup perjalanan kembali ke 139 :)
Fried Egg
1
126 byte: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;. Karena Anda sudah membaca dari sysparm, Anda bisa menjalankannya sebagai langkah data. Dan jika Anda berjalan dalam batch, Anda tidak perlu run;.
Alex A.
1
Tapi Anda bisa mendapatkan 129 dengan menggunakan makro gaya modern yang tidak membaca dari argumen baris perintah:%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 byte

Bukan yang terpendek, tapi apa lagi yang Anda harapkan dari PHP?

Untuk menggunakannya, tetapkan kunci pada COOKIE, POST, DAPATKAN, SESI ...

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

Apporach adalah dasar:

  • Pisahkan string menjadi nama-nama makhluk
  • Hitung berapa banyak elemen yang ada
  • Kurangi 1 (string kosong akan memberikan array dengan 1 elemen)
  • Keluarkan hitungan dan nama makhluk
  • Gabungkan semuanya bersama-sama, menggunakan string kosong (yang akan mengurangi string dan menghapus makhluk terakhir)

Mudah kan?

Ismael Miguel
sumber
2

JavaScript, 108 116 byte

Hanya pendekatan yang lurus ke depan, tidak ada yang mewah

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
sumber
1
Tidak bekerja: All 6 counts must be shown, separated by spaces, even when they are 0.. Test case:N
edc65
@ edc65 Woah. Saya baru saja melewatkan bagian itu. Terima kasih telah menunjukkannya. Memperbaikinya dengan biaya 8chars
C5H8NNaO4
2

Perl, 46

#!perl -p
$_="NBM BM NB M B N"=~s/\w+/~~s!$&!x!g.$&/ger
nutki
sumber
Penjelasan tentang cara kerjanya?
Kain
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$

Menggunakan pendekatan yang sama seperti banyak orang lain. Baris 4 terus berputar di atas string (dari yang terbesar pertama), menggantikannya jika ditemukan.

SpecBAS memiliki beberapa sentuhan yang bagus pada ZX / Sinclair BASIC asli (pengulangan daftar, menemukan karakter) yang saya masih temukan.

Brian
sumber
1

C, 205 186 184 byte

Pendekatan yang sedikit berbeda berdasarkan mesin negara. dimana tnegara

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

Diperluas

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

Fungsi tes

#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]);
}
beberapa pengguna
sumber
Tidak akan menggunakan for(;;*s++){...}alih-alih do{...}while(*s++);menyimpan beberapa byte? Anda juga tidak memerlukan karakter baris baru di printf.
Spikatrix
Saya pikir Anda maksud for(;*s;s++). Tapi saya perlu mengulang dengan nol karakter terakhir. Panggilan yang baik untuk menyimpan \n, yang tidak diperlukan.
beberapa pengguna
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
sumber
1

Haskell - 177 byte (tanpa impor)

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

(Maaf untuk necromancy internet di sini.)

Platform Haskell tidak memiliki pencarian string tanpa impor, dan saya ingin memamerkan dan mengeksploitasi fakta bahwa string yang dicari adalah semua substring dari satu (tanpa pengulangan), sehingga karakter pengelompokan dapat dilakukan dengan mengidentifikasi pasangan yang diizinkan untuk saling mengikuti, itulah yang fdilakukan di sini.

Saya masih memerlukan daftar lengkap lpada akhirnya untuk memeriksa kesetaraan dan menampilkan persis seperti yang disyaratkan, tetapi tidak akan, jika tantangannya hanya melaporkan jumlah kemunculan yang mungkin wordsdalam urutan apa pun.

Leif Willerts
sumber
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\ ;}

Lewati string sebagai argumen pertama.

bash nmb.sh MBNNBBMNBM 

Dijelaskan sedikit:

# 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
sumber
0

rs , 275 byte

(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 dan tes langsung.

Cara kerjanya sederhana tetapi sedikit aneh:

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

Ini secara kreatif menggunakan grup untuk mengubah input seperti:

NBMBM

ke

aNBMbcdeBMfghijkl

Baris selanjutnya:

[A-Z]+/_

Ini menggantikan urutan huruf kapital dengan garis bawah.

#

Ini hanya menyisipkan tanda pound pada awal baris.

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

Ini adalah bagian awal yang keren. Pada dasarnya ia mengambil urutan huruf kecil dan garis bawah, mengubahnya menjadi huruf besar, mengelompokkannya, dan menempatkannya di depan pound yang dimasukkan. Tujuan dari pound adalah untuk mengelola urutan yang sudah diproses.

#

Pound dimasukkan kembali pada awal baris.

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

Huruf kapital diganti dengan padanan teksnya dengan jumlah yang terkait. Karena bug di rs (saya tidak ingin mengambil risiko memperbaikinya dan didiskualifikasi), urutan kosong diubah menjadi (^^), yang digantikan oleh 0 pada baris kedua hingga terakhir. Baris terakhir hanya menghilangkan pound.

kirbyfan64sos
sumber
0

KDB (Q), 76 byte

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

Penjelasan

                                                   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

Uji

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
sumber
0

Haskell: 244 byte

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
Daftar Jeremy
sumber
Beberapa saran: Anda menggunakan pdan shanya sekali, jadi tidak perlu memberi nama (-> a#[]=[]:a#"NBM", sama untuk p). BTW: words"N B M NB BM NBM"bukannya daftar string menyimpan byte tambahan. The importhanya untuk intercalate, itu lebih pendek te re menerapkan-itu: ...putStrLn.tail.((' ':)=<<)$map...dan menyingkirkan import. Letakkan semua penjaga |dalam definisi #dalam satu baris dan gunakan 1<2sebagai ganti True: ...#(b:m)|a==b=...l#m|1<2=[]......
nimi
... ?dapat didefinisikan lebih pendek dengan daftar pemahaman: c?t=sum[1|x<-c,x==t]. Sekali lagi, Anda menggunakan? hanya sekali, jadi gunakan tubuh secara langsung: ...show(sum[1|x<-l#[],x==t]).
nimi