Зніміть струну


35

Змійований рядок виглядає приблизно так:

T AnE eOf ifi ing
h s x l A k e r
isI amp Sna dSt

Ваше завдання

Візьміть рядок sі розмір n, а потім виведіть змійований рядок. Вхідні дані ThisIsAnExampleOfaSnakifiedStringі 3дають приклад вище.

Технічні умови

  • s міститиме лише символи ASCII між кодовими точками 33 та 126 включно (без пробілів та нових рядків).
  • s міститиме від 1 до 100 символів.
  • nявляє собою ціле число, що представляє розмір кожного сегмента вихідного рядка. Кожен рядок символів (вгору / вниз або вліво / вправо), які складають криві у "змії", є nсимволами довгими. Див приклади тестових прикладів.
  • n буде від 3 до 10 включно.
  • Вихідний рядок завжди починає спрямований вниз.
  • Доступні пробіли в кожному рядку.
  • У кінцевому підсумку випуску нових рядків також дозволено.
  • Провідні місця не дозволяються.
  • означає найкоротший код у виграші байтів.

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

a 3

a

----------

Hello,World! 3

H Wor
e , l
llo d!

----------

ProgrammingPuzzlesAndCodeGolf 4

P  ngPu  Code
r  i  z  d  G
o  m  z  n  o
gram  lesA  lf

----------

IHopeYourProgramWorksForInputStringsWhichAre100CharactersLongBecauseThisTestCaseWillFailIfItDoesNot. 5

I   gramW   tStri   100Ch   gBeca   CaseW   DoesN
H   o   o   u   n   e   a   n   u   t   i   t   o
o   r   r   p   g   r   r   o   s   s   l   I   t
p   P   k   n   s   A   a   L   e   e   l   f   .
eYour   sForI   Which   cters   ThisT   FailI

----------

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 10

!        <=>?@ABCDE        `abcdefghi
"        ;        F        _        j
#        :        G        ^        k
$        9        H        ]        l
%        8        I        \        m
&        7        J        [        n
'        6        K        Z        o        ~
(        5        L        Y        p        }
)        4        M        X        q        |
*+,-./0123        NOPQRSTUVW        rstuvwxyz{

Я припускаю, що наступним викликом буде перетворення змікованого рядка до початкових 2 параметрів ...
abligh

@abligh У мене не було подальших планів, але це насправді звучить як гідна ідея. Хоча може бути якась форма дубліката, тому мені потрібно перевірити це спочатку. Будьте в курсі!
користувач81655

зворотний виклик був би веселішим, якщо змія може мати довільну форму ...
abligh

@abligh Це саме те, що я планував робити ха-ха!
користувач81655

Відповіді:



12

Рубі, 87 байт

->s,n{p=0
a=(' '*(w=s.size)+$/)*n
w.times{|i|a[p]=s[i];p+=[w+1,1,-w-1,1][i/(n-1)%4]}
a}

Деякі незначні зловживання правилом Trailing spaces on each line are allowed.Кожен рядок виводу єw символи довжиною плюс новий рядок, де wдовжина початкового рядка, тобто достатньо довга, щоб вмістити весь вхід. Звідси є велика кількість зайвого пробілу праворуч для великих n.

Ungolfed в тестовій програмі

f=->s,n{
  p=0                            #pointer to where the next character must be plotted to
  a=(' '*(w=s.size)+$/)*n        #w=length of input. make a string of n lines of w spaces, newline terminated
  w.times{|i|                    #for each character in the input (index i)
    a[p]=s[i]                    #copy the character to the position of the pointer
    p+=[w+1,1,-w-1,1][i/(n-1)%4] #move down,right,up,right and repeat. change direction every n-1 characters
  }
a}                               #return a

puts $/,f['a',3]

puts $/,f['Hello,World!',3]

puts $/,f['ProgrammingPuzzlesAndCodeGolf',4]

puts $/,f['IHopeYourProgramWorksForInputStringsWhichAre100CharactersLongBecauseThisTestCaseWillFailIfItDoesNot.',5]

puts $/,f['!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~',10]

7

JavaScript (ES6), 143 байти

(s,n)=>[...s].map((c,i)=>(a[x][y]=c,i/=n)&1?y++:i&2?x--:x++,a=[...Array(n--)].map(_=>[]),x=y=0)&&a.map(b=>[...b].map(c=>c||' ').join``).join`\n`

Де \nпредставляє буквальний новий рядок. Безголівки:

function snakify(string, width) {
    var i;
    var result = new Array(width);
    for (i = 0; i < width; i++) result[i] = [];
    var x = 0;
    var y = 0;
    for (i = 0; i < string.length; i++) {
       result[x][y] = string[i];
       switch (i / (width - 1) & 3) {
       case 0: x++; break;
       case 1: y++; break;
       case 2: x--; break;
       case 3: y++; break;
    }
    for (i = 0; i < width; i++) {
        for (j = 0; j < r[i].length; j++) {
            if (!r[i][j]) r[i][j] = " ";
        }
        r[i] = r[i].join("");
    }
    return r.join("\n");
}

7

Pyth, 85 74 59 байт

Kl@Q0J0=Y*]d-+*@Q1K@Q1 1FNr1@Q1=XY-+*KNN1b;VK=XYJ@@Q0N=+J@[+K1 1-_K1 1).&3/N-@Q1 1;sY

=G@Q1=H@Q0KlHJ0=Y*]dt+*GKGFNr1G=XYt+*KNNb;VK=XYJ@HN=+J@[hK1t_K1).&3/NtG;sY

Klz=Ym;+*QKQVQ=XYt+*KhNhNb;VK=XYZ@zN=+Z@[hK1_hK1).&3/NtQ;sY

Дякуємо @FryAmTheEggman за велику допомогу мені!

Гольфували, наскільки я міг. Спробуйте тут! Чомусь обертання рядків робить висновок дивним. Ви можете ознайомитись із результатами на повній сторінці

Пояснення

Вдихніть секунду і зосередьтеся. Це можна розділити на три розділи, як майже будь-який "класичний" алгоритм.

Перший розділ

Тут ініціалізовані змінні. Його можна розділити на дві частини:

Klz=Ym;+*QKQ
Klz                Assign len(input[0]) to K. (length of input String)
   =Ym;+*QKQ       Assign an empty list to Y of length K*input[1]-input[1]-1, where input[1] is the size of the snake 
                   (thus the height of the final string)

друга частина:

VQ=XYt+*KhNhNb;
VQ                       For N in range(0, input[1]), where input[1] is the size of the snake 
  =                        Assign to Y. Y is implicit, it is the last variable we used.
   XYt+*KhNhNb               Y[K*N+N-1]="\n". Can be broken down in four parts :
   X                           Replace function. X <A: list> <B: int> <C: any> is A[B]=C
    Y                          A: The array we initialized in the first section.
     t+*KhNhN                  B: K*(N+1)+N+1 (N is the for loop variable)
             b                 C: Newline character ("\n")
              ;          End the loop.

Другий розділ

Він містить фактичну логіку.

VK=XYZ@zN=+Z@[hK1_hK1).&3/NtQ;
VK                                         For N in range(0, K), where K is the length of the input string (see first section)
  =                                          Assign to Y. Y is implicit, it is the last variable we used.
   XYZ@zN                                    Same as in section 2. This is a replacement function. Y[Z] = input[0][N]. Z is initially 0.
         =+Z@[hK1_hK1).&3/NtQ                Again this can be broken down :
         =+Z                                   Add to Z
             [hK1_hK1)                         Array containing directions. Respectively [K+1, 1, -K-1, 1]
            @         .&3/NtQ                  Lookup in the array, on index .&3/N-@Q1 1:
                      .&3                        Bitwise AND. .& <int> <int>
                         /NtQ                    (input[1]-1)/N, where input[1] is the size of the snake
                             ;             End the loop

Третій розділ

Це вихідна частина. Не дуже цікаво ...

sY    Join the array Y. Implicitly print.

БОНУС

Я написав програму pyth із цього сценарію python.

input=["ThisIsAnExampleOfASnakifiedString", 4];
width=len(input[0]);
height=input[1];
pointer=0;
directions = [width+1,1,-width-1,1] #Respectively Down, right, up, right (left is replaced by right because of snake's nature. Doesn't go left).
output=[' ' for i in range(0, width*height+height-1)];
for N in range(1, height):
    output[width*N+N-1]="\n";
for N in range(0, len(input[0])):  
    output[pointer]=input[0][N];
    pointer+=directions[3&(N/(height-1))];
print "".join(output);

5

JavaScript (ES6), 122 байти

document.write("<pre>"+(

// --- Solution ---
s=>n=>[...s].map((c,i)=>(a[p]=c,p+=[l+1,1,-l-1,1][i/n%4|0]),p=0,a=[...(" ".repeat(l=s.length)+`
`).repeat(n--)])&&a.join``
// ----------------

)("IHopeYourProgramWorksForInputStringsWhichAre100CharactersLongBecauseThisTestCaseWillFailIfItDoesNot.")(5))

Той самий алгоритм, що і у відповіді @ LevelRiverSt.


4

C, 138 байт

char*h[]={"\e[B\e[D","","\e[A\e[D",""},t[999];i;main(n){system("clear");for(scanf("%s%d",t,&n),--n;t[i];++i)printf("%c%s",t[i],h[i/n%4]);}

Для цього використовуються втечі ANSI. Працює в Linux-терміналі.

Безголівки:

char*h[]={"\e[B\e[D","","\e[A\e[D",""},
    /* cursor movement - h[0] moves the cursor one down and one left,
    h[2] moves the cursor one up and one left. */
t[999];i;
main(n){
    system("clear");
    for(scanf("%s%d",t,&n),--n;t[i];++i)
        printf("%c%s",t[i],h[i/n%4]);
}

1

JavaScript (ES6), 131

Алгоритм: відображення позиції x,yу виводі на індекс у вхідному рядку, якось так, як ця (не пов'язана) відповідь.

Я запозичив у @LevelRiverSt хитрість збереження горизонтальної ширини, що дорівнює вхідній довжині.

a=>m=>eval('for(--m,t=y=``;y<=m;++y,t+=`\n`)for(x=0;a[x];)t+=a[2*(x-x%m)+((h=x++%(2*m))?h-m?!y&h>m?h:y<m|h>m?NaN:m+h:m-y:y)]||`.`')

Менше гольфу

Це був перший робочий проект перед гольфом

f=(a,n)=>{
  l=a.length
  m=n-1
  s=m*2 // horizontal period

  b=-~(~-l/s)*m // total horizontal len, useless in golfed version
  t=''
  for(y=0;y<n;y++)
  {
    for(x=0;x<b;x++)
    {
      k = x / m | 0
      h = x % s
      if (h ==0 )
        c=k*s+y
      else if (h == m)
        c=k*s+m-y
      else if (y == 0 && h>m)
        c=k*s+h
      else if (y == m && h<m)
        c=k*s+m+h
      else
        c=-1
      t+=a[c]||' '
    }
    t+='\n'
  }
  return t
}  

Тест

F=a=>m=>eval('for(--m,t=y=``;y<=m;++y,t+=`\n`)for(x=0;a[x];)t+=a[2*(x-x%m)+((h=x++%(2*m))?h-m?!y&h>m?h:y<m|h>m?NaN:m+h:m-y:y)]||` `')

function test()
{
  var n=+N.value
  var s=S.value
  O.textContent=F(s)(n)
}  

test()
#S {width:80%}
#N {width:5%}
<input id=N value=5 type=number oninput='test()'>
<input id=S 5 oninput='test()'
value='IHopeYourProgramWorksForInputStringsWhichAre100CharactersLongBecauseThisTestCaseWillFailIfItDoesNot.'>
<pre id=O></pre>


0

Pyth, 122 байти

=k@Q0J-@Q1 1K*4J=T*@Q1[*lkd;Vlk=Z+*%NJ/%N*J2J*/N*J2J=Y.a-+**/%N*J2J!/%NK*J2J*%NJ!/%N*J2J**!/%N*J2J/%NK*J2J XTYX@TYZ@kN;jbT

Я створив формулу для обчислення позицій x, y кожного символу на основі розміру сегмента / модуля, але вони стали більшими, ніж я очікував: c

Пояснення:

=k@Q0                                                                                                                     # Initialize var with the text
     J-@Q1 1                                                                                                              # Initialize var with the segment size (minus 1)
            K*4J                                                                                                          # Initialize var with the "block" size (where the pattern start to repeat)
                =T*@Q1[*lkd;                                                                                              # Initialize output var with an empty array of strings
                            Vlk                                                                                           # Interate over the text
                               =Z+*%NJ/%N*J2J*/N*J2J                                                                      # Matemagics to calculate X position
                                                    =Y.a-+**/%N*J2J!/%NK*J2J*%NJ!/%N*J2J**!/%N*J2J/%NK*J2J                # Matemagics to calculate Y position
                                                                                                          XTYX@TYZ@kN;    # Assign the letter being iterated at x,y in the output
                                                                                                                      jbT # Join with newlines and print the output

Тестуйте тут

Для формул Math я використав мод для генерації прапорців 0/1, а потім помножив на коефіцієнт на основі вхідних даних n, додав таблицю з кожним кроком на фрагменті нижче


Чи можете ви пояснити Matemagics? тобто писати їх більш людським способом?
FliiFe

@FliiFe зроблено з:
Rod

0

PHP, 127 126 124 120 119 118 117 110 106 байт

Використовує кодування ISO-8859-1.

for(;($q=&$o[$y+=$d]||$q=~ÿ)&&~Ï^$q[$x+=!$d]=$argv[1][$a];$a++%($argv[2]-1)?:$d-=-!$y?:1)?><?=join(~õ,$o);

Виконати так ( -dдодано лише для естетики):

php -r 'for(;($q=&$o[$y+=$d]||$q=~ÿ)&&~Ï^$q[$x+=!$d]=$argv[1][$a];$a++%($argv[2]-1)?:$d-=-!$y?:1)?><?=join(~õ,$o);' "Hello W0rld!" 3 2>/dev/null;echo

Безголівки:

// Iterate over ...
for (
    ;
    // ... the characters of the input string. Prepend `0` so a 0 in the input
    // becomes truthy.
    0 . $char = $argv[1][$a];

    // Use modulo to determine the end of a stretch (where direction is
    // changed).
    // Change direction (`0` is right, `-1` is up and `1` is down). When
    // y coordinate is `0`, increment the direction, else decrement.
    $a++ % ($argv[2] - 1) ?: $direction += $y ? -1 : 1
)

    (
        // Increase or decrease y coordinate for direction -1 or 1 respectively.
        // Check whether the array index at new y coordinate is already set.
        $reference =& $output[$y += $direction] ||
        // If not, create it as a string (otherwise would be array of chars).
        // Null byte, won't be printed to prevent leading char.
        $reference = ~ÿ;

        // Increment x coordinate for direction 0. Set the output char at the
        // current coordinates to the char of the current iteration.
    ) & $reference[$x += !$direction] = $char;

// Output all lines, separated by a newline.
echo join(~õ, $output);

Налаштування

  • Збережено байт за допомогою, <а не!=
  • Збережено 2 байти, встановивши рядок 0на перший, тому мені не доведеться додавати інший 0(у випадку, якщо перший вихід у рядку був а 0), даючи truthy00 .
  • Збережено 4 байти, використовуючи посилання замість повторення $o[$y]
  • Збережено байт, використовуючи модуль замість ==порівняння напряму з 1 для зміни координати x
  • Збережено байт, видаливши тип cast nullдо intзміщення рядка, оскільки зміщення рядка передається int у будь-якому випадку
  • Збережено байт за допомогою тегу короткого друку
  • Збережено 7 байт, покращивши логіку напрямку
  • Збережено 4 байти, безпосередньо призначивши таблицю для запобігання проміжного $c
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.