Впорядкування рядків, що перекриваються


17

(Натхненний, малюючи на сухій дошці стирання)

Виклик:

Давши рядок введення, що містить символи, які представляють різні кольори маркерів сухого стирання на білій дошці, виведіть порядок, у якому вони були намальовані, від першого до останнього.

Вхід:

Рядок, що містить кольори маркерів із сухим стиранням, представлені алфавітними літерами (верхні букви відрізняються від малих літер; ви можете замінити будь-які символи, які використовуються в моїх прикладах, якщо кожен колір має окрему літеру). Інша частина дошки буде пробілом. Буде лише один рядок кожного кольору на дошці. Не буде входів, де всі рядки перетинаються один з одним (див. Тестовий випадок 4). Усі лінії будуть прямими, або горизонтальними, або вертикальними.

Вихід:

Порядок, в якому на дошці були намальовані лінії, від першої, намальованої до останньої. Якщо для будь-якого вводу є кілька рішень, ви можете вивести будь-яке з них. Вихід може бути відформатований у будь-якому випадку, який ви хочете: один рядок символів або розділений пробілами, новими рядками тощо, до тих пір, поки використовувані символи відповідають тим, які використовуються у вашому введенні.

Випробування:

Введення 1:

  R
  R
BBRBB
  R

Вихід 1:

BR

Введення 2:

    GY
    GY
RRRRGYRRR
    GY
    GY
BBBBBBBB
    GY
    GY

Вихід 2:

RGYB // or RYGB

Введення 3:

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

Вихід 3:

AGPR // or APGR

Введення 4:

 O Y
RRRYR
 O Y
GOGGG
 O Y

Вихід 4:

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

Введення 5:

YYYB
   B
   B

Вихід 5:

// YB or BY

Правила:

Це , тому найкоротший код у байтах виграє.


@StewieGriffin Тут може бути стільки, скільки друкованих символів ASCII (33-127). Я використовував звичайні кольори у своїх тестових випадках, але оскільки вони є символами, вони насправді не відповідають дійсним кольорам (Червоний, Зелений, Жовтий тощо), вони просто представляють унікальні кольори (R - це інший колір від G та Y) .
Йодл

1
Так, добре, я скажу лише алфавітні символи (65-90 та 97-122).
Йодл

Всі лінії будуть горизонтальними чи вертикальними, правда? Вам, мабуть, слід вказати це у питанні.

@ ais523 Так, відредагував це.
Yodle

Чи можемо ми припустити, що на вході вкладено пробіли до прямокутника?
PurkkaKoodari

Відповіді:


5

Perl, 103 + 2 = 105 байт

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

Виконати з -n0(2 байт штрафу).

Пояснення:

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

Тут є одна незначна тонкоща з таким вкладом:

   ABC
DDDDDDDDD
   ABC
   ABC
   ABC

Подивіться тут четвертий рядок. Якби порядок написання був BACBD, там справді може бути горизонтальна лінія Bs, не порушуючи жодного з припущень проблеми (крім того, що є лише один рядок кожного кольору, те, що ми не перевіряємо). Для того, щоб обійти це, ми гарантуємо, що в останньому зворотному виразі кожен рядок починається з літери (або цифри або підкреслення, але це неможливо), і спираємось на те, що паралельні рядки знайдуться зліва направо і вгорі -донизу (тому що регулярний вираз знайде першу відповідність у рядку). Таким чином, перший символ кожного неоднозначного рядка тут перезаписується перед тим, як сам рядок розглядається як збіг, і це перешкоджає збігу регулярних виразів.


Дуже вражаюче ... Молодці! (Я був у 161 байті, з 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'(що вимагає, щоб лінії вводу були забиті правою стороною, щоб пробіли були однакової довжини))
Dada

2

Python 2, 199 байт

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)

Це закінчилося набагато довше, ніж я спочатку думав, що це станеться. Крім того, rindexя міг бачити це як дуже гарну програму для перекладу на Pyth.

Візьме в список рядків і виводить список символів. Код генерує перестановки рекурсивно, переконуючись, що жодна із намальованих ліній не повинна бути намальована вгорі поточного рядка.

Код зловживає безліччю можливостей Python, наприклад, переймаючись wна потужність булевого випробування, перевіряючи порожні набори шляхом перевірки підмножини {0}(оскільки мої набори ніколи не містять рядків), і мій улюблений, відрізняючи будь-який список від Noneперевірки, чи є його представництво більше, ніж Z.

Пояснений код

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.