Ordinamento di linee sovrapposte


17

(Ispirato mentre si disegna su una lavagna a secco)

Sfida:

Data una stringa di input contenente caratteri che rappresentano diversi colori dei marker di cancellazione a secco su una lavagna bianca, emette l'ordine in cui sono stati disegnati, dal primo all'ultimo.

Ingresso:

Una stringa che contiene colori marcatori di cancellazione a secco che sono rappresentati da lettere alfabetiche (quelli superiori sono diversi da quelli minuscoli, puoi sostituire qualsiasi carattere usato nei miei esempi purché ogni colore abbia una lettera distinta). Il resto della lavagna sarà uno spazio bianco. Ci sarà solo una riga di ciascun colore per ogni scheda. Non ci saranno input in cui tutte le linee si sovrappongono (vedere il caso di test 4). Tutte le linee saranno diritte e orizzontali o verticali.

Produzione:

L'ordine in cui le linee sono state tracciate sul tabellone, dal primo disegnato all'ultimo. Se esistono più soluzioni per qualsiasi input, è possibile produrre una qualsiasi di esse. L'output può essere formattato come preferisci: stringa singola di caratteri o separata da spazi, newline, ecc. Purché i caratteri utilizzati corrispondano a quelli utilizzati nel tuo input.

Casi test:

Ingresso 1:

  R
  R
BBRBB
  R

Uscita 1:

BR

Ingresso 2:

    GY
    GY
RRRRGYRRR
    GY
    GY
BBBBBBBB
    GY
    GY

Uscita 2:

RGYB // or RYGB

Ingresso 3:

    R    P
    R    P
AAAARAAAAPA
    R    P
    R    P
GGGGRGGG P
    R

Uscita 3:

AGPR // or APGR

Ingresso 4:

 O Y
RRRYR
 O Y
GOGGG
 O Y

Uscita 4:

// Undefined, does not need to be handled by your program

Ingresso 5:

YYYB
   B
   B

Uscita 5:

// YB or BY

Regole:

Questo è , quindi vince il codice più breve in byte.


@StewieGriffin Possono esserci tanti quanti i caratteri ASCII stampabili (33-127). Ho usato colori normali nei miei casi di test, ma poiché sono personaggi non corrispondono effettivamente ai colori effettivi (rosso, verde, giallo, ecc.), Rappresentano solo colori unici (R è un colore diverso da G e Y) .
Yodle,

1
Eh sì buon punto, dirò solo caratteri alfabetici (65-90 e 97-122).
Yodle,

Tutte le linee saranno orizzontali o verticali, giusto? Probabilmente dovresti specificarlo nella domanda.

@ ais523 Sì, modificato in.
Yodle,

Possiamo supporre che l'input sia riempito con spazi in un rettangolo?
PurkkaKoodari,

Risposte:


5

Perl, 103 + 2 = 105 byte

s/$/$"x y===c/gem;$a=$_;$_.=$"while$a=~s/^./!($_.=$&)/gem;s/$1/-/g,$b="$&$b"while/\s(\w)(\1|-)+ /;say$b

Esegui con -n0(penalità di 2 byte).

Spiegazione:

# -n0: read entire input into `$_` at start of program
# (technically speaking it reads to the first NUL byte, but there aren't any)

# We want to be able to extract columns from the input, so we need to add spaces
# to the ends of each line such that each column is complete. Adding too many
# space is OK, so to ensure we have enough, we add a number of spaces equal to the
# length of the input.
s/$/             # At the end of {something},
$" x             # append a number of spaces ($" is a space by default)
y===c            # obtained by counting the characters in $_
/gem;            # where {something} is each (g) line (m)

$a = $_;         # store a copy of the transformed input in $a

# The next step is to create a transposition of the input. To do that, we
# repeatedly extract the first column of $a and append it to $_. This will lead to
# a bunch of junk whitespace at the end of $_ (of varying lengths, because once a
# line is empty it's omitted from the extracted column), but we're OK with that.
# To transpose properly, we'd want to place newlines between the extracted
# columns; however, it happens that the rest of the program treats space the same
# way it would newline, and separating via spaces is shorter, so we do that.

while (          # keep looping as long as there are matches
  $a =~ s/^./    # replace the first character of {something related to $a}
  !(             # with the null string (NOT of something truthy)
    $_.=$&)      # but append that character ($&) to $_
  /gem) {        # {something} is each (g) line (m) of $a
  $_.=$"         # append a space ($", equivalent to newline here) to $_
}

# Finally, we repeatedly replace every character in the topmost line with the -
# character (treating a line as continuous through the - character but not through
# other characters), thus finding the lines from top to bottom. Because we
# appended the transpose of $_ to $_ above, each line appears twice: once
# horizontally, once vertically. We find only the horizontal copy, but replace
# both with hyphens.
# (Note: I rewrote the regex into a bit more readable of a form in this ungolfed
# version, because the original version wouldn't allow me room to write comments
# inside it. The two should be equivalent; I tested the golfed version.)
while (          # keep looping as long as there are matches
  /\s(\w)        # match a space or newline, $1 (a letter/digit/underscore),
    (\1|-)+      # any positive number of $1s and hyphens,
    \ /x) {      # and a space
  s/$1/-/g,      # changes all $1s to spaces; set $& to $1, $1 becomes invalid
  $b = "$&$b"    # prepend $& to $b
}

# We need to output the lines from first (i.e. bottom) to last (i.e. top).
# We found them in the opposite order, but reversed them via prepending
# (not appending) the partial results to $b.
say $b           # output $b

Una leggera sottigliezza qui viene fornita con input come questo:

   ABC
DDDDDDDDD
   ABC
   ABC
   ABC

Guarda la quarta riga qui. Se l'ordine di scrittura fosse BACBD, potrebbe davvero esserci una linea orizzontale di Bs lungo lì senza violare alcuna delle ipotesi del problema (a parte il fatto che esiste solo una riga di ogni colore, qualcosa che non controlliamo). Per ovviare a questo, assicuriamo nell'ultima regex che ogni riga inizi con una lettera (o cifra o trattino basso, ma quelli sono impossibili), e facciamo affidamento sul fatto che le linee parallele saranno trovate da sinistra a destra e in alto -to-bottom (perché il regex troverà la prima corrispondenza all'interno della stringa). Pertanto, il primo carattere di ogni riga ambigua viene sovrascritto prima che la riga stessa venga vista come una corrispondenza e ciò impedisce la corrispondenza della regex.


Molto impressionante ... Ben fatto! (Ero a 161 byte, con perl -n0E '/.*/;for$i(/(\S)(?=(?:(?:.{@{+}})?(?:\1| ))*(?!.*\1))/gs){/.*/;unless(/$i+[^$i\s]+$i/||/$i(.{@{+}}[^$i ])+.{@{+}}$i/s){$r="$i$r";s/$i/ /g;last}}/\S/?redo:say$r'(che richiede che le linee di input siano riempite a destra con spazi della stessa lunghezza))
Dada,

2

Python 2, 199 byte

l=input()
w=len(l[0])
j="".join(l)
c=set(j)-{" "}
def f(s):
 for h in s:
  i=j.index(h);I=j.rindex(h);o=f(s-{h})
  if{0}>c-s&set(j[i:I:w**(i+w<=I)])and`o`>"Z":return[h]+o
 if{0}>s:return[]
print f(c)

Questo è finito molto più a lungo di quanto inizialmente pensassi. A parte questo rindexho potuto vedere questo come un ottimo programma da tradurre in Pyth.

Comprende un elenco di righe e genera un elenco di caratteri. Il codice genera permutazioni in modo ricorsivo, assicurandosi che nessuna delle linee disegnate debba essere tracciata sopra la linea corrente.

Il codice abusa di molte funzionalità di Python, ad esempio prendendo wil potere di un valore booleano, testando set vuoti controllando sottoinsiemi {0}(poiché i miei set non contengono mai non stringhe) e il mio preferito, distinguendo qualsiasi elenco Noneda controllando se il suo la rappresentazione è maggiore diZ .

Codice spiegato

lines = input()
width = len(lines[0])
joined = "".join(lines)
characters = set(joined) - {" "} # find unique characters except space in input

def solve(chars_left): # returns a solution for the given set of lines
    for try_char in chars_left: # try all lines left

        start_index = joined.index(try_char) # find start position of this line
        end_index = joined.rindex(try_char) # and end position

        step = width ** (start_index + width <= end_index) # take every width'th character if start
                                                           # and end indices differ by at least width

        used_chars = characters - chars_left # find all drawn lines

        line_chars = set(joined[start_index:end_index:step]) # find the characters inside the current line
        missed_chars = used_chars & line_chars # find all lines that are already drawn but should be on
                                               # top of this line

        solution = solve(chars_left - {try_char}) # find solutions if this line was drawn now

        if {0} > missed_chars and `solution` > "Z": # there should be no missed lines and a solution
                                                    # should exist
            return [try_char] + solution # solution found, prepend current character and return

    if {0} > chars_left: # if no lines are left
        return [] # solution found

print solve(characters) # solve for all lines
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.