패턴에서 홀수 문자 찾기


20

입력

첫 번째 줄은 특정 문자열이 여러 번 반복됩니다. 예를 들어,가 수 abcabcabcabc, [];[];[];등 그것은 잘릴 수 있습니다; 예를 들면 다음과 같습니다 1231231231.. 항상 가장 짧은 줄을 찾으십시오. 예를 들어, 라인 인 경우 22222, 다음 문자열입니다 2, 아니 22하거나 22222또는 다른 것. 문자열은 항상 2 번 이상 반복됩니다.

모든 후속 라인은 임의의 숫자만큼 패턴 오프셋됩니다. 예를 들어 다음과 같습니다.

abcabcabc
cabcabcab
bcabcabca

(1로 오프셋) 또는 다음과 같을 수 있습니다.

abcdefabcdefabcdefabc
cdefabcdefabcdefabcde
efabcdefabcdefabcdefa

(4로 오프셋).

입력 된 문자 중 하나가 잘못되었습니다. (첫 번째 줄에 있지는 않습니다.) 예를 들어이 입력에서 :

a=1a=1a=1
=1a=1a=1a
1a=11=1a=
a=1a=1a=1
=1a=1a=1a

1라인 3 홀수 하나 아웃이다.

산출

홀수 좌표의 (좌측에서 시작하여) 좌표를 출력해야합니다. 예를 들어, 위 입력에서 해당 출력은 4,2입니다. 또한 출력을 할 수있다 4 2, 또는 "4""2", 또는 [[4],[2]], 또는 다른 형식은 한 당신은 출력이 있어야하는데 무엇을 말할 수 있습니다.

테스트 사례

입력:

codegolfcodegolfco
egolfcodegolfcodeg
lfcodegolfcodegoff
odegolfcodegolfcod
golfcodegolfcodego
fcodegolfcodegolfc

산출: 16,2

입력:

][[][][[][][[][][[][][[
[][][[][][[][][[][][[][
[][[][][[][][[][][[][][
[[][][[]]][[][][[][][[]

산출: 8,3

입력:

...
. .
...

산출: 1,1

입력:

ababa
babab
ababb
babab

산출: 4,2

가기!


문자열에 어떤 문자를 포함 할 수 있습니까? 인쇄 가능한 ASCII? ASCII? 유니 코드?
Dennis

@Dennis 그냥 인쇄 가능한 ASCII (기본적으로 문자열과 관련된 모든 문제에 대해 가정 할 수 있습니다. 그렇지 않으면 거의 모든 문제에 대해 지정해야합니다 .P)
Doorknob

나는 그렇게 추측했다. 사용하지 않는 문자가 필요한 접근법에 대해 생각하고 있으므로 물어볼 것이라고 생각했습니다.
Dennis

: 우리는이 같은 경우 확인해야합니다 abc/cab/abc및 출력 - 0 2여기?
user2846289

@VadimR 아니요. 한 문자 만 틀리기 때문입니다.
Doorknob

답변:


7

배시231 229 218 178 164 166 138 106 74 바이트

/^(((.*).*)\2+)\3$/;$_.=$1x2;$.--,die$+[1]if/^(.*)(.)(.*)
.*\1(?!\2).\3/

스크립트는 -n스위치를 사용해야하며 ,이 중 2 바이트를 설명합니다.

패턴의 전체 반복의 두 복사본을 추가한다는 아이디어는 MT0의 답변 에서 가져 왔습니다 .

다른 모든 답변과 달리이 방법은 각 반복에서 현재 입력 라인의 패턴을 추출하려고 시도합니다. 홀수 문자를 포함하는 행에서 실패하고 대신 이전 행의 패턴을 사용합니다. 이것은 루프에 패턴 추출을 포함하기 위해 수행되며 몇 바이트를 절약합니다.

언 골프 버전

#!/usr/bin/perl -n

# The `-n' switch makes Perl execute the entire script once for each input line, just like
# wrapping `while(<>){…}' around the script would do.

/^(((.*).*)\2+)\3$/;

# This regular expression matches if `((.*).*)' - accessible via the backreference `\2' -
# is repeated at least once, followed by a single repetition of `\3" - zero or more of the
# leftmost characters of `\2' - followed by the end of line. This means `\1' will contain
# all full repetitions of the pattern. Even in the next loop, the contents of `\1' will be
# available in the variable `$1'.

$_.=$1x2;

# Append two copies of `$1' to the current line. For the line, containing the odd
# character, the regular expression will not have matched and the pattern of the previous
# line will get appended.
#
# Since the pattern is repeated at least two full times, the partial pattern repetition at
# the end of the previous line will be shorter than the string before it. This means that
# the entire line will the shorter than 1.5 times the full repetitions of the pattern, 
# making the two copies of the full repetitions of the pattern at least three times as 
# long as the input lines.

$.-- , die $+[1] if

# If the regular expression below matches, do the following:
#
#   1. Decrement the variable `$.', which contains the input line number.
#
#      This is done to obtain zero-based coordinates.
#
#   2. Print `$+[1]' - the position of the last character of the first subpattern of the
#      regular expression - plus some additional information to STDERR and exit.
#
#      Notably, `die' prints the (decremented) current line number.

/^(.*)(.)(.*)
.*\1(?!\2).\3/;

# `(.*)(.)(.*)', enclosed by `^' and a newline, divides the current input line into three
# parts, which will be accesible via the backreferences `\1' to `\3'. Note that `\2'
# contains a single character.
#
# `.*\1(?!\2).\3' matches the current input line, except for the single character between
# `\1' and `\3' which has to be different from that in `\2', at any position of the line
# containing the pattern repetitions. Since this line is at least thrice as long as
# `\1(?!\2).\3', it will be matched regardless of by how many characters the line has been
# rotated.

테스트 사례

codegolfcodegolfco
egolfcodegolfcodeg
lfcodegolfcodegoff
odegolfcodegolfcod
golfcodegolfcodego
fcodegolfcodegolfc

골프 버전의 출력은

16 at script.pl line 1, <> line 2.

홀수 문자에 좌표가 있음을 의미합니다 16,2.

이것은 명백히 남용 으로 인해 자유 주의적 출력 형식을 이용합니다.

종료하기 전에 Perl의 특수 변수 내용은 다음과 같습니다.

$_  = lfcodegolfcodegoff\ncodegolfcodegolfcodegolfcodegolf
$1  = lfcodegolfcodego
$2  = f
$3  = f

( $n역 참조를 통해 액세스 할 수있는 서브 패턴의 경기를 포함 \n.)


응답 장치를 영리하게 잡습니다. 1 바이트로 최적화 할 수 있습니다.^((.*?)(.*?))(?=\1+\2$)
Heiko Oberdiek

나는 인기있는 아이들이 사용하는 언어로 전환했습니다. 아마 더 아래로 골프를 칠 수 있습니다; 이것은 10 년이 넘는 시간 동안의 첫 번째 Perl 스크립트입니다.
Dennis

2
... 그리고 펄이 인기있는 아이들이 사용하고 있다고 생각하면 10 년이 늦었습니다
ardnew

이 답변은 그 가치가있는 사랑을 얻지 못하고 있습니다. 나에게 외모는 우승자 @Doorknob 좋아
ardnew

8

212 191 181 168 바이트

$_=<>;/^(((.*?)(.*?))\2+)\3$/;$x=$1x4;while(<>){chop;$x=~/\Q$_\E/&&next;for$i(0..y///c-1){for$r(split//,$x){$b=$_;$b=~s/(.{$i})./$1$r/;$x=~/\Q$b\E/&&die$i,$",$.-1,$/}}}
  • 이 버전은 Dennis의 답변 에서 배운 응답 단위를 잡기 위해 최적화 된 트릭을 사용합니다 .
  • 모든 줄의 길이가 같은 속성을 사용하여 최적화
  • 마지막 줄에도 줄 끝이 필요합니다. 그렇지 않은 경우 chomp대신 chop사용해야합니다.
  • ardnew 님의 댓글이 추가되었습니다.

이전 버전, 212 바이트 :

$_=<>;chop;/^(.+?)\1+(??{".{0,".(-1+length$1).'}'})$/;$;=$1;while(<>){$x=$;x length;chop;$x=~/\Q$_\E/&&next;for$i(0..-1+length$_){for$r(split//,$;){$b=$_;$b=~s/(.{$i})./$1$r/;$x=~/\Q$b\E/&&exit print$i,$",$.-1}}}

언 골프 버전 :

$_ = <>;  # read first line
/^(((.*?)(.*?))\2+)\3$/;
# The repeat unit \2 consists of \3 and \4,
# and the start part \2 can be added at the end (as partial or even full unit).
$x = $1 x 4; # $x is long enough to cover each following line

# Old version:
# /^(.+?)\1+(??{ ".{0," . (-1 + length $1) . '}' })$/;
# $a = $1; # $a is the repeat unit.
# The unit is caught by a non-greedy pattern (.+?) that is
# repeated at least once: \1+
# The remaining characters must be less than the unit length.
# The unit length is known at run-time, therefore a "postponed"
# regular expression is used for the remainder.

# process the following lines until the error is found
while (<>) {
    # old version:
    # $x = $a x length;
    # $x contains the repeated string unit, by at least one unit longer
    # than the string in the current line
    chop; # remove line end of current line
    $x =~ /\Q$_\E/ && next;
          # go to next line, if current string is a substring of the repeated units;
          # \Q...\E prevents the interpretation of special characters
    # now each string position $x is checked, if it contains the wrong character:
    for $i (0 .. y///c - 1) {  # y///c yields the length of $_
        for $r (split //, $x) { #/ (old version uses $a)
            # replace the character at position $i with a
            # character from the repeat unit
            $b = $_;
            $b =~ s/(.{$i})./$1$r/;
            $x =~ /\Q$b\E/
               && die $i, $", $. - 1, $/;
               # $" sets a space and the newline is added by $/;
               # the newline prevents "die" from outputting line numbers
        }
    }
}

훌륭한 해결책과 의견, 더 많은 정규식을 배울 필요가 있습니다.)
Newbrict

1
첫 번째 chop는 불필요합니다. 제거해야합니다. 최종 항목 exit print은 (필요한 경우 die추가 항목 ,$/을 숨기려면 추가) 로 바꿀 수 있습니다 . 다음 length$_으로 대체 될 수도 있습니다y///c
ardnew

@ardnew : 많은 감사, 문자열의 끝에 줄 바꿈 앞에 일치하기 chop때문에 첫 번째를 제거했습니다 $. die추가 된 줄 바꿈 을 통해 추가 항목을 숨기는 것이 나에게 필요한 것 같습니다. 또한 불필요한 것 y///c보다 훨씬 짧고 length$_1 바이트 더 짧습니다 . length$_
Heiko Oberdiek 12

1
@ardnew : 나는 die 의 장황함을 잊었다 . 라인 번호도 인쇄합니다! 다음 업데이트에서 사용하겠습니다.
Dennis

3

C, 187 바이트

한계.

  • 98 자보다 긴 입력 문자열을 사용하지 마십시오. :)

골프 버전

char s[99],z[99],*k,p,i,I,o,a;c(){for(i=0;k[i]==s[(i+o)%p];i++);return k[i];}main(){for(gets(k=s);c(p++););for(;!(o=o>p&&printf("%d,%d\n",I,a))&&gets(k=z);a++)while(o++<p&&c())I=I<i?i:I;}

언 골프 버전

char s[99],z[99],*k,p,i,I,o,a;

c()
{
    for(i=0
       ;k[i]==s[(i+o)%p]
       ;i++)
       ;
    return k[i];
}

main()
{
    for(gets(k=s);c(p++);)
         ;
    for(;!(o=o>p&&printf("%d,%d\n",I,a)) && gets(k=z);a++)
           while(o++ < p && c())
            I=I<i?i:I;
}

2

파이썬, 303 292

r=raw_input
R=range
s=r()
l=len(s)
m=1
g=s[:[all((lambda x:x[1:]==x[:-1])(s[n::k])for n in R(k))for k in R(1,l)].index(True)+1]*l*2
while 1:
 t=r()
 z=[map(lambda p:p[0]==p[1],zip(t,g[n:l+n]))for n in R(l)]
 any(all(y)for y in z)or exit("%d,%d"%(max(map(lambda b:b.index(False),z)),m))
 m+=1

입력이 stdin을 통과합니다. 수요가 있으면 설명하지만 어쨌든 내가 이길 것 같지는 않습니다.


1

157 154

편집 : ardnew '제안에 -3 감사합니다.

<>=~/^(((.*?).*?)\2+)\3$/;$p=$2;$n=$+[1];while(<>){s/.{$n}/$&$&/;/(\Q$p\E)+/g;$s=$p;1while/./g*$s=~/\G\Q$&/g;print$n>--($m=pos)?$m:$m-$n,$",$.-1,$/if pos}

시간이 좀 걸렸습니다 (물론, 5 일이 아니고 ;-)), 알고리즘에 대한 아이디어는 처음에는 어려웠지만 (필자가 있었지만) 마침내 (그리고 갑자기) 모든 것이 명확 해졌습니다.

문자열 길이가 패턴 길이의 배수이고 문자열이 패턴의 시작으로 시작하지 않더라도 문자열 자체를 연결하면 연결 대신 패턴이 생성됩니다 (원형 리본에서 단어의 무한 반복 상상- 용접은 중요하지 않습니다). 따라서 아이디어는 선을 여러 단위 길이로 자르고 원본을 연결하는 것입니다. 잘못된 문자가 포함 된 문자열의 경우에도 결과는 최소한 한 번은 패턴과 일치해야합니다. 거기에서 불쾌감을주는 캐릭터의 위치를 ​​쉽게 찾을 수 있습니다.

첫 번째 줄은 Heiko Oberdiek의 답변에서 뻔뻔스럽게 차용되었습니다 :-)

<>=~/^(((.*?).*?)\2+)\3$/;      # Read first line, find the repeating unit
$p=$2;                          # and length of whole number of units.
$n=$+[1];                       # Store as $p and $n.
while(<>){                      # Repeat for each line.
    s/.{$n}/$&$&/;              # Extract first $n chars and
                                # append original line to them.
    /(\Q$p\E)+/g;               # Match until failure (not necessarily from the
                                # beginning - doesn't matter).
    $s=$p;                      # This is just to reset global match position
                                # for $s (which is $p) - we could do without $s,
                                # $p.=''; but it's one char longer.
                                # From here, whole pattern doesn't match -
    1while/./g*$s=~/\G\Q$&/g;   # check by single char.
                                # Extract next char (if possible), match to 
                                # appropriate position in a pattern (position 
                                # maintained by \G assertion and g modifier).
                                # We either exhaust the string (then pos is 
                                # undefined and this was not the string we're
                                # looking for) or find offending char position.

    print$n>--($m=pos)?$m:$m-$n,$",$.-1,$/if pos
}

1
잘 하셨어요. 난 당신이 바꿀 수 있다고 생각 /.{$n}/;$_=$&.$_;s/.{$n}/$&$&/;
ardnew

1

자바 스크립트 (ES6) - 147 개 133 136 문자

s.split('\n').map((x,i)=>(v=/^(.*)(.)(.*)᛫.*\1(?!\2).\3/.exec(x+'᛫'+(a=/^(((.*).*)\2+)\3\n/.exec(s)[1])+a))&&console.log(v[1].length,i))

테스트 할 문자열이 변수에있을 것으로 예상 s하고 결과를 콘솔에 출력합니다.

var repetitionRE = /^(((.*).*)\2+)\3\n/;
                                        // Regular expression to find repeating sequence
                                        // without any trailing sub-string of the sequence.
var sequence = repetitionRE.exec(s)[1]; // Find the sequence string.
s.split('\n')                           // Split the input into an array.
 .map(
   ( row, index ) =>                    // Anonymous function using ES6 arrow syntax
   {
     var testStr = row + '᛫'+ sequence + sequence;
                                        // Concatenate the current row, a character which won't
                                        // appear in the input and two copies of the repetitions
                                        // of the sequence from the first line.
     var match = /^(.*)(.)(.*)᛫.*\1(?!\2).\3/.exec(testStr);
                                        // Left of the ᛫ finds sub-matches for a single
                                        // character and the sub-strings before and after.
                                        // Right of the ᛫ looks for any number of characters
                                        // then the before and after sub-matches with a
                                        // different character between.
      if ( match )
       console.log( match[1].length, index );
                                        // Output the index of the non-matching character
                                        // and the row.
   }         
 );

테스트 사례 1

s="codegolfcodegolfco\negolfcodegolfcodeg\nlfcodegolfcodegoff\nodegolfcodegolfcod\ngolfcodegolfcodego\nfcodegolfcodegolfc"
s.split('\n').map((x,i)=>(v=/^(.*)(.)(.*)᛫.*\1(?!\2).\3/.exec(x+'᛫'+(a=/^(((.*).*)\2+)\3\n/.exec(s)[1])+a))&&console.log(v[1].length,i))

출력

16 2

테스트 사례 2

s="][[][][[][][[][][[][][[\n[][][[][][[][][[][][[][\n[][[][][[][][[][][[][][\n[[][][[]]][[][][[][][[]"
s.split('\n').map((x,i)=>(v=/^(.*)(.)(.*)᛫.*\1(?!\2).\3/.exec(x+'᛫'+(a=/^(((.*).*)\2+)\3\n/.exec(s)[1])+a))&&console.log(v[1].length,i))

출력

8 3

테스트 사례 3

s="...\n. .\n..."
s.split('\n').map((x,i)=>(v=/^(.*)(.)(.*)᛫.*\1(?!\2).\3/.exec(x+'᛫'+(a=/^(((.*).*)\2+)\3\n/.exec(s)[1])+a))&&console.log(v[1].length,i))

출력

1 1

테스트 사례 4

s="ababa\nbabab\nababb\nbabab"
s.split('\n').map((x,i)=>(v=/^(.*)(.)(.*)᛫.*\1(?!\2).\3/.exec(x+'᛫'+(a=/^(((.*).*)\2+)\3\n/.exec(s)[1])+a))&&console.log(v[1].length,i))

출력

4 2

테스트 사례 5

s="xyxy\nyyxy"
s.split('\n').map((x,i)=>(v=/^(.*)(.)(.*)᛫.*\1(?!\2).\3/.exec(x+'᛫'+(a=/^(((.*).*)\2+)\3\n/.exec(s)[1])+a))&&console.log(v[1].length,i))

출력

0 1

테스트 사례 6

s="ababaababa\nababaaaaba"
s.split('\n').map((x,i)=>(v=/^(.*)(.)(.*)᛫.*\1(?!\2).\3/.exec(x+'᛫'+(a=/^(((.*).*)\2+)\3\n/.exec(s)[1])+a))&&console.log(v[1].length,i))

출력

6 1

안타깝게도이 방법은 예를 들어 s="xyxy\nyyxy". 두 번째 줄의 match[4]경우 yy; 그냥 있어야합니다 y.
Dennis

재 작업 및 14 자 단축
MT0

아주 좋아요! 나는 어느 시점에서 똑같은 두 번째 정규 표현식을 시도했지만 최대 패턴 대신 최소 패턴을 두 번 추가했습니다 (따라서 비참한 실패). 하나의 사소한 문제 : 첫 번째 정규식보고 abab의 패턴 AST ababaababa; 을 사용해야 ^…$합니다.
Dennis

/^…\n/작동/^…$/m
MT0

1
선행을 필요로하지 않을 수도 있습니다 ^(적어도 내가 나열된 6 가지 테스트 사례 중 하나에 해당하지는 않지만 아마도 남아있는 반례가있을 수 있습니다).
MT0
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.