Bộ so khớp chuỗi FizzBuzz-ish


25

Nói rằng bạn có một chuỗi như thế này:

abaabbbbbaabba

Đếm số lần mà một ký tự được chỉ định xuất hiện trong chuỗi đầu vào, nhưng chỉ khi ký tự đó chỉ xuất hiện một lần trong một hàng . Ví dụ: nếu nhân vật là a,

abaabbbbbaabba
^ x      x   ^

Tổng cộng sẽ là 2 ( aasẽ không được tính vì axuất hiện hai lần liên tiếp).

Làm thế nào điều này có liên quan đến FizzBuzz?

Nếu ký tự xuất hiện 3 (hoặc bội số của 3) lần liên tiếp hoặc 5 (hoặc bội số của 5) lần liên tiếp, thay vào đó bộ đếm sẽ giảm dần . Nếu nó là bội số của cả 3 5 lần, bộ đếm vẫn tăng. Hãy nhớ rằng bộ đếm cũng được tăng lên nếu nhân vật chỉ xuất hiện một lần liên tiếp và nó sẽ bị bỏ qua nếu nhân vật xuất hiện bất kỳ số lần nào khác liên tiếp (bên cạnh các tình huống được mô tả ở trên).

Để tóm tắt lại, nếu chuỗi phù hợp là 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)

Tham chiếu thực hiện (chưa được chỉnh sửa) trong 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);
    }   
}
  • Chuỗi sẽ được tìm kiếm có thể có độ dài bất kỳ, nhưng mẫu sẽ chỉ là một ký tự.
  • Cả chuỗi sẽ không có ký tự đặc biệt regex.
  • Đây là ; chương trình ngắn nhất trong byte thắng.
  • Không có sơ hở tiêu chuẩn.

3
Nó sẽ hữu ích nếu bạn có thể cung cấp thêm một vài ví dụ thử nghiệm. Đặc biệt là những nơi mà chuỗi có nhiều hơn một chữ cái.
Reto Koradi

Tôi đã thêm một vài trường hợp - hy vọng điều đó có ích. Nói cho tôi biết nếu tôi cần thêm trường hợp - đây là lần đầu tiên tôi đến PPCG.
Daniel M.

Tôi sẽ thay đổi các yêu cầu để chuỗi chỉ có một ký tự duy nhất, vì việc thực hiện khá giống nhau, nhưng ít gây nhầm lẫn.
Daniel M.

Đây giống như câu hỏi 1 thưa nhưng với phần bổ sung FizzBuzz
ev3commander

Câu trả lời:


32

Funciton , 1840 byte

Chết tiệt, ngôn ngữ này là vô đối.

Chương trình này hy vọng ký tự đầu tiên của đầu vào là ký tự cần tìm và phần còn lại của đầu vào để tạo chuỗi tìm kiếm thông qua. Điều này có nghĩa là aaabasẽ tìm kiếm atrong đầu vào aaba(và do đó đầu ra 1). Bạn có thể tách chúng bằng một dòng mới hoặc dấu cách ( a aaba) nhưng chỉ vì dòng mới / dấu cách thêm không tạo ra sự khác biệt cho đầu ra.

Như mọi khi, bạn có thể có được kết xuất trông đẹp hơn (không có khoảng cách dòng) nếu bạn thực thi $('pre').css('line-height',1)trong bảng điều khiển trình duyệt của mình.

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

(1840 byte khi được mã hóa dưới dạng UTF-16.)

Giải trình

  • ¹ trả về ký tự đầu tiên của chuỗi.
  • ²đếm số lần xuất hiện của một ký tự khi bắt đầu một chuỗi đã cho. Ví dụ, được đưa ra ký tự avà chuỗi aaba, nó trả về 2. Cho abaa , nó trả về 0.
  • ³gọi ²để lấy số lượng ký tự khi bắt đầu, kiểm tra xem số đó có chia hết cho 3 và 5 hay không và liệu nó có bằng 1 hay không và xác định mức tăng / giảm thích hợp. Nó cũng loại bỏ một ký tự phụ từ đầu chuỗi (ví dụ: aaabbanó loại bỏ 3 + 1 = 4 ký tự, cho ba). Sau đó, nó tự gọi đệ quy với chuỗi ngắn hơn và thêm kết quả.
  • Chương trình chính gọi ¹để loại bỏ ký tự đầu tiên khỏi đầu vào và gọi ³với ký tự đó và phần còn lại của chuỗi dưới dạng các đối số riêng biệt.

10
Tôi sẽ không bao giờ không upvote Funciton.
orlp

14

CJam, 40 36 35 32 30 byte

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

Cảm ơn @ MartinBüttner vì đã chơi golf 1 byte!

Cảm ơn @AndreaBiondo vì đã chơi golf 2 byte và mở đường cho 3 người nữa!

Dùng thử trực tuyến trong trình thông dịch CJam .

Làm thế nào nó hoạt động

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#

Bạn có thể lưu thêm 2 byte với bảng tra cứu được mã hóa cơ sở và lập chỉ mục mô-đun: llcf=e`::*0-{(_!\6563282Zb:(=}%1blà 33 byte.
Andrea Biondo

@AndreaBiondo Điều đó thực sự đã lưu 3 byte. Cảm ơn!
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);}

Có lẽ có thể được thực hiện tốt hơn ... Điều này lấy đầu vào từ các đối số dòng lệnh (đối số đầu tiên là mẫu, thứ hai là chuỗi). Không hỗ trợ tìm kiếm mẫu của NULL char (\ x00).

CHỈNH SỬA ** 126 125 119 114 109 104 100 byte **: Sau khi kết hợp các đề xuất của Dennis và một số ý tưởng bổ sung (loại bỏ mệnh đề khác, kết hợp thời gian thành một câu lệnh duy nhất và sử dụng phép trừ thay vì! =). Đồng thời xóa thêm dấu chấm phẩy trong vòng lặp for (đó thực sự là một phần trong đề xuất của Dennis). Rút ngắn hơn nữa bằng cách loại bỏ các biến 'i' và '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);}

Đã xóa các toán tử if và phủ định ('!') Bằng cách lạm dụng toán tử ternary. Nén các kiểm tra mô đun bằng cách sử dụng bitwise 'AND' lừa đôi && vì bitwise '&' có lỗi và đặt so sánh (t <2) bên trong các toán tử ternary. Đã thay thế !! t * (...) bằng cách di chuyển !! t vào toán tử ternary, do đó cho phép tôi xóa dấu ngoặc đơn.

Man, tôi thực sự muốn có được nó dưới mốc 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);}

Các giải pháp TENTECT: Tôi không chắc chắn liệu những điều này có được coi là hợp lệ hay không, nhưng tôi có thể nhận được tới 93 ký tự nếu tôi sử dụng lối ra thay vì printf ("% d", s). Nhưng sau đó đầu ra sẽ không hiển thị, thay vào đó sẽ là mã trả về. Nếu đầu ra thực sự cần thiết, tôi cũng có thể giảm xuống còn 98 byte, nhưng nó sẽ yêu cầu in tất cả các giá trị trung gian của s trước câu trả lời cuối cùng ...


3
Chào mừng bạn đến với Câu đố lập trình & Code Golf! Tôi chưa kiểm tra kỹ, nhưng 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);}cũng hoạt động tốt (và nó ngắn hơn 23 byte).
Dennis

Ồ, thật tuyệt khi biến mệnh đề if () {} thành một câu lệnh!
Tob Ernack

Một vài byte nữa: Nếu bạn bắt đầu mainvới for(a=*z[1];c;i++), bạn không cần {}xung quanh nếu ... khác.
Dennis


4

Con trăn 3 361, 300, 296, 263, 256, 237, 229, 188, 178 , 164 byte.

Đã lưu 15 byte nhờ vaultah từ SOPython.
Đã lưu 9 byte nhờ Joe Kington từ SOPython.
Đã lưu 11 byte nhờ DSM ​​từ SOPython.

Đây là lần đầu tiên tôi gửi câu trả lời, vì vậy tôi chắc chắn rằng điều này có thể ngắn hơn nhiều. Nó lấy chuỗi thử nghiệm làm phản hồi đầu tiên cho đầu vào và char tìm kiếm làm chuỗi thứ hai.

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

Phiên bản bị đánh cắp:

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

Phát hiện ra tôi đã thất bại một trong những trường hợp thử nghiệm.


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 Làm công việc.


3

Java, 146 152 143 138 139 136 byte

  1. Đã sửa lỗi.
  2. hoạt động thay đổi, chuyển sang toán tử bitwise cho %3&%5 kiểm tra.
  3. Rút ngắn i<2so sánh.
  4. Đã sửa lỗi ( %3&%5kiểm tra không hoạt động như suy nghĩ).
  5. Đã sử dụng lối tắt nhân như đã thấy trong câu trả lời Ruby của @ w0lf .

Được triển khai như BiFunction<String, String, Integer>trong Java 8, hãy cho tôi biết nếu điều này được yêu cầu phải là một chương trình đầy đủ (hoặc nếu tôi thậm chí có thể bỏ java.util.regextiền tố gói bên dưới).

Số byte ở trên không bao gồm dòng mới bên dưới, được thêm đơn giản cho mục đích định dạng trên trang web này.

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

Giải thích sơ bộ:

  1. Áp dụng regex với mẫu không khớp b, nghĩa là "[^"+b+"]".
  2. Nhận độ dài của mỗi mã thông báo (ví dụ "a" -> 1).
  3. Áp dụng ánh xạ mong muốn cho -1, 01.
  4. sum() để có câu trả lời.

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}

Mở rộng:

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

Giải trình:

Tôi đang sử dụng regex để đếm tổng số lần một nhân vật xuất hiện, sau đó trừ đi tất cả số lần nó xuất hiện trong các nhóm. Cuối cùng, tôi đi qua các nhóm và thực hiện tăng / giảm âm lượng fizz buzz.

Vượt qua các trường hợp thử nghiệm được đưa ra trong câu hỏi:

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

và v.v.


Xóa new, sử dụng execthay vì matchvà bí danh length, và bạn sẽ tốt.
Mama Fun Roll

2

Perl, 82 65 63 59 byte

Tham số dòng lệnh 58 byte + 1 byte

Không đặc biệt ngắn, nhưng đó là một khởi đầu - sẽ tiếp tục rút ngắn nó.

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

Giả sử -icó thể được sử dụng để cung cấp cho chuỗi đầu vào một cách sử dụng ví dụ như sau:

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


0

chim ưng, 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""

Nhập dưới dạng "chuỗi không gian char", như vậy

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

Bị đánh cắp

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

Bình thường, 27 byte

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

Bộ kiểm tra

Đầu vào ở dạng, ví dụ:

a
aaaba

Giải trình:

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.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.