Il matcher String di FizzBuzz


25

Supponi di avere una stringa come questa:

abaabbbbbaabba

Contare il numero di volte in cui un carattere specificato appare nella stringa di input, ma solo se il carattere appare solo una volta di fila . Ad esempio, se il personaggio è a,

abaabbbbbaabba
^ x      x   ^

Il totale sarebbe 2 ( aai non contano perché aappare due volte di seguito).

Che relazione c'è con FizzBuzz?

Se il personaggio appare 3 (o un multiplo di 3) volte di fila, oppure 5 (o un multiplo di 5) volte di fila, il contatore viene invece decrementato . Se è un multiplo di 3 e 5 volte, il contatore viene comunque incrementato. Ricorda che il contatore viene incrementato anche se il personaggio appare solo una volta di fila, e viene ignorato se il personaggio appare un altro numero di volte di seguito (oltre alle situazioni sopra descritte).

Per ricapitolare, se la stringa da abbinare è a,

input            counter (explanation)

a                 1 (single occurence)
aaa               -1(multiple of 3)
aaaaa             -1(multiple of 5)  
aaaaaaaaaaaaaaa   1 (multiple of 15)
aa                0 (none of the above)

aba               2 (two single instances)
aaba              1 (one single occurence(+1) and one double occurence(ignored))
aaaba             0 (one single occurence(+1) and one triple (-1)
aaaaaa            -1 (six is a multiple of three)

Implementazione di riferimento (ungolfed) in Java:

import java.util.Scanner;
import java.util.regex.*;

public class StrMatcher {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in); //Scanner to get user input
        int total = 0;//Running total of matches

        System.out.println("Enter a string: ");
        String strBeingSearched = sc.nextLine(); //String that will be searched

        System.out.println("Enter string to match with: ");
        String strBeingMatched = sc.nextLine(); //Substring used for searching

        //Simple regex matcher
        Pattern pattern = Pattern.compile("(" + strBeingMatched + ")+");
        Matcher matcher = pattern.matcher(strBeingSearched);

        while(matcher.find()){  //While there are still matches

            int length = matcher.end() - matcher.start();
            int numberOfTimes = length/strBeingMatched.length();//Calculate how many times in a row the string is matched

            if((numberOfTimes == 1)||((numberOfTimes % 3 == 0) && (numberOfTimes % 5 == 0))){
                total++; //Increment counter if single match or divisible by 15
            } else if((numberOfTimes % 3 == 0)||(numberOfTimes % 5 == 0)) {
                total--; //Decrement counter if divisible by 3 or 5 (but not 15)
            }

            strBeingSearched = strBeingSearched.substring(matcher.end());
            matcher = pattern.matcher(strBeingSearched); //Replace string/matcher and repeat
        }

        System.out.println(total);
    }   
}
  • La stringa che verrà cercata può avere qualsiasi lunghezza, ma il modello sarà solo un singolo carattere.
  • Nessuna delle stringhe avrà caratteri speciali regex.
  • Questo è ; vince il programma più breve in byte.
  • Nessuna scappatoia standard.

3
Sarebbe utile se potessi fornire alcuni altri esempi di test. Soprattutto quelli in cui la sequenza ha più di una lettera.
Reto Koradi,

Ho aggiunto alcuni casi, si spera che aiuti. Dimmi se ho bisogno di più casi, è la mia prima volta in PPCG.
Daniel M.,

Cambierò i requisiti in modo che la sequenza sia solo un singolo carattere, poiché l'implementazione è praticamente la stessa, ma meno confusa.
Daniel M.,

È come la domanda sparsa ma con l'aggiunta di
FizzBuzz

Risposte:


32

Funciton , 1840 byte

Accidenti, questa lingua è ungolfable.

Questo programma prevede che il primo carattere dell'input sia il carattere da cercare, e il resto dell'input per rendere la stringa da cercare. Ciò significa che aaabacercherà anell'input aaba(e quindi nell'output 1). È possibile separarli con un ritorno a capo o uno spazio ( a aaba), ma solo perché il ritorno a capo / spazio in più non fa alcuna differenza per l'uscita.

Come sempre, puoi ottenere un rendering più gradevole (senza l'interlinea) se esegui $('pre').css('line-height',1)nella console del browser.

      ┌───┐
      │╓─╖└─────────────┐
      └╢³╟┐    ┌─────┐ ┌┴┐╓─╖
┌─────┐╙─╜└────┤┌─╖ ┌┴╖│┌┘║¹║
│     ├───────┐└┤²╟─┤·╟┘│ ╙┬╜╔═══════╗
│    ┌┴╖╔═╗┌─╖├┐╘╤╝ ╘╤╝┌┘  └┬╢2097151║
│    │♭║║5╟┤%╟┘└─┴──┐│┌┘┌───┘╚═══════╝
│    ╘╤╝╚═╝╘╤╝╔═╗┌─╖│││┌┴┐┌────┐
│    ┌┴╖   ┌┘ ║3╟┤%╟┘││└┬┘│╔══╗└┐
│  ┌─┤·╟─┐ │  ╚═╝╘╤╝ │└┐  │║21╟┐│
│  │ ╘╤╝ ├─┘┌─────┘  └┐└┐ │╚══╝│└─┐
│ ┌┴╖┌┴╖┌┴╖┌┴╖┌─╖    ┌┴╖│ │┌─╖┌┴─╖│
│┌┤·╟┤?╟┤?╟┤?╟┤+╟────┤³║│ └┤²╟┤>>║└──┐
││╘╤╝╘╤╝╘╤╝╘╤╝╘╤╝    ╘╤╝│  ╘╤╝╘╤═╝╓─╖│
││ │ ┌┴╖┌┴╖┌┴╖┌┴╖╔═╗ ┌┴╖│  ┌┴╖ ├──╢²╟┤
││ └─┤·╟┤·╟┤?╟┤·╟╢1║┌┤·╟┘  │♯║┌┴╖ ╙─╜│
│└──┐╘╤╝╘╤╝╘╤╝╘╤╝╚═╝│╘╤╝   ╘╤╝│¹║┌───┘
└──┐│╔╧╗ └┬─┘ ┌┴╖   │┌┴─╖   │ ╘╤╝│
   ││║1║ ┌┴┐┌─┤?╟───┴┤>>╟┐ ┌┴╖┌┴╖│
   ││╚═╝ └┬┘│ ╘╤╝    ╘══╝│┌┤?╟┤=║│
   │└────┐│╔╧╗     ┌─────┘│╘╤╝╘╤╝│
╔═╗└────┐│├╢0║╔══╗┌┴╖┌─╖ ╔╧╗   └─┘
║ ║     │└┘╚═╝║21╟┤×╟┤♯╟┐║0║
╚╤╝     └──┐  ╚══╝╘═╝╘═╝│╚═╝
 │┌──┴────╖└────────────┘
 ││int→str║
 │╘══╤════╝
┌┴─╖┌┴╖┌─╖╔╗
│>>╟┤³╟┤¹╟╢║
╘═╤╝╘═╝╘═╝╚╝
╔═╧╗
║21║
╚══╝

(1840 byte se codificato come UTF-16.)

Spiegazione

  • ¹ restituisce il primo carattere di una stringa.
  • ²conta il numero di occorrenze di un carattere all'inizio di una determinata stringa. Ad esempio, dato il carattere ae la stringa aaba, restituisce 2. Per ae baa, restituisce 0.
  • ³chiama ²per ottenere il numero di caratteri all'inizio, esamina se il numero è divisibile per 3 e 5 e se è uguale a 1 e determina l'incremento / decremento corretto. Rimuove anche un carattere in più dall'inizio della stringa (es. Dato aaabbache rimuove 3 + 1 = 4 caratteri, dando ba). Quindi si chiama ricorsivamente con la stringa più corta e aggiunge il risultato.
  • Il programma principale chiama ¹per rimuovere il primo carattere dall'input e chiama ³con quel carattere e il resto della stringa come argomenti separati.

10
Non voterò mai su Funciton.
orlp,

14

CJam, 40 36 35 32 30 byte

0llcf=e`::*{(_g+Y13515Yb+=(+}/

Grazie a @ MartinBüttner per il golf off 1 byte!

Grazie a @AndreaBiondo per il golf off 2 byte e spianando la strada per altri 3!

Provalo online nell'interprete CJam .

Come funziona

0          e# Push a 0 (accumulator).
l          e# Read a line from STDIN.
lc         e# Read a second line and keep only the first character.
f=         e# Check each character from the first line for equality.
           e# This results in 1 for the specified character and 0 for others.
e`         e# Perform run-length encoding.
::*        e# Multiply each element by its number of repetitions.
{          e# For each remaining integer I:
  (_!      e#   Subtract 1, copy and push sign(I-1).
  +        e#   Add the results.
           e#     If I == 0, I-1 + sign(I-1) =  -1 + -1 = -2.
           e#     If I == 1, I-1 + sign(I-1) =   0 +  0 =  0.
           e#     If I >= 2, I-1 + sign(I-1) = I-1 +  1 =  I.
  Y        e#   Push 2.
  13515Yb  e#   Convert 13515 into the array of its binary digits.
  +        e#   Concatenate 2 and the array.
           e#   This pushes [2 1 1 0 1 0 0 1 1 0 0 1 0 1 1].
  =        e#   Retrieve the digit at (index I-1 + sign(I-1))%15.
           e#     If I == 0, this pushes 1.
           e#     Else, if I == 1, this pushes 2.
           e#     Else, if I%15 == 0, this pushes 2.
           e#     Else, if I%3==0 or I%5==0, this pushes 0.
           e#     Else, this pushes 1.
  (        e#   Decrement the result.
  +        e#   Add it to the accumulator.
}/         e#

È possibile salvare altri 2 byte con una tabella di ricerca con codifica di base e indicizzazione modulare: llcf=e`::*0-{(_!\6563282Zb:(=}%1b33 byte.
Andrea Biondo,

@AndreaBiondo Che in realtà ha salvato 3 byte. Grazie!
Dennis,

7

C, 160 126 125 119 114 109 104 100 byte

main(int q,char **z){int i=0,t=0,s=0,a=z[1][0],c;do{if((c=z[2][i])!=a){s+=(!!t)*((t==1)-!(t%3)-!(t%5)+3*!(t%15));t=0;}else{++t;}++i;}while(c);printf("%d\n",s);}

Probabilmente può essere migliorato ... Questo richiede input dagli argomenti della riga di comando (il primo argomento è il modello, il secondo è la stringa). Non supporta la ricerca di pattern di NULL char (\ x00).

MODIFICA ** 126 125 119 114 109 104 100 byte **: dopo aver incorporato i suggerimenti di Dennis e alcune idee aggiuntive (clausola else rimossa, ha combinato il tempo in una singola istruzione e ha usato la sottrazione invece di! =). Rimosso anche il punto e virgola aggiuntivo in for loop (che in realtà faceva parte del suggerimento di Dennis). Abbreviato ancora di più rimuovendo le variabili 'i' e 'a'.

t,s;main(c,z)char**z;{for(;c;t++)if((c=*z[2]++)-*z[1])s+=!!t*((t<2)-!(t%3)-!(t%5)+3*!(t%15)),t=-1;printf("%d",s);}

Rimossi gli operatori if e negation ('!') Abusando dell'operatore ternario. Compresso i controlli di modularità usando quel "AND" bit per bit un doppio && perché bitwise "&" ha un bug e inserendo il confronto (t <2) all'interno degli operatori ternari. Sostituito !! t * (...) spostando !! t nell'operatore ternario, permettendomi così di rimuovere le parentesi.

Amico, voglio davvero portarlo sotto il segno di 100 byte: S

t,s;main(c,z)char**z;{for(;c;)(c=*z[2]++)-*z[1]?s+=t%15?t%3&&t%5?t<2:-1:!!t,t=0:t++;printf("%d",s);}

Soluzioni TENTATIVE: non sono sicuro che possano essere considerate valide, ma posso scendere a 93 caratteri se uso exit (s) invece di printf ("% d", s). Ma quindi l'output non sarebbe visibile, piuttosto sarebbe un codice di ritorno. Se l'output è davvero necessario, posso anche ridurlo a 98 byte, ma richiederebbe anche la stampa di tutti i valori intermedi di s prima della risposta finale ...


3
Benvenuto in Programmazione di puzzle e codice golf! Non l'ho testato a fondo, ma i,t,s,a;main(c,z)char**z;{a=*z[1];while(c){if((c=z[2][i])!=a)s+=(!!t)*((t<2)-!(t%3)-!(t%5)+3*!(t%15)),t=0;else++t;++i;}printf("%d",s);}dovrebbe funzionare altrettanto bene (ed è più corto di 23 byte).
Dennis,

Oh, cosa carina nel trasformare la clausola if () {} in una frase!
Tob Ernack,

Qualche byte in più: se inizi maincon for(a=*z[1];c;i++), non hai bisogno di {}around the if ... else.
Dennis,


4

Python 3, 361, 300, 296, 263, 256, 237, 229, 188, 178 , 164 byte.

Risparmiato 15 byte grazie a vaultah di SOPython.
Salvato 9 byte grazie a Joe Kington di SOPython.
Salvato 11 byte grazie a DSM da SOPython.

Questa è la prima volta che invio una risposta, quindi sono sicuro che potrebbe essere molto più breve. Prende la stringa di test come prima risposta per l'input e il carattere di ricerca come secondo.

t=input()
m=input()
c=u=0
g=iter(t)
while g:
 r=next(g,0)
 if r==0:print(c);g=0
 while r==m:u+=1;r=next(g,0)
 if u:b=u%3<1;v=u%5<1;c+=((0,-1)[b|v],1)[u<2or b&v];u=0

Versione non golfata:

import sys
test = sys.argv[1]
match_char = sys.argv[2]
counter = char_counter = 0
char_generator = (c for c in test)
while char_generator:
    try:
        char = next(char_generator)
    except StopIteration:
        print(counter)
        break
    while char == match_char:
        char_counter += 1
        try:
            char = next(char_generator)
        except StopIteration:
            break
    if char_counter == 0:
        continue
    counter += 1 if char_counter == 1 or (char_counter % 3 == 0 and char_counter % 5 == 0) else -1 if char_counter % 3 == 0 or char_counter % 5 == 0 else 0
    char_counter = 0

Ho scoperto che stavo fallendo uno dei casi di test.


3

Haskell, 120 byte

import Data.List
f c=sum.map(v.length).filter((==c).head).group
v 1=1
v n|n%3&&n%5=1|(n%3||n%5)=(-1)|0<1=0
x%y=x`mod`y<1

f fa il lavoro.


3

Java, 146 152 143 138 139 136 byte

  1. Risolto un bug.
  2. operazioni spostate, passate all'operatore bit a bit per i %3&%5controlli.
  3. i<2Confronto abbreviato .
  4. Risolto un bug ( %3&%5controllare che non funzionasse come previsto).
  5. Scorciatoia di moltiplicazione usata come visto nella risposta di Ruby di @ w0lf .

Implementato come BiFunction<String, String, Integer>in Java 8, fammi sapere se questo deve essere un programma completo (o se posso anche eliminare il java.util.regexprefisso del pacchetto di seguito).

Il conteggio dei byte sopra non include la nuova riga di seguito, che viene semplicemente aggiunta ai fini della formattazione su questo sito.

(a,b)->java.util.regex.Pattern.compile("[^"+b+"]").splitAsStream(a)
.mapToInt(v->v.length()).map(i->i<2?i:i%15<1?1:i%3*i%5<1?-1:0).sum();

Spiegazione approssimativa:

  1. Applica regex con pattern che non corrispondono b, ad es "[^"+b+"]".
  2. Ottieni la lunghezza di ogni token (ad es "a" -> 1.).
  3. Applicare la mappatura desiderata -1, 0e 1.
  4. sum() per ottenere risposta.

2

Javascript, 206 byte

function f(n,e){var t=n.match(new RegExp(e,"g")).length,g=n.match(new RegExp(e+"{2,}","g"));return null!==g&&g.forEach(function(n){t-=n.length,n.length%15==0?t+=1:(n.length%3==0||n.length%5==0)&&(t-=1)}),t}

Allargato:

function funkyFizzb(n, c) {
    var score = n.match(new RegExp(c, "g")).length; 
    var repeatOccurence = n.match(new RegExp(c + "{2,}", "g"));

    if(repeatOccurence !== null) {
        repeatOccurence.forEach(function(v,i){
            // remove multiple occurrence counts
            score -= v.length;

            if(v.length % 15 == 0) {
                score += 1;
            }

            else if(v.length % 3 == 0 || v.length % 5 == 0) {
                score -= 1;
            }
        });
    }

    return score;
};

Spiegazione:

Sto usando regex per contare il totale delle volte in cui appare un personaggio, quindi sottrarre tutte le volte che è apparso in gruppi. Infine, passo in rassegna i gruppi e eseguo l'incremento / decremento del buzz fizz.

Supera i casi di test indicati nella domanda:

funkyFizzb("aaa", "a") => -1

e così via


Rimuovi new, usa al execposto di matche alias lengthe dovresti essere bravo.
Mama Fun Roll

2

Perl, 82 65 63 59 byte

58 byte + 1 byte parametro della riga di comando

Non particolarmente breve, ma è un inizio - continuerà ad accorciarlo.

$l=y///c,$i+=!($l>1&&$l%15)||-!($l%3*$l%5)for/$^I+/g;$_=$i

Supponendo che si -ipossa dare alla stringa di input un esempio di utilizzo è il seguente:

echo "aaabaaa" | perl -pi"a" entry.pl

0

Pyth, 32 byte

così vicino! Altri 2 byte per legare l'eccellente voce di CJam di Dennis

s.b?qYz?tN@+,0_1 1+}3PN}5PN1Zrw8

Provalo online


0

gawk, 140

p=$2{b="[^"$1"]";for($0=2;$i-->0;){sub("^"b"*",_,p);p=substr(p,$++i=match(p,b))}for($i=length(p);$++j;)s+=$j%5?$j%3?$j<2:-1:$j%3?-1:1}$0=s""

Immettere come "stringa spazio char", in questo modo

echo "x axxbxcxdexxxfffghixxj" | awk 'p=$2{b="[^"$1"]";for($0=2;$i-->0;){sub("^"b"*",_,p);p=substr(p,$++i=match(p,b))}for($i=length(p);$++j;)s+=$j%5?$j%3?$j<2:-1:$j%3?-1:1}$0=s""'

Ungolfed

p=$2{
    #i=j=s=0                # make reusable
    b="[^"$1"]";           # pattern "not matching char"
    $0=2;                  # help starting the while loop
    while($i-->0){         # match didn't return -1; dec stack top
        sub("^"b"*",_,p);  # remove not matching chars at head of string
        $++i=match(p,b);   # push index of first occurence of not matching char
        p=substr(p,$i)     # remove matching chars from head of string
    };
    $i=length(p);          # get last value
    while($++j)            # sometimes last value on stack is 0
        s+=$j%5?$j%3?$j<2:-1:$j%3?-1:1

        # if $j%5!=0
        #   if $j%3!=0     (not divisible by 5 AND 3)
        #     s+=($j==1)   (single character)
        #   else           (divisible by 3 but not by 5)
        #     s-=1
        # else             (divisble by 5)
        #   if $j%3!=0
        #     s-=1         (divisible by 5 but not by 3)
        #   else
        #     s+=1         (divisible by 3 AND 5)

}$0=s"" # output

0

Pyth, 27 byte

sm|!JPdx,02+}3J}5JhMf}zTrw8

Suite di test

Inserire nel modulo ad es .:

a
aaaba

Spiegazione:

sm|!JPdx,02+}3J}5JhMf}zTrw8
                               z = input() (The match character)
                         w     input() (The string)
                        r 8    Run length encode
                    f}zT       Filter for the runs z is in.
                  hM           Take their lengths
 m|                            Map (d) to the logical or of
    Pd                         Find all prime factors of the current run length
   J                           Save them in J
  !                            Take the logical negation. This will be 1 if
                               d is 1, and 0 otherwise.
           +}3J                If d wasn't 1, add up 1 if 3 is in J
               }5J             and 1 if 5 is in J.
       x,02                    Then, take the index of the result in [0,2]
                               so 0 -> 0, 2 -> 1, 1 -> -1 (not found)
s                              Sum up the values for each run.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.