Combinazione lineare di due vettori


11

Sintesi

Dato un input che rappresenta due vettori e i loro rispettivi "pesi", produce un output che rappresenta anche la somma ponderata di quei vettori.

Sfida

L'input sarà costituito da una o più righe dei seguenti caratteri:

  • esattamente un'occorrenza della cifra 0, che rappresenta l'origine in un piano bidimensionale;
  • esattamente altre due cifre (1-9; può essere o meno la stessa cifra), le cui posizioni relative all'origine rappresentano i vettori e i cui valori rappresentano i pesi associati a questi vettori;
  • un certo numero di "personaggi di sfondo". Il risolutore può scegliere un carattere di sfondo specifico; per esempio, sceglierò "." (principalmente per la leggibilità umana). In alternativa, i personaggi di sfondo possono essere qualsiasi cosa che assomigli a uno spazio vuoto.

(Il solutore può scegliere se l'input è una stringa a più righe o un array di stringhe a una riga.)

Ad esempio, l'input

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

rappresenta un vettore alle coordinate (3,1) con peso 2 e un vettore alle coordinate (2, -1) con peso 3.

L'output dovrebbe essere quasi uguale all'input, con le seguenti modifiche:

  • un "carattere risultato", scelto dal solutore, da aggiungere nella posizione specificata dalla somma ponderata dei vettori di input (equivalentemente, nella posizione che è la combinazione lineare appropriata dei vettori di input);
  • tutti i caratteri di sfondo necessari per adattarsi all'origine, ai due vettori di input e al vettore di output nella stessa immagine. Se lo si desidera, è possibile includere caratteri di sfondo aggiuntivi; l'unico vincolo è che, se il carattere di sfondo è un carattere visibile, l'intero output deve essere di forma rettangolare e ogni carattere che non rappresenta un vettore deve essere il carattere di sfondo. (Se lo spazio vuoto viene utilizzato come caratteri di sfondo, non è necessario applicare questi vincoli.)

(In generale, se abbiamo un vettore (v, w) con peso a e un secondo vettore (x, y) con peso b, la loro somma ponderata è a (v, w) + b (x, y) = (av + BX, aw + da).)

Nell'esempio precedente, la combinazione lineare appropriata è 2 * (3,1) + 3 * (2, -1) = (12, -1). Se utilizziamo "X" come carattere risultante, l'output potrebbe apparire come

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

o

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

Punteggio abituale : la risposta più breve, in byte, vince.

Esempio di input e output

Se viene utilizzato uno spazio vuoto, l'aspetto sopra riportato sarebbe simile

    2
 0
   3

e l'output sarebbe simile

    2
 0
   3         X

I caratteri / le righe degli spazi bianchi iniziali / finali sono irrilevanti; se sono invisibili al lettore, va bene. (Detto questo, per il resto degli esempi tornerò a usare "." Per il personaggio di sfondo, per facilitare la lettura.)

Se entrambi i vettori hanno peso 1, il risultato apparirà come un parallelogramma: l'input

.1.
...
1.0

porta all'output

X.1.
....
.1.0

Si noti che questo parallelogramma può essere degenerato se i vettori di input sono collineari: l'input

0.1..1

porta all'output

0.1..1.X

È possibile che il vettore risultante sia uguale a uno dei vettori di input o all'origine; in questo caso, sovrascrive semplicemente il carattere di input. Ad esempio, l'input

..2.0.1...

produce l'output

..X.0.1...

(dove in input e / o output, i periodi iniziali e finali potrebbero essere eliminati). L'input

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

produce l'output

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

Finalmente l'input

90
.8

produce l'output

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

1
Benvenuti in PPCG! Bella prima sfida.
AdmBorkBork,

@TimmyD Grazie per l'accoglienza e l'incoraggiamento :)
Greg Martin,

1
Infine, dato che sono sicuro che altri lo faranno emergere, questo è civettuosamente vicino a una sfida camaleontica poiché un grosso pezzo di codice analizzerà semplicemente l'input, quando non è proprio la spinta principale della sfida.
AdmBorkBork,

esiste un limite al numero di righe / colonne nell'input o nell'output corretto?
Sparr,

@TimmyD Ho aggiunto la formula generale per la somma ponderata e ho anche chiarito che entrambi i formati di input vanno bene. Sono d'accordo che questo è vicino a una sfida camaleontica (anche se speravo che alcune lingue potessero avere la capacità di "camminare" direttamente sul tabellone per risolvere il problema); tuttavia il feedback su Sandbox è stato modestamente più positivo che negativo, quindi ho deciso di seguirlo.
Greg Martin,

Risposte:


7

MATL , 48 byte

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

Il personaggio di sfondo è lo spazio. L'input è un array di caratteri 2D con righe separate da punti e virgola. Quindi i casi di test hanno i rispettivi input:

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

L'output include una quantità significativa di spazio bianco di riempimento.

Provalo online!


2

Python 3, 374 355 byte

Soluzione in pitone non troppo raffinata che è molto generosa con l'imbottitura (utilizza la massima distanza della scacchiera). L'input è una singola riga in cui le righe sono separate da pipe | (sebbene l'algoritmo possa facilmente usare qualsiasi cosa non alfanumerica che non sia una newline o un EOF). Qualsiasi cosa non alfanumerica o | funziona per il padding di input, il padding di output utilizza i punti. Sono apprezzati feedback e miglioramenti da parte di più esperti golfisti di pitone.

Modifica: alcuni miglioramenti grazie a @TheBikingViking. Inoltre ho aggiunto ancora più margini poiché non ero abbastanza generoso con l'imbottitura.

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

Bella risposta! Dai un'occhiata ai suggerimenti di Python . Alcuni suggerimenti: 1. È una buona idea specificare se hai usato Python 2/3, poiché alcune funzionalità differiscono. 2.Puoi fare [a,b][condition]invece della b if condition else clinea 2. sortedprende qualsiasi iteratore, inclusa un'istruzione generatore, in modo da poter eliminare la coppia esterna di parentesi quadre. 3. zip(p)dovrebbe funzionare invece di p[0] for p in P.
TheBikingViking

4. Puoi fare P+=[stuff]invece della P.append([stuff])linea 7. 5. Fai ["."]invece di list("."). (3. avrebbe dovuto essere zip(p)[0].)
TheBikingViking

Siamo spiacenti, dovrebbe essere capitale Pin zip.
TheBikingViking

5. Dovresti essere in grado di fare S=[stuff]*2*Lsulla linea 10.
TheBikingViking

[1] Un buon punto, aggiungerà la versione di Python. [2] Buon modello, ma non funzionerà con index(errore su nulla trovato). Funzionerà con findperò. [Ri. ordinato] Grazie, ho perso la rimozione di quelli quando si aggiunge il sorted. [3] zip (* P) ​​[0] non funziona in Python 3 (oggetto zip non indicizzabile). [4] P + = [stuff] non funzionerà, sebbene P + = [[stuff]] funzionerà. [5] Grazie. [l'altro 5] Non funziona. Ho bisogno di nuove liste, non di riferimenti.
algmyr,

2

JavaScript, 534 528 502 byte

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

Si noti che l'imbottitura è ottimale. Questo programma presuppone che io contenga la stringa non elaborata, con le linee separate da \ncaratteri. Il riempimento viene eseguito con spazi e il carattere risultante è minuscolo x.

Questo è il mio primo tentativo di giocare a golf.

Materiale tecnico: - Le dimensioni del programma sono quasi raddoppiate (e la sua complessità è aumentata drammaticamente) per tener conto del carattere del risultato, soprattutto perché le stringhe JavaScript sono immutabili.


Spiegazione riga per riga:

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

Li uso molto, quindi memorizzarli in stringhe mi ha fatto risparmiare un po 'di spazio. Di seguito puoi vedere che per la splitfunzione, ho semplicemente creato un alias; questo perché avevo solo bisogno di un argomento, l'altro essendo costante. Per indexOfe join, tuttavia, sarebbe stato più lungo.

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

Niente di complicato qui, sto leggendo la larghezza e l'altezza dell'array iniziale. Si noti l'uso di i[n]per accedere indexOf, mentre splitè gestito in modo diverso.

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

Questo sta diventando interessante. Questa funzione fondamentalmente crea concatenati J-1 volte la stringa X e la restituisce. Questo è usato per generare stringhe di spazi per il riempimento.

C=[0,0,0]

Questo array conterrà il numero di righe e colonne aggiunte dal riempimento (disattivato da un fattore h nel primo caso). L'ultima cella è spazzatura e mi impedisce di avere un argomento aggiuntivo nella funzione di seguito.

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

Questa sola funzione gestisce l'imbottitura (sia linee che colonne); determina, in base a una coordinata del vettore del risultato (X) e al numero di righe / colonne da generare (E), se è necessario crearne uno. il X+E+1+Tè solo un trucco per risparmiare un po 'di spazio, Uè la stringa di riempimento (uno spazio per le colonne, e un'intera linea per le linee), e torneremo a R. Questa funzione sostanzialmente restituisce, nel caso di una linea, il riempimento richiesto all'inizio o alla fine di detta linea e, nel caso di una colonna, restituisce le linee di riempimento necessarie prima o dopo le linee originali.

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

Qui leggiamo la posizione dell'origine e ne recuperiamo le coordinate. L è una funzione per convertire un indice in un numero di riga.

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

Ho aggiunto degli spazi bianchi per rendere più facile la lettura. Quello che succede qui è che per ogni possibile numero, continuiamo a cercarlo nella stringa originale. Il ~trucco è relativamente comune in Javascript; è l'operatore bit a bit NOT, ma tutto ciò che conta qui è quello ~-1==0, che mi permette di testare la fine del loop. Quindi cancello il carattere nella stringa (motivo per cui ho creato una copia), questo mi consente di continuare la ricerca per tutto il tempo necessario. Aggiungo quindi le coordinate del vettore (x, y), usando una semplice sottrazione.

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

Qui ho diviso la stringa originale in linee e, per ogni linea, chiamo Gche genererà il riempimento prima e dopo le linee. Il l-w+2e così via provengono da un semplice calcolo dell'indice che mi consente di verificare se è necessario aggiungere padding o meno. Ad esempio, se x>0e x+l-w+1>0, quindi gli (x+l-w+1)+1spazi devono essere aggiunti dopo la riga. La +xsta per essere rimosso a causa essendo il primo parametro, e X+E+1+Tutilizzato nella definizione di G.

Una cosa simile viene fatta per i primi personaggi e poi per le colonne. C'è molta fattorizzazione qui che mi permette di usare solo una funzione. Nota l'ultimo parametro; nel primo caso, voglio scrivere per C[0]poter sapere in seguito quante colonne ho aggiunto all'inizio di ogni riga; questo mi permette di recuperare la posizione finale del carattere risultato. Tuttavia, non mi importa delle colonne aggiunte dopo la riga originale, motivo per cui la seconda chiamata a Gscrive nella cella indesiderata C[2]che non viene utilizzata.

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

Qui leggo semplicemente la nuova lunghezza delle linee e ne creo una linea di spazi. Questo verrà utilizzato per creare l'imbottitura verticale.

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

Questo è esattamente lo stesso di due righe sopra. L'unica differenza è scrivere C[1]questa volta e usare i separatori N+Oe O+N. Ricorda che Oè una newline ed Nè una linea di spazi. Applico quindi Bil risultato per dividerlo di nuovo (ho bisogno di recuperare la riga contenente il carattere del risultato per modificarlo).

M=y+c+C[1]

Questo è l'indice verticale del carattere risultante.

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

Qui sono costretto a modificare Oper poter dividere la riga appropriata in una matrice di caratteri. Questo perché le stringhe JavaScript sono immutabili; l'unico modo per modificare una stringa è convertirla in un array (che è quello che sto facendo qui), modificare nella posizione corretta e unire nuovamente la stringa. Notare anche il hfattore, perché la Gfunzione è stata chiamata una volta per riga iniziale.

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

Alla fine sostituisco la nuova stringa nell'array e la unisco nuovamente in una stringa. Woohoo!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.