Trova il personaggio strano in uno schema


20

Ingresso

La prima riga sarà una determinata stringa ripetuta per un numero di volte. Ad esempio, potrebbe essere abcabcabcabc, [];[];[];ecc Può essere tagliato; per esempio: 1231231231. Trova sempre la stringa più corta; per esempio, se la linea è 22222, allora la stringa è 2, non è 22o 22222o qualsiasi altra cosa. La stringa verrà sempre ripetuta almeno 2 volte complete.

Tutte le righe successive saranno quel modello sfalsato di qualsiasi numero. Ad esempio, potrebbe essere:

abcabcabc
cabcabcab
bcabcabca

(offset di 1), oppure potrebbe essere:

abcdefabcdefabcdefabc
cdefabcdefabcdefabcde
efabcdefabcdefabcdefa

(offset di 4).

Uno dei caratteri nell'input sarà errato. (È garantito che non si trova sulla prima riga.) Ad esempio, in questo input:

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

la 1riga 3 è quella dispari.

Produzione

È necessario emettere le coordinate (in base zero, iniziando dalla parte superiore sinistra) di quella dispari. Ad esempio, nell'input sopra, l'output corrispondente è 4,2. Puoi anche produrre 4 2, o "4""2", o anche [[4],[2]], o qualsiasi altro formato, purché tu possa dire quale dovrebbe essere l'output.

Casi test

Ingresso:

codegolfcodegolfco
egolfcodegolfcodeg
lfcodegolfcodegoff
odegolfcodegolfcod
golfcodegolfcodego
fcodegolfcodegolfc

Produzione: 16,2

Ingresso:

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

Produzione: 8,3

Ingresso:

...
. .
...

Produzione: 1,1

Ingresso:

ababa
babab
ababb
babab

Produzione: 4,2

Partire!


Quali caratteri possono essere contenuti nella stringa? ASCII stampabile? ASCII? Unicode?
Dennis,

@Dennis Semplicemente ASCII stampabile (che in pratica può essere assunto per qualsiasi sfida riguardante le stringhe; altrimenti dovremmo specificare che per quasi ogni sfida: P)
Maniglia

L'ho indovinato. Sto pensando a un approccio che richiederebbe un carattere inutilizzato, quindi ho pensato di chiedere.
Dennis,

Dovremmo controllare il caso in questo modo: abc/cab/abc- ed emettere 0 2qui?
user2846289

@VadimR No, poiché solo un personaggio sarà sbagliato.
Maniglia della porta

Risposte:


7

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

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

Lo script richiede l'utilizzo -ndell'opzione, che rappresenta due byte.

L'idea di aggiungere due copie di tutte le ripetizioni complete del modello è stata presa dalla risposta di MT0 .

Contrariamente a tutte le altre risposte, questo approccio tenta di estrarre lo schema della linea di input corrente in ogni iterazione; avrà esito negativo sulla riga contenente il carattere dispari (e utilizzerà invece il modello della riga precedente). Questo viene fatto per includere l'estrazione del pattern nel loop, che riesce a salvare alcuni byte.

Versione Ungolfed

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

Esempio

Per il caso di test

codegolfcodegolfco
egolfcodegolfcodeg
lfcodegolfcodegoff
odegolfcodegolfcod
golfcodegolfcodego
fcodegolfcodegolfc

l'output della versione golfed è

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

nel senso che il carattere dispari ha le coordinate 16,2.

Questo palese abuso sfrutta il formato liberale di output.

Poco prima di uscire, i contenuti di alcune delle variabili speciali di Perl sono:

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

( $ncontiene la corrispondenza del sottotatro accessibile tramite il backreference \n.)


Cattura intelligente dell'unità di risposta. Può essere ottimizzato di un byte:^((.*?)(.*?))(?=\1+\2$)
Heiko Oberdiek

Sono passato alla lingua che usano i bambini popolari. Probabilmente si può giocare a golf ulteriormente; questa è la mia prima sceneggiatura in Perl in oltre un decennio ...
Dennis

2
... e sei in ritardo di oltre un decennio se pensi che il perl sia quello che usano i bambini popolari
ardnew,

questa risposta non sta ottenendo l'amore che merita. mi sembra il vincitore @Doorknob
ardnew

8

Perl, 212 191 181 168 byte

$_=<>;/^(((.*?)(.*?))\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,$/}}}
  • Questa versione utilizza un trucco ottimizzato per catturare l'unità di risposta, appreso nella risposta di Dennis .
  • Ottimizzazione utilizzando la proprietà che tutte le linee hanno uguale lunghezza.
  • La fine della linea è necessaria anche per l'ultima riga, altrimenti chompinvece chopdovrebbe essere utilizzata.
  • Aggiunte ottimizzazioni del commento di ardnew .

Vecchia versione, 212 byte:

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

Versione non golfata:

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

Ottima soluzione e commenti, ho bisogno di saperne di più regex;)
Newbrict

1
il primo chopnon è necessario, dovrebbe essere rimosso. il finale exit printpuò essere sostituito con die(aggiungi ,$/per nascondere le cose extra (se richiesto)). length$_può anche essere sostituito cony///c
ardnew il

@ardnew: Mille grazie, ho rimosso la prima chop, perché $corrisponde prima della nuova riga alla fine della stringa. dieMi sembra necessario nascondere le cose extra di tramite la nuova riga aggiunta. Inoltre y///cè molto più breve di length$_e un byte più corto che lengthsenza inutili $_.
Heiko Oberdiek,

1
@ardnew: mi ero dimenticato della verbosità di die . Include anche la stampa del numero di riga! Lo userò nel mio prossimo aggiornamento.
Dennis,

3

C, 187 byte

Limitazioni.

  • Non utilizzare stringhe di input più lunghe di 98 caratteri :)

Versione golfizzata

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

Versione Ungolfed

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

L'input passa attraverso lo stdin. Lo spiegherò se c'è qualche richiesta, ma non sembra che vincerò comunque.


1

Perl, 157 154

Modifica : -3 grazie al suggerimento di 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}

Mi ci è voluto un po 'di tempo (acceso e spento, ovviamente, non 5 giorni ;-)) e l'idea dell'algoritmo era inizialmente sfuggente (anche se sentivo che era lì), ma alla fine (e improvvisamente) è diventato tutto chiaro.

Se la lunghezza della stringa è multipla della lunghezza del motivo e anche se la stringa non inizia con l'inizio del motivo, la concatenazione della stringa con se stessa produrrà il motivo al posto della concatenazione (immagina la ripetizione infinita di una parola sul nastro circolare - il luogo di la saldatura non è importante). Quindi, l'idea è di tagliare la linea a più unità di lunghezza e concatenare l'originale ad essa. Il risultato, anche per la stringa che contiene il carattere sbagliato, è garantito per abbinare al modello almeno una volta. Da lì in poi è facile trovare la posizione del personaggio offensivo.

La prima linea è spudoratamente presa in prestito dalla risposta di 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
bel lavoro. penso che puoi sostituire /.{$n}/;$_=$&.$_;cons/.{$n}/$&$&/;
ardnew il

1

JavaScript (ES6) - 147 133 136 caratteri

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

Si aspetta che la stringa da testare sia nella variabile se trasmette il risultato alla console.

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

Caso di prova 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))

Uscite

16 2

Caso di prova 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))

Uscite

8 3

Caso di prova 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))

Uscite

1 1

Caso di prova 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))

Uscite

4 2

Caso di prova 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))

Uscite

0 1

Caso di prova 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))

Uscite

6 1

Purtroppo, questo approccio fallisce se, ad es s="xyxy\nyyxy". Per la seconda riga, match[4]sarà yy; dovrebbe essere giusto y.
Dennis,

Rielaborato e abbreviato di 14 caratteri.
MT0,

Molto bella! Avevo provato la stessa seconda regex ad un certo punto, ma ho aggiunto il modello minimo due volte invece di quello massimo (e, quindi, fallito miseramente). Un problema minore: il primo regex riporterà abablo schema di ababaababa; devi usare ^…$.
Dennis,

/^…\n/funziona o/^…$/m
MT0

1
Potrebbe non aver bisogno del lead ^(almeno non per nessuno dei 6 casi di test che ho elencato - ma probabilmente c'è un contro esempio in cui lo fa, quindi l'ho lasciato).
MT0,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.