Teilen Sie Arrays und Programme in zwei Hälften

10

Einführung

Sie wurden beauftragt, ein Programm zu schreiben, das ein rechteckiges Integer-Array gleichmäßig in zwei Hälften teilt (aus welchem ​​Grund auch immer). Diese Aufgabe ist rechenintensiv, aber zum Glück haben Sie eine Dual-Core-Maschine, um die Berechnungen durchzuführen. Um die Vorteile der Parallelität zu maximieren, teilen Sie das Programm gleichmäßig in zwei Hälften und lassen jeden Kern einen der Teile unabhängig vom anderen ausführen.

Ein- und Ausgabe

Ihre Eingabe ist ein rechteckiges 2D-Array aus nichtnegativen Ganzzahlen mit einer Größe von mindestens 1 × 1 , die in einem beliebigen vernünftigen Format erstellt wurden. Eine Aufteilung eines solchen Arrays wird erhalten, indem jede horizontale Zeile in ein Präfix und ein Suffix (von denen jedes leer sein kann) aufgeteilt wird. Damit eine Aufteilung gültig ist, müssen zwei benachbarte Zeilen am selben Index oder an benachbarten Indizes aufgeteilt werden. Betrachten Sie beispielsweise das Array

2 4 5 5 6 3
9 7 1 7 7 0
0 0 3 6 7 8
1 2 4 7 6 1
6 6 8 2 0 0

Dies ist eine gültige Aufteilung:

 2;4 5 5 6 3
;9 7 1 7 7 0
;0 0 3 6 7 8
 1;2 4 7 6 1
 6 6;8 2 0 0

Dies ist auch eine gültige Aufteilung:

2 4 5 5 6 3;
9 7 1 7 7;0
0 0 3 6 7;8
1 2 4 7;6 1
6 6 8;2 0 0

Dies ist keine gültige Aufteilung:

2 4;5 5 6 3
9 7 1;7 7 0
0;0 3 6 7 8
1 2;4 7 6 1
6 6;8 2 0 0

Ihre Ausgabe muss der Mindestwert von sein

abs(sum_of_prefixes - sum_of_suffixes)

über alle gültigen Aufteilungen der Eingabe.

Regeln und Wertung

Sie müssen zwei Programme (entweder vollständige Programme oder Funktionen) in derselben Sprache schreiben , zwischen denen sich kein gemeinsamer Code befinden darf. Nennen wir sie P1 und P2 . Programm P1 nimmt das Eingabearray und gibt etwas aus . Das Programm P2 nimmt dies als Eingabe und gibt die Antwort der obigen Aufgabe für das Eingabearray aus.

Ihre Punktzahl ist das Maximum der Byteanzahl von P1 und P2 , wobei eine niedrigere Punktzahl besser ist.

Einige Klarstellungen:

  • Sie können zwei vollständige Programme, eine Funktion und ein vollständiges Programm oder zwei Funktionen schreiben.
  • Bei zwei vollständigen Programmen wird der gesamte Ausgang von P1 wie in der Unix-Pipeline als Eingang an P2 weitergeleitetP1 | P2 . Die Programme müssen korrekt funktionieren, wenn sie aus zwei separaten Quelldateien kompiliert / interpretiert werden.
  • Wenn eines der beiden Programme eine Funktion ist, wird es durch Hinzufügen des erforderlichen Boilerplate-Codes in ein vollständiges Programm konvertiert, und die obige Regel wird darauf angewendet. Insbesondere können zwei Funktionen keine gemeinsam genutzten Hilfsfunktionen, gemeinsam genutzten Importanweisungen oder gemeinsam genutzten globalen Variablen verwenden.

Testfälle

[[1]] -> 1
[[4,5],[8,3]] -> 4
[[8],[11],[8],[10],[4]] -> 1
[[5,7,0,9,11,2,1]] -> 7
[[146,194,71,49],[233,163,172,21],[121,173,14,302],[259,169,26,5],[164,30,108,37],[88,55,15,2]] -> 3
[[138,2,37,2],[168,382,33,77],[31,199,7,15],[192,113,129,15],[172,88,78,169],[28,6,97,197]] -> 7
[[34,173,9,39,91],[169,23,56,74,5],[40,153,80,60,28],[8,34,102,60,32],[103,88,277,4,2]] -> 0
[[65,124,184,141],[71,235,82,51],[78,1,151,201],[12,24,32,278],[38,13,10,128],[9,174,237,113]] -> 2
[[164,187,17,0,277],[108,96,121,263,211],[166,6,57,49,73],[90,186,26,82,138],[173,60,171,265,96]] -> 8
Zgarb
quelle
Für einen Moment dachte ich, dies sei eine Multithreading- Frage. Ich habe mich auf mehr solche gefreut.
Adám

Antworten:

2

Haskell, 102 Bytes

Funktion 1 (102 Bytes):

l=length
[]#i=[[]]
(r:s)#i=id=<<[(splitAt j r:)<$>s#j|j<-[i-1..i+1],j>=0,j<l r]
f r=(r#)=<<[0..l$r!!0]

Funktion 2 (90 Bytes):

g::[[([Int],[Int])]]->Int 
g a=minimum$map(\(x,y)->abs$sum(sum<$>x)-sum(sum<$>y))$unzip<$>a

Fehlende Boilerplate für F1, um ein vollständiges Programm zu erstellen, einschließlich des fest zu überprüfenden fest codierten Integer-Arrays:

main = print $ f [[164,187,17,0,277],[108,96,121,263,211],[166,6,57,49,73],[90,186,26,82,138],[173,60,171,265,96]]

und für F2:

main = print . g . read =<< getContents

Jetzt können Sie runhaskell f1.hs | runhaskell f2.hswelche Ausgänge aufrufen 8.

So funktioniert es: fNimmt eine Liste mit Ganzzahlen.

f r = (r#)=<<[0..l$r!!0]          -- for each index [0 .. length r] call # with
                                  -- the first parameter being r and
                                  -- collect the results in a single list

[]#i=[[]]                         -- base case. If the list of lists is empty, stop
(r:s)#i                           -- else let r be the first list, s all others
           j<-[i-1..i+1],         -- foreach possible index j for the next line
                 j>=0,j<l r       --    (skipping out of range indices)
     (splitAt j r:)<$>            -- split the current line at j into a pair of
                                  -- lists and prepend it to every element of
                      s#j         -- a recursive call with s and j
id=<<                             -- flatten into a single list

Jetzt haben wir eine Liste aller möglichen Teilungen, zum Beispiel die erste und eine zufällige aus der Mitte

[([],[164,187,17,0,277]),                  [([164,187],[17,0,277]),
 ([],[108,96,121,263,211]),                 ([108,96],[121,263,211]),
 ([],[166,6,57,49,73]),                     ([166],[6,57,49,73]),
 ([],[90,186,26,82,138]),                   ([90,186],[26,82,138]),
 ([],[173,60,171,265,96])]                  ([173,60,171],[265,96])]

Funktion gnimmt eine solche Liste und

                    unzip<$>a       -- turn every pair of lists into a list of pairs
  map(\(x,y)->                      -- foreach such pair     
      abs$sum(sum<$>x)-sum(sum<$>y) -- calculate the score
minimum                             -- and find the minimum

Hinweis: Die zweite Funktion kann etwas mehr gespielt werden, ändert aber nichts an der Punktzahl.

Nimi
quelle