Golf un tornado de cuerdas


24

Cómo se tuercen las cuerdas

El algoritmo de torsión es muy simple. Cada columna se desplaza hacia abajo por su índice (col 0 se mueve hacia abajo 0, col 1 se mueve 1, ...). El cambio de columna se ajusta a la parte superior. Funciona así:

aaaa
bbbb
cccc

Se convierte en:

a
ba
cba
----
 cba
  cb
   c

Con todo debajo de la línea envolviendo a la cima. Ejemplo real:

Original:
\\\\\\\\\\\\
............
............
............

Twisted:
\...\...\...
.\...\...\..
..\...\...\.
...\...\...\

Entrada

La entrada es una matriz de cadenas o una cadena de varias líneas. Todas las líneas tienen la misma longitud.

Salida

La cadena retorcida, salida multilínea a salida estándar (o la alternativa más cercana).

Ejemplos:

( >denota entrada, el espacio final es importante)

>Hello, world!
>I am another 
>string to be 
>twisted!     

Hwrmoe oo br!
Ieii ,dttr e 
s lsna !ohl  
ttaltgnw  ed 


>\\\\\\\\\\\\
>............
>............
>............

\...\...\...
.\...\...\..
..\...\...\.
...\...\...\


>abcdefg
>.......

a.c.e.g
.b.d.f.


>abcdefghij
>..........
>..........

a..d..g..j
.b..e..h..
..c..f..i.


>\\\\.....././
>...../.......
>........././.
>..../.^\\....

\.........../
.\....^..../.
..\../.\../..
...\/...\/...

>cdeab
>deabc
>eabcd
>abcde

cbbbb
ddccc
eeedd
aaaae


>aeimquy37
>bfjnrvz48
>cgkosw159
>dhlptx260

ahknqx147
beloru258
cfipsvy69
dgjmtwz30


>abcdefghi
>jklmnopqr
>stuvwxyz1
>234567890

a3ume7yqi
jb4vnf8zr
skc5wog91
2tld6xph0

12
Es mejor que no haya un Mathematica incorporado para esto.
Mama Fun Roll

1
¿Podemos suponer que la entrada solo contendrá ASCII? ¿O solo avances de línea ASCII + imprimibles o algo así?
Martin Ender

Sí, solo ASCII y nueva línea (a menos que tome la entrada como una matriz).
J Atkin

Respuestas:


3

Brachylog , 5 bytes

iᵇ↻₎ᵐ

Pruébalo en línea!

Obtiene entrada como una matriz de columnas (que parece estar dentro de las especificaciones de la pregunta).

iᵇ- Para cada elemento de la matriz, emparejarlo con su índice (basado en 0)
- asignar este predicado a cada elemento del resultado:
↻₎- permutar (la columna) circularmente por la cantidad especificada como el último elemento (el índice)

Se extiende fácilmente a una versión que acepta una sola cadena multilínea:

13 bytes

ṇẹ\iᵇ↻₎ᵐ\cᵐ~ṇ

Pruébalo en línea!


Esta es una compresión de información sorprendente.
J Atkin

7

Pyth, 11

jC.>R~hZC.z

Pruébalo aquí

jC.>R~hZC.z    ##  implicit: .z = list of input split by lines
        C.z    ##  transpose .z to get columns
  .>R~hZ       ##  shift each column by it's index
               ##  equivalent to .e.>bk
jC             ##  transpose back and join by newlines

7

APL (Dyalog) , 7 bytes

⊖⊖⊖⍨⍬⍋⍉

Requiere ⎕io←0

Pruébalo en línea!

⍬⍋⍉obtiene el rango de 0 al número de columnas invertidas gira
verticalmente
⊖⊖⍨⍬⍋⍉(verticalmente) la entrada invertida (verticalmente) invirtiendo 0,1..
eso, y devuélvelo.


6

Retina , 111 101 92 87 bytes

El recuento de bytes supone la codificación ISO 8859-1.

(?<=((.))*)(?=(?<1>.*¶)*.*(?<=(?=(?<-2>.)*(.))(?<-1>.+¶)*.*(.(?<=^(?<-1>¶?.+)*))*)).
$3

Woo, lo resolvió en una sola sustitución de expresiones regulares. :) (Lo más probable es que haya una solución más corta usando varios, pero ¿dónde está la diversión en eso ...)

Pruébalo en línea!

Explicación

Esto requiere un conocimiento básico de grupos de equilibrio . En resumen, el sabor de expresiones regulares de .NET le permite capturar varias veces con un solo grupo, empujando todas las capturas a una pila. Esa pila también se puede extraer, lo que nos permite usarla para contar cosas dentro de la expresión regular.

(?<=((.))*)

Esto empuja una captura en ambos grupos 1y2 para cada personaje en frente de la partida (en la línea actual). Es decir, cuenta la posición horizontal del partido.

El resto está en una anticipación:

(?=(?<1>.*¶)*.* [...] )

Emparejamos cada línea y también la empujamos hacia el grupo 1, de modo que el grupo 1ahora es la suma de la posición horizontal y vertical (donde esta última se cuenta desde abajo ). Esto esencialmente etiqueta las diagonales de la cuadrícula con valores crecientes a partir de la esquina inferior izquierda. Ese.* entonces solo mueve el cursor del motor al final de la cadena.

Ahora cambiamos a un mirar hacia atrás, que coincide de derecha a izquierda en .NET:

(?<= [...] (.(?<=^(?<-1>¶?.+)*))*)

Esto repetidamente hará estallar exactamente las Hcapturas del grupo 1(donde Hes la altura de la entrada). El propósito de esto es tomar el módulo grupal H. Luego, el grupo 1contiene la fila (contada desde la parte inferior) de la cual elegir el nuevo personaje en la columna actual.

(?=(?<-2>.)*(.))(?<-1>.+¶)*.*

Otra mirada atrás, otra vez desde la derecha. (?<-1>.+¶)*.+ahora usa group 1para encontrar la fila desde la cual elegir el nuevo personaje y luego la búsqueda anticipada encuentra la columna correcta usando group 2.

El carácter deseado es capturado en grupo 3y reescrito por la sustitución.


Ah, leer la fuente de Retina fue agradable y claro :) $+parece útil ... especialmente si solo quieres hacer una sustitución: ^)
FryAmTheEggman

@FryAmTheEggman en $+realidad es bastante inútil ... su descripción en MSDN suena mucho más útil de lo que es porque implica que (a)|(b)-> $+$+duplicaría todos los asy bs, pero en su lugar elimina todos los as, porque solo se refiere al último grupo sintáctico . Eso significa que es solo una forma de evitar contar todos los grupos si eres demasiado vago (como yo). Para jugar al golf, solo ahorra bytes cuando tienes más de 9 grupos, lo que probablemente es bastante raro para empezar.
Martin Ender

Eso es desafortunado ... ¿Quizás la retina podría tener un nuevo tipo de grupo de reemplazo que devolvería el último grupo de partido no vacío? De todos modos, gracias por la explicación! :)
FryAmTheEggman 01 de

@FryAmTheEggman Lo hará (es una de las cosas que tenía en mente al reescribir Regex.Replacepara Retina, pero aún no pude implementarlo).
Martin Ender

4

CJam, 13 bytes

qN/zee::m>zN*

Pruébalo aquí.

Explicación

q    e# Read all input.
N/   e# Split into lines.
z    e# Transpose to get an array of columns.
ee   e# Enumerate, pairing each column with its index.
::m> e# Map: fold: rotate (cyclically shifting each column by its index).
z    e# Transpose again.
N*   e# Join with linefeeds.

2
Casi puedes pronunciar ese código fuente.
mınxomaτ

4

TeaScript, 10 bytes

xHl@C(r╢tD

Gracias a la sintaxis extremadamente concisa de TeaScript 3, esto es realmente corto: D

Sería 1 byte más corto si el bucle Sigma no tuviera errores

Pruébalo en línea

Explicación

      // Implicit, x = input
xH    // Transpose input
l@    // Loop
 C(r╢   // Cycle column by index
        // `╢` exits loop
t    // Transpose
D    // Join on \n

3

Python 3, 164 bytes

No es la mejor respuesta por asomo, pero la primera en Python ...

s=list(zip(*open(0).readlines()))[:-1]
r=[[s[i][(j-i)%len(s[i])] for j in range(len(s[i]))] for i in range(len(s))]
print('\n'.join([''.join(l) for l in zip(*r)]))

1
Puede guardar un puñado de bytes sacando el espacio que sigue a una )o ]en la mayoría de los casos, por ejemplo, ''.join(l)for l in....es perfectamente válido
wnnmaw

3

MATLAB, 92 36 bytes

s=bsxfun(@circshift,s,0:size(s,2)-1)

Suponiendo que la cadena de entrada sya tiene la forma de una matriz / matriz de caracteres 2D, por ejemplo

s = ['abcdefg';'.......'];
s = ['\\\\.....././';'...../.......';'........././.';'..../.^\\....'];

Explicación: iterar a través de las columnas de la matriz. Para cada columna, realice un desplazamiento circular de sus elementos por el número de caracteres que equivale al índice de la columna (-1 debido a la indexación de MATLAB).


2

Brachylog , 96 bytes

$\:0{h_.|[M:I]hh:I{bh0,?h.|[C:I]h$)D,I-1=:Dr:2&.}C,I+1=J,Mb:J:1&:[C]rc.}$\{hA,[A]:"~s
"w,?b:3&;}

Esto espera una lista de cadenas de códigos de caracteres como entrada y sin salida, p. Ej. brachylog_main([`aaaa`,`bbbb`,`cccc`],_).

Esa es una respuesta ridículamente larga, y probablemente haya una forma mucho más corta de hacerlo.

Explicación

§ Main Predicate

$\:0{}$\{}                            § Create a list containing the transposed input and 0
                                      § Call sub-predicate 1 with this list as input
                                      § Transpose its output and pass it as input to
                                      § sub-predicate 3


§ Sub-predicate 1

h_.                                   § If the matrix is empty, output is empty list
   |                                  § Else
    [M:I]hh:I{}C,                     § Input is [M,I], call sub-predicate 2 with the first
                                      § line of M and I as input. Its output is C.
                 I+1=J,Mb:J:1&        § Call sub-predicate 1 with M minus the first line
                                      § and I+1 as input
                              :[C]rc. § Its output is appended after C, which is then
                                      § unified with the output of sub-predicate 1.


§ Sub-predicate 2

bh0,?h.                               § If the second element of the input list is 0,
                                      § output is the first element of the input
       |                              § Else
        [C:I]                         § Input is [C,I]
             h$)D,                    § Perform a circular permutation of C from left to
                                      § right (e.g. [a,b,c] => [c,a,b]) and unify it with D
                  I-1=:Dr:2&.         § Call sub-predicate 2 with D and I-1 as input, unify
                                      § its output with sub-predicate 2's output


§ Sub-predicate 3

hA,[A]:"~s\n"w,                       § Write the first line of the input as a char codes
                                      § string followed by a new line

               ?b:3&;                 § Call sub-predicate 3 with input minus the first
                                      § line. If it fails (empty input), terminate

2

JavaScript, 92 89 bytes

3 bytes de descuento gracias @Neil .

s=>(z=s.split`
`).map((m,i)=>m.replace(/./g,(n,j)=>z[((l=z.length)*j+i-j)%l][j])).join`
`


Puede guardar 3 bytes utilizando replace: m.replace(/./g,(n,j)=>z[((l=z.length)*j+i-j)%l][j]).
Neil

1
De hecho, [...m].map(todo el camino hasta e incluyendo el primero .join.
Neil

2

Python 2, 115 bytes

lambda s:'\n'.join("".join(s)for s in zip(*[k[-i%len(k):]+k[:-i%len(k)]for i,k in enumerate(zip(*s.split('\n')))]))

Gracias a la maravilla de haber ziplogrado reducir esto a una línea. Véalo en acción aquí .


2

MATL , 18 21 bytes

Zy2):"G@Z)@qYS]N$h

La entrada es de la forma

['Hello, world!'; 'I am another '; 'string to be '; 'twisted!']

Pruébalo en línea!

Cómo funciona :

Zy       % implicitly take input: 2D char array. Get its size
2)       % second element from size vector: number of columns, say n
:        % create vector [1,2,...,n]
"        % for each element k in that vector
  G      %   push input
  @      %   push k
  Z)     %   k-th column from input
  @qYS   %   circularly shift k-1 positions
]        % end for loop
N$h      % concatenate all stack contents horizontally
         % implicitly display

1

F #, 105 bytes

Mi primer intento (solo \nse requiere un personaje):

let m x y=(x%y+y)%y
let f(a:string[])=Array.mapi(fun i x->String.mapi(fun j _->a.[m(i-j)a.Length].[j])x)a

Uso:

f [| @"\\\\\\\\\\\\"
     "............"
     "............"
     "............" |]

No creo haber visto F # antes en PPCG.
J Atkin

1

JavaScript (ES6), 73 bytes

t=>t.replace(/./g,(_,i)=>t[(i+s*l-i%l*l)%s],l=t.search`
`+1,s=t.length+1)

Explicación

t=>
  t.replace(/./g,(_,i)=> // replace each character at index i
    t[                   // get the character at index:
      (i                 // start at i
        +s*l             // add s*l to ensure the result is always positive for %s
        -i%l*l           // move the index upwards the num of chars from start of the line
      )%s                // shift the index into the the range of s
    ],
    l=t.search`
`+1,                     // l = line length
    s=t.length+1         // s = input grid length (+1 for the missing newline at the end)
  )

Prueba


1

Japt, 29 bytes

Uy £XsV=(Y*Xl -Y %Xl)+X¯V}R y

¡Pruébalo en línea!

Cómo funciona

Uy        // Transpose rows and columns in the input string.
£     }R  // Map each item X and index Y in the result, split at newlines, to:
Y*Xl -Y   //  Take Y times X.length and subtract Y.
%Xl)      //  Modulate the result by X.length.
XsV=      //  Set V to the result of this, and slice off the first V chars of X.
+X¯V      //  Concatenate this with the first V chars of X.
y         // Transpose the result again.
          // Implicit: output last expression

1

Haskell, 81 bytes

let t=transpose in t.snd.mapAccumR(\c l -> 1+c,take(length l)(drop c$cycle l))0.t

reimplementación del ejemplo de CJam, aunque el reverso, el mapa y la enumeración son parte de mapAccumR, el snd elimina el acumulador ya que ya no lo necesitamos, la reversión es solo un efecto secundario del pliegue derecho.


1

Haskell, 65 bytes

g l@("":_)=l;g l|t<-tail<$>l=zipWith(:)(head<$>l)$g$last t:init t

Ejemplo de uso: g ["1111","2222","3333"]-> ["1321","2132","3213"].


1

MATL , 9 bytes

"@X@qYS&h

Pruébalo en línea!

Bastante similar en el núcleo a la respuesta MATL existente de Luis Mendo , pero más corta al usar características que probablemente no estaban en el lenguaje en ese momento: 1. "itera a través de las columnas de una matriz automáticamente ahora, por lo que no es costoso construir índices de columnas e indexarlas ( este es el problema), 2. &hcomo una forma abreviada de decir N$h, y 3. final de ciclo implícito si] no se especifica.

Alternativamente, para el mismo bytecount:

tsn:ql&YS

Pruébalo en MATL Online

      &YS   % circularly shift the matrix
     l      % across rows (i.e. shift each column) by the amounts
            %  given by this array:
tsn         % duplicate input, get the sum of each column, get the 
            %  number of elements in that (which is the number of columns)
   :q       % construct range 1 to ncols, then decrement to start at 0
            % (implicit output)

0

C (clang) , 114 bytes

Funciona en GCC bajo MinGW. El GCC de TIO se confunde al usar strlenen la expresión init del primer bucle for.

f(L,n)char**L;{for(int l=strlen(*L),i=0,j,c;i<n;i++)for(j=c=0;j<=l;j++,c=c?c-1:n-1)putchar(l^j?L[(c+i)%n][j]:10);}

Pruébalo en línea!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.