Сделайте Поцелуй Эластичных Змей

57

Эластичная змея выглядит примерно так:

<||=|||:)~

Каждая отдельная последовательность вертикальных столбцов ( |) в эластичной змеи, известная как эластичная часть , индивидуально расширяется вдвое по ширине и рисуется с помощью чередующихся косых черт ( /, \) после расширения.

У конкретной змеи выше есть две такие эластичные части, что дает ей четыре возможных позы:

<||=|||:)~

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

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

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

Общая форма эластичной змеи в ее наименее растянутой позе определяется этим регулярным выражением :

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

Который можно выразить словами:

<, За которым следует любое количество последовательностей |«ы вступил с =признаками, а затем :)~.

Так <|:)~и <||:)~и <|=|:)~и <|=|=||=|||||=||:)~растягиваются змеями, но <=:)~и <=|:)~и <||=:)~и <|==||:)~не являются.

Эластичные змеи также могут быть направлены влево, а не вправо, например ~(:|||=||>. Формы одинаковые, просто зеркальные.

Вызов

Напишите программу, которая принимает в одну строку строку из двух растягивающихся змей, обращенных друг к другу, с некоторым количеством пробелов между ними. Обе змеи будут в своей наименее растянутой позе (все вертикальные полосы, без слешей). Строка начинается с хвоста змеи, обращенной вправо, и заканчивается хвостом змеи, обращенной налево (вы можете при желании предположить, что есть также завершающий символ новой строки).

Например, вот возможный ввод с пятью пробелами между змеями:

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

Я использую period ( .) вместо реальных пробелов для ясности.

Ноль пробелов между змеями также допустим:

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

Мы говорим, что змеи целуются, когда их языки соприкасаются вот так.

Ваша программа должна расширить некоторую комбинацию растягивающихся частей обеих змей так, чтобы у змей было как можно меньше промежутков между ними (без наложения), то есть так, чтобы змеи были как можно ближе к поцелуям .

Хвосты обеих змей фиксированы, но их головы и тела могут двигаться - вправо для змеи, обращенной вправо, влево для змеи, обращенной налево, - в зависимости от того, какие вытянутые части были вытянуты.

Результатом вашей программы является однострочная строка (плюс необязательный завершающий символ новой строки), который показывает змей как можно ближе к поцелуям, с чередующимися косыми чертами вместо вертикальных полос для растянутых участков, которые были расширены.


Например, вывод для <|=||:)~.....~(:||||>(сверху) будет:

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

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


Если существует несколько возможных решений, вывод может быть любым из них.

Например, если входные данные были

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

выход может быть

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

или же

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

Помните, что не всегда можно поцеловать змей, но вам все равно нужно как можно ближе подойти к ним.

Например, если входные данные были

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

выход может быть

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

или же

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

Если змеи уже целуются, результат будет таким же, как и у входа. например

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

В общем, выходные данные будут такими же, как и входные, если расширение любой растянутой части приведет к перекрытию змей. например

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

Примечания

  • Принимает ввод из stdin или командной строки, как обычно, или пишет функцию, которая принимает строку. Распечатать или вернуть вывод.
  • Вы можете использовать period ( .) на входе и выходе вместо пробелов ( ), если хотите.
  • Важно только, чтобы косые черты чередовались в последовательности вертикальных полос, которые они заменяли. Их порядок в змее в целом или то, идет ли вперед или назад косая черта, не имеет значения.
  • Эластичные участки не могут расширяться частично - это ровно удвоение или вообще не удлинение.

счет

Это код-гольф . Победит самая короткая подача в байтах. Tiebreaker - более ранний ответ.

Кальвин Хобби
источник
17
Snex Education 101 - Как правильно целоваться
Оптимизатор
45
«Мы говорим, что змеи целуются, когда их языки соприкасаются». Что я читаю ...
Fatalize
8
Так змеи только делают по-французски?
Оптимизатор
3
@PeterTaylor Ну, «зеркальный», а не «перевернутый» (иначе >не стал бы <ни тот же, для for (и )), но он также говорит: «Важно, чтобы косые черты чередовались в последовательности вертикальных полос, которые они заменяли. Их порядок в змея на свободе, или то, будет ли впереди или сзади косая черта, не имеет значения ".
Мартин Эндер
7
@qwr Воображение.
Увлечения Кельвина,

Ответы:

9

CJam, 87 71 70 68 байт

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

Попробуйте онлайн в интерпретаторе CJam .

Как это устроено

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.
Деннис
источник
19

Retina , 209 107 99 97 92 байта

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

В целях подсчета каждая строка идет в отдельном файле, но вы можете запустить код из одного файла с -sфлагом.

Объединение лучших возможностей регулярных выражений .NET и Retina: балансировка групп, просмотр за произвольной длиной и повторная замена регулярных выражений.

По сути, длинное регулярное выражение кодирует правильное решение, и средство отслеживания движка регулярного выражения находит одно из оптимальных для меня.

объяснение

Во-первых, давайте рассмотрим, как мы можем найти правильное решение (не обязательно производящее правильный вывод) с помощью регулярного выражения. Мы можем использовать группы балансировки .NET, чтобы помочь нам подсчитать растягивающиеся части. Рассмотрим следующее более простое регулярное выражение:

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

Мы можем разобрать это.

\S+( )+.+

Это соответствует всей строке, помещая один захват в 1стек групп для каждого пробела во входных данных. Мы будем использовать этот стек, чтобы гарантировать, что эластичные части точно заполняют пространство, занятое в этих группах.

Следующее - взгляд назад. Загвоздка в том, что взгляды совпадают справа налево в .NET (так вы должны их читать). Это дает нам возможность пересечь строку во второй раз, выяснив, есть ли подмножество растягивающейся части, которое суммируется с количеством соответствующих пробелов. Пройдя сквозь обзор справа налево:

>

Это просто гарантирует, что мы на самом деле начинаем с конца строки (хвост змеи).

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

Для каждой эластичной части это либо просто совпадает со всей частью, ничего не делая ( \|+), либо совпадает со всей частью, пока выталкивание захватывает из stack 1( (?<-1>\|)*). Наличие этого чередования гарантирует, что мы можем только полностью вытянуть эластичную часть или оставить ее без изменений, и не получать подобные вещи |/\|. Затем мы переходим к следующей эластичной части с [^|]+.

(?(1)!)^

Наконец, мы гарантируем, что мы прошли всю строку (обе змеи), и этот стек 1полностью пуст. Т.е. мы нашли подмножество растягивающейся части, которое точно соответствует количеству пробелов, которые мы захватили ранее.

Бэктрекер будет перебирать строку вперед и назад, пробуя все комбинации неизмененных и расширенных частей до тех пор, пока проблема суммы подмножеств не будет решена. Если такого подмножества не существует, просмотр сзади не удастся. Это заставит бэктрекер вернуться к \S+( )+.+части и попытаться захватить на один пробел меньше ( )+(который будет .+вместо этого прикрыт). +Поэтому из-за жадности мы стараемся заполнить как можно больше пробелов.

Вы можете проверить правильность этого подхода с помощью этой слегка измененной замены:

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

Что даст вам строку =spaces=с точным количеством пробелов, которые могут быть заполнены заданными змеями.

Мне пришлось добавить еще одну хитрость, чтобы действительно расширить правильные значения |. По сути, я хочу заменить все |s, которые были сопоставлены с использованием (?<-1>\|)+ветви. Идея состоит в том, чтобы соответствовать индивидуальному персонажу, поместить решатель в обход и установить флаг, если совпадение происходит внутри этой ветви. Если этот флаг не был установлен, мы аннулируем совпадение в конце, чтобы избежать замены других символов.

Для этого мы используем несколько вложенных lookarounds. Опять же, взглядовые объекты переменной длины .NET сопоставляются справа налево, поэтому, если мы вкладываем в объекты lookaheads и lookbehinds, мы можем позволить механизму регулярных выражений проходить строку несколько раз. По причинам, связанным с игрой в гольф, решатель перевернут в моем реальном решении (начиная с конца, выбирая пробелы справа налево, а затем решая сумму поднабора слева направо), но в остальном структура решателя точно такая же , Давайте рассмотрим полное регулярное выражение:

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

Мы сопоставляем один символ, затем фиксируем остаток строки и перемещаем курсор в конец строки. Мы будем использовать эту группу 1позже, чтобы проверить в решателе, находимся ли мы в позиции матча.

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

Это похоже на первую часть простого решателя выше, за исключением того, что мы выбираем пробелы справа налево. Возврат количества пробелов работает точно так же, как и раньше, за исключением того, что мы сейчас используем группу 5.

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

Это то же самое, что и раньше, за исключением того, что мы идем слева направо, и всякий раз, когда мы сопоставляем a |в расширяющейся ветви, мы проверяем, совпадает ли это с правой

(?=\1())?

Это необязательный взгляд. Он 1снова пытается сопоставить группу (что, в данном случае, возможно только в том случае, если мы находимся сразу после сопоставляемого символа), и если мы это сделаем, мы собираем пустую строку в группу 4, что указывает на то, что мы нашли текущий символ в одном из расширенных битов. Если \1не совпадает, 4не будет ничего захватывать, и ?гарантирует, что неудачный просмотр не повлияет на решатель вообще.

Наконец, после того, как все решение завершено, мы просто проверяем, использовался \4ли этот прогноз. Если это так, мы хотим заменить текущий символ на /\.

Остается одна трудность: удаление нужного количества пробелов. Я нашел самый короткий способ сделать это, вставить пробел вместе с /\и затем избавиться от одного пробела между языками для каждого из этих маркерных пространств на отдельном шаге:

+` (.*~|~.*) 
$1
Мартин Эндер
источник
6

Рубин 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}

Это функция, которая принимает строку в качестве параметра и возвращает строку.

Онлайн тесты: http://ideone.com/uhdfXt

Вот читаемая версия:

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

В версии для гольфа основная функция является эквивалентом KISSфункции, указанной выше, и эта COMBINATIONSфункция была встроена.

Кристиан Лупаску
источник
Сбой при вводе <|=||:)~~(:||||>, что в спецификации является допустимым вводом.
Стоимость чернил
6

Python, 205 байт

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","/\\")

Одна лямбда выглядит аккуратно, но я почти уверен, что это не лучший способ. Но я публикую это, потому что все, что у меня есть, выглядит наполовину прилично.

Это простая перебор всех возможных замен |с /\, отфильтровывая недопустимые конфигурации. Единственный аккуратный немного я думаю, что мы на самом деле не заменить какой - либо |с /\напрямую - мы сначала заменим |с Xи опускаем .с середины для каждой замены, возьмите строку минимальной длины на все действительные строки, а затем заменить Xс с /\.

Я попробовал несколько других подходов, включая рекурсивные, но они оказались довольно грязными. Я также узнал, что в re.splitнастоящее время не разбиваются на пустые строки, что было неудачно, потому что одна из моих идей заключалась в разделении на \bграницы слов.

Sp3000
источник
5

Mathematica, 381 байт

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~"~"&

Чистая функция, принимающая строку в качестве аргумента. Ожидает, .а не между змеями.

Я не думал, что это будет так плохо ... Вот что у меня было до того, как я разбил его и вставил все.

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[#, "~"] &

Вот пример прогона с объяснением:

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
источник
Легко снижается до 355, начиная с того, a=StringReplace;b=StringSplit;c=StringLength;d=Total;что нужно, и заменяя их в других местах: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~"~"&
Алекс Мейбург
3

Пролог (ECLiPSe), 438 байт

Мои другие ответы решали не ту проблему (извините за шум). Вот еще одна попытка в Прологе, которая на самом деле соблюдает все правила.

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

тесты

(формат: ввод, вывод, перевод строки)

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

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

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

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

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

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

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

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

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

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

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

Пояснения

  • Основной предикат s/2, который принимает входные данные в качестве первого аргумента и возвращает результат со вторым аргументом (обе строки). Вход преобразуется в список кодов символов, E.

  • Затем s(E,Z,X,Y,L)разбивает список на следующие элементы:

    • Z количество пробелов между змеями
    • Xи Y, абстрактное представление левого и правого органов

      Формат тела - это список n:Nили s:Nвыражения, где Nположительная длина; nсредства normalи sсредства stretched.

    • L общая длина списка

Что интересно, такs/5 это то, что он идет обоими путями , то есть мы можем построить змею, если будут созданы другие аргументы:

    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.
  • Мы строим измененные левое и правое тела, где каждая часть либо нормальная, либо растянутая, минимизируя пространство Q, разделяющее новых змей. Общая длина вычисляемой строки ограничена, поэтому поиск прекращается.
CoreDump
источник
1

Python 2.7.3 427 421 400 371 байт

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

Код не для игры в гольф здесь -

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

Тестирование гольф-решения -

$ 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] =>  <|=||:)~~(:||||>

Конечно, это можно сделать лучше (я не могу понять, как :)).
Дайте мне знать, если я упустил что-то очевидное во время игры в гольф (это мой первый код-гольф, возможно, я делаю что-то глупое: P)

Kamehameha
источник
@ Sp3000 Это хорошо. Заменил exitна sys.exit()(забыл, exitсуществовал). И вы правы, __import__могут быть удалены, что устранено, как 20 символов :)
Kamehameha
Между прочим, эмпирическое правило: для псевдонимов вам нужны > 6символы, которые стоит использовать для псевдонимов, если вы используете его дважды, и > 3символы, если вы используете его три раза. Я не уверен, что f=' 'псевдоним того стоит (я считаю дважды)
Sp3000
@ Sp3000 да ты прав. В более ранней версии я использовал эту переменную трижды. Спасли меня еще пару байтов :) :)
Kamehameha
1

05AB1E , 93 байта

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

Слишком долго ..>.>

Попробуйте онлайн или проверьте все тестовые случаи или проверьте все возможные результаты для всех тестовых случаев .

Объяснение:

#õ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)
Кевин Круйссен
источник