Bir desendeki tek karakteri bulma


20

Giriş

İlk satır, herhangi bir miktarda tekrarlanan belirli bir dize olacaktır. Örneğin, olabilir abcabcabcabc, [];[];[];vb Bu kesilmiş olabilir; örneğin: 1231231231. Her zaman en kısa dizeyi bulun; örneğin, çizgi ise 22222, o zaman dize 2değil, 22ya 22222veya başka bir şey. Dize her zaman en az 2 tam kez tekrarlanır.

Sonraki tüm satırlar, herhangi bir sayı ile bu desen kayması olacaktır. Örneğin, şunlar olabilir:

abcabcabc
cabcabcab
bcabcabca

(1 ile ofset) veya şunlar olabilir:

abcdefabcdefabcdefabc
cdefabcdefabcdefabcde
efabcdefabcdefabcdefa

(4 ile ofset).

Girişteki karakterlerden biri yanlış olacaktır. (İlk satırda olmaması garanti edilir.) Örneğin, bu girişte:

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

13. hatta tek bir çıktı.

Çıktı

Tekin çıkışının (sol üst köşeden başlayarak) koordinatlarını çıkarmalısınız. Örneğin, yukarıdaki girişte karşılık gelen çıkış 4,2. Ayrıca, çıktının ne olması gerektiğini söyleyebildiğiniz sürece çıktı alabilir 4 2, "4""2"hatta [[4],[2]], hatta başka bir biçim de verebilirsiniz.

Test senaryoları

Giriş:

codegolfcodegolfco
egolfcodegolfcodeg
lfcodegolfcodegoff
odegolfcodegolfcod
golfcodegolfcodego
fcodegolfcodegolfc

Çıktı: 16,2

Giriş:

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

Çıktı: 8,3

Giriş:

...
. .
...

Çıktı: 1,1

Giriş:

ababa
babab
ababb
babab

Çıktı: 4,2

Git!


Dizede hangi karakterler bulunabilir? Yazdırılabilir ASCII? ASCII? Unicode?
Dennis

@Dennis Sadece yazdırılabilir ASCII (temelde dizeleri içeren herhangi bir zorluk için kabul edilebilir; aksi takdirde hemen hemen her zorluk için bunu belirtmeliyiz: P)
Kapı tokmağı

Öyle tahmin ettim. Kullanılmayan bir karakter gerektirecek bir yaklaşım düşünüyorum, bu yüzden sormam gerektiğini düşündüm.
Dennis

Durumu şöyle kontrol etmeliyiz: abc/cab/abc- ve çıktı 0 2burada mı?
user2846289 21:14

@VadimR Hayır, çünkü sadece bir karakter yanlış olacak.
Kapı tokmağı

Yanıtlar:


7

Bash Perl, 231 229 218 178 164 166 138 106 74 bayt

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

Komut dosyası, -niki bayttan oluşan anahtarı kullanmayı gerektirir .

Desenin tüm tekrarlarının iki kopyasını ekleme fikri MT0'ın cevabından alınmıştır .

Diğer tüm cevapların aksine, bu yaklaşım her bir yinelemede mevcut giriş çizgisinin desenini çıkarmaya çalışır; tek karakteri içeren satırda başarısız olur (ve bunun yerine önceki satırın desenini kullanır). Bu, birkaç bayt kaydetmeyi başaran döngüdeki desen çıkarma işlemini dahil etmek için yapılır.

Ungolfed sürümü

#!/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.

Misal

Test senaryosu için

codegolfcodegolfco
egolfcodegolfcodeg
lfcodegolfcodegoff
odegolfcodegolfcod
golfcodegolfcodego
fcodegolfcodegolfc

Golf versiyonunun çıktısı

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

yani tek karakterin koordinatları vardır 16,2.

Bu açıkça istismar , liberal çıktı formatından yararlanır.

Çıkmadan hemen önce, Perl'in bazı özel değişkenlerinin içeriği şunlardır:

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

( $narka referans üzerinden erişilebilen alt şablonun eşleşmesini içerir \n.)


Yanıtlama biriminin akıllıca yakalanması. Bir bayt tarafından optimize edilebilir:^((.*?)(.*?))(?=\1+\2$)
Heiko Oberdiek

Popüler çocukların kullandığı dile geçtim. Muhtemelen daha da aşağı golf edilebilir; Bu on yıldan fazla bir süredir ilk Perl senaryom ...
Dennis

2
... ve
perl'in

bu cevap hak ettiği aşkı elde etmiyor. kazanan gibi görünüyor @Doorknob
ardnew

8

Perl, 212 191 181 168 bayt

$_=<>;/^(((.*?)(.*?))\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,$/}}}
  • Bu sürüm, Dennis'in cevabında öğrenilen cevap birimini yakalamak için optimize edilmiş bir numara kullanır .
  • Tüm satırların eşit uzunluklara sahip olduğu özelliği kullanarak optimizasyon.
  • Son satır için satır sonu da gereklidir, aksi halde chompyerine chopkullanılmalıdır.
  • Ardnew yorumunun optimizasyonu eklendi.

Eski sürüm, 212 bayt:

$_=<>;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}}}

Ungolfed sürümü:

$_ = <>;  # 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
        }
    }
}

Harika bir çözüm ve yorumlar, daha fazla regex öğrenmem gerekiyor;)
Newbrict

1
birincisi chopgereksizdir- çıkarılmalıdır. final exit printile değiştirilebilir die( ,$/ekstra öğeleri gizlemek için ekleyin (gerekirse)). ayrıca length$_değiştirilebiliry///c
ardnew

@ardnew: Çok teşekkürler, ilkini kaldırdım chop, çünkü $dizenin sonundaki yeni satırdan önceki eşleşmeler. dieEklenen yeni satır üzerinden fazladan şeyleri gizlemek benim için gerekli görünüyor. Ayrıca gereksiz olmayandan y///cçok daha kısa length$_ve bir bayt daha kısa . length$_
Heiko Oberdiek

1
@ardnew: Ben unutmuştu kalıp 'ın ayrıntı. Hatta satır numarasını yazdırır içerir! Bunu bir sonraki güncellememde kullanacağım.
Dennis

3

C, 187 bayt

Sınırlamalar.

  • 98 karakterden daha uzun giriş dizeleri kullanmayın :)

Golf versiyonu

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

Ungolfed sürümü

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

Girdi stdin'den geçer. Herhangi bir talep varsa açıklayacağım, ama yine de kazanacağım gibi görünmüyor.


1

Perl, 157 154

Düzenleme : -3 ardnew 'önerisi sayesinde.

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

Biraz zaman aldı (açık ve kapalı, elbette, 5 gün değil ;-)) ve algoritma hakkındaki fikir başlangıçta (orada olduğunu hissettiğim halde) zor oldu, ama sonunda (ve aniden) hepsi netleşti.

Dize uzunluğu desen uzunluğundan birden fazla ise ve dize desenin başlangıcıyla başlamasa bile, dizeyi kendisiyle birleştirmek, birleştirme yerine desen üretecektir (dairesel şeritteki bir kelimenin sonsuz tekrarını hayal edin - kaynak önemli değildir). Bu nedenle, fikir hattı birden fazla birim uzunluğa kesmek ve orijinali ona birleştirmektir. Sonuç, yanlış karakter içeren dize için bile, en az bir kez kalıpla eşleşeceği garanti edilir. Oradan rahatsız edici karakterin konumunu bulmak kolaydır.

İlk satır utanmadan Heiko Oberdiek'in cevabından ödünç alındı ​​:-)

<>=~/^(((.*?).*?)\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
iyi iş. i yerini alabilir mi /.{$n}/;$_=$&.$_;iles/.{$n}/$&$&/;
ardnew

1

JavaScript (ES6) - 147 133 136 Karakterler

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

Test edilecek dizenin değişken içinde olmasını bekler ve ssonucu konsola çıkarır.

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

Test Durumu 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))

çıktılar

16 2

Test Durumu 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))

çıktılar

8 3

Test Durumu 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))

çıktılar

1 1

Test Durumu 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))

çıktılar

4 2

Test Örneği 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))

çıktılar

0 1

Test Örneği 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))

çıktılar

6 1

Ne yazık ki, bu yaklaşım, örneğin, başarısız olursa s="xyxy\nyyxy". İkinci satır match[4]için yy; sadece olmalı y.
Dennis

14 karakterle yeniden çalıştı ve kısaldı.
MT0

Çok hoş! Bir noktada aynı ikinci normal ifadeyi denemiştim, ancak en az bir model yerine en az iki model ekledim (ve böylece, sefil başarısız oldu). Küçük bir sorun: İlk normal ifade ababast modelini rapor edecektir ababaababa; kullanmanız gerekir ^…$.
Dennis

/^…\n/çalışır veya/^…$/m
MT0

1
Lider gerektirmeyebilir ^(en azından listelediğim 6 test durumundan herhangi biri için değil - muhtemelen bıraktığı bir karşı örnek var).
MT0
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.