Chia mảng và chương trình làm đôi


10

Giới thiệu

Bạn đã được giao nhiệm vụ viết một chương trình chia một mảng số nguyên hình chữ nhật thành một nửa (vì bất kỳ lý do gì). Nhiệm vụ này được tính toán chuyên sâu, nhưng may mắn là bạn có một máy lõi kép để thực hiện các tính toán. Để tối đa hóa lợi ích của việc xử lý song song, bạn quyết định chia đều chương trình thành một nửa và để mỗi lõi chạy một trong các phần độc lập với phần kia.

Đầu vào và đầu ra

Đầu vào của bạn là một mảng 2D hình chữ nhật gồm các số nguyên không âm có kích thước tối thiểu 1 × 1 , được lấy ở bất kỳ định dạng hợp lý nào. Một sự phân tách của một mảng như vậy có được bằng cách tách từng hàng ngang thành tiền tố và hậu tố (một trong hai có thể để trống). Để việc chia tách có hiệu lực, hai hàng liền kề phải được phân chia tại cùng một chỉ mục hoặc các chỉ mục liền kề. Ví dụ, hãy xem xét mảng

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

Đây là một phân tách hợp lệ:

 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

Đây cũng là một sự chia tách hợp lệ:

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

Đây không phải là một phân tách hợp lệ:

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

Đầu ra của bạn sẽ là giá trị tối thiểu của

abs(sum_of_prefixes - sum_of_suffixes)

trên tất cả các mối nối hợp lệ của đầu vào.

Quy tắc và tính điểm

Bạn sẽ viết hai chương trình (chương trình đầy đủ hoặc chức năng) trong cùng một ngôn ngữ, không được có bất kỳ mã chia sẻ nào giữa chúng. Hãy gọi chúng là P1P2 . Chương trình P1 lấy mảng đầu vào và xuất ra thứ gì đó . Chương trình P2 lấy thứ này làm đầu vào và đưa ra câu trả lời của tác vụ trên cho mảng đầu vào.

Điểm của bạn là tối đa số byte của P1P2 , điểm thấp hơn sẽ tốt hơn.

Một số làm rõ:

  • Bạn có thể viết hai prorgams đầy đủ, một chức năng và một chương trình đầy đủ hoặc hai chức năng.
  • Trong trường hợp có hai chương trình đầy đủ, toàn bộ đầu ra của P1 được đưa đến P2 làm đầu vào, như trong đường ống Unix P1 | P2. Các chương trình phải hoạt động chính xác nếu được biên dịch / giải thích từ hai tệp nguồn riêng biệt.
  • Nếu một trong hai chương trình là một hàm, nó được chuyển đổi thành một chương trình đầy đủ bằng cách thêm mã soạn sẵn cần thiết và quy tắc trên được áp dụng cho nó. Cụ thể, hai hàm không thể sử dụng các hàm phụ trợ chung, báo cáo nhập chung hoặc biến chung chung.

Các trường hợp thử nghiệm

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

Trong một khoảnh khắc, tôi nghĩ rằng đây là một câu hỏi đa luồng . Tôi đã mong chờ nhiều hơn như vậy.
Adám

Câu trả lời:


2

Haskell, 102 byte

Hàm 1 (102 byte):

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]

Hàm 2 (90 byte):

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

Thiếu phần soạn sẵn cho F1 để biến nó thành một chương trình đầy đủ, bao gồm cả mảng số nguyên được mã hóa để kiểm tra:

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

và cho F2:

main = print . g . read =<< getContents

Bây giờ bạn có thể gọi runhaskell f1.hs | runhaskell f2.hsđầu ra nào 8.

Cách thức hoạt động: flấy danh sách các số nguyên.

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

Bây giờ chúng tôi có một danh sách tất cả các phân chia có thể, ví dụ như phân tách đầu tiên và ngẫu nhiên từ giữa

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

Hàm gcó một danh sách như vậy và

                    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

Lưu ý: chức năng thứ hai có thể được đánh gôn nhiều hơn một chút, nhưng nó không thay đổi điểm số.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.