Lineare Kombination zweier Vektoren

11

Zusammenfassung

Wenn eine Eingabe gegeben wird, die zwei Vektoren und ihre jeweiligen "Gewichte" darstellt, wird eine Ausgabe erzeugt, die auch die gewichtete Summe dieser Vektoren darstellt.

Herausforderung

Die Eingabe besteht aus einer oder mehreren Zeilen mit folgenden Zeichen:

  • genau ein Vorkommen der Ziffer 0, die den Ursprung in einer zweidimensionalen Ebene darstellt;
  • genau zwei andere Ziffern (1-9; kann dieselbe Ziffer sein oder nicht), deren Positionen relativ zum Ursprung Vektoren darstellen und deren Werte die Gewichte darstellen, die diesen Vektoren zugeordnet sind;
  • eine Anzahl von "Hintergrundzeichen". Der Löser kann ein bestimmtes Hintergrundzeichen auswählen. Zum Beispiel werde ich "." (hauptsächlich für die menschliche Lesbarkeit). Alternativ können die Hintergrundzeichen alles sein, was wie ein Leerzeichen aussieht.

(Der Solver kann wählen, ob die Eingabe eine einzelne mehrzeilige Zeichenfolge oder ein Array von einzeiligen Zeichenfolgen ist.)

Zum Beispiel die Eingabe

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

repräsentiert einen Vektor an Koordinaten (3,1) mit Gewicht 2 und einen Vektor an Koordinaten (2, -1) mit Gewicht 3.

Die Ausgabe sollte mit den folgenden Änderungen fast identisch mit der Eingabe sein:

  • ein "Ergebniszeichen", das vom Löser ausgewählt wird und an der Position hinzugefügt wird, die durch die gewichtete Summe der Eingabevektoren angegeben wird (äquivalent an der Position, die die geeignete lineare Kombination der Eingabevektoren ist);
  • Es werden so viele Hintergrundzeichen benötigt, wie für den Ursprung, die beiden Eingabevektoren und den Ausgabevektor im selben Bild erforderlich sind. Falls gewünscht, können zusätzliche Hintergrundzeichen eingefügt werden. Die einzige Einschränkung besteht darin, dass, wenn das Hintergrundzeichen ein sichtbares Zeichen ist, die gesamte Ausgabe eine rechteckige Form haben muss und jedes Zeichen, das keinen Vektor darstellt, das Hintergrundzeichen sein muss. (Wenn Leerzeichen als Hintergrundzeichen verwendet werden, müssen diese Einschränkungen nicht erzwungen werden.)

(Wenn wir im Allgemeinen einen Vektor (v, w) mit Gewicht a und einen zweiten Vektor (x, y) mit Gewicht b haben, ist ihre gewichtete Summe a (v, w) + b (x, y) = (av + bx, aw + von).)

Im vorherigen Beispiel ist die geeignete lineare Kombination 2 * (3,1) + 3 * (2, -1) = (12, -1). Wenn wir "X" als Ergebniszeichen verwenden, könnte die Ausgabe so aussehen

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

oder

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

Übliche Wertung: Die kürzeste Antwort in Byte gewinnt.

Beispiel für Ein- und Ausgabe

Wenn Leerzeichen verwendet werden, sieht die obige Eingabe folgendermaßen aus

    2
 0
   3

und die Ausgabe würde so aussehen

    2
 0
   3         X

Führende / nachfolgende Leerzeichen / Zeilen sind irrelevant. Wenn sie für den Leser unsichtbar sind, ist es in Ordnung. (Abgesehen davon werde ich für den Rest der Beispiele wieder "." Für das Hintergrundzeichen verwenden, um das Lesen zu erleichtern.)

Wenn beide Vektoren das Gewicht 1 haben, sieht das Ergebnis wie ein Parallelogramm aus: die Eingabe

.1.
...
1.0

führt zum Ausgang

X.1.
....
.1.0

Beachten Sie, dass dieses Parallelogramm entartet sein kann, wenn die Eingabevektoren kollinear sind: die Eingabe

0.1..1

führt zum Ausgang

0.1..1.X

Es ist möglich, dass der Ergebnisvektor einem der Eingabevektoren oder dem Ursprung entspricht; In diesem Fall wird das Eingabezeichen einfach überschrieben. Zum Beispiel die Eingabe

..2.0.1...

ergibt die Ausgabe

..X.0.1...

(wobei bei der Eingabe und / oder Ausgabe die führenden und nachfolgenden Perioden gelöscht werden könnten). Die Eingabe

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

ergibt die Ausgabe

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

Zum Schluss die Eingabe

90
.8

ergibt die Ausgabe

........90
.........8
..........
..........
..........
..........
..........
..........
X.........
Greg Martin
quelle
1
Willkommen bei PPCG! Schöne erste Herausforderung.
AdmBorkBork
@TimmyD Vielen Dank für die Begrüßung und Ermutigung :)
Greg Martin
1
Da ich mir sicher bin, dass andere es ansprechen werden, kommt dies einer Chamäleon-Herausforderung flirtend nahe, da ein beträchtlicher Teil des Codes einfach die Eingabe analysiert, wenn dies nicht wirklich der Hauptschwerpunkt der Herausforderung ist.
AdmBorkBork
Gibt es eine Begrenzung für die Anzahl der Zeilen / Spalten in der Eingabe oder der korrekten Ausgabe?
Sparr
@TimmyD Ich habe die allgemeine Formel für die gewichtete Summe hinzugefügt und auch klargestellt, dass beide Eingabeformate in Ordnung sind. Ich bin damit einverstanden, dass dies einer Chamäleon-Herausforderung nahe kommt (obwohl ich gehofft hatte, dass einige Sprachen die Fähigkeit haben könnten, direkt auf dem Brett zu "laufen", um das Problem zu lösen); Das Feedback zu Sandbox war jedoch eher positiv als negativ, daher habe ich mich dafür entschieden.
Greg Martin

Antworten:

7

MATL , 48 Bytes

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

Das Hintergrundzeichen ist Leerzeichen. Die Eingabe ist ein 2D-Zeichenarray mit durch Semikolons getrennten Zeilen. Die Testfälle haben also entsprechende Eingaben:

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

Die Ausgabe enthält eine erhebliche Menge an Leerzeichen.

Probieren Sie es online aus!

Luis Mendo
quelle
2

Python 3, 374 355 Bytes

Nicht zu raffinierte Python-Lösung, die sehr großzügig mit Polsterung ist (verwendet den maximalen Schachbrettabstand). Die Eingabe ist eine einzelne Zeile, in der Zeilen durch Pipes | getrennt sind (obwohl der Algorithmus leicht alles verwenden kann, was nicht alphanumerisch ist und kein Zeilenumbruch oder EOF ist). Alles, was nicht alphanumerisch ist oder | funktioniert für das Auffüllen von Eingaben, das Auffüllen von Ausgaben verwendet Punkte. Feedback und Verbesserungen von erfahreneren Python-Golfern werden geschätzt.

Bearbeiten: Einige Verbesserungen dank @TheBikingViking. Außerdem wurden noch mehr Ränder hinzugefügt, da ich mit Polsterung nicht großzügig genug war.

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))
Algmyr
quelle
Gute Antwort! Schauen Sie sich die Python-Tipps an . Einige Hinweise: 1. Es ist eine gute Idee anzugeben, ob Sie Python 2/3 verwendet haben, da sich einige Funktionen unterscheiden. 2. Sie können [a,b][condition]anstelle von b if condition else cZeile 2 einen sortedbeliebigen Iterator verwenden, einschließlich einer Generatoranweisung, sodass Sie das äußere Paar eckiger Klammern entfernen können . 3. zip(p)sollte statt funktionieren p[0] for p in P.
TheBikingViking
4. Sie können P+=[stuff]statt P.append([stuff])in Zeile 7 tun . 5. Tun Sie ["."]statt list("."). (3. hätte sein sollen zip(p)[0].)
TheBikingViking
Sorry, sollte Kapital Pin sein zip.
TheBikingViking
5. Sie sollten in der Lage sein, S=[stuff]*2*Lauf Linie 10 zu tun .
TheBikingViking
[1] Guter Punkt, wird Python-Version hinzufügen. [2] Gutes Muster, aber es funktioniert nicht mit index(Fehler bei nichts gefunden). Wird aber funktionieren find. [Re. sortiert] Danke, ich habe diese beim Hinzufügen von nicht entfernt sorted. [3] zip (* P) ​​[0] funktioniert in Python 3 nicht (zip-Objekt nicht indizierbar). [4] P + = [Zeug] wird nicht funktionieren, obwohl P + = [[Zeug]] wird. [5] Danke. [die anderen 5] Funktioniert nicht. Ich brauche neue Listen, keine Referenzen.
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")

Beachten Sie, dass die Polsterung optimal ist. Dieses Programm geht davon aus, dass i die Rohzeichenfolge enthält, wobei die Zeilen durch \nZeichen getrennt sind . Das Auffüllen erfolgt mit Leerzeichen, und das Ergebniszeichen ist klein geschrieben x.

Dies ist mein erster Versuch, Code zu spielen.

Technische Daten: - Die Größe des Programms hat sich ungefähr verdoppelt (und seine Komplexität hat sich dramatisch erhöht), um nur das Ergebniszeichen zu berücksichtigen, hauptsächlich weil JavaScript-Zeichenfolgen unveränderlich sind.


Zeile für Zeile Erklärung:

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

Ich benutze diese häufig, daher hat mir das Speichern in Strings etwas Platz gespart. Sie können unten sehen, dass splitich für die Funktion einfach einen Alias ​​erstellt habe; Das liegt daran, dass ich nur ein Argument brauchte, das andere ist konstant. Für indexOfund joinwäre es jedoch länger gewesen.

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

Hier ist nichts kompliziert, ich lese die Breite und Höhe des anfänglichen Arrays. Beachten Sie die Verwendung von i[n]für den Zugriff indexOf, während splitanders gehandhabt wird.

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

Das wird interessant. Diese Funktion erstellt grundsätzlich J-1-fache der Zeichenfolge X und gibt sie zurück. Dies wird verwendet, um Leerzeichenfolgen für die Auffüllung zu generieren.

C=[0,0,0]

Dieses Array enthält die Anzahl der Zeilen und Spalten, die durch das Auffüllen hinzugefügt wurden (im ersten Fall um den Faktor h versetzt). Die letzte Zelle ist eine Junk-Zelle und verhindert, dass ich in der folgenden Funktion ein zusätzliches Argument habe.

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

Diese Funktion übernimmt allein das Auffüllen (sowohl Zeilen als auch Spalten). Sie bestimmt anhand einer Koordinate des Ergebnisvektors (X) und der Anzahl der zu generierenden Zeilen / Spalten (E), ob eine erstellt werden muss. Dies X+E+1+Tist nur ein Trick, um Platz zu sparen. Es Uhandelt sich um die Füllzeichenfolge (ein Leerzeichen für Spalten und eine ganze Zeile für Zeilen), und wir werden darauf zurückkommen R. Diese Funktion gibt im Fall einer Zeile im Wesentlichen die am Anfang oder am Ende dieser Zeile erforderliche Auffüllung zurück, und im Fall einer Spalte gibt sie die erforderlichen Auffüllzeilen vor oder nach den ursprünglichen Zeilen zurück.

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

Hier lesen wir die Position des Ursprungs und rufen seine Koordinaten ab. L ist eine Funktion zum Konvertieren eines Index in eine Zeilennummer.

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

Ich habe einige Leerzeichen hinzugefügt, um das Lesen zu erleichtern. Was hier passiert ist, dass wir für jede mögliche Zahl in der ursprünglichen Zeichenfolge danach suchen. Der ~Trick ist in Javascript relativ häufig; Es ist der bitweise NICHT-Operator, aber alles, was hier zählt, ~-1==0ist der, mit dem ich das Ende der Schleife testen kann. Ich lösche dann das Zeichen in der Zeichenfolge (weshalb ich eine Kopie erstellt habe), damit ich die Suche so lange wie nötig fortsetzen kann. Ich addiere dann die Koordinaten des Vektors zu (x, y), indem ich eine einfache Subtraktion verwende.

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

Ich teile hier die ursprüngliche Zeichenfolge in Zeilen auf und rufe für jede Zeile auf, Gwodurch die Auffüllung vor und nach den Zeilen generiert wird. Die l-w+2und so weiter stammen aus einer einfachen Indexberechnung, mit der ich testen kann, ob ich Polster hinzufügen muss oder nicht. Wenn beispielsweise x>0und x+l-w+1>0, (x+l-w+1)+1müssen nach der Zeile Leerzeichen hinzugefügt werden. Das +xwird entfernt, da es der erste Parameter ist und X+E+1+Tin der Definition von verwendet wird G.

Ähnliches gilt für die ersten Zeichen und dann für die Spalten. Hier gibt es viele Faktoren, die es mir ermöglichen, nur eine Funktion zu verwenden. Beachten Sie den letzten Parameter; Im ersten Fall möchte ich schreiben, C[0]um später wissen zu können, wie viele Spalten ich am Anfang jeder Zeile hinzugefügt habe. Dadurch kann ich die endgültige Position des Ergebniszeichens abrufen. Die nach der ursprünglichen Zeile hinzugefügten Spalten interessieren mich jedoch nicht, weshalb der zweite Aufruf zum GSchreiben in die nicht verwendete Junk-Zelle C[2]erfolgt.

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

Hier lese ich einfach die neue Länge der Zeilen und erstelle daraus eine Zeile mit Leerzeichen. Dies wird verwendet, um die vertikale Polsterung zu erstellen.

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

Dies entspricht genau den beiden obigen Zeilen. Der einzige Unterschied besteht darin, in C[1]diese Zeit zu schreiben und die Trennzeichen N+Ound zu verwenden O+N. Denken Sie daran, dass dies Oeine neue NZeile und eine Zeile von Leerzeichen ist. Ich wende dann Bdas Ergebnis an, um es erneut zu teilen (ich muss die Zeile mit dem Ergebniszeichen abrufen, um es zu bearbeiten).

M=y+c+C[1]

Dies ist der vertikale Index des resultierenden Zeichens.

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

Hier muss ich Änderungen vornehmen O, um die entsprechende Zeile in ein Array von Zeichen aufteilen zu können. Dies liegt daran, dass JavaScript-Zeichenfolgen unveränderlich sind. Die einzige Möglichkeit, eine Zeichenfolge zu bearbeiten, besteht darin, sie in ein Array zu konvertieren (was ich hier mache), an der richtigen Position zu bearbeiten und die Zeichenfolge erneut zu verbinden. Beachten Sie auch den hFaktor, da die GFunktion einmal pro Anfangszeile aufgerufen wurde.

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

Ich ersetze schließlich die neue Zeichenfolge im Array und füge sie wieder zu einer Zeichenfolge zusammen. Woohoo!

pie3636
quelle