Свернуть ковер


15

Этот вопрос вдохновлен вопросом Кевина Круйссена .

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

Процедура одного шага раскатывания ковра заключается в следующем. Есть пример, чтобы проиллюстрировать, что я имею в виду. Обратите внимание, что пример начинается с частично свернутого ковра для лучшего понимания:

ac
rpet
  • отделите «голову» от «хвоста» ковра: голова - это то, что было свернуто до сих пор, хвост - это то, что остается катиться.
Head: ac   Tail:
      rp          et
  • Поверните головку на 90 ° по часовой стрелке.
Rotated head: ra   Tail (unchanged):
              pc                       et
  • если ширина новой головы (здесь 2) меньше или равна длине хвоста (здесь 2)
    • затем положить его на хвост
    • иначе, ковер (как это было в начале шага) был свернут
New carpet: ra
            pc
            et

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


Два примера, показывающие все этапы ковроткачества:

carpet

 c
 arpet

  ac
  rpet

    ra
    pc
    et
0123456789

 0
 123456789

  10
  23456789

    21
    30
    456789

      432
      501
      6789

Некоторые точности:

  • Вам не нужно показывать все промежуточные шаги, только свернутый ковер (например, если вы найдете не итеративный способ вычисления результата, он идеален). Кроме того, вам не нужно печатать начальные пробелы, в приведенных выше примерах я только показываю их для выравнивания.
  • Ввод - это строка, список / массив символов
  • Вывод выводится на стандартный вывод или в файл.
  • Входные данные хороши: длина по крайней мере 1 символ, и максимум константа достаточно мала, чтобы не вызывать проблем, но вы не можете использовать эту константу в своей программе; содержимое строки - только хорошие символы ([a-zA-Z0-9]), кодирование по вашему усмотрению.
  • Это , поэтому выигрывает самый короткий ответ в байтах. Не позволяйте языкам кода-гольфа отговаривать вас от публикации ответов на языках, не относящихся к кодексу. Попробуйте найти как можно более короткий ответ для «любого» языка программирования.
  • По умолчанию лазейки запрещены.
  • Если возможно, добавьте ссылку с тестом для вашего кода.
  • Также добавьте пояснение к своему ответу, если считаете, что это необходимо.


2
Также этот: codegolf.stackexchange.com/questions/125966/… , но ни один не включает проверку завершения.
Броминд

3
Предлагаемый тестовый пример: ProgrammingPuzzlesAndCodeGolf- конечная длина хвоста больше 1 споткнула меня.
Сок

1
Я думаю, что вы поменяли слова «голова» и «хвост» здесь: «если ширина новой головы [...] больше или равна длине хвоста [...]».
Эрик Outgolfer

1
Понижено из-за чрезмерно ограничительных правил ввода / вывода; Я удалил свой ответ на Python 2, так как нельзя использовать printвнутри a lambda.
Час Браун

Ответы:


7

Древесный уголь , 15 байт

FS«F¬℅§KV⁰⟲⁶→Pι

Попробуйте онлайн! Ссылка на подробную версию кода. Объяснение:

FS«

Зациклиться на ковре.

F¬℅§KV⁰

Проверьте, есть ли что-нибудь над курсором.

⟲⁶

Если нет, тогда катите ковер.

→Pι

Двигайтесь вправо и выводите текущий символ.

Пример: для ввода 0123456789выполняются следующие действия:

0

0 печатается.

01

Курсор перемещается вправо и 1печатается.

0
1

Поскольку нет ничего выше 1, холст вращается.

0
12

Курсор перемещается вправо и 2печатается.

10
2

Поскольку нет ничего выше 2, холст вращается.

10
23

Курсор перемещается вправо и 3печатается.

10
234

Курсор перемещается вправо и 4печатается.

21
30
4

Поскольку нет ничего выше 4, холст вращается.

21
30
45

Курсор перемещается вправо и 5печатается.

21
30
456

Курсор перемещается вправо и 6печатается.

432
501
6

Поскольку нет ничего выше 6, холст вращается.

432
501
67

Курсор перемещается вправо и 7печатается.

432
501
678

Курсор перемещается вправо и 8печатается.

432
501
6789

Курсор перемещается вправо и 9печатается.


Это потрясающе. Так в основном у Charcoal есть встроенный оператор "roll" ?
Иона

1
@Jonah Ну, это не будет катиться для меня, как это идет, но выводя строку символ за символом, я могу катиться, как я иду, да.
Нил

3

Pyth, 37 байт

.U+j;bZ.WgleHJlhH,+_MChZ<eZJ>eZJ,]hQt

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

.U+j;bZ.WgleHJlhH,+_MChZ<eZJ>eZJ,]hQtQ   Implicit: Q=eval(input())
                                         Trailing Q inferred
                                 ]hQ     First character of Q, wrapped in an array
                                    tQ   All but the first character of Q
                                ,        2-element array of the two previous results
                                           This yields array with rolled carpet (as array of strings) followed by the tail
       .W                                While condition function is truthy, execute inner function, with initial value of the above:
         gleHJlhH                          Condition function, input H
             JlhH                            Number of layers in the current rolled carpet, store in J
          leH                                Lenth of the tail
         g   J                               Is the above greater than or equal to J?
                 ,+_MChZ<eZJ>eZJ           Inner function, input Z
                   _MChZ                     Rotate the current rolled carpet (transpose, then reverse each row)
                  +     <eZJ                 Append the first J characters of the tail as a new row
                 ,                           Pair the above with...
                            >eZJ             ... all but the first J characters of the tail - this is the new tail
.U+j;bZ                                  Join the carpet roll on newlines and append the tail, implicit print

3

Шелуха , 24 байта

►S=ÖLmFȯ:T↔ø§z:oΘḣĠ+CṘ2N

Попробуйте онлайн!

объяснение

Implicit input, say s="carpets"

CṘ2N  Break s into chunks:
   N   Natural numbers: [1,2,3,4,..
 Ṙ2    Repeat each twice: [1,1,2,2,3,3,4,4,..
C      Break s into chunks of these lengths: ["c","a","rp","et","s"]
       The last chunk is shorter if we run out of characters.

§z:oΘḣĠ+  Attempt to merge suffix of chunks:
      Ġ    Cumulative reduce chunk list from right
       +   by concatenation: ["carpets","arpets","rpets","ets","s"]
   oΘḣ     Prefixes of chunk list (empty and nonempty): [[],["c"],..,["c","a","rp","et","s"]]
§z         Zip these by
  :        appending: [["carpets"],["c","arpets"],..,["c","a","rp","et","s"]]
           These are all versions of the chunk list where some suffix has been merged.

mFȯ:T↔ø  Roll each list:
m         Map
 F        reduce from left
      ø   starting from empty character matrix
  ȯ:T↔    by this function:
    T↔     Reverse and transpose (rotating by 90 degrees)
  ȯ:       then append next chunk as new row.
         Result: [["carpets"],["c","arpets"],..,["epr","tca","s"]]

►S=ÖL  Select the matrix rolled by the correct amount:
►       Find element that maximizes
 S=     being equal to
   ÖL   sort by length.
        This selects a matrix whose rows have non-decreasing lengths.
        Ties are broken by choosing the rightmost one.
       Result: ["ra","pc","ets"]

Implicitly print each row separated by newlines.

2

J 69 байт

-3 байта благодаря FrownyFrog

[:(}:@[,{:@[,])&>/[:((|:@|.@[,#@[$]);#@[}.])&>/^:(<:&#&>/)^:_,.@{.;}.

Попробуйте онлайн!

объяснение

[: (}:@[ , {:@[ , ])&>/ [: ((|:@|.@[ , #@[ {. ]) ; #@[ }. ])&>/^:(<:&#&>/)^:_ }. ;~ 1 1 $ {.

Алгоритм прост, несмотря на то, что он немного многословен для J.

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

По мере сокращения мы будем использовать список из 2 элементов. Наш «результат до сих пор» будет первым блоком, а «элементы, оставшиеся для обработки» - вторым блоком. Первое поле будет инициализировано для заголовка ввода (но преобразовано в таблицу):

1 1 $ {.

и «элементы, оставшиеся для обработки» будут хвостом ввода:

}. ;~

Теперь у нас есть:

┌─┬─────┐
│c│arpet│
└─┴─────┘

где 'c' на самом деле является таблицей 1x1.

Мы уменьшаем это, используя цикл J Do ... while:

^:(...)^:_

Где часть в круглых скобках является условием "продолжать идти":

<:&#&>/

который говорит: «продолжайте идти, пока длина правого прямоугольника больше или равна длине левого прямоугольника (то есть длина стороны квадратной матрицы)

Что значит "продолжать идти"? Это определено в глаголе слева от первого ^:, который говорит нам, как взять текущий результат и произвести следующую итерацию. Этот глагол:

((|:@|.@[ , #@[ {. ]) ; #@[ }. ])&>/

Давайте разберемся с этим:

((|:@|.@[ , #@[ {. ]) ; #@[ }. ])&>/
(  verb in parens               )&>/ NB. put the verb in parens
                                     NB. between the two items
                                     NB. of our list, and unbox
                                     NB. them into left / right
                                     NB. args ([ / ]) for the verb
 (|:@|.@[ , #@[ {. ]) ; #@[ }. ]     NB. breaking down verb in 
                                     NB. parens...
                      ; ....         NB. new "remaining items":
                            }. ]     NB. remove from remaining
                        #@[          NB. the size of a side of
                                     NB. the result matrix
                ....  ;              NB. new "result":
  |:@|.@[                            NB. rotate existing result
          ,                          NB. and put it on top of
            #@[ {. ]                 NB. the items we removed
                                     NB. from remaining items

То есть это просто алгоритм, описанный в ОП, переведенный буквально на J.

Наконец, мы имеем дело с (возможно, 0) оставшимися предметами, хвостом нашего рулона ковра:

(}:@[ , {:@[ , ])&>/

Это говорит «возьми все, кроме последнего вяза результата»:

}:@[ 

и добавить его к ,последним элементам результата {:@[с оставшимися элементами, добавленными к этому последнему элементу, ]


Ах, J ... буквы для нубов
РК.

,.может делать то, что 1 1$]делает и $может быть использован как {..
FrownyFrog

@FrownyFrog ty. Я получил его до 70 байт с вашим первым предложением, но не был уверен, что понял $ can be used as {.- вы можете уточнить?
Иона

1
В последней строке объяснения вы используете {. укоротить, что, насколько я понимаю, можно получить $.
FrownyFrog

Также вы можете заменить право [: на @
FrownyFrog

1

R , 146 132 байт

function(s){m=F[F]
while({m=rbind(t(m)[,F:0],s[1:F])
s=s[-1:-F]
length(s)>sum(F<-dim(m))})0
write(m[F:1,],1,F[1],,"")
cat(s,sep="")}

Попробуйте онлайн!

Реализует процедуру ковролинга. Принимает ввод как список символов и печатает на стандартный вывод.

Сэкономили 14 байтов, найдя способ использовать do-whileцикл и инициализировав его F.

function(s){
m=F[F]					# logical(0); create an empty array (this gets automatically promoted to character(0) later
while(					# do-while loop
      {m=rbind(t(m)[,F:0],s[1:F])	# rotate m counterclockwise and add the first F characters of s to the bottom
       s=s[-1:-F]			# remove those characters
       length(s)>sum(F<-dim(m))})0	# while the number of characters remaining is greater than the sum of m's dimensions
write(m[F:1,],1,F[1],,"")		# write the rolled portion write writes down the columns, we reverse each column
cat(s,sep="")				# and write the remaining characters
}

1

Желе , 30 байт

Кажется слишком долго ...

ḢW,ðZU;Ls@¥©ḢWɗ,®Ẏ¤ð/ẈṢƑ$¿ḢY;Ɗ

Попробуйте онлайн!

Как?

ḢW,ðZU;Ls@¥©ḢWɗ,®Ẏ¤ð/ẈṢƑ$¿ḢY;Ɗ - Main Link: list of characters
Ḣ                              - pop and yield head
 W                             - wrap in a list
  ,                            - pair with (the remaining list after Ḣ)
                         ¿     - while...
                        $      - ...condition: last two links as a monad:
                     Ẉ         -   length of each
                       Ƒ       -   is invariant under:
                      Ṣ        -     sort
                    /          - ...do: reduce by:
   ð               ð           -   the enclosed dyadic chain -- i.e. f(head, tail):
    Z                          -     transpose
     U                         -     reverse each (giving a rotated head)
              ɗ                -     last three links as a dyad:
          ¥                    -       last two links as a dyad:
       L                       -         length (i.e. number of rows in current roll)
         @                     -         with swapped arguments:
        s                      -           split (the tail) into chunks of that length
           ©                   -       (copy to register for later)
            Ḣ                  -       pop and yield head (Note register "copy" is altered too)
             W                 -       wrap in a list
      ;                        -     concatenate (the rotated head with the first chunk of the tail)
                  ¤            -     nilad followed by link(s) as a nilad:
                ®              -       recall from register (other chunks of tail, or an empty list)
                 Ẏ             -       tighten (the chunks to a flat list)
               ,               -     pair (the concatenate result with the tightened chunks)
                             Ɗ - last three links as a monad:
                          Ḣ    -   pop and yield head
                           Y   -   join with newline characters
                            ;  -   concatenate (the remaining tail)
                               - when running as a full program implicitly prints

1

05AB1E , 41 байт

g©L¦€DD2šηO®>‹Ï©IŽ8OS®g4α._.ΛðÜI®O®g->.$«

Слишком долго, но я хотел использовать Canvas .. Что, вероятно, было плохим выбором, когда я закончил, и оказалось, что это так долго ...

Попробуйте онлайн . (Нет тестового набора, потому что, кажется, есть странная проблема со встроенным ..)

Объяснение:

Позвольте мне начать с общего объяснения Canvas и того, чего я хотел, чтобы мой код выполнял. Более подробную информацию можно найти в этой соответствующей статье 05AB1E , но для этой задачи я хотел сделать следующее:

Встроенная Canvas принимает три параметра:

  • a[2,2,3,3,4,4,5,5,...]
  • б
  • с[2,0,6,4][,,,]Ncarpet[0,6,4,2]0123456789ABCDEFGHI[6,4,2,0]

Что касается кода:

g                # Get the length of the (implicit) input-string
 ©               # Store it in the register (without popping)
  L              # Create a list in the range [1,length]
   ¦             # Remove the first item to make the range [2,length]
    D           # Duplicate each to get the list [2,2,3,3,4,4,5,5,...]
      D2š        # Create a copy and prepend a 2: [2,2,2,3,3,4,4,5,5,...]
         η       # Get the prefixes: [[2],[2,2],[2,2,2],[2,2,2,3],...]
          O      # Sum each prefix: [2,4,6,9,12,16,20,...]
           ®     # Push the length from the register again
            >‹   # Check for each summed prefix if it's <= length
              Ï  # And only leave the truthy values
               © # And store this in the register (without popping)
                 # (This is our `a` for the Canvas builtin)
I                # Push the input-string
                 # (This is our `b` for the Canvas builtin)
Ž8O              # Push compressed integer 2064
   S             # Converted to a list of digits: [2,0,6,4]
    ®g           # Push the list from the register, and get its length
      4α         # Get the absolute difference with 4
        ._       # And rotate the [2,0,6,4] that many times towards the left
                 # (This is our `c` for the Canvas builtin)
               # Now use the Canvas builtin, without printing it yet
  ðÜ             # Remove any trailing spaces (since the Canvas implicitly makes a rectangle)
     ®O          # Push the sum of the list from the register
       ®g-       # Subtract the length of the list from the register
          >      # And add 1
    I      .$    # Remove that many leading characters from the input-string
             «   # And append it at the end of the roll created by the Canvas
                 # (after which the result is output implicitly)

Посмотрите эту подсказку 05AB1E (раздел Как сжать большие целые числа? ), Чтобы понять, почему Ž8Oэто так 2064.


0

Python 3 , 112 байт

r=lambda t,h=[[]]:len(h)>len(t)and h[:-1]+[h[-1]+list(t)]or r(t[len(h):],list(zip(*h[::-1]))+[list(t)[:len(h)]])

В этом случае выводом является значение функции.

Попробуйте онлайн!

Если вы предпочитаете, вот другое (более длинное, 129 байт ) решение, которое печатает непосредственно свернутый ввод:

r=lambda t,h=['']:len(h)>len(t)and set(map(print,h[:-1]+[h[-1]+t]))or r(t[len(h):],list(map(''.join,zip(*h[::-1])))+[t[:len(h)]])

Попробуйте онлайн!


1
нужно распечатать
только ASCII

@ ASCII-only: цитирование автора вопроса: «Если возврат вместо печати показывает большое улучшение или хороший трюк, опубликуйте ответ (и укажите, что вы возвращаете, а не печатаете)» . Так что я думаю, что все в порядке.
PieCot

0

MATLAB / Octave , 154 байта

Не самый короткий, но играть в гольф в MATLAB / Octave всегда весело :)

function h=r(t,h);n=fliplr(h');s=size(n,2);q=numel(t);if s<=q h=r(t(max(s,1)+1:end),[n; t(1:max(s,1))]);elseif q>0 h(:,end+q)=' ';h(end,end-q+1:end)=t;end

Попробуйте онлайн!


1
к сожалению, op говорит, что вы должны печатать
только ASCII

@ Только для ASCII, как описано здесь ( it.mathworks.com/matlabcentral/answers/… ), стандартный вывод в мире Matlab относится к окну команд. Учитывая, что результат оценки каждой команды автоматически выводится в командное окно, я думаю, что этот ответ можно считать соответствующим требованиям вопроса.
PieCot

может быть, хочу прояснить это
только ASCII

@ ASCII-только я не понимаю, что ты имеешь в виду на самом деле. Вы называете это функцией, результат будет автоматически распечатан в командном окне (т. Е. Стандартный вывод). Что с этим не так? Даже ответ R работает следующим образом ...
PieCot

1
Сейчас ты dispэто, я бы сказал , что вы должны удалить , dispчтобы люди , которые не знают R , что делает запись в STDOUT по умолчанию
ASCII-только
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.