एक सरणी से मिनीम सम राशि निकालें


18

सीम नक्काशी एल्गोरिथ्म, या इसका एक अधिक जटिल संस्करण, विभिन्न ग्राफिक्स कार्यक्रमों और पुस्तकालयों में सामग्री-जागरूक छवि के लिए उपयोग किया जाता है। चलो इसे गोल्फ!

आपका इनपुट पूर्णांक आयताकार दो पूर्णांक होगा।

आपका आउटपुट एक ही सरणी, एक कॉलम संकरा होगा, जिसमें प्रत्येक पंक्ति से एक प्रविष्टि को हटा दिया जाएगा, वे प्रविष्टियाँ ऐसे सभी रास्तों के निम्नतम योग के साथ ऊपर से नीचे तक एक पथ का प्रतिनिधित्व करती हैं।

सीम नक्काशी चित्रण https://en.wikipedia.org/wiki/Seam_carving

उपरोक्त उदाहरण में, प्रत्येक कोशिका का मान लाल रंग में दिखाया गया है। काली संख्या एक कोशिका के मूल्य का योग है और इसके ऊपर की तीन कोशिकाओं में से एक में सबसे कम काली संख्या है (हरे तीरों द्वारा इंगित)। सफेद हाइलाइट किए गए पथ दो सबसे कम राशि वाले मार्ग हैं, दोनों 5 (1 + 2 + 2 और 2 + 2 + 2) के योग के साथ हैं।

ऐसे मामले में जहां सबसे कम राशि के लिए दो रास्ते बंधे हैं, इससे कोई फर्क नहीं पड़ता कि आप किसे हटाते हैं।

इनपुट को स्टैडेन से या फंक्शन पैरामीटर के रूप में लिया जाना चाहिए। यह आपकी पसंद की भाषा के लिए सुविधाजनक तरीके से स्वरूपित किया जा सकता है, जिसमें ब्रैकेट और / या सीमांकक शामिल हैं। कृपया अपने उत्तर में बताएं कि इनपुट कैसे अपेक्षित है।

आउटपुट को स्पष्ट रूप से सीमांकित प्रारूप में, या आपकी भाषा में एक मान वापसी मान के रूप में 2d सरणी के बराबर होना चाहिए (जिसमें नेस्टेड सूची शामिल हो सकती है, आदि)।

उदाहरण:

Input:
1 4 3 5 2
3 2 5 2 3
5 2 4 2 1
Output:
4 3 5 2      1 4 3 5
3 5 2 3  or  3 2 5 3
5 4 2 1      5 2 4 2

Input:
1 2 3 4 5
Output:
2 3 4 5

Input:
1
2
3
Output:
(empty, null, a sentinel non-array value, a 0x3 array, or similar)

संपादित करें: संख्या सभी गैर-नकारात्मक होगी, और हर संभव सीम में एक राशि होगी जो हस्ताक्षरित 32 बिट पूर्णांक में फिट होती है।


उदाहरणों में, सभी सेल मान एकल अंक संख्या हैं। क्या इसकी गारंटी है? यदि नहीं, तो क्या अन्य धारणाएं हैं जो मूल्यों के आकार / सीमा के बारे में बनाई जा सकती हैं? उदाहरण के लिए कि योग 16/32-बिट मूल्य में फिट बैठता है? या कम से कम यह कि सभी मूल्य सकारात्मक हैं?
रेटो कोराडी

@RetoKoradi ने विवरण के साथ संपादित किया
स्पियर

जवाबों:


5

CJam, 51 44 बाइट्स

{_z,1$,m*{_1>.-W<2f/0-!},{1$.=:+}$0=.{WtW-}}

यह एक अनाम फ़ंक्शन है जो स्टैक से 2 डी सरणी पॉप करता है और बदले में एक धक्का देता है।

CJam दुभाषिया में परीक्षण मामलों को ऑनलाइन आज़माएं1

विचार

यह दृष्टिकोण पंक्ति तत्वों के सभी संभावित संयोजनों पर निर्भर करता है, उन लोगों को फ़िल्टर करता है जो सीम के अनुरूप नहीं होते हैं, इसी राशि के आधार पर, न्यूनतम का चयन करें और सरणी से संबंधित तत्वों को हटा दें। 2

कोड

_z,   e# Get the length of the transposed array. Pushes the number of columns (m).
1$,   e# Get the length of the array itself. Pushes the number of rows (n).
m*    e# Cartesian power. Pushes the array of all n-tuples with elements in [0 ... m-1].
{     e# Filter:
  _1> e#     Push a copy of the tuple with first element removed.
  .-  e#     Vectorized difference.
  W<  e#     Discard last element.
  2f/ e#     Divide all by 2.
  0-  e#     Remove 0 from the results.
  !   e#     Push 1 if the remainder is empty and 0 otherwise.
},    e#     Keep only tuples which pushed a 1.

      e# The filtered array now contains only tuples that encode valid paths of indexes.

{     e# Sort by:
  1$  e#     Copy the input array.
  .=  e#     Retrieve the element of each row that corresponds to the index in the tuple.
  :+  e#     Add all elements.
}$    e#
0=    e# Retrieve the tuple of indexes with minimum sum.
.{    e# For each row in the array and the corresponding index in the tuple:
  Wt  e#     Replace the element at that index with -1.
  W-  e#     Remove -1 from the row.
}

1 ध्यान दें कि CJam खाली सरणियों और खाली तारों के बीच अंतर नहीं कर सकता है, क्योंकि तार सिर्फ सरणियाँ हैं जिनके तत्व वर्ण हैं। इस प्रकार, खाली सरणियों और खाली तारों दोनों का स्ट्रिंग प्रतिनिधित्व है ""

2 जबकि विकिपीडिया पृष्ठ पर दिखाए गए एल्गोरिथम की समय जटिलता एक n × m मैट्रिक्स के लिए O (nm) की होनी चाहिए , यह कम से कम O (m n ) है



अफसोस की बात है, कि दूसरे परीक्षण मामले के लिए काम नहीं करेगा। मैंने इस बारे में दो हफ्ते पहले बग रिपोर्ट दर्ज की है ।
डेनिस

5

हास्केल, 187 बाइट्स

l=length
f a@(b:c)=snd$maximum$(zip=<<map(sum.concat))$map(zipWith((uncurry((.drop 1).(++)).).flip splitAt)a)$iterate((\e@(f:_)->[f-1:e,f:e,min(f+1)(l b-1):e])=<<)[[y]|y<-[0..l b-1]]!!l c

उपयोग उदाहरण:

*Main> f [[1,4,3,5,2],[3,2,5,2,3],[5,2,4,2,1]]
[[4,3,5,2],[3,5,2,3],[5,4,2,1]]

*Main> f [[1],[2],[3]]
[[],[],[]]

*Main> f [[1,2,3,4,5]]
[[2,3,4,5]]

यह कैसे काम करता है, लघु संस्करण: प्रत्येक पथ (1) की सूची बनाएँ, प्रति पथ: संबंधित तत्वों (2) को हटा दें और सभी शेष तत्वों (3) को योग करें। सबसे बड़े योग (4) के साथ आयत लें।

लंबा संस्करण:

Input parameters, assigned via pattern matching:
a = whole input, e.g. [[1,2,4],[2,5,6],[3,1,6]]
b = first line, e.g. [1,2,4]
c = all lines, except first, e.g. [[2,5,6],[3,1,6]]

Step (1), build all paths:

iterate((\e@(f:_)->[f-1:e,f:e,min(f+1)(l b-1):e])=<<)[[y]|y<-[0..l b-1]]!!l c

     [[y]|y<-[0..l b-1]]           # build a list of single element lists
                                   # for all numbers from 0 to length b - 1
                                   # e.g. [[0],[1],[2]] for a 3 column input.
                                   # These are all possible start points

     \e@(f:_)->[f-1:e,f:e,min(f+1)(l b-1):e]
                                   # expand a list of paths by replacing each
                                   # path with 3 new paths (up-left, up, up-right)

     (...)=<<                      # flatten the list of 3-new-path lists into
                                   # a single list

     iterate (...) [...] !! l c    # repeatedly apply the expand function to
                                   # the start list, all in all (length c) times.


Step (2), remove elements

map(zipWith((uncurry((.drop 1).(++)).).flip splitAt)a)

     (uncurry((.drop 1).(++)).).flip splitAt
                                   # point-free version of a function that removes
                                   # an element at index i from a list by
                                   # splitting it at index i, and joining the
                                   # first part with the tail of the second part

      map (zipWith (...) a) $ ...  # per path: zip the input list and the path with
                                   # the remove-at-index function. Now we have a list
                                   # of rectangles, each with a path removed

Step (3), sum remaining elements

zip=<<map(sum.concat)             # per rectangle: build a pair (s, rectangle)
                                  # where s is the sum of all elements


Step (4), take maximum

snd$maximum                      # find maximum and remove the sum part from the
                                 # pair, again.

3

आईडीएल 8.3, 307 बाइट्स

मेह, मुझे यकीन है कि यह जीत नहीं होगी क्योंकि यह लंबा है, लेकिन यहां एक सीधा समाधान है:

pro s,a
z=size(a,/d)
if z[0]lt 2then return
e=a
d=a*0
u=max(a)+1
for i=0,z[1]-2 do begin
e[*,i+1]+=min([[u,e[0:-2,i]],[e[*,i]],[e[1:*,i],u]],l,d=2)
d[*,i]=l/z[0]-1
endfor
v=min(e[*,-1],l)
r=intarr(z[1])+l
for i=z[1]-2,0,-1 do r[0:i]+=d[r[i+1],i]
r+=[0:z[1]-1]*z[0]
remove,r,a
print,reform(a,z[0]-1,z[1])
end

Ungolfed:

pro seam, array
  z=size(array, /dimensions)
  if z[0] lt 2 then return
  energy = array
  ind = array * 0
  null = max(array) + 1
  for i=0, z[1]-2 do begin
    energy[*, i+1] += min([[null, energy[0:-2,i]], [energy[*,i]], [energy[1:*,i], null]], loc ,dimension=2)
    ind[*, i] = loc / z[0] - 1
  endfor
  void = min(energy[*,-1], loc)
  rem = intarr(z[1]) + loc
  for i=z[1]-2, 0, -1 do rem[0:i] += ind[rem[i+1], i]
  rem += [0:z[1]-1]*z[0]
  remove, rem, array
  print, reform(array, z[0]-1, z[1])
end

हम पुनरावृत्त रूप से ऊर्जा सरणी बनाते हैं और ट्रैक करते हैं कि सीम किस दिशा में जाती है, फिर अंतिम स्थिति को जानने के बाद एक निष्कासन सूची बनाएं। 1 डी इंडेक्सिंग के माध्यम से सीम निकालें, फिर नए आयामों के साथ सरणी में वापस सुधार करें।


3
हे भगवान ... मुझे लगता है कि मैंने सिर्फ आईडीएल (फिर से) को देखकर थोड़ा फेंक दिया। मैंने सोचा था कि मुझे स्नातक होने के बाद किया गया था ...
काइल कानोस

उस ने कहा, मुझे संदेह है कि यह जीडीएल के लिए भी काम करता है, ताकि लोग एकल उपयोगकर्ता लाइसेंस के लिए $ 1 बिलियन का भुगतान करने को तैयार न हों?
काइल कानोस

मैंने कभी जीडीएल का उपयोग नहीं किया है, इसलिए मैं नहीं कह सकता (ईमानदारी से मैं इसे भूल गया)। केवल एक चीज जो समस्या का कारण हो सकती है यदि जीडीएल वाक्य रचना के सरणी निर्माण को संभाल नहीं सकती है [0:n]; कि अगर सच है, तो यह बदलने के लिए आसान है r+=[0:z[1]-1]*z[0]के साथ r+=indgen(z[1]-1)*z[0]
सैपरकैवल

इसके अलावा, जब मैं अपने गोल्फ के लिए अजगर का उपयोग करूंगा, तो कोई और नहीं IDL करता है, इसलिए मुझे लगता है कि मैं XD में योगदान करने के लिए बाध्य हूं। साथ ही, यह कुछ चीजों को बहुत अच्छी तरह से करता है।
सैपरकैवल

3
मैं मुझे बहुत अच्छे से रोता / रोता हूँ;)
काइल कानोस

3

जावास्क्रिप्ट ( ईएस 6 ) 197 209 215

विकिपीडिया एल्गोरिदम का चरणबद्ध कार्यान्वयन।

शायद अधिक छोटा किया जा सकता है।

फ़ायरफ़ॉक्स में स्निपेट का परीक्षण करें।

// Golfed

F=a=>(u=>{for(r=[i=p.indexOf(Math.min(...p))];l--;i=u[l][i])(r[l]=[...a[l]]).splice(i,1)})
(a.map(r=>[r.map((v,i)=>(q[i]=v+~~p[j=p[i+1]<p[j=p[i-1]<p[i]?i-1:i]?i+1:j],j),q=[++l]),p=q][0],p=[l=0]))||r

// LESS GOLFED

U=a=>{
  p = []; // prev row
  u = a.map( r => { // in u the elaboration result, row by row
      q=[];
      t = r.map((v,i) => { // build a row for u from a row in a
        j = p[i-1] < p[i] ? i-1 : i; // find position of min in previous row
        j = p[i+1] < p[j] ? i+1 : j;
        q[i] = v + ~~p[j]; // values for current row
        // ~~ convert to number, as at first row all element in p are 'undefined'
        return j;//  position in u, row by row
      });
      p = q; // current row becomes previous row 
      return t;
  });
  n = Math.min(...p) // minimum value in the last row
  i = p.indexOf(n); // position of minimum (first if there are more than one present)
  r = []; // result      
  // scan u bottom to up to find the element to remove in the output row
  for(j = u.length; j--;)
  {
    r[j] = a[j].slice(); // copy row to output
    r[j].splice(i,1); // remove element
    i = u[j][i]; // position for next row
  }
  return r;
}

// TEST        
out=x=>O.innerHTML += x + '\n';        

test=[
  [[1,4,3,5,2],[3,2,5,2,3],[5,2,4,2,1]],
  [[1,2,3,4,5]],
  [[1],[2],[3],[4]]
];  

test.forEach(t=>{
  out('Test data:\n' + t.map(v=>'['+v+']').join('\n'));
  r=F(t);
  out('Golfed version:\n' + r.map(v=>'['+v+']').join('\n'))      
  r=U(t);
  out('Ungolfed version:\n' + r.map(v=>'['+v+']').join('\n'))
})  
<pre id=O></pre>


1

पिप, 91 बाइट्स

यह कोई पुरस्कार नहीं जीतेगा, लेकिन मुझे इस पर काम करने में मज़ा आया। व्हॉट्सएप केवल कॉस्मेटिक कारणों के लिए है और बाइट की गिनती में शामिल नहीं है।

{
 p:{(zaj-1+,3RMv)}
 z:a
 w:,#(a0)
 Fi,#a
  Fjw
   Ii
    z@i@j+:MN(pi-1)
 s:z@i
 Ti<0{
  j:s@?MNs
  a@i@:wRMj
  s:(p--i)
 }
 a
}

यह कोड एक अनाम फ़ंक्शन को परिभाषित करता है जिसका तर्क और वापसी मूल्य नेस्टेड सूचियां हैं। यह विकिपीडिया पृष्ठ से एल्गोरिथ्म को लागू करता है: a(तर्क) लाल संख्या है, और zकाली संख्या है।

यहाँ परीक्षण दोहन के साथ एक संस्करण है:

f:{p:{(zaj-1+,3RMv)}z:aw:,#(a0)Fi,#aFjwIiz@i@j+:MN(pi-1)s:z@iTi<0{j:s@?MNsa@i@:wRMjs:(p--i)}a}
d:[
 [[1 4 3 5 2]
  [3 2 5 2 3]
  [5 2 4 2 1]]
 [[1 2 3 4 5]]
 [[1]
  [2]
  [3]]
 ]
Fld
 P(fl)

परिणाम:

C:\> pip.py minSumSeam.pip -p
[[4;3;5;2];[3;5;2;3];[5;4;2;1]]
[[2;3;4;5]]
[[];[];[]]

और यहाँ पाइथन में लगभग बराबर है 3. यदि कोई पिप कोड का बेहतर स्पष्टीकरण चाहता है, तो बस टिप्पणियों में पूछें।

def f(a):
    z = [row.copy() for row in a]
    w = range(len(a[0]))

    for i in range(len(a)):
        for j in w:
            if i:
                z[i][j] += min(z[i-1][max(j-1,0):j+2])
    s = z[i]
    while i >= 0:
        j = s.index(min(s))
        del a[i][j]
        i -= 1
        s = z[i][max(j-1,0):j+2]
    return a
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.