Pencocokan String FizzBuzz-ish


25

Katakan bahwa Anda memiliki string seperti ini:

abaabbbbbaabba

Hitung berapa kali karakter tertentu muncul dalam string input, tetapi hanya jika karakter hanya muncul sekali dalam satu baris . Misalnya, jika karakternya adalah a,

abaabbbbbaabba
^ x      x   ^

Totalnya adalah 2 ( aatidak akan dihitung karena amuncul dua kali berturut-turut).

Bagaimana ini terkait dengan FizzBuzz?

Jika karakter muncul 3 (atau kelipatan 3) kali berturut-turut, atau 5 (atau kelipatan 5) kali berturut-turut, penghitung akan dikurangi sebagai gantinya. Jika kelipatan 3 dan 5 kali, penghitung masih bertambah. Ingat bahwa penghitung juga bertambah jika karakter hanya muncul sekali dalam satu baris, dan diabaikan jika karakter muncul beberapa kali berturut-turut (selain situasi yang dijelaskan di atas).

Untuk rekap, jika string yang cocok adalah 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)

Implementasi referensi (ungolfed) di 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);
    }   
}
  • String yang akan dicari bisa panjang, tetapi polanya hanya satu karakter.
  • String tidak akan memiliki karakter khusus regex.
  • Ini adalah ; program terpendek dalam byte menang.
  • Tidak ada celah standar.

3
Akan bermanfaat jika Anda bisa memberikan beberapa contoh uji lagi. Terutama yang urutannya memiliki lebih dari satu huruf.
Reto Koradi

Saya menambahkan beberapa kasus - mudah-mudahan itu membantu. Beri tahu saya jika saya perlu lebih banyak kasus - ini pertama kalinya saya di PPCG.
Daniel M.

Saya akan mengubah persyaratan sehingga urutannya hanya satu karakter, karena implementasinya hampir sama, tetapi kurang membingungkan.
Daniel M.

Ini seperti pertanyaan 1-jarang tetapi dengan penambahan FizzBuzz
ev3commander

Jawaban:


32

Funciton , 1840 byte

Sialan, bahasa ini tidak bisa diubah.

Program ini mengharapkan karakter pertama dari input menjadi karakter untuk dicari, dan sisanya dari input untuk membuat string untuk dicari. Ini berarti bahwa aaabaakan mencari ainput aaba(dan dengan demikian output 1). Anda dapat memisahkannya dengan baris baru atau spasi ( a aaba) tetapi hanya karena baris baru / spasi tidak membuat perbedaan pada output.

Seperti biasa, Anda bisa mendapatkan rendering yang tampak lebih bagus (tanpa spasi baris) jika Anda mengeksekusi $('pre').css('line-height',1)di konsol browser Anda.

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

(1840 byte ketika dikodekan sebagai UTF-16.)

Penjelasan

  • ¹ mengembalikan karakter pertama dari sebuah string.
  • ²menghitung jumlah kemunculan karakter pada awal string yang diberikan. Misalnya, mengingat karakter adan string aaba, ia mengembalikan 2. Untuk adan baa, mengembalikan 0.
  • ³panggilan ²untuk mendapatkan jumlah karakter di awal, memeriksa apakah jumlahnya dapat dibagi 3 dan 5 dan apakah itu sama dengan 1 dan menentukan kenaikan / penurunan yang tepat. Itu juga menghilangkan satu karakter tambahan dari awal string (mis. Diberikan aaabbaitu menghilangkan 3 + 1 = 4 karakter, memberi ba). Kemudian ia memanggil dirinya secara rekursif dengan string yang lebih pendek dan menambahkan hasilnya.
  • Panggilan program utama ¹untuk menghapus karakter pertama dari input dan panggilan ³dengan karakter itu dan sisa string sebagai argumen terpisah.

10
Saya tidak akan pernah memperbaiki Funciton.
orlp

14

CJam, 40 36 35 32 30 byte

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

Terima kasih kepada @ MartinBüttner untuk bermain golf 1 byte!

Terima kasih kepada @AndreaBiondo untuk bermain golf 2 byte dan membuka jalan untuk 3 lagi!

Cobalah online di juru bahasa CJam .

Bagaimana itu bekerja

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#

Anda dapat menyimpan 2 byte lainnya dengan tabel pencarian berbasis-kode dan pengindeksan modular: llcf=e`::*0-{(_!\6563282Zb:(=}%1badalah 33 byte.
Andrea Biondo

@ AndreaBiondo Itu sebenarnya menyelamatkan 3 byte. Terima kasih!
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);}

Mungkin bisa dibuat lebih baik ... Ini mengambil input dari argumen baris perintah (argumen pertama adalah pola, kedua adalah string). Tidak mendukung pencarian pola NULL char (\ x00).

EDIT ** 126 125 119 114 109 104 100 byte **: Setelah memasukkan saran Dennis, dan beberapa ide tambahan (dihapus klausa lain, menggabungkan sementara ke dalam satu pernyataan tunggal dan menggunakan pengurangan bukannya! =). Juga menghapus titik koma ekstra untuk loop (yang sebenarnya merupakan bagian dari saran Dennis). Lebih singkat lagi dengan menghapus variabel 'i' dan '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);}

Menghapus operator if dan negation ('!') Dengan menyalahgunakan operator ternary. Mengompresi pemeriksaan modularitas dengan menggunakan bitwise 'DAN' trik ganda && karena bitwise '&' memiliki bug, dan menempatkan perbandingan (t <2) di dalam operator ternary. Digantikan !! t * (...) dengan memindahkan !! t ke operator ternary, sehingga memungkinkan saya untuk menghapus tanda kurung.

Sobat, saya benar-benar ingin mendapatkannya di bawah tanda 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);}

Solusi TENTATIF: Saya tidak yakin apakah ini akan dianggap valid, tetapi saya bisa turun ke 93 karakter jika saya menggunakan exit (bukan) printf ("% d", s). Tapi kemudian output tidak akan terlihat, melainkan kode balik. Jika output benar-benar diperlukan, saya juga bisa turun ke 98 byte, tetapi akan membutuhkan pencetakan semua nilai menengah sebelum jawaban akhir juga ...


3
Selamat Datang di Programming Puzzles & Code Golf! Saya belum mengujinya secara menyeluruh, tetapi 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);}harus bekerja dengan baik (dan 23 byte lebih pendek).
Dennis

Oh, bagusnya dengan mengubah klausa if () {} menjadi satu pernyataan!
Tob Ernack

Beberapa byte lagi: Jika Anda mulai maindengan for(a=*z[1];c;i++), Anda tidak perlu {}sekitar if ... else.
Dennis


4

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

Disimpan 15 byte berkat vaultah dari SOPython.
Disimpan 9 byte berkat Joe Kington dari SOPython.
Disimpan 11 byte berkat DSM dari SOPython.

Ini adalah pertama kalinya saya mengirimkan jawaban, jadi saya yakin ini bisa menjadi jauh lebih singkat. Dibutuhkan string uji sebagai respons pertama terhadap input, dan char pencarian sebagai yang kedua.

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

Versi tidak disatukan:

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

Mengetahui saya gagal dalam salah satu kasus uji.


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 melakukan pekerjaan.


3

Java, 146 152 143 138 139 136 byte

  1. Memperbaiki bug.
  2. operasi bergeser, beralih ke operator bitwise untuk %3&%5pemeriksaan.
  3. i<2Perbandingan singkat .
  4. Memperbaiki bug ( %3&%5centang tidak berfungsi seperti yang diperkirakan).
  5. Digunakan pintasan multiplikasi seperti yang terlihat di @ w0lf 's Ruby answer.

Diterapkan sebagai BiFunction<String, String, Integer>dalam Java 8, beri tahu saya apakah ini diperlukan untuk menjadi program lengkap (atau jika saya bahkan dapat java.util.regexmeletakkan awalan paket di bawah).

Jumlah byte di atas tidak termasuk baris baru di bawah ini, yang hanya ditambahkan untuk keperluan pemformatan di situs ini.

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

Penjelasan kasar:

  1. Terapkan regex dengan pola yang tidak cocok b, yaitu "[^"+b+"]".
  2. Dapatkan panjang setiap token (mis "a" -> 1.).
  3. Terapkan pemetaan yang diinginkan ke -1, 0dan 1.
  4. sum() untuk mendapat jawaban.

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}

Diperluas:

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

Penjelasan:

Saya menggunakan regex untuk menghitung total kali karakter muncul, lalu kurangi dari itu setiap kali muncul dalam grup. Akhirnya, saya pergi melalui kelompok dan melakukan kenaikan / penurunan desis desis.

Lulus uji kasus yang diberikan dalam pertanyaan:

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

dan seterusnya


Hapus new, gunakan execbukan match, dan alias length, dan Anda harus baik.
Mama Fun Roll

2

Perl, 82 65 63 59 byte

58 byte + 1 byte parameter baris perintah

Tidak terlalu pendek, tapi ini awal - akan terus memperpendeknya.

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

Dengan asumsi -idapat digunakan untuk memberikan string input contoh penggunaan adalah sebagai berikut:

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


0

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

Masukkan sebagai "string spasi", seperti itu

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

Tidak disatukan

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 uji

Masukan dalam bentuk misalnya:

a
aaaba

Penjelasan:

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.
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.