Combinação linear de dois vetores


11

Sumário executivo

Dada a entrada que representa dois vetores e seus respectivos "pesos", produza saída que também represente a soma ponderada desses vetores.

Desafio

A entrada consistirá em uma ou mais linhas dos seguintes caracteres:

  • exatamente uma ocorrência do dígito 0, que representa a origem em um plano bidimensional;
  • exatamente dois outros dígitos (1-9; podem ou não ser o mesmo dígito), cujas posições em relação à origem representam vetores e cujos valores representam os pesos associados a esses vetores;
  • algum número de "caracteres de fundo". O solucionador pode escolher um caractere de plano de fundo específico; por exemplo, vou escolher "." (principalmente para legibilidade humana). Como alternativa, os caracteres de segundo plano podem ser qualquer coisa que pareça com espaço em branco.

(O solucionador pode escolher se a entrada é uma única sequência de múltiplas linhas ou uma matriz de seqüências de uma linha.)

Por exemplo, a entrada

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

representa um vetor nas coordenadas (3,1) com peso 2 e um vetor nas coordenadas (2, -1) com peso 3.

A saída deve ser quase a mesma que a entrada, com as seguintes alterações:

  • um "caractere de resultado", escolhido pelo solucionador, a ser adicionado na posição especificada pela soma ponderada dos vetores de entrada (equivalentemente, na posição que é a combinação linear apropriada dos vetores de entrada);
  • quantos caracteres de plano de fundo forem necessários para ajustar a origem, os dois vetores de entrada e o vetor de saída na mesma imagem. Caracteres extras de fundo podem ser incluídos, se desejado; a única restrição é que, se o caractere de segundo plano for um caractere visível, toda a saída deverá ter uma forma retangular e todo caractere que não represente um vetor deverá ser o caractere de segundo plano. (Se o espaço em branco for usado como caracteres de segundo plano, essas restrições não precisarão ser impostas.)

(Em geral, se tivermos um vetor (v, w) com peso a e o segundo vetor (x, y) com peso b, sua soma ponderada é a (v, w) + b (x, y) = (av + bx, aw + por).)

No exemplo anterior, a combinação linear apropriada é 2 * (3,1) + 3 * (2, -1) = (12, -1). Se usarmos "X" como o caractere de resultado, a saída poderá parecer

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

ou

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

Pontuação usual de : a resposta mais curta, em bytes, vence.

Exemplo de entrada e saída

Se espaço em branco for usado, a entrada acima seria semelhante

    2
 0
   3

e a saída pareceria

    2
 0
   3         X

Caracteres / linhas em branco à esquerda / à esquerda são irrelevantes; se eles são invisíveis para o leitor, tudo bem. (Dito isto, no restante dos exemplos, voltarei a usar "." Para o caractere de segundo plano, para facilitar a leitura.)

Se ambos os vetores tiverem peso 1, o resultado será semelhante a um paralelogramo: a entrada

.1.
...
1.0

leva à saída

X.1.
....
.1.0

Observe que esse paralelogramo pode ser degenerado se os vetores de entrada forem colineares: a entrada

0.1..1

leva à saída

0.1..1.X

É possível que o vetor de resultado seja igual a um dos vetores de entrada ou à origem; neste caso, simplesmente substitui o caractere de entrada. Por exemplo, a entrada

..2.0.1...

produz a saída

..X.0.1...

(onde na entrada e / ou saída, os períodos inicial e final podem ser excluídos). A entrada

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

produz a saída

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

Finalmente, a entrada

90
.8

produz a saída

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

1
Bem-vindo ao PPCG! Bom primeiro desafio.
AdmBorkBork 29/07

@TimmyD Obrigado pelas boas-vindas e encorajamento :)
Greg Martin

1
Finalmente, como tenho certeza de que outras pessoas o abordarão, isso está muito próximo de um desafio de camaleão, já que um pedaço considerável de código será simplesmente analisando a entrada, quando esse não é realmente o principal objetivo do desafio.
AdmBorkBork 29/07

existe algum limite no número de linhas / colunas na entrada ou na saída correta?
Sparr 29/07

@ TimmyD Adicionei a fórmula geral para a soma ponderada e também esclareci que qualquer um dos formatos de entrada está correto. Concordo que isso se aproxima de um desafio de camaleão (embora eu esperasse que alguns idiomas pudessem ter a capacidade de "caminhar" diretamente no quadro para resolver o problema); no entanto, o feedback no Sandbox foi modestamente mais positivo que negativo, então decidi continuar.
Greg Martin

Respostas:


7

MATL , 48 bytes

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

O caractere de plano de fundo é o espaço. Entrada é uma matriz de caracteres 2D com linhas separadas por ponto e vírgula. Portanto, os casos de teste têm entradas respectivas:

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

A saída inclui uma quantidade significativa de espaço em branco do preenchimento.

Experimente online!


2

Python 3, 374 355 bytes

Solução python não muito refinada que é muito generosa com o preenchimento (usa a distância máxima do tabuleiro de xadrez). Entrada é uma única linha em que as linhas são separadas por tubos | (embora o algoritmo possa usar com facilidade qualquer coisa não alfanumérica que não seja uma nova linha ou um EOF). Qualquer coisa não alfanumérica ou | funciona para preenchimento de entrada, o preenchimento de saída usa períodos. Comentários e melhorias de jogadores experientes em python são apreciados.

Edit: Algumas melhorias graças ao @TheBikingViking. Também adicionei ainda mais margens, já que eu não era suficientemente generoso com o preenchimento.

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

Boa resposta! Dê uma olhada nas dicas do Python . Alguns indicadores: 1. É uma boa idéia especificar se você usou o Python 2/3, pois alguns recursos diferem. 2.Você pode fazer em [a,b][condition]vez da b if condition else clinha 2. sortedusa qualquer iterador, incluindo uma instrução de gerador, para que você possa descartar o par externo de colchetes. 3. zip(p)deve funcionar em vez de p[0] for p in P.
TheBikingViking

4. Você pode fazer em P+=[stuff]vez da P.append([stuff])linha 7. 5. Faça em ["."]vez de list("."). (3. deveria ter sido zip(p)[0]).
TheBikingViking 30/07

Desculpe, deveria ser a capital Pem zip.
TheBikingViking

5. Você deve conseguir fazer S=[stuff]*2*Lna linha 10.
TheBikingViking 30/07/16

[1] Bom ponto, irá adicionar a versão python. [2] Bom padrão, mas não funciona index(erro em nada encontrado). Vai trabalhar com findembora. [Ré. classificado] Obrigado, perdi a remoção deles ao adicionar o sorted. [3] zip (* P) ​​[0] não funciona no python 3 (o objeto zip não é indexável). [4] P + = [coisas] não funcionará, embora P + = [[coisas]] funcione. [5] Obrigado. [os outros 5] não funcionam. Preciso de novas listas, não de referências.
31816 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")

Observe que o preenchimento é ideal. Este programa assume que i contém a cadeia bruta, com as linhas separadas por \ncaracteres. O preenchimento é feito com espaços e o caractere resultado é minúsculo x.

Esta é a minha primeira tentativa no código de golfe.

Coisas técnicas: - O tamanho do programa praticamente dobrou (e sua complexidade aumentou dramaticamente) para apenas levar em consideração o caractere do resultado, principalmente porque as strings do JavaScript são imutáveis.


Linha por linha explicação:

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

Eu uso muito isso, então armazená-los em strings me salvou um pouco de espaço. Você pode ver abaixo que, para a splitfunção, eu simplesmente criei um alias; isso é porque eu só precisava de um argumento, o outro sendo constante. Para indexOfe join, no entanto, teria sido mais longo.

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

Nada complicado aqui, estou lendo a largura e a altura da matriz inicial. Observe o uso de i[n]para acessar indexOf, enquanto splité tratado de maneira diferente.

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

Isso está ficando interessante. Essa função basicamente cria concatena J-1 vezes a string X e a retorna. Isso é usado para gerar cadeias de espaços para o preenchimento.

C=[0,0,0]

Essa matriz conterá o número de linhas e colunas adicionadas pelo preenchimento (desativado por um fator h no primeiro caso). A última célula é não solicitada e me impede de ter um argumento adicional na função abaixo.

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

Esta função sozinha lida com o preenchimento (linhas e colunas); determina, com base em uma coordenada do vetor de resultado (X), e o número de linhas / colunas para gerar (E), se é necessário criar um. o X+E+1+Té apenas um truque para poupar algum espaço, Ué a seqüência de enchimento (um espaço de colunas e uma linha inteira de linhas), e nós vamos voltar R. Esta função basicamente retorna, no caso de uma linha, o preenchimento necessário no início ou no final da referida linha e, no caso de uma coluna, retorna as linhas de preenchimento necessárias antes ou depois das linhas originais.

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

Aqui lemos a posição da origem e recuperamos suas coordenadas. L é uma função para converter um índice em um número de linha.

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

Adicionei alguns espaços em branco para facilitar a leitura. O que acontece aqui é que, para cada número possível, continuamos procurando na string original. O ~truque é relativamente comum em Javascript; é o operador NOT bit a bit, mas tudo o que importa aqui é o que ~-1==0me permite testar o final do loop. Em seguida, apago o caractere na string (e foi por isso que fiz uma cópia), o que me permitiu continuar a pesquisa pelo tempo necessário. Em seguida, adiciono as coordenadas do vetor a (x, y), usando uma subtração simples.

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

Aqui, divido a sequência original em linhas e, para cada linha, chamo Gque gerará o preenchimento antes e depois das linhas. O l-w+2e assim por diante vêm de um cálculo simples de índice que permite testar se preciso adicionar preenchimento ou não. Por exemplo, se x>0e x+l-w+1>0, (x+l-w+1)+1espaços devem ser adicionados após a linha. O +xestá sendo removido por ser o primeiro parâmetro e o X+E+1+Tusado na definição de G.

Uma coisa semelhante é feita para os primeiros caracteres e depois para as colunas. Há muita fatoração aqui, permitindo que eu use apenas uma função. Observe o último parâmetro; no primeiro caso, quero escrever para C[0]saber depois quantas colunas adicionei no início de cada linha; isso me permite recuperar a posição final do caractere resultado. No entanto, não me importo com as colunas adicionadas após a linha original, e é por isso que a segunda chamada para Ggravações na célula indesejada C[2]não é utilizada.

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

Aqui, simplesmente leio o novo comprimento das linhas e crio uma linha de espaços a partir dele. Isso será usado para criar o preenchimento vertical.

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

É exatamente o mesmo que as duas linhas acima. A única diferença é escrever até C[1]agora e usar os separadores N+Oe O+N. Lembre-se de que Oé uma nova linha e Né uma linha de espaços. Aplico Bo resultado para dividi-lo novamente (preciso recuperar a linha que contém o caractere de resultado para editá-lo).

M=y+c+C[1]

Este é o índice vertical do caractere resultante.

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

Aqui sou forçado a modificar Opara poder dividir a linha apropriada em uma matriz de caracteres. Isso ocorre porque as strings JavaScript são imutáveis; a única maneira de editar uma string é convertê-la em uma matriz (que é o que estou fazendo aqui), editar na posição correta e unir a string novamente. Observe também o hfator, porque a Gfunção foi chamada uma vez por linha inicial.

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

Finalmente substituo a nova string na matriz e associo-a novamente a uma string. Woohoo!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.