Paeth-Transform-Arrays

8

Einer der Hauptbestandteile des Komprimierungsalgorithmus von PNG ist die Paeth-Transformation, die das Bild so transformiert, dass es (normalerweise) besser komprimiert wird. Bei dieser Herausforderung besteht Ihre Aufgabe darin, ein Programm zum Berechnen einer Paeth-Transformation zu schreiben. Die Funktionsweise einer Paeth-Transformation wird unten beschrieben.

Die Paeth Transformation

Die Paeth-Transformation subtrahiert von jedem Mitglied Xeines zweidimensionalen Arrays einen Prädiktor. Der Prädiktor ist das Element des Array-Elements links ( A), oben ( B) und oben links ( C), Xdessen Wert den geringsten Unterschied zu aufweist A + B - C.

┼─┼─┼
│C│B│
┼─┼─┼
│A│X│
┼─┼─┼

Wenn einer A, Boder Csei außerhalb der Grenzen, wird sein Wert durch 0 ersetzt Hier ist Pseudo - Code aus der PNG - Spezifikation darlegt , wie dieser Prädiktor berechnet:

function PaethPredictor (a, b, c)
begin
     ; a = left, b = above, c = upper left
     p := a + b - c        ; initial estimate
     pa := abs(p - a)      ; distances to a, b, c
     pb := abs(p - b)
     pc := abs(p - c)
     ; return nearest of a,b,c,
     ; breaking ties in order a,b,c.
     if pa <= pb AND pa <= pc then return a
     else if pb <= pc then return b
     else return c
end

Für diese Herausforderung sind die Array-Mitglieder natürliche Zahlen im Bereich von 0 bis 255. Wenn die Paeth-Transformation zu einem Wert außerhalb dieses Bereichs führt, muss modulo 256 auf einen Wert in diesem Bereich reduziert werden.

Ein- und Ausgabe

Die Eingabe besteht aus zwei Ganzzahlen x und y im Bereich von 2 bis 1023, die die Breite und Höhe der zu transformierenden Matrix und ein Array von x × y- Elementen angeben. Die Eingabe wird als Dezimalzahl formatiert, die durch ein Leerzeichen getrennt ist, das mit einem Zeilenvorschub abgeschlossen wird. So könnte diese Eingabe aussehen:

2 3 4 5 6 7 8 9

Dies würde eine 2 mal 3 Matrix mit den Einträgen darstellen:

4 5
6 7
8 9

Die Ausgabe muss das gleiche Format wie die Eingabe mit der Entspannung haben, dass die Zahlen durch eine beliebige Anzahl von Leerzeichen ungleich Null (Leerzeichen, horizontaler oder vertikaler Tabulator, Zeilen- oder Formularvorschub) getrennt und durch eine beliebige Anzahl von Leerzeichen abgeschlossen werden können Leerzeichen.

Die Eingabe soll von empfangen werden stdin, die Ausgabe soll an gehen stdout. Wenn dies nicht möglich ist, wählen Sie eine andere Art des Empfangens und Schreibens von Ausgaben, die die Eingabe nicht fest codiert.

Das Verhalten Ihres Programms bei ungültigen Eingaben ist nicht Teil dieser Herausforderung.

Beurteilung und Referenzimplementierung

Ein ANSI C-Programm wird bereitgestellt , um Beispieleingaben zu generieren, Instanzen zu lösen und Lösungen zu überprüfen. Rufen Sie das Programm mit gzu g enerate Eingang, mit san s Ølve eine Eingangsinstanz und mit vbis v erify die Richtigkeit einer Lösung.

Wenn Sie der Meinung sind, dass die Referenzimplementierung fehlerhaft ist, lassen Sie es mich bitte wissen, damit ich sie so schnell wie möglich korrigieren kann.

Beispiel für Ein- und Ausgabe

Auf vielfachen Wunsch.

10 5 166 156 108 96 63 227 122 99 117 135 125 46 169 247 116 55 151 1 232 114 214 254 6 127 217 88 206 102 252 237 75 250 202 145 86 198 172 84 68 114 58 228 66 224 186 217 210 108 11 179

Darstellen des Arrays

166 156 108  96  63 227 122  99 117 135
125  46 169 247 116  55 151   1 232 114
214 254   6 127 217  88 206 102 252 237
 75 250 202 145  86 198 172  84  68 114
 58 228  66 224 186 217 210 108  11 179

verwandelt sich in

166 246 208 244 223 164 151 233  18  18
215 177 123  78 125  84  96 135 231 138
 89 129   8 121 101 228  55 101  20 123
117 175 196 199 125 112 222 238  72  46
239 234 120 158  41  19  12  24 183 111

welches als kodiert ist

10 5 166 246 208 244 223 164 151 233 18 18 215 177 123 78 125 84 96 135 231 138 89 129 8 121 101 228 55 101 20 123 117 175 196 199 125 112 222 238 72 46 239 234 120 158 41 19 12 24 183 111

Gewinnbedingung

Schreiben Sie für diese Herausforderung ein Programm , das die korrekte Paeth-Transformation der Eingabe generiert und ausschreibt. Dies ist Code-Golf, das Programm mit der geringsten Anzahl von Zeichen im Quellcode gewinnt. Bitte versuchen Sie, Ihrer Einreichung eine Erklärung und eine lesbare Version Ihres Codes beizufügen, damit andere sehen können, was er tut.

FUZxxl
quelle
1
Was meinen Sie mit " Wenn die Paeth-Transformation zu einem Wert außerhalb dieses Bereichs führt "? Da das Ergebnis immer aus drei Elementen besteht, die sich alle in Reichweite befinden, scheint dies einen unmöglichen Fall abzudecken.
Peter Taylor
@PeterTaylor Die Paeth-Transformation ist für jedes Array-Mitglied die Differenz zwischen dem Wert dieses Mitglieds und dem Prädiktor für dieses Mitglied, die negativ sein kann.
FUZxxl
@ MartinBüttner Das muss durch die Kopierbearbeitung gerutscht sein.
FUZxxl
1
@FUZxxl: Wahrheit. Wusste erst vor einem Moment, dass es darüber keine allgemeine Übereinstimmung gibt. Aber das war total beiseite. Schöne Herausforderung.
Alex A.
3
Übrigens, herzlichen Glückwunsch zum Posten der Frage Nr. 3000! (Ohne gelöschte und gesperrte Fragen.)
Martin Ender

Antworten:

3

J - 77 char

Ein Ansatz, der anders aussieht als die Antwort von FUZxxl, aber tatsächlich sehr ähnlich ist.

1!:2&4":2({.,|.@{.,@(256|$-0(0{[/:+`-/|@-])"1@|:(-#:1 2 3)|.!.0$)}.)0".1!:1]3

Einige Kommentare zu den interessanten Teilen.

  • 1!:2&4":(...) 0".1!:1]3- Wenn J in Bezug auf E / A und Analyse nicht schrecklich wäre, könnte dies überarbeitet werden &.".&.stdin'', um 3 Zeichen zu sparen. Aber so können wir nicht. Ruhe in Frieden, kostbare Charaktere.
  • 2 ({.,|.@{.,@( ... stuff using $ ... )}.)- Dadurch wird der Eingang zerlegt und der Ausgang wieder zusammengesetzt. Wir verwenden $sowohl als Referenz auf die Eingabe in stuff using $als auch als Operation, die wir an der Eingabe ausführen müssen, bevor wir sie ausführen stuff.
  • 0( blah )"1@|:- Ja, das ist eine dyadische Transponierung: Wir gruppieren die drei Rotationsergebnisse als innerste Array-Achse neu, sodass die Paeth-Logik für jeden Satz separat mit angewendet werden kann "1.
  • 0{[/:+`-/|@-]- Die Paeth-Logik: Sortieren Sie a,b,cnach den Größen von ( pminus jeder von a,b,c) und nehmen Sie die erste.
Algorithmushai
quelle
Das ist wirklich ordentlich.
FUZxxl
2

J, 97 91 88 87 Zeichen

Lassen Sie uns damit beginnen. Beachten Sie die Abwesenheit exit; J druckt eine Eingabeaufforderung (drei Leerzeichen), nachdem die gesamte Ausgabe geschrieben wurde, aktiviert dann jedoch eine EOF stdin, wodurch sie beendet wird.

Ich glaube, dass in diesem Code einige Verbesserungen möglich sind.

1!:2&4":(|.@$,,)256|((-+`-/+[:(>&|{,)"0/]-"2+`-/)(3 2$-*i.3)|.!.0])2(|.@{.$}.)0".1!:1]3

Hier ist der Code vor dem Golfen; Es entspricht größtenteils dem aktuellen Code.

NB. A, B, and C values
abc =: (0 _1 , _1 0 ,: _1 _1)&(|.!.0)
p =: +`-/@abc
NB. minimum of magnitudes
mmin =: (>&| { ,)"0
pred =: p + [: mmin/ abc -"2 2 p
paeth =: 256 | ] - pred
input =: [: (2&}. $~ 2 |.@{. ]) 0 ". 1!:1
output =: [: 1!:2&4 LF ,~ [: ": |.@$ , ,
output paeth input 3
exit 0
FUZxxl
quelle
Dieser Code gibt eine falsche Ausgabe aus: 3 2$-*i:3entspricht nicht 0 _1,_1 0,:_1 _1.
Algorithmushai
@algorithmshark Entschuldigung. besser so?
FUZxxl