重複する行順序


17

(乾式消去ボードでの描画中に触発)

チャレンジ:

ホワイトボード上の乾燥消去マーカーのさまざまな色を表す文字を含む入力文字列が与えられた場合、最初から最後までそれらが描画された順序を出力します。

入力:

アルファベットで表されるドライ消去マーカーの色を含む文字列(上の文字は小文字とは異なります。各色に異なる文字が含まれている限り、私の例で使用されている文字に置き換えることができます)。ホワイトボードの残りの部分は空白になります。ボードごとに各色が1行だけ存在します。すべての行が互いに重なる入力はありません(テストケースを参照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

ここでの微妙な点の1つは、次のような入力です。

   ABC
DDDDDDDDD
   ABC
   ABC
   ABC

ここの4行目を見てください。書き込みの順序がBACBDである場合、問題の仮定に違反することなく、そこに沿ってsの水平線が本当に存在する可能B性があります(それ以外は、各色の1行のみであり、チェックしないものです)。これを回避するために、最後の正規表現では、各行文字(または数字またはアンダースコア、ただしそれらは不可能)で始まることを確認し、平行線が左から右および上にあるという事実に依存します-to-bottom(正規表現が文字列内で最初に一致するものを見つけるため)。このように、各曖昧な行の最初の文字は、行自体が一致と見なされる前に上書きされるため、正規表現の一致が妨げられます。


非常に印象的...よくやった!(私は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'(入力行はすべて同じ長さのスペースで右詰めする必要があります))
ダダ

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)

これは、当初考えていたよりもずっと長くなりました。それとは別に、これはrindexPythに翻訳するための非常に良いプログラムとして見ることができました。

行のリストを取り込んで、文字のリストを出力します。コードは順列を再帰的に生成し、描画された線が現在の線の上に描画されないようにします。

コードは多くの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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.