ค้นหาตัวละครที่แปลกออกมาในรูปแบบ


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? Unicode?
Dennis

@Dennis เพียงแค่พิมพ์ ASCII (ซึ่งโดยทั่วไปสามารถสันนิษฐานได้สำหรับความท้าทายใด ๆ ที่เกี่ยวข้องกับสตริงมิฉะนั้นเราจะต้องระบุว่าสำหรับความท้าทายเกือบทุกครั้ง: P)
Doorknob

ฉันเดาอย่างนั้น ฉันกำลังคิดเกี่ยวกับวิธีการที่ต้องใช้ถ่านที่ไม่ได้ใช้ดังนั้นฉันคิดว่าฉันจะถาม
Dennis

เราควรตรวจสอบกรณีนี้: abc/cab/abc- และเอาท์พุท0 2ที่นี่?
user2846289

@VadimR ไม่เนื่องจากมีอักขระเพียงตัวเดียวเท่านั้นที่จะผิด
Doorknob

คำตอบ:


7

Bash Perl, 231 229 218 178 164 166 138 106 74 ไบต์

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

สคริปต์ต้องใช้-nสวิตช์ซึ่งบัญชีสำหรับสองไบต์

ความคิดของการผนวกสองสำเนาของทุกซ้ำเต็มรูปแบบของรูปแบบที่ได้รับมาจากคำตอบของ 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

ผลลัพธ์ของรุ่น golfed คือ

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

16,2หมายความว่าตัวละครที่แปลกมีพิกัด

การละเมิดที่โจ่งแจ้งนี้ใช้ประโยชน์จากรูปแบบเอาท์พุตแบบเสรี

ก่อนออกจากเนื้อหาของตัวแปรพิเศษของ Perl คือ:

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

( $nมีการจับคู่ของรูปแบบย่อยที่สามารถเข้าถึงได้ผ่านทาง backreference \n)


การจับอย่างชาญฉลาดของหน่วยตอบกลับ สามารถปรับให้เหมาะสมโดยหนึ่งไบต์:^((.*?)(.*?))(?=\1+\2$)
Heiko Oberdiek

ฉันเปลี่ยนเป็นภาษาที่เด็ก ๆ นิยมใช้กัน อาจจะสามารถเล่นกอล์ฟต่อไปได้ นี้เป็นสคริปต์ Perl ครั้งแรกของฉันในช่วงทศวรรษที่ ...
เดนนิส

2
... และคุณมากกว่าทศวรรษที่ผ่านมาในช่วงปลายถ้าคุณคิด Perl คือสิ่งที่เด็กนิยมใช้
ardnew

คำตอบนี้ไม่ได้รับความรักที่สมควรได้รับ ดูเหมือนว่าฉันจะเป็นผู้ชนะ @Doorknob
ardnew

8

Perl, 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,$/}}}
  • รุ่นนี้ใช้เคล็ดลับที่ดีที่สุดสำหรับการจับหน่วยตอบกลับได้เรียนรู้ในเดนนิสคำตอบ
  • การปรับให้เหมาะสมโดยใช้คุณสมบัติที่บรรทัดทั้งหมดมีความยาวเท่ากัน
  • ปลายสายยังเป็นสิ่งจำเป็นสำหรับบรรทัดสุดท้ายมิฉะนั้น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
        }
    }
}

ทางออกที่ดีและความเห็นฉันต้องเรียนรู้เพิ่มเติม regex;)
Newbrict

1
ครั้งแรกchopไม่จำเป็น - ควรถูกลบออก สุดท้ายexit printสามารถถูกแทนที่ด้วยdie(เพิ่ม,$/เพื่อซ่อนสิ่งพิเศษ (ถ้าจำเป็น)) ยังlength$_สามารถถูกแทนที่ด้วยy///c
ardnew

@ardnew: ขอบคุณมากฉันได้ลบแรกchopเพราะ$ตรงก่อนขึ้นบรรทัดใหม่ในตอนท้ายของสตริง การซ่อนสิ่งเพิ่มเติมdieผ่านทางบรรทัดใหม่ที่เพิ่มเข้ามานั้นเป็นสิ่งจำเป็นสำหรับฉัน นอกจากนี้ยังy///cเป็นที่สั้นกว่าlength$_และหนึ่งไบต์สั้นกว่าโดยไม่ต้องที่ไม่จำเป็นlength $_
Heiko Oberdiek

1
@ardnew: ฉันลืมเกี่ยวกับคำฟุ่มเฟื่อยของตาย มันยังรวมถึงพิมพ์หมายเลขบรรทัด! ฉันจะใช้สิ่งนั้นในการปรับปรุงครั้งต่อไปของฉัน
Dennis

3

C, 187 ไบต์

ข้อ จำกัด

  • อย่าใช้สตริงอินพุตที่ยาวเกิน 98 ตัวอักษร :)

รุ่น Golfed

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

Python, 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

Perl, 157 154

แก้ไข : -3 ขอบคุณคำแนะนำของ ardnew

<>=~/^(((.*?).*?)\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

JavaScript (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

ดีมาก! ฉันได้ลอง regex ที่สองเหมือนกันในบางจุด แต่ฉันผนวกรูปแบบที่น้อยที่สุดสองครั้งแทนที่จะเป็นค่าสูงสุด (และดังนั้นจึงล้มเหลวที่น่าสังเวช) ปัญหาเล็กน้อยหนึ่งประการ: regex แรกจะรายงานababรูปแบบของ ast ababaababa; ^…$คุณจำเป็นต้องใช้
Dennis

/^…\n/ทำงานหรือ/^…$/m
MT0

1
มันอาจไม่จำเป็นต้องมีผู้นำ^(อย่างน้อยก็ไม่ได้สำหรับกรณีทดสอบ 6 ข้อใด ๆ ที่ฉันได้ระบุไว้ - แต่อาจมีตัวอย่างที่เคาน์เตอร์ที่เป็นเช่นนั้น
MT0
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.