FizzBuzz-ish 문자열 매처


25

다음과 같은 문자열이 있다고 가정하십시오.

abaabbbbbaabba

지정된 문자가 입력 문자열에 나타나는 횟수를 계산하지만 문자가 한 번에 한 번만 나타나는 경우에만 계산하십시오 . 예를 들어, 문자 인 경우 a,

abaabbbbbaabba
^ x      x   ^

총계는 2입니다 ( aa' a는 연속으로 두 번 나타나기 때문에 계산에 포함되지 않습니다 ).

이것은 FizzBuzz와 어떤 관련이 있습니까?

문자가 행에 3 (또는 3의 배수)으로 나타나거나 행에 5 (또는 5의 배수)로 나타나면 카운터가 대신 감소 합니다. 3 배 5 배의 배수이면 카운터는 계속 증가합니다. 문자가 한 행에 한 번만 나타나는 경우 카운터가 증가하고 문자가 행에 다른 횟수로 나타나는 경우 (위에 설명 된 상황 외에) 카운터가 증가한다는 점을 기억하십시오.

요약하면 일치하는 문자열이입니다 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)

자바에서 참조 (중복되지 않은) 구현 :

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);
    }   
}
  • 검색 할 문자열은 길이에 제한이 없지만 패턴은 단일 문자입니다.
  • 문자열에는 정규 표현식 특수 문자가 없습니다.
  • 이것은 . 바이트 단위의 최단 프로그램이 이깁니다.
  • 표준 허점이 없습니다.

3
몇 가지 테스트 예제를 더 제공 할 수 있다면 유용 할 것입니다. 특히 서열이 하나 이상의 문자를 갖는 것.
Reto Koradi

도움이 되길 바랍니다. 더 많은 사례가 필요한지 알려주십시오. PPCG에서 처음입니다.
Daniel M.

구현이 거의 동일하지만 혼동이 적기 때문에 시퀀스가 ​​단일 문자 일 수 있도록 요구 사항을 변경합니다.
Daniel M.

이는 1 스파 스 질문처럼하지만 FizzBuzz의 추가와 함께
ev3commander

답변:


32

Funciton , 1840 바이트

젠장,이 언어는 말로 표현할 수 없습니다.

이 프로그램은 입력의 첫 문자가 검색 할 문자이고 나머지 입력이 문자열을 검색하도록 기대합니다. 즉 , 입력에서 aaaba검색 하므로 출력 1 이 검색됩니다 . 당신은 할 수 있습니다 줄 바꿈 또는 공간 (로 구분 )하지만 여분의 줄 바꿈 / 공간이 출력에 차이가 없습니다 때문.aaabaa aaba

$('pre').css('line-height',1)브라우저 콘솔에서 실행하면 항상 줄 간격없이 더 멋진 렌더링을 얻을 수 있습니다 .

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

(UTF-16으로 인코딩 된 경우 1840 바이트)

설명

  • ¹ 문자열의 첫 문자를 반환합니다.
  • ²주어진 문자열의 시작에서 문자의 발생 횟수를 계산합니다. 예를 들어, 문자 a와 문자열이 주어지면 aaba2를 반환 a하고 baa,와를 0으로 반환합니다.
  • ³²시작시 문자 수를 얻기위한 호출 , 숫자를 3과 5로 나눌 수 있는지 여부와 1과 같은지 여부를 검사하고 적절한 증감을 결정합니다. 또한 문자열의 시작 부분에서 하나의 추가 문자를 제거합니다 (예 : aaabba3 + 1 = 4자를 제거하고 ba). 그런 다음 더 짧은 문자열로 재귀 적으로 호출하고 결과를 추가합니다.
  • 기본 프로그램 ¹은 입력에서 첫 번째 문자를 제거하기 위해 호출 ³하고 해당 문자와 ​​나머지 문자열을 별도의 인수로 호출합니다.

10
나는 결코 Funciton을지지하지 않을 것입니다.
orlp

14

CJam, 40 36 35 32 30 바이트

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

1 바이트를 골라 낸 @ MartinBüttner에게 감사드립니다!

2 바이트를 골라 내고 3 개 더 길을 포장 한 @AndreaBiondo에게 감사합니다!

CJam 통역사 에서 온라인으로 사용해보십시오 .

작동 원리

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#

기본 인코딩 된 조회 테이블과 모듈 식 인덱싱을 사용하여 다른 2 바이트를 저장할 수 있습니다 llcf=e`::*0-{(_!\6563282Zb:(=}%1b. 33 바이트입니다.
Andrea Biondo

@AndreaBiondo 실제로 3 바이트를 절약했습니다. 감사!
Dennis

7

C, 160 126 125 119 114 109 104 100 바이트

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

아마도 더 나아질 수 있습니다 ... 이것은 명령 줄 인수에서 입력을받습니다 (첫 번째 인수는 패턴이고 두 번째는 문자열입니다). NULL 문자 (\ x00) 패턴 검색을 지원하지 않습니다.

편집 ** 126 125 119 114 109 104 100 바이트 ** : Dennis의 제안과 몇 가지 추가 아이디어 (else 절을 ​​제거하고 while를 하나의 문장으로 결합하고! = 대신 뺄셈을 사용함)를 통합 한 후. 또한 for 루프에서 실제로 세미콜론을 추가로 제거했습니다 (실제로 Dennis의 제안의 일부였습니다). 변수 'i'및 '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);}

삼항 연산자를 남용하여 if 및 부정 ( '!') 연산자를 제거했습니다. 비트 단위 '&'에는 버그가 있기 때문에 비트 단위 'AND'트릭 에 이중 && 를 사용하고 모듈러 검사를 압축하고 삼항 연산자 내에 (t <2) 비교를 넣습니다. !! t를 삼항 연산자로 이동하여 !! t * (...)를 대체하여 괄호를 제거 할 수있었습니다.

남자, 나는 정말로 그것을 100 바이트 마크 아래로 가져 가고 싶다 : 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);}

임시 해결책 : 이것이 유효한지 확실하지 않지만 printf ( "% d", s) 대신 exit를 사용하면 93 자까지 줄일 수 있습니다. 그러나 출력이 보이지 않고 리턴 코드가됩니다. 출력이 실제로 필요한 경우 98 바이트로 줄일 수도 있지만 최종 답변 전에 s의 모든 중간 값을 인쇄해야합니다.


3
프로그래밍 퍼즐 및 코드 골프에 오신 것을 환영합니다! 나는 그것을 철저히 테스트하지는 않았지만 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);}잘 작동해야합니다 (그리고 23 바이트 더 짧습니다).
Dennis

아, if () {} 절을 하나의 문장으로 바꾸는 것이 좋습니다!
Tob Ernack

몇 바이트 더 : 시작하면 mainfor(a=*z[1];c;i++), 당신은 필요하지 않습니다 {}은 if ... 다른 주변.
Dennis


4

Python 3, 361, 300, 296, 263, 256, 237, 229, 188, 178 , 164 바이트

SOPython의 Vaultah 덕분에 15 바이트가 절약되었습니다.
SOPython의 Joe Kington 덕분에 9 바이트가 절약되었습니다.
SOPython의 DSM 덕분에 11 바이트를 절약했습니다.

답변을 제출 한 것은 이번이 처음이므로 훨씬 짧을 수 있습니다. 테스트 문자열을 입력에 대한 첫 번째 응답으로 사용하고 검색 문자를 두 번째 응답으로 사용합니다.

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

언 골프 버전 :

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

테스트 사례 중 하나가 실패했음을 발견했습니다.


3

하스켈, 120 바이트

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 일을한다.


3

자바 146 152 143 138 139 136 바이트

  1. 버그가 수정되었습니다.
  2. %3&%5검사 를 위해 비트 단위 연산자로 전환했습니다 .
  3. 단축 된 i<2비교.
  4. 버그 수정 ( %3&%5생각대로 확인되지 않음).
  5. @ w0lf 의 Ruby 답변 에서 볼 수있는 곱셈 단축키를 사용했습니다 .

BiFunction<String, String, Integer>Java 8에서 구현되었으므로 이것이 전체 프로그램이어야하는지 또는 java.util.regex아래 패키지 접두사를 삭제할 수도 있는지 알려주십시오 .

위의 바이트 수에는 아래 줄 바꿈이 포함되어 있지 않습니다.이 줄 바꿈은이 사이트의 서식을 위해 추가 된 것입니다.

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

대략적인 설명 :

  1. 패턴 정규식 적용 하지 않는 일치 b, 즉 "[^"+b+"]".
  2. 각 토큰의 길이를 가져옵니다 (예 :) "a" -> 1.
  3. 에 원하는 매핑을 적용 -1, 0하고 1.
  4. sum() 대답을 얻을 수 있습니다.

2

자바 스크립트, 206 바이트

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}

넓히는:

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

설명:

정규식을 사용하여 문자가 나타나는 총 횟수를 계산 한 다음 그룹에서 나타난 모든 시간을 뺍니다. 마지막으로 그룹을 살펴보고 피즈 버즈 증가 / 감소를 수행합니다.

질문에 주어진 테스트 사례를 통과합니다.

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

등등


을 제거하고 대신에 alias를 new사용 하면 좋을 것입니다. execmatchlength
Mama Fun Roll

2

펄, 82 65 63 59 바이트

58 바이트 + 1 바이트 명령 줄 매개 변수

특히 짧지는 않지만 시작입니다. 계속 짧아 질 것입니다.

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

-i입력 문자열에 예제 사용법을 제공하기 위해 가정 할 수 있습니다.

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


0

개크, 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"으로 입력

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

언 골프

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 바이트

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

테스트 스위트

다음과 같은 형식으로 입력 :

a
aaaba

설명:

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.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.