Dizileri ve programları ikiye bölün


10

Giriş

Dikdörtgen bir tamsayı dizisini (her ne nedenle olursa olsun) eşit olarak ikiye ayıran bir program yazmakla görevlendirildiniz. Bu görev hesaplama açısından yoğun, ancak neyse ki hesaplamaları yapmak için çift çekirdekli bir makineniz var. Paralelliğin faydalarını en üst düzeye çıkarmak için, programı eşit olarak ikiye bölmeye karar verirsiniz ve her çekirdeğin parçalardan birini diğerinden bağımsız olarak çalıştırmasına izin verirsiniz.

Giriş ve çıkış

Girişiniz , herhangi bir makul formatta alınmış, en az 1 × 1 büyüklüğünde, negatif olmayan tamsayılardan oluşan dikdörtgen bir 2D dizisidir . Bir bölme , örneğin bir dizi ve bir ön ek eki (bunlardan herhangi biri boş) olabilir bölünerek her yatay satır elde edilir. Bir bölmenin geçerli olması için, iki bitişik satırın aynı dizinde veya bitişik dizinlerde bölünmesi gerekir. Örneğin, diziyi düşünün

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

Bu geçerli bir bölünme:

 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

Bu aynı zamanda geçerli bir ayrımdır:

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

Bu geçerli bir bölme değil:

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

Çıktınız minimum değeri

abs(sum_of_prefixes - sum_of_suffixes)

girişin tüm geçerli bölümlerinde.

Kurallar ve puanlama

Aynı dilde iki program (tam programlar veya işlevler) yazmalısınız , bunlar arasında paylaşılan kod bulunmamalıdır. Onlara P1 ve P2 diyelim . P1 programı girdi dizisini alır ve bir şeyler çıkarır . P2 programı bunu girdi olarak alır ve girdi dizisi için yukarıdaki görevin yanıtını verir.

Skorunuz P1 ve P2'nin bayt sayısının maksimumudur , daha düşük skor daha iyidir.

Bazı açıklamalar:

  • İki tam proggam, bir fonksiyon ve bir tam program veya iki fonksiyon yazabilirsiniz.
  • İki tam program durumunda, P1'in tüm çıkışı , Unix boru hattında olduğu gibi giriş olarak P2'ye beslenir P1 | P2. İki ayrı kaynak dosyasından derlenmiş / yorumlanmışsa, programların düzgün çalışması gerekir.
  • Her iki program da bir işlevse, gerekli ortak plaka kodu eklenerek tam bir programa dönüştürülür ve yukarıdaki kural buna uygulanır. Özellikle, iki işlev paylaşılan yardımcı işlevleri, paylaşılan içe aktarma deyimlerini veya paylaşılan genel değişkenleri kullanamaz.

Test senaryoları

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

Bir an için bunun çok iş parçacıklı bir soru olduğunu düşündüm . Daha fazlasını dört gözle bekliyordum.
Adám

Yanıtlar:


2

Haskell, 102 bayt

İşlev 1 (102 bayt):

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]

İşlev 2 (90 bayt):

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

Kontrol etmek için sabit kodlu tamsayı dizisi de dahil olmak üzere tam bir program yapmak için F1 için eksik plaka:

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

ve F2 için:

main = print . g . read =<< getContents

Şimdi runhaskell f1.hs | runhaskell f2.hshangi çıkışları çağırabilirsiniz 8.

Nasıl çalışır: ftamsayıların bir listesini alır.

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

Şimdi tüm olası bölünmelerin bir listesi var, örneğin ilk ve ortadan rastgele bir

[([],[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])]

İşlev gböyle bir liste alır ve

                    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

Not: İkinci fonksiyon biraz daha golf edilebilir, ancak skoru değiştirmez.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.