Combinación lineal de dos vectores.


11

Resumen Ejecutivo

Dada una entrada que representa dos vectores y sus respectivos "pesos", produce una salida que también representa la suma ponderada de esos vectores.

Desafío

La entrada consistirá en una o más líneas de los siguientes caracteres:

  • exactamente una aparición del dígito 0, que representa el origen en un plano bidimensional;
  • exactamente otros dos dígitos (1-9; pueden o no ser el mismo dígito), cuyas posiciones relativas al origen representan vectores, y cuyos valores representan los pesos unidos a estos vectores;
  • cierto número de "personajes de fondo". El solucionador puede elegir un carácter de fondo específico; por ejemplo, elegiré "." (principalmente para la legibilidad humana). Alternativamente, los caracteres de fondo pueden ser cualquier cosa que parezca un espacio en blanco.

(El solucionador puede elegir si la entrada es una sola cadena de varias líneas o una matriz de cadenas de una línea).

Por ejemplo, la entrada

....2
.0...
...3.

representa un vector en coordenadas (3,1) con peso 2, y un vector en coordenadas (2, -1) con peso 3.

La salida debería ser casi la misma que la entrada, con los siguientes cambios:

  • un "carácter de resultado", elegido por el solucionador, que se agregará en la posición especificada por la suma ponderada de los vectores de entrada (de manera equivalente, en la posición que es la combinación lineal apropiada de los vectores de entrada);
  • tantos caracteres de fondo como sean necesarios para ajustar el origen, los dos vectores de entrada y el vector de salida en la misma imagen. Se pueden incluir caracteres de fondo adicionales si se desea; La única restricción es que, si el carácter de fondo es un carácter visible, toda la salida debe ser de forma rectangular y cada carácter que no represente un vector debe ser el carácter de fondo. (Si se utiliza el espacio en blanco como caracteres de fondo, entonces no es necesario aplicar estas restricciones).

(En general, si tenemos un vector (v, w) con peso a y un segundo vector (x, y) con peso b, su suma ponderada es a (v, w) + b (x, y) = (av + bx, aw + por).)

En el ejemplo anterior, la combinación lineal apropiada es 2 * (3,1) + 3 * (2, -1) = (12, -1). Si usamos "X" como el carácter de resultado, entonces la salida podría verse como

....2.........
.0............
...3.........X

o

................
...2............
0...............
..3.........X...
................
................

Puntuación de habitual : la respuesta más corta, en bytes, gana.

Ejemplo de entrada y salida

Si se utiliza un espacio en blanco, la entrada anterior se vería como

    2
 0
   3

y la salida se vería así

    2
 0
   3         X

Los caracteres / líneas de espacios en blanco iniciales / finales son irrelevantes; si son invisibles para el lector, está bien. (Dicho esto, para el resto de los ejemplos volveré a usar "." Para el carácter de fondo, para que sea más fácil de leer).

Si ambos vectores tienen peso 1, entonces el resultado se verá como un paralelogramo: la entrada

.1.
...
1.0

conduce a la salida

X.1.
....
.1.0

Tenga en cuenta que este paralelogramo puede degenerarse si los vectores de entrada son colineales: la entrada

0.1..1

conduce a la salida

0.1..1.X

Es posible que el vector resultante sea igual a uno de los vectores de entrada o al origen; en este caso, simplemente sobrescribe el carácter de entrada. Por ejemplo, la entrada

..2.0.1...

produce la salida

..X.0.1...

(donde en entrada y / o salida, los períodos iniciales y finales podrían eliminarse). La entrada

.....3
......
...0..
......
......
2.....

produce la salida

.....3
......
...X..
......
......
2.....

Finalmente la entrada

90
.8

produce la salida

........90
.........8
..........
..........
..........
..........
..........
..........
X.........

1
Bienvenido a PPCG! Bonito primer desafío.
AdmBorkBork

@TimmyD Gracias por la bienvenida y el aliento :)
Greg Martin

1
Finalmente, ya que estoy seguro de que otros lo mencionarán, esto es coquetamente cercano a un desafío de camaleón, ya que una porción considerable de código simplemente analizará la entrada, cuando ese no es realmente el objetivo principal del desafío.
AdmBorkBork

¿Hay algún límite en el número de filas / columnas en la entrada o salida correcta?
Sparr

@TimmyD He agregado la fórmula general para la suma ponderada y también he aclarado que cualquiera de los formatos de entrada está bien. Estoy de acuerdo en que esto está cerca de un desafío de camaleón (aunque esperaba que algunos idiomas pudieran tener la capacidad de "caminar" directamente en el tablero para resolver el problema); Sin embargo, los comentarios sobre Sandbox fueron modestamente más positivos que negativos, así que decidí ir con ellos.
Greg Martin

Respuestas:


7

MATL , 48 bytes

tZyyX:UX>*Yat48-tt0>*3#fbbhb~2#fh-*s7M+'X'wZ}4$(

El personaje de fondo es el espacio. La entrada es una matriz de caracteres 2D con filas separadas por punto y coma. Entonces los casos de prueba tienen entradas respectivas:

['    2'; ' 0   '; '   3 ']
[' 1 '; '   '; '1 0']
['0 1  1']
['  2 0 1   ']
['     3'; '      '; '   0  '; '      '; '      '; '2     ']
['90'; ' 8']

La salida incluye una cantidad significativa de espacios en blanco de relleno.

Pruébalo en línea!


2

Python 3, 374355 bytes

Solución de Python no muy refinada que es muy generosa con el relleno (usa la distancia máxima del tablero de ajedrez). La entrada es una sola línea donde las filas se separan con tuberías | (aunque el algoritmo puede usar fácilmente cualquier cosa que no sea alfanumérica que no sea una nueva línea o un EOF). Cualquier cosa no alfanumérica o | funciona para el relleno de entrada, el relleno de salida utiliza puntos. Se agradece la retroalimentación y la mejora de los golfistas de pitón más experimentados.

Editar: Algunas mejoras gracias a @TheBikingViking. También agregué aún más márgenes ya que no era lo suficientemente generoso con el relleno.

s=input()
l=[len(s),1+s.find('|')]['|'in s]
P=sorted([int(c),i%l,i//l]for i,c in enumerate(s)if c.isalnum())
L=X=Y=0
P[0][0]=-sum(p[0]for p in P)
for w,x,y in P:L=max(abs(x),abs(y),L);X+=x*w;Y+=y*w
P+=[['X',P[0][1]+X,P[0][2]+Y]]
P[0][0]=0
L=2*max(abs(X),abs(Y),L)
S=[2*L*["."]for _ in[0]*2*L]
for w,x,y in P:S[L+y][L+x]=str(w)
for s in S:print(''.join(s))

¡Buena respuesta! Echa un vistazo a los consejos de Python . Algunos punteros: 1. Es una buena idea especificar si usó Python 2/3, ya que algunas características difieren. 2.Puede hacer en [a,b][condition]lugar de b if condition else cen la línea 2. sortedtoma cualquier iterador, incluida una declaración de generador, para que pueda soltar el par externo de corchetes. 3. zip(p)debería funcionar en lugar de p[0] for p in P.
TheBikingViking

4. Puede hacer en P+=[stuff]lugar de P.append([stuff])en la línea 7. 5. Hacer en ["."]lugar de list("."). (3. debería haber sido zip(p)[0].)
TheBikingViking

Lo sentimos, debería ser capital Pen zip.
TheBikingViking

5. Deberías poder hacerlo S=[stuff]*2*Len la línea 10.
TheBikingViking

[1] Buen punto, agregará la versión de Python. [2] Buen patrón, pero no funcionará con index(error en nada encontrado). Trabajará con findsin embargo. [Re. ordenado] Gracias, perdí eliminarlos al agregar el sorted. [3] zip (* P) ​​[0] no funciona en python 3 (el objeto zip no se puede indexar). [4] P + = [cosas] no funcionará, aunque P + = [[cosas]] sí. [5] Gracias. [los otros 5] No funciona. Necesito nuevas listas, no referencias.
algmyr

2

JavaScript, 534 528 502 bytes

n="indexOf"
J="join"
B=X=>X.split(O)
O='\n'
w=i[n](O)+1
h=B(i).length
Z=(X,Y,R)=>{C[R]+=X-1;return Array(X)[J](Y)}
C=[0,0,0]
G=(X,E,T,U,R)=>X>0&E>=0?Z(X+E+1+T,U,R):""
o=i[n]("0")
L=X=>Math.floor(X/(w-1))
l=L(o)
c=o%w
x=y=0
j=i
for(z="1";z<="9";z++){while(p=~j[n](z)){j=j.replace(z," ")
x+=~p%w-l
y+=L(~p)-c}}
I=B(i).map(X=>G(-x,-l,0," ",0)+X+G(x,l-w+2,0," ",2))
N=Z(I[0].length+1," ",2)
A=B(G(-y,-c,0,N+O,1)+I[J](O)+G(y,c-h,1,O+N,2))
M=y+c+C[1]
O=""
m=B(A[M])
m[x+l+C[0]/h]="x"
A[M]=m[J]("")
A[J]("\n")

Tenga en cuenta que el relleno es óptimo. Este programa supone que contiene la cadena sin formato, con las líneas separadas por \ncaracteres. El relleno se realiza con espacios, y el carácter resultante es minúscula x.

Este es mi primer intento de golf de código.

Aspectos técnicos: - El tamaño del programa se duplicó aproximadamente (y su complejidad aumentó drásticamente) para tener en cuenta el carácter del resultado, principalmente porque las cadenas de JavaScript son inmutables.


Explicación línea por línea:

n="indexOf"
J="join"
B=X=>X.split(O)

Los uso mucho, por lo que almacenarlos en cadenas me ahorró algo de espacio. Puede ver a continuación que para la splitfunción, simplemente he creado un alias; Esto se debe a que solo necesitaba un argumento, el otro era constante. Para indexOfy join, sin embargo, habría sido más largo.

O='\n'
w=i[n](O)+1
h=B(i).length

Nada complicado aquí, estoy leyendo el ancho y la altura de la matriz inicial. Tenga en cuenta el uso de i[n]para acceder indexOf, mientras que splitse maneja de manera diferente.

Z=(X,Y,R)=>{C[R]+=X-1;return Array(X)[J](Y)}

Esto se está poniendo interesante. Básicamente, esta función crea concatena J-1 veces la cadena X y la devuelve. Esto se utiliza para generar cadenas de espacios para el relleno.

C=[0,0,0]

Esta matriz contendrá el número de líneas y columnas agregadas por el relleno (desactivado por un factor h en el primer caso). La última celda es basura, y me impide tener un argumento adicional en la función a continuación.

G=(X,E,T,U,R)=>X>0&E>=0?Z(X+E+1+T,U,R):""

Esta función solo maneja el relleno (tanto líneas como columnas); determina, basándose en una coordenada del vector de resultados (X), y el número de líneas / columnas para generar (E), si es necesario crear uno. el X+E+1+Tes sólo un truco para ahorrar algo de espacio, Ues la cadena de llenado (un espacio para las columnas, y una línea completa de líneas), y volveremos a R. Esta función básicamente devuelve, en el caso de una línea, el relleno requerido al principio o al final de dicha línea y, en el caso de una columna, devuelve las líneas de relleno requeridas antes o después de las líneas originales.

o=i[n]("0")
L=X=>Math.floor(X/(w-1))
l=L(o)
c=o%w

Aquí leemos la posición del origen y recuperamos sus coordenadas. L es una función para convertir un índice en un número de línea.

x=y=0
j=i
for(z="1";z<="9";z++){
    while(p=~j[n](z)){
        j=j.replace(z," ")
        x+=~p%w-l
        y+=L(~p)-c
    }
}

Agregué algunos espacios en blanco para que sea más fácil de leer. Lo que sucede aquí es que para cada número posible, seguimos buscándolo en la cadena original. El ~truco es relativamente común en Javascript; es el operador NOT a nivel de bit, pero lo único que importa aquí es eso ~-1==0, lo que me permite probar el final del ciclo. Luego borro el carácter de la cadena (por eso hice una copia), lo que me permite continuar la búsqueda todo el tiempo que sea necesario. Luego agrego las coordenadas del vector a (x, y), usando una simple resta.

I=B(i).map(X=>G(-x,-l,0," ",0)+X+G(x,l-w+2,0," ",2))

Aquí divido la cadena original en líneas, y para cada línea, invoco Glo que generará el relleno antes y después de las líneas. El l-w+2etc. provienen de un simple cálculo del índice, que me permite probar si tengo que añadir el relleno o no. Por ejemplo, si x>0y x+l-w+1>0, entonces se (x+l-w+1)+1deben agregar espacios después de la línea. Se +xestá eliminando debido a que es el primer parámetro y se X+E+1+Tutiliza en la definición de G.

Algo similar se hace para los primeros caracteres y luego para las columnas. Aquí hay mucha factorización que me permite usar solo una función. Tenga en cuenta el último parámetro; en el primer caso, quiero escribir para C[0]poder saber luego cuántas columnas agregué al comienzo de cada línea; Esto me permite recuperar la posición final del personaje resultante. Sin embargo, no me importan las columnas agregadas después de la línea original, razón por la cual la segunda llamada a Gescribe en la celda basura C[2]que no se utiliza.

N=Z(I[0].length+1," ",2)

Aquí simplemente leo la nueva longitud de las líneas y creo una línea de espacios a partir de ella. Esto se usará para crear el relleno vertical.

A=B(G(-y,-c,0,N+O,1)+I[J](O)+G(y,c-h,1,O+N,2))

Esto es exactamente lo mismo que dos líneas anteriores. La única diferencia es escribir en C[1]este momento y usar los separadores N+Oy O+N. Recuerde que Oes una nueva línea, y Nes una línea de espacios. Luego aplico Bsobre el resultado para dividirlo nuevamente (necesito recuperar la línea que contiene el carácter del resultado para editarlo).

M=y+c+C[1]

Este es el índice vertical del carácter resultante.

O=""
m=B(A[M])
m[x+l+C[0]/h]="x"

Aquí me veo obligado a modificar Opara poder dividir la línea apropiada en una matriz de caracteres. Esto se debe a que las cadenas de JavaScript son inmutables; la única forma de editar una cadena es convertirla en una matriz (que es lo que estoy haciendo aquí), editar en la posición correcta y unir la cadena nuevamente. También tenga en cuenta el hfactor, que se debe a que la Gfunción se llamó una vez por línea inicial.

A[M]=m[J]("")
A[J]("\n")

Finalmente reemplazo la nueva cadena en la matriz y la vuelvo a unir en una cadena. Woohoo!

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.