Spraw, by pocałunki elastycznych węży

57

Elastyczny wąż wygląda mniej więcej tak:

<||=|||:)~

Każdą oddzielną sekwencję pionowych pasków ( |) w rozciągliwym wężu, znanym jako odcinek rozciągliwy , można indywidualnie rozciągać do dwukrotnej szerokości i rysować naprzemiennymi ukośnikami ( /, \) po rozciągnięciu.

Konkretny wąż powyżej ma dwie takie rozciągliwe części, co daje mu cztery możliwe pozy:

<||=|||:)~

</\/\=|||:)~

<||=/\/\/\:)~

</\/\=/\/\/\:)~

Ogólna forma rozciągliwego węża w jego najmniej rozciągniętej pozycji jest zdefiniowana przez ten regex :

<(\|+=)*\|+:\)~

Które można wyrazić słowami:

<, Po czym przez dowolną liczbę sekwencji |„S połączone z =oznaczeń, a następnie :)~.

Więc <|:)~i <||:)~i <|=|:)~i <|=|=||=|||||=||:)~są rozciągliwe węże, ale <=:)~i <=|:)~i <||=:)~i <|==||:)~nie są.

Elastyczne węże mogą również być skierowane w lewo zamiast w prawo, np ~(:|||=||>. Formy są takie same, tylko odzwierciedlone.

Wyzwanie

Napisz program, który pobiera jeden ciąg linii dwóch rozciągliwych węży skierowanych do siebie, z pewną liczbą odstępów pomiędzy nimi. Oba węże będą w najmniej rozciągniętej pozycji (wszystkie pionowe kreski, bez ukośników). Sznurek zacznie się od ogona węża zwróconego w prawo, a skończy się ogonem węża skierowanego w lewo (możesz opcjonalnie założyć, że jest też nowa linia).

Na przykład, oto możliwe dane wejściowe z pięcioma spacjami między wężami:

<|=||:)~.....~(:||||>

.Dla jasności używam kropek ( ) zamiast rzeczywistych znaków spacji.

Zero spacji między wężami jest również prawidłowym wejściem:

<|=||:)~~(:||||>

Mówimy, że węże całują się, gdy ich języki dotykają się w ten sposób.

Twój program musi rozszerzyć kombinację rozciągliwych części obu węży, tak aby węże miały możliwie najmniejszą liczbę odstępów między nimi (bez nakładania się), tj. Tak, aby węże były tak blisko pocałunku, jak to możliwe .

Oba ogony węży są nieruchome, ale ich głowy i ciała mogą się poruszać - w prawo w przypadku węża skierowanego w prawo, w lewo węża w lewo - w zależności od tego, jakie rozciągnięte części zostały rozciągnięte.

Dane wyjściowe twojego programu to ciąg pojedynczej linii (plus opcjonalny znak nowej linii), który pokazuje węże tak blisko pocałunku, jak to możliwe, z naprzemiennymi ukośnikami rysowanymi zamiast pionowych pasków dla rozciągniętych części, które zostały rozciągnięte.


Na przykład dane wyjściowe dla <|=||:)~.....~(:||||>(z góry) to:

</\=||:)~~(:/\/\/\/\>

Jest to jedyne rozwiązanie tutaj, ponieważ przy każdej innej kombinacji rozciągniętych odcinków węże zachodzą na siebie lub są bardziej oddalone od całowania.


Jeśli możliwych jest wiele rozwiązań, wyjściem może być dowolne z nich.

Na przykład, jeśli dane wejściowe to

<|=||:)~.....~(:|||=|>

wyjście może być

<|=/\/\:)~~(:/\/\/\=|>

lub

</\=||:)~~(:/\/\/\=/\>

Pamiętaj, że nie zawsze będzie możliwe pocałowanie węży, ale nadal musisz zbliżyć je jak najbliżej.

Na przykład, jeśli dane wejściowe to

<||=||||:)~...~(:||>

wyjście może być

</\/\=||||:)~.~(:||>

lub

<||=||||:)~.~(:/\/\>

Jeśli węże już się całują, wyjście będzie takie samo jak wejście. na przykład

<|=||:)~~(:||||>

Ogólnie rzecz biorąc, wyjście będzie takie samo jak wejście, jeśli przedłużenie dowolnej rozciągliwej części sprawi, że węże będą się nakładać. na przykład

<|||=|||:)~..~(:||||=|||||=||||||>

Notatki

  • Pobiera dane wejściowe ze standardowego wejścia lub wiersza poleceń jak zwykle lub zapisuje funkcję, która pobiera ciąg znaków. Wydrukuj lub zwróć wydruk.
  • Możesz użyć kropek ( .) na wejściu i wyjściu zamiast spacji ( ), jeśli wolisz.
  • Ważne jest tylko, aby nacięcia były zmieniane naprzemiennie w sekwencji pionowych pasków, które zastąpiły. Ich kolejność w ogóle w wężu lub to, czy najpierw chodzi o cięcie do przodu, czy do tyłu, nie ma znaczenia.
  • Rozciągliwe części nie mogą się częściowo rozciągać - są dokładnie podwójne lub w ogóle się nie rozciągają.

Punktacja

To jest golf golfowy . Najkrótsze przesłanie w bajtach wygrywa. Tiebreaker to wcześniejsza odpowiedź.

Hobby Calvina
źródło
17
Snex Education 101 - Jak prawidłowo pocałować
Optymalizator
45
„Mówimy, że węże całują się, gdy ich języki dotykają się w ten sposób”. Co czytam ...
Fatalize
8
Więc węże robią tylko francuski?
Optymalizator
3
@PeterTaylor Cóż, „dublowany”, a nie „odwrócony” (inaczej >nie stałby się <albo taki sam dla (i )), ale także powiedział: „Ważne jest tylko, aby przecinać naprzemiennie w sekwencji pionowych pasków, które zastąpiły. wąż na wolności lub to, czy najpierw nastąpi cięcie do przodu, czy do tyłu, nie ma znaczenia. ”
Martin Ender
7
@qwr Imagination.
Calvin's Hobbies

Odpowiedzi:

9

CJam, 87 71 70 68 bajtów

l:L"|"f&Qa%_,Y\m*\f{.{_,"/\\"*?}L'|%.\s" /"1$fe=:-\a+}${0a>}=~S%\S**

Wypróbuj online w interpretatorze CJam .

Jak to działa

l:L        e# Read a line from STDIN and save it in L.
"|"f&      e# Intersect each character with the string "|".
           e# This pushes either "|" or "".
Qa%        e# Split the resulting array at runs of "".
_,         e# Compute the length of the resulting array (A).
           e# This yield K, the number of stretchy parts.
Y\m*       e# Push the array of all vectores in {0,1}^K.
\f{        e# For each vector V in {0,1}^K, push V and A; then:
  .{       e#   For each C in V and the corresponding P in A:
    _,     e#     Compute the length of the stretchy part P.
    "/\\"* e#     Repeat "/\" that many times.
    ?      e#     If C, select P; else, select "/\"*length(P).
  }        e#   This modifies A.
  L'|%     e#   Split L at runs of vertical lines.
  .\s      e#   Interleave the chunks of L and the modified A. Sringify.
           e#   In each iteration, this constructs a different modification of L,
           e#   with some stretched out stretchy parts.
  " /"1$   e#   Push " /" and a copy of the modified L.
  fe=      e#   Calculate the number of spaces and slashes in the modifed L.
  :-       e#   Subtract the number of occurrences.
  \a+      e#   Construct the array [difference modified-L].
}          e#
$          e# Sort the array (by final number of spaces).
{0a>}=     e# Find the first element greater than [0].
           e# This skips over too far stretched snakes, where the number of
           e# slashes is less than the number of spaces.
~          e# Dump the difference (D) and modified L on the stack.
S%         e# Split L at runs of spaces.
\S*        e# Construct a string of D spaces.
*          e# Join the split L, delimiting by D spaces.
Dennis
źródło
19

Retina , 209 107 99 97 92 bajtów

.(?=(.+)(?<=(?=<((\|+|(?<-5>\|(?=\1())?)+)[^|]+)+$(?(5)!)).+( )+\S+))\4
/ \
+` (.*~|~.*) 
$1

Dla celów zliczania każda linia przechodzi w osobny plik, ale możesz uruchomić kod z jednego pliku z -sflagą.

Połączenie najlepszych cech wyrażeń regularnych .NET i Retina: równoważenie grup, szukanie dowolnych długości i wielokrotne zastępowanie wyrażeń regularnych.

Zasadniczo długi regex koduje prawidłowe rozwiązanie, a moduł cofania silnika regex znajduje dla mnie jedno z optymalnych.

Wyjaśnienie

Najpierw zastanówmy się, w jaki sposób możemy znaleźć poprawne rozwiązanie (niekoniecznie generujące poprawny wynik) za pomocą wyrażenia regularnego. Możemy użyć grup równoważących .NET, aby pomóc nam policzyć elastyczne części. Rozważ następujące prostsze wyrażenie regularne:

\S+( )+.+(?<=(?(1)!)^([^|]+(\|+|(?<-1>\|)*))+>)

Możemy to wyłączyć.

\S+( )+.+

To dopasowuje cały ciąg, wypychając jedno przechwytywanie na 1stos grupy dla każdego miejsca na wejściu. Wykorzystamy ten stos, aby upewnić się, że rozciągliwe części dokładnie wypełniają przestrzeń przechwyconą w te grupy.

Dalej jest spojrzenie. Chodzi o to, że w Lookout .hindhinds są dopasowywane od prawej do lewej strony (tak należy je czytać). Daje nam to możliwość powtórnego przejścia przez łańcuch, aby dowiedzieć się, czy istnieje podzbiór rozciągliwej części, która sumuje się z liczbą dopasowanych spacji. Przeglądając wygląd od prawej do lewej:

>

To tylko upewnienie się, że zaczynamy od końca sznurka (ogona węża).

(
  [^|]+
  (
    \|+
  |
    (?<-1>\|)+
  )
)+

Dla każdej rozciągliwej części, to albo dopasowuje całą część bez robienia czegokolwiek ( \|+), albo dopasowuje całą część podczas wyskakiwania przechwytuje stos 1( (?<-1>\|)*). Taka zmiana zapewnia, że ​​możemy w pełni rozciągnąć tylko rozciągliwą część lub pozostawić ją niezmienioną, i nie dostać takich rzeczy |/\|. Następnie przechodzimy do następnej elastycznej części za pomocą [^|]+.

(?(1)!)^

Na koniec upewniamy się, że przemierzyliśmy cały łańcuch (oba węże), a ten stos 1jest całkowicie pusty. To znaczy, że znaleźliśmy podzbiór rozciągliwej części, która dokładnie sumuje się do liczby miejsc, które zrobiliśmy wcześniej.

Cofacz będzie przechodził do przodu i do tyłu przez łańcuch, wypróbowując wszystkie kombinacje niezmienionych i rozszerzonych części, aż problem sumy podzbiorów zostanie rozwiązany. Jeśli taki podzbiór nie istnieje, szukanie nie powiedzie się. Spowoduje to, że cofający się wróci do \S+( )+.+części i spróbuje przechwycić o jedno miejsce mniej ( )+(co będzie tylko osłoną .+). Ze względu na chciwość +staramy się zatem wypełnić jak najwięcej miejsc.

Możesz sprawdzić ważność tego podejścia za pomocą tej nieznacznie zmodyfikowanej substytucji:

\S+(( )+).+(?<=(?(2)!)^([^|]+(\|+|(?<-2>\|)*))+>)
=$1=

Który da ci ciąg =spaces=z dokładnie taką liczbą spacji, jaką można wypełnić danymi wężami.

Musiałem dodać trochę więcej sztuczek, aby faktycznie rozszerzyć poprawne |s. Zasadniczo chcę zastąpić wszystkie, |które zostały dopasowane za pomocą (?<-1>\|)+gałęzi. Chodzi o to, aby dopasować indywidualną postać, umieścić solver w otoczeniu i ustawić flagę, jeśli zdarzy się dopasowanie wewnątrz tej gałęzi. Jeśli ta flaga nie została ustawiona, unieważniamy dopasowanie na końcu, aby uniknąć zamiany innych znaków.

Aby to zrobić, korzystamy z wielu zagnieżdżonych opisów. Ponownie, zmienne długości lookbeindów .NET są dopasowywane od prawej do lewej, więc jeśli zagnieżdżymy lookaheads i lookbehinds, możemy pozwolić silnikowi wyrażeń regularnych przemierzać ciąg kilka razy. Z powodów golfowych solver jest odwrócony w moim rzeczywistym rozwiązaniu (zaczynając od końca, zbierając spacje od prawej do lewej, a następnie rozwiązując sumę podzbioru od lewej do prawej), ale w przeciwnym razie struktura solvera jest dokładnie taka sama . Przeanalizujmy pełne wyrażenie regularne:

.(?=(.+)...)

Dopasowujemy pojedynczy znak, a następnie przechwytujemy pozostałą część ciągu i przesuwamy kursor na koniec ciągu. Użyjemy tej grupy 1później, aby sprawdzić w solverie, czy jesteśmy na pozycji meczu.

(?<=....+( )+\S+)

To jest jak pierwsza część prostego solwera powyżej, z tym wyjątkiem, że zbieramy spacje od prawej do lewej. Cofanie liczby spacji działa dokładnie tak samo jak poprzednio, tyle że teraz używamy grupy 5.

(?=<((\|+|(?<-5>\|(?=\1())?)+)[^|]+)+$(?(5)!))

To jest tak samo jak poprzednio, z tym wyjątkiem, że przechodzimy od lewej do prawej i za każdym razem, gdy dopasowujemy |aw rozwijającej się gałęzi, sprawdzamy, czy jest to ta dopasowana z

(?=\1())?

To jest opcjonalny lookahead. Próbuje 1ponownie dopasować grupę (co tutaj jest możliwe tylko wtedy, gdy jesteśmy tuż po dopasowaniu znaku), a jeśli to zrobimy, przechwytujemy pusty ciąg do grupy 4, co wskazuje, że znaleźliśmy bieżący znak w jednym rozwiniętych bitów. Jeśli \1nie pasuje, 4nie przechwyci niczego, a to ?gwarantuje, że nieudany lookahead w ogóle nie wpłynie na solver.

Wreszcie, po zakończeniu całego rozwiązywania, sprawdzamy tylko, \4czy zastosowano ten lookahead. Jeśli tak, chcemy zastąpić obecną postać /\.

Pozostaje jedna trudność: usunięcie odpowiedniej ilości spacji. Najkrótszym sposobem na to, jaki do tej pory znalazłem, jest wstawienie spacji wraz z, /\a następnie pozbycie się jednego miejsca między językami dla każdego z tych pól znaczników w osobnym kroku:

+` (.*~|~.*) 
$1
Martin Ender
źródło
6

Rubin 191 187 186 170 162

->t{s=r=t.size
i=m=t[o=/ +/].size
(0...2**t.scan(y=/\|+/).size).map{|n|q=-1
x=t.gsub(y){|r|n[q+=1]<1?r:'\/'*r.size}
d=i+s-x.size
d<0||d<m&&r=x.gsub(o,' '*m=d)}
r}

Jest to funkcja, która pobiera ciąg jako parametr i zwraca ciąg.

Testy online: http://ideone.com/uhdfXt

Oto czytelna wersja:

# enumerates the possible states for any string containing snakes
COMBINATIONS =-> snake {
  expandable_fragments = snake.scan /(\|+)/

  (0...2**(expandable_fragments.size)).map{ |i|
    x=-1
    snake.gsub(/\|+/){|r| i[x+=1]>0 ? '\/'*r.size : r}
  }
}

# finds the configuration in which snakes are closest to each other
KISS=
-> input {
  result = input
  s = input.size
  initial_distance = min_distance = input[/ +/].size

  COMBINATIONS[input].map{|c|
    distance = initial_distance + s - c.size
    if distance > -1 && distance < min_distance
      min_distance = distance
      result = c.gsub(/ +/,' '*distance)
    end
  }

  result
}

W wersji golfowej główna funkcja jest odpowiednikiem KISSpowyższej funkcji, a COMBINATIONSfunkcja została wstawiona.

Cristian Lupascu
źródło
Nie udaje się na wejściu <|=||:)~~(:||||>, którego specyfikacja jest poprawnym wejściem.
Wartość tuszu
6

Python, 205 bajtów

from itertools import*
f=lambda s:min([c.replace(".","",c.count("X"))for c in map("".join,product(*map({"|":"|X"}.get,s,s)))if{c.count("X")>c.count("."),"|X"in c,"X|"in c}=={0}],key=len).replace("X","/\\")

Posiadanie pojedynczej lambdy wygląda schludnie, ale jestem prawie pewien, że nie jest to najlepsza droga. Ale publikuję to, ponieważ wszystko, co do tej pory mam, wygląda na całkiem przyzwoite.

Jest to proste brute force na wszystkich możliwych wymian |z /\, filtrowanie nieprawidłowe konfiguracje. Jedynym schludny nieco Chyba jest to, że w rzeczywistości nie zastąpi każdy |z /\bezpośrednio - najpierw wymienić |z Xi upuść .od połowy do każdej wymianie, podejmują minimalna długość łańcucha w stosunku do wszystkich ważnych ciągów, a następnie zastąpić Xsz /\.

Próbowałem kilku innych podejść, w tym rekurencyjnych, ale okazały się dość nieuporządkowane. Dowiedziałem się również, że re.splitobecnie nie dzieli się na puste ciągi, co było niefortunne, ponieważ jeden z moich pomysłów dotyczył podziału na \bgranicy słów.

Sp3000
źródło
5

Mathematica, 381 bajtów

StringReplace[MapAt[StringReplace[#,"|"->"/\\"]&,StringSplit[#<>"="<>#2,"="],#3]~StringRiffle~"=",")="->")~"<>If[#4>0,"."~StringRepeat~#4,""]<>"~"]&[#1,#3,Sequence@@Function[{l,s},{#,#2-Total@Extract[l,#]}&[Flatten[l~Position~#~Take~#2&@@@Tally@#&@@Select[Subsets@l,Total@#<=s&]~MaximalBy~Total,1],s]][StringLength/@StringCases[#1<>#3,"|"..],StringLength@#2]]&@@#~StringSplit~"~"&

Czysta funkcja przyjmująca ciąg za argument. Oczekuje .raczej niż węży.

Nie sądziłem, że będzie tak źle ... Oto, co miałem, zanim zmiażdżyłem to i naprawiłem wszystko.

f[lhs_, rhs_, 
  spaces_] := {StringLength /@ StringCases[lhs <> rhs, "|" ..], 
  StringLength@spaces}

g[barLens_, 
   spaceLen_] := {#, #2 - Total@Extract[barLens, #]} & @@ {Flatten[
     Take[Position[barLens, #], #2] & @@@ 
      Tally[First[
        MaximalBy[Select[Subsets[barLens], Total@# <= spaceLen &], 
         Total]]], 1], spaceLen};

h[lhs_, rhs_, partspec_, newSpaceLen_] := 
 StringReplace[
  StringRiffle[
   MapAt[StringReplace[#, "|" -> "/\\"] &, 
    StringSplit[lhs <> "=" <> rhs, "="], partspec], "="], 
  ")=" -> ")~" <> 
    If[newSpaceLen > 0, StringRepeat[".", newSpaceLen], ""] <> "~"]

 h[#1, #3, Sequence @@ g @@ f[#1, #3, #2]] & @@ 
     StringSplit[#, "~"] &

Oto przykładowy przegląd z objaśnieniem:

Input: "<|=||:)~.....~(:||||>"
@Call StringSplit[#, "~"] &, yielding  {"<|=||:)", ".....", "(:||||>"}
@@Apply h[#1, #3, Sequence @@ g @@ f[#1, #3, #2]] &, but first
Set arguments: h["<|=||:)", "(:||||>", Sequence @@ g @@ f["<|=||:)", "(:||||>", "....."]]
@Call f, yielding {{1, 2, 4}, 5} = {# of bars in each segment, # of spaces}
@@Apply g, let's trace from the interior:
Subsets[barLens] = all subsets of {1, 2, 4}
Select those subsets whose sum is less than # of spaces {{},{1},{2},{4},{1,2},{1,4}}
MaximalBy Total, yielding a list of all subsets whose sum is maximal {{1, 4}}
First of these subsets, can be any of them {1, 4}
Tally the subset, yielding frequencies of each {{1, 1}, {4, 1}}
@@@Apply Take[Position[barLens, #], #2] & at the first level, yielding
    {Take[Position[{1, 2, 4}, 1], 1], Take[Position[{1, 2, 4}, 4, 1]]}
    which takes the first 1 positions of 1 and the first 1 positions of 4, yielding
    {{{1}},{{3}}}
Flatten at the first level, yielding {{1}, {3}}
Create a list {{{1}, {3}}, 5}
@@Apply {#, #2 - Total@Extract[barLens, #]} &, inserting arguments:
    {{{1}, {3}}, 5 - Total@Extract[{1, 2, 4}, {{1}, {3}}]} = {{{1}, {3}}, 0}
    where the second element becomes the # of spaces left over.
Done with g, it returned {{{1}, {3}}, 0}
@@Apply Sequence, splicing the return of g into h, yielding the
@Call, h["<|=||:)", "(:||||>", {{1}, {3}}, 0]; let's start from the interior
StringSplit the concatenated "<|=||:)=(:||||>" with delimiter "=", {"<|","||:)","(:||||>"}
MapAt the part specification {{1}, {3}} and StringReplace at those indices any | with /\
    yielding {"</\","||:)","(:/\/\/\/\>"}
StringRiffle together, inserting back the delimiter "=", yielding "</\=||:)=(:/\/\/\/\>"
StringReplace ")=" with ")~", concat the new number of spaces, concat "~"
Yields "</\=||:)~~(:/\/\/\/\>", done.
jcai
źródło
Łatwo zredukowane do 355, zaczynając od, a=StringReplace;b=StringSplit;c=StringLength;d=Total;a następnie zastępując je w razie potrzeby w innym miejscu w środku:a=StringReplace;b=StringSplit;c=StringLength;d=Total;a[MapAt[a[#,"|"->"/\\"]&,b[#<>"="<>#2,"="],#3]~StringRiffle~"=",")="->")~"<>If[#4>0,"."~StringRepeat~#4,""]<>"~"]&[#1,#3,Sequence@@Function[{l,s},{#,#2-d@Extract[l,#]}&[Flatten[l~Position~#~Take~#2&@@@Tally@#&@@Select[Subsets@l,d@#<=s&]~MaximalBy~d,1],s]][c/@StringCases[#1<>#3,"|"..],c@#2]]&@@#~b~"~"&
Alex Meiburg
3

Prolog (ECLiPSe), 438 bajtów

Inne moje odpowiedzi rozwiązały niewłaściwy problem (przepraszam za hałas). Oto kolejna próba w Prologu, która faktycznie przestrzega wszystkich zasad.

:-lib(fd).
a([],[]).
a([H|T],L):-append(H,X,L),a(T,X).
s(E,Z,X,Y,L):-length(E,L),a([[60],M,[58,41,126],T,[126,40,58],W,[62]],E),checklist(=(32),T),length(T,Z),b(M,X-[]),b(W,Y-[]).
b(I,[K:M|R]-E):-(I:K=[47,92|L]:s;I:K=[124|L]:n),M#=N+1,N#>=0,b(L,[K:N|R]-E).
b([61|L],[_:0|R]-E):-b(L,R-E).
b([],[_:0|E]-E).
d(_:N,Y:N):-Y=s;Y=n.
s(W,P):-string_list(W,E),s(E,_,X,Y,L),minimize((maplist(d,X,U),maplist(d,Y,V),s(K,Q,U,V,L)),Q),string_list(P,K).

Testy

(format: wejście, wyjście, nowa linia)

<===:)~         ~(:>
<===:)~         ~(:>

<|||:)~         ~(:||||=|>
</\/\/\:)~ ~(:/\/\/\/\=/\>

<=|=:)~         ~(:||||=|>
<=/\=:)~   ~(:/\/\/\/\=/\>

<===|:)~         ~(:||=|>
<===/\:)~     ~(:/\/\=/\>

<|=|=|||=|:)~         ~(:=|>
</\=/\=/\/\/\=/\:)~  ~(:=/\>

<||||||:)~         ~(:=|>
</\/\/\/\/\/\:)~  ~(:=/\>

<||||||:)~         ~(:||>
</\/\/\/\/\/\:)~ ~(:/\/\>

<||=||||:)~ ~(:||>
<||=||||:)~ ~(:||>

<||=||||:)~   ~(:||>
</\/\=||||:)~ ~(:||>

<||=||||:)~    ~(:||>
</\/\=||||:)~~(:/\/\>

<||=||||:)~~(:||>
<||=||||:)~~(:||>

Objaśnienia

  • Główny predykat to s/2, który przyjmuje dane wejściowe jako pierwszy argument, a wynik drugiego argumentu (oba ciągi) ujednolica wynik. Wejście jest konwertowany do listy kodów znakowych E.

  • Następnie s(E,Z,X,Y,L)rozkłada listę na następujące elementy:

    • Z liczba odstępów między wężami
    • Xoraz Yabstrakcyjna reprezentacja lewego i prawego ciała

      Format treści to lista n:Nlub s:Nwyrażenia, których Ndługość jest dodatnia; nśrodki normali sśrodki stretched.

    • L całkowita długość listy

Interesujące jests/5 to, że idzie w obie strony , tzn. Możemy zbudować węża, jeśli pojawią się inne argumenty:

    s(E,5,[n:3],[s:2,n:7,s:1],_),string_list(S,E).

... unifies `S` with `"<|||:)~     ~(:/\\/\\=|||||||=/\\>"` (backslashes are quoted). This is due to how `b/2` is written, which can parse the character list or generate it.
  • Budujemy zmodyfikowane lewe i prawe ciała, w których każda część jest albo normalna, albo rozciągnięta, minimalizując przestrzeń Qoddzielającą nowe węże. Całkowita długość obliczonego ciągu jest ograniczona, więc wyszukiwanie kończy się.
rdzeń rdzeniowy
źródło
1

Python 2.7.3 427 421 400 371 bajtów

import re,itertools as K
g,o,k='\|+',len,raw_input()
d=k.count(' ')
if d==0:exit(k)
p,x,y,s=re.sub,0,0,map(o,re.findall(g,k))
for e in [A for w in range(o(s)+1)for A in K.combinations(s,w)]:
 v=sum(e)
 if v==d or x<v<d:x,y=v,list(e)
print p(" +",' '*(d-x),p(g,lambda m:('/\\'*o(m.group(0))if y.remove(o(m.group(0)))or True else 1)if o(m.group(0))in y else m.group(0),k))

Kod do gry w golfa tutaj -

#!/usr/bin/env python
import sys
import re

def find_dist_combo(li, d):
    #Listing all combinations
    from itertools import combinations as c
    max_dist = -1
    max_dist_combo = []
    for p_len in xrange(1,len(li)+1):
        for e in c(li, p_len):
            e_sum = sum(e)
            cond1 = e_sum == d
            cond2 = max_dist < e_sum < d
            if cond1 or cond2:
                max_dist = e_sum
                max_dist_combo = list(e)
                if cond1:
                    return (max_dist, max_dist_combo)
    return (max_dist, max_dist_combo)

def snakes_foreplay(snakes):
    #find distance
    distance = snakes.count(" ")

    #already kissing
    if distance == 0:
        return snakes

    #find num_stretches
    stretch = map(len, re.findall("\|+", snakes))

    #find lowest combination of numbers
    (e_dist, res_stretch) = find_dist_combo(stretch, distance)

    def sub_callback(m):
        s = m.group(0)
        l = len(s) 
        if l in res_stretch:
            res_stretch.remove(l)
            return '/\\'*l
        return s

    #Resultant substitution
    res_snakes = re.sub("\s+", " "*(distance - e_dist), re.sub("\|+", sub_callback, snakes))

    return res_snakes

if __name__ == "__main__":
    for s in [ip.strip() for ip in sys.stdin]:
        print snakes_foreplay(s)

Testowanie rozwiązania golfowego -

$ python stretchy_snakes.py
[In]  <=  <|=||:)~     ~(:||||>
[Out] =>  </\=||:)~~(:/\/\/\/\>

$ python stretchy_snakes.py
[In]  <=  <|=||:)~             ~(:||||>
[Out] =>  </\=/\/\:)~      ~(:/\/\/\/\>

$ python stretchy_snakes.py
[In]  <=  <|=||:)~     ~(:|||=|>
[Out] =>  </\=||:)~~(:/\/\/\=/\>

$ python stretchy_snakes.py
[In]  <=  <||=||||:)~   ~(:||>
[Out] =>  </\/\=||||:)~ ~(:||>

$ python stretchy_snakes.py
[In]  <=  <|=||:)~~(:||||>
[Out] =>  <|=||:)~~(:||||>

Z pewnością można to zrobić lepiej (nie mogę wymyślić, jak :)).
Daj mi znać, jeśli przegapiłem coś oczywistego podczas gry w golfa (to mój pierwszy codegolf, może robię coś głupiego: P)

Kamehameha
źródło
@ Sp3000 To jest dobre. Zamieniono exitna sys.exit()(zapomniałem, że exitistnieje). I masz rację, __import__można go usunąć, który wyeliminował jak 20 znaków :)
Kamehameha
btw reguła: do aliasingu potrzebujesz > 6znaków, które powinny być warte aliasingu, jeśli użyjesz go dwa razy, > 3znaków, jeśli użyjesz go trzy razy. Nie jestem pewien, czy f=' 'alias jest tego wart (liczę dwa razy)
Sp3000,
@ Sp3000 tak, masz rację. We wcześniejszej wersji trzy razy użyłem tej zmiennej. Uratowałem mi jeszcze kilka bajtów :) :)
Kamehameha
1

05AB1E , 93 bajty

#õKDεγʒ'|å]©ε€gxøDgU`XG‘]`âDε˜ODI„| Ãg>‹*}ZQÏε˜ε®˜NèDgyÊi„/\y∍]н©J'/¢Ið¢αð×ý'|¡õK®.ιJIðå≠iI

Zbyt długo ..>.>

Wypróbuj online lub sprawdź wszystkie przypadki testowe lub sprawdź wszystkie możliwe wyniki dla wszystkich przypadków testowych .

Wyjaśnienie:

#õK                   # Split the (implicit) input by one or multiple adjacent spaces
                      # (we now have both snakes as separated items
                      #  - if any spaces were in the input-string)
   D                  # Duplicate this list
    ε                 # Map both snakes to:
     γ                #  Split the snake into chunks of the same character-type
      ʒ'|å]          '#  And only leave the chunks of "|" characters
    ©                 #  Store this list in variable `r` (without popping)
     ε                #  Map the "|" chunks of both snakes again:
      g              #  Get the length of each chunk of "|"
        xø            #  Pair each length with double itself
          DgU`XG‘   #  Create all possible combinations for the current snake
     ]`â              # After the map: create all possible combinations for both snakes
        ε             # Map over each possible combination
         ˜O           #  Get the flattened sum
            I„| Ãg    #  Count the amount of "|" and spaces in the input
                  >‹  #  Check if it's smaller than or equal to this sum
                      #  (1 if truthy; 0 if falsey)
           D        * #  And multiply it by the sum
        }ZQ           # After the map, get the positions of the largest flattened sum,
                      # still below (or equal to) the amount of "|" and spaces combined
       D   Ï          # And only keep those combinations
ε                     # Then map over the remaining combinations
 ˜ε                   #  Flatten it, and map over each value `y`
   ®˜Nè               #   Get the `N`'th part of the snakes
                      #   (where `N` is the index of the map for the current combination)
       D              #   Duplicate this "|"-part
        gyÊi          #   If the length of this "|"-part is not equal to the map-value:
            „/\       #    Push the string "/\"
               y     #    Extended to a size equal to the map-value
                      #   (implicit else:
                      #    use the duplicated value)
                    # After the map: only leave the first (since we don't have
                      # to output all possibilities)
 ©                    # Store it in variable `r` (without popping)
  J'/¢               '# Count the amount of "/" in it
      Ið¢             # Count the amount of spaces in the input
         α            # Get the difference between those
          ð×ý         # And join the list of snakes by that many spaces
'|¡õK                '# Then split by one or multiple adjacent "|"
     ®.ι              # Interleave it with the modified parts of variable` r`
        J             # And join everything together to a single string
Iðå≠i                 # If the input didn't contain any spaces:
     I                #  Output the input instead
                      # (implicit else:
                      #  output the top of the stack before this if)
Kevin Cruijssen
źródło