FizzBuzz-ish String eşleştiricisi


25

Bunun gibi bir dize olduğunu söyleyin:

abaabbbbbaabba

Girilen dizgede belirtilen bir karakterin görünme sayısını, ancak karakter bir satırda yalnızca bir kez göründüğünde sayın . Örneğin, karakter a,

abaabbbbbaabba
^ x      x   ^

Toplam 2 olur ( aaçünkü abir satırda iki kez belirir).

Bunun FizzBuzz ile ilişkisi nedir?

Karakter, üst üste 3 (veya 3 katı) veya üst üste 5 (veya 5 katı) gösterirse, sayaç yerine düşürülür . Hem 3'ün katları ise ve 5 kez, sayaç hala artırılır. Karakterin bir satırda yalnızca bir kez görünmesi durumunda sayacın da arttırıldığını ve karakterin bir satırda başka bir sayıda görünmesi durumunda göz ardı edildiğini unutmayın (yukarıda açıklanan durumlar dışında).

Özetlemek gerekirse, maça dize ise 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)

Java'da referans (topraksız) uygulama:

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);
    }   
}
  • Aranacak dize herhangi bir uzunlukta olabilir, ancak desen yalnızca tek bir karakter olacaktır.
  • Her iki dizede de regex özel karakterleri olmaz.
  • Bu ; bayt cinsinden en kısa program kazanır.
  • Standart boşluklar yok.

3
Birkaç test örneği daha sunabilmeniz faydalı olacaktır. Özellikle dizinin birden fazla harfe sahip olduğu yerler.
Reto Koradi

Birkaç vaka ekledim - umarım yardımcı olur. Daha fazla davaya ihtiyacım olursa söyle, bu PPCG'de ilk defa.
Daniel M.

Gereksinimleri değiştireceğim, böylece uygulama hemen hemen aynı, ancak daha az kafa karıştırıcı olduğundan, dizi yalnızca tek bir karakter olacak.
Daniel M.

Bu 1 seyrek soru gibi ama FizzBuzz ilavesiyle
ev3commander

Yanıtlar:


32

Funciton , 1840 bayt

Kahretsin, bu dil ungolfable.

Bu program, girişin ilk karakterinin aranacak karakter olmasını ve girişin geri kalanının dizenin aranmasını sağlamasını bekler. Bu , girdi içinde aaabaarama yapacağı anlamına gelir (ve dolayısıyla çıktı 1). Sen edebilir bir satır ya da boşluk (ayırın ) ama ekstra satır / uzay çıkışına hiç fark etmez diye.aaabaa aaba

$('pre').css('line-height',1)Tarayıcı konsolunuzda yürütürseniz, her zaman olduğu gibi, daha iyi görünümlü bir görüntü elde edebilirsiniz (satır aralığı olmadan) .

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

(UTF-16 olarak kodlandığında 1840 bayt.)

açıklama

  • ¹ Bir dizenin ilk karakterini döndürür.
  • ²Belirli bir dizgenin başlangıcında bir karakterin oluşum sayısını sayar. Örneğin, karakter ave dize verildiğinde aaba2 döndürür. İçin ave baa0 döndürür.
  • ³²Başlangıçta karakter sayısını almak için yapılan çağrılar , sayının 3 ve 5'e bölünebilir olup olmadığını ve 1'e eşit olup olmadığını inceler ve uygun artış / azalmayı belirler. Ayrıca, dizgenin başından itibaren bir ekstra karakter çıkarır (örneğin aaabba3 + 1 = 4 karakter vererek, verilen ba). Sonra kısa dizeyle özyinelemeli olarak çağırır ve sonucu ekler.
  • Ana program ¹girdiden ilk karakteri çıkarmaya çağırır ³ve bu karakterle ve dizginin geri kalanını ayrı argümanlar olarak çağırır .

10
Funciton'u asla affetmeyeceğim.
orlp

14

CJam, 40 36 35 32 30 bayt

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

1 byte'lık golf için @ MartinBüttner'e teşekkürler!

2 baytlık golf atma ve 3 yol daha atma için @AndreaBiondo'ya teşekkürler!

CJam tercümanında çevrimiçi olarak deneyin .

Nasıl çalışır

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#

Baz kodlu bir arama tablosu ve modüler indeksleme ile başka 2 byte kaydedebilirsiniz: llcf=e`::*0-{(_!\6563282Zb:(=}%1b33 byte
Andrea Biondo

@AndreaBiondo Bu aslında 3 bayt kurtardı. Teşekkürler!
Dennis,

7

C, 160 126 125 119 114 109 104 100 bayt

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

Muhtemelen daha iyi yapılabilir ... Bu komut satırı argümanlarından girdi alır (ilk argüman desen, ikincisi dizedir). NULL char modelinin aranmasını desteklemiyor (\ x00).

EDIT ** 126 125 119 114 109 104 100 bayt **: Dennis'in önerilerini ve bazı ek fikirleri ekledikten sonra (başka bir cümle kaldırıldı, süreyi bir tek ifadeyle birleştirip, yerine çıkarma =!) Kullandı. Ayrıca döngü için fazladan noktalı virgül kaldırıldı (bu aslında Dennis'in önerisinin bir parçasıydı). 'İ' ve 'a' değişkenlerini kaldırarak daha da kısaltın.

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

Üçlü işleci kötüye kullanarak if ve negation ('!') İşleçleri kaldırıldı. Modülerlik kontrollerini bu bitsel 'AND' i iki katına hile & & kullanarak yapın ; çünkü bitsel '&' bir hata içeriyor ve üçlü operatörlerin içine (t <2) karşılaştırmasını koyuyor. !! t * (...) yerine, ● terner operatörünü hareket ettirerek parantezleri çıkarmama izin verin.

Dostum, gerçekten 100 byte işaretinin altına almak istiyorum: 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);}

TENTATIVE çözümleri: Bunların geçerli sayılacağından emin değilim, ancak printf ("% d", s) yerine exit (s) kullanırsam 93 karaktere kadar indirebilirim. Fakat çıktı daha sonra görünür olmayacak, bir dönüş kodu olacaktır. Eğer çıktı gerçekten gerekliyse, onu 98 byte'a kadar indirebilirim, ancak son cevaptan önce tüm s nin ara değerlerini yazdırmayı gerektirir.


3
Programlama Bulmacaları ve Kod Golf'üne Hoşgeldiniz! İyice test etmedim, ancak 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);}tam da çalışması gerekiyor (ve 23 byte daha kısa).
Dennis

İf () {} yan tümcesini bir ifadeye dönüştürmenin güzel bir yanı!
Tob Ernack 21:15

Birkaç bayt: Eğer başlarsanız mainile for(a=*z[1];c;i++), ihtiyacınız olmayan {}varsa ... etrafta başka.
Dennis


4

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

SOPythonlu vaultah sayesinde 15 bayt kurtarıldı.
SOPython'dan Joe Kington sayesinde 9 bayt kurtarıldı.
SOPython'dan DSM sayesinde 11 bayt kurtarıldı.

Bu benim ilk kez bir cevap gönderiyorum, bu yüzden bunun çok daha kısa olabileceğinden eminim. Test dizesini girdiye ilk yanıt olarak ve arama karakterini ikinci olarak alır.

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

Ungolfed versiyonu:

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

Keşfetti, test vakalarından birini alamadım.


3

Haskell, 120 bayt

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 işi yapar.


3

Java, 146 152 143 138 139 136 bayt

  1. Bir hata düzeltildi.
  2. değişen operasyonlar, %3&%5çekler için bit yönünde operatöre geçildi .
  3. Kısaltılmış i<2karşılaştırma.
  4. Bir hata düzeltildi ( %3&%5kontrol düşünce olarak çalışmıyor).
  5. @ W0lf 'in Ruby cevabında görüldüğü gibi çarpım kısayolu kullanılır .

BiFunction<String, String, Integer>Java 8'de uygulandığı gibi , bunun tam bir program olması gerekip gerekmediğini (ya da java.util.regexaşağıdaki paket önekini bile düşürebilirsem ) bana bildirin .

Yukarıdaki bayt sayısı, yalnızca bu sitede biçimlendirme amacıyla eklenmiş olan aşağıdaki yeni satırı içermez.

(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();

Kaba açıklama:

  1. Desenli regex uygula vermez maç byani "[^"+b+"]".
  2. Her jetonun uzunluğunu alın (örn. "a" -> 1).
  3. İstediğiniz eşlemeyi -1, 0ve öğesine uygulayın 1.
  4. sum() cevap almak için

2

Javascript, 206 bayt

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}

Expanded:

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

Açıklama:

Bir karakterin göründüğü toplam süreyi saymak için regex kullanıyorum, sonra gruplar halinde göründüğü zamanları çıkardım. Sonunda, gruplar arasında gidip fizz buzz artışını / azalışını yapıyorum.

Soruda verilen test durumlarını geçmektedir:

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

ve bunun gibi


Kaldır new, kullanmak execyerine match, ve takma lengthve iyi olmalıdır.
Mama Fun Roll

2

Perl, 82 65 63 59 bayt

58 bayt + 1 bayt komut satırı parametresi

Özellikle kısa değil, ama bu bir başlangıç ​​- kısaltmaya devam edecek.

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

-iGiriş dizesini vermek için kullanılabileceğini varsayarsak , örnek kullanım aşağıdaki gibidir:

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


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

"Char space string" olarak giriş yapın

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 bayt

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

Test odası

Formdaki giriş örn .:

a
aaaba

Açıklama:

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.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.