Çoraplarımı sıralamama yardım et!


30

Çiftler halinde sıralamak istediğim temiz çoraplarım var. Ne yazık ki, ortadaki değil, yığının her iki ucundan da çorap alabilirim. Dahası, bir kerede yalnızca eşleştirme çiftinden eşleşen bir çifti çıkarabilirim. Stratejim önce yığını bir veya daha fazla küçük kazıklara bölmek. Bence bazı örnekler bunu netleştirecek. Her çorapı pozitif bir tamsayı olarak temsil edeceğim (eşleşen tamsayılar eşit çorapları gösterir).

Çorapların ilk yığını

1 2 3 3 2 1

o zaman herhangi bir bölme yapmak zorunda değilim. Her iki 1çorap, sonra iki 2çorap, sonra iki 3çorap kaldırabilirim .

Eğer öyleyse, başlangıç ​​yığını

1 2 3 2 3 1

o zaman önce bölmeliyim çünkü tüm çorapları baştan çıkararak eşleştiremem. Bir olasılık onu ikiye bölmek

1 2 3 and 2 3 1

Şimdi 1çorapları çıkarabilir , bırakabilir 2 3 and 2 3, ardından 3çorapları bırakabilir 2 and 2ve sonunda çorapları çıkarabilirim 2.

Senin işin

İlk çorap yığını göz önüne alındığında, çorapları sıralamama izin verecek daha küçük yığınlara ayıracak bir program yazın. Programınız yığını en az sayıda kazıklara bölmelidir (eğer birden fazla en iyi çözüm varsa, sadece birini bulmanız gerekir).

Giriş bir liste, sınırlandırılmış dize veya başka uygun bir form olarak verilecektir. Her bir tamsayı tam olarak iki kere meydana geldiğinde, sadece 1ve bazı maksimum değerler arasında tamsayılar içerecektir n.

Çıktı, uygun herhangi bir biçimde verilen giriş listelerinden daha küçük listelere bölünmelidir.

Örnekler

Input             Sample Output
1 1               1 1
1 2 1 2           1; 2 1 2
1 3 2 4 3 2 1 4   1 3 2; 4 3 2 1 4
1 2 3 4 3 4 1 2   1; 2 3; 4 3 4 1 2
1 1 2 2 3 3       1 1 2; 2 3 3
4 3 4 2 2 1 1 3   4 3 4 2; 2 1 1 3

Bunun, bu girişlerin çoğu için izin verilen tek çıkış olmadığını unutmayın. İkinci durumda, örneğin, çıktılar 1 2; 1 2da 1 2 1; 2kabul edilirdi.

Bazı test önerileri için Sp3000'e teşekkürler!

Kıyafetlerimi sıralayarak uzun süre harcamaktan nefret ediyorum, bu yüzden kodunuzu mümkün olduğunca kısa tutun. Bayt cinsinden en kısa cevap kazanır!

notlar

  • Eşleşen çiftin orada olup olmadığını görmek için bir çorabın arkasına bakmak istemiyorum, bu yüzden her iki çorabı aynı uçtan bir çifte almak yasaktır. Örneğin, eğer tüy 1 1 2 2o zaman tek bir kazık olarak bırakamaz 1ve soldan iki çorabını alabilirsin .

5
PPCG Carmeister'a hoş geldiniz diyebilir miyim? Bu çok iyi bir ilk meydan okuma + 1.
Mantık Şövalyesi

1
PPCG'ye Hoşgeldiniz! Bu çok iyi bir ilk soru. Bu sorunun önemli bir sorunu yok gibi görünmesine rağmen, kullanıcıları göndermeden önce zorlukları hakkında geribildirim almak için Sandbox'ı kullanmalarını öneririz .
Mego

Öyleyse ( -> -> ) 123213ayrılabilir mi? 1; 23; 2131; 23; 2131; 2; 21; 2; 2
R. Kap,

@Mego Teşekkürler! Bunu gelecekte yapacağınızdan emin olacağım. @ R.Kap Bu onu bölmek için geçerli bir yol olabilir, ancak cevap mümkün olan en az sayıda kazıklara bölen bir bölme vermelidir. 123213Sadece iki kazık kullanarak bölmek mümkün olduğundan , cevabınız iki kazık bölmeden birini vermek zorunda kalacak.
Carmeister

1
@ven Sorunuzu anladığımdan tam olarak emin değilim, ancak alınabilecek çoraplar her yığının başında ve her yığının sonunda olanlar.
Carmeister

Yanıtlar:


6

Pyth, 25 bayt

hf!u #-R.-F{BhMs_BMGGT)./

Test odası

Açıklama:

hf!u #-R.-F{BhMs_BMGGT)./
                       ./    Form all partitions (implicitly) of the input.
 f                           Filter the permutations on
   u                 T)      Run the following function on the partition
                             until it reaches a fixed point:
                _BMG         Bifurcate the lists on reversal
               s             Concatenate
             hM              Take the first element of each list. 
                             These elements are all the ones on the ends of lists.
           {B                Bifurcate on deduplication
        .-F                  Bagwise subtraction.
                             Only elements repeated in ends of lists remain.
      -R            G        Remove these elements from each list.
   ' #'                      Filter out empty lists.
  !                          Negate. Only an empty list as fixed point succeeds.
h                            Output the first successful partition.

5

JavaScript (ES6), 329

Birleştirici yerleşik olmayan bir dil için kolay bir iş değil.

Muhtemelen daha yumuşak bir şekilde golf oynamak mümkün.

Not: Tüm bölümler en az 2 boyuttadır, çünkü tek elemanlı bölümler her zaman daha az faydalıdır.

Example: [1] [2 3 4] // can take 1 or 2 or 4  
Better: [1 2] [3 4] // can take 3 too  
a=>{G=(v,i,u=v)=>{if(i--){for(;r[i]=--u;)if(G(u,i))return 1;}else for(w=[...r,n=l].map((x,i)=>a.slice(z,z=x-~i),z=0),y=w.join`;`;w.map(b=>[0,1].map(q=>(x=b[q*=~-b.length])&&(t[x]?([c,p]=t[x],n-=2,p?c.pop():c.shift(),q?b.pop():b.shift()):t[x]=[b,q])),c=0,t=[]),c;)if(!n)return 1};for(l=a.length,r=[],k=0;!G(l-k-1,k);k++);return y}

Parça açıklaması

(Aşırı derecede ayrıntılı, ama açıklamak zor buldum - sonunda "hepsini bir araya koymak" için atlayın)

Bir dizinin tüm olası bölümlerini numaralandırmak için bir özyinelemeli işlev

// v: array length
// i number of splits
// fill the global array r that must exists
G=(v,i,u=v)=>
{
  if(i--)
  {
    for(;r[i]=--u;)
      G(u,i)
  }
  else
  {
    // the current split position are in r, ready to use
    // for instance...
    parts = [...r,a.length].map(x=>a.slice(z,z=x),z=0)
    console.log(r, parts)
  }
};

r=[]
a=['A','B','C','D']
G(4, 2)

// output in console (firebug)
[2, 3] [["A", "B"], ["C"], ["D"]]
[1, 3] [["A"], ["B", "C"], ["D"]]
[1, 2] [["A"], ["B"], ["C", "D"]]

Şimdi, 2 veya daha büyük boyutta bölümlere ihtiyacım var, bu yüzden bu işlevi kaydırmalı olarak farklı parametrelerle kullanmalıyım. V parametresi "dizi boyutu - istenen bölüm sayısı - 1" dir. O zaman bölümleri biraz farklı bir şekilde oluşturmalıyım.

// Same call (4,2), same r, but the array b is of size 7
part = [...r,b.length].map((x,i)=>
          b.slice(z,z=x+i+1) // add 1 more element to each partition
       ,z=0))
// output in console (firebug) 
[2, 3] [["A", "B", "C"], ["D", "E"], ["F", "G"]]
[1, 3] [["A", "B"], ["C", "D", "E"], ["F", "G"]]
[1, 2] [["A", "B"], ["C", "D"], ["E", "F", "G"]]

Böylece, hiçbir bölünme, 1 bölme, 2 bölme vb. İçin bölümlerin listesini numaralandırabilirim. Çalışan bir bölüm bulduğumda, sonuçta duracağım ve çıktısını alacağım.

Kontrol etmek için, bölüm listesini tarayın, eğer her birinin başında ve sonunda bulunan değerleri not alın. Sonunda hiçbir şey çıkarılana kadar tekrarlayın: eğer tüm çiftler çıkarılmışsa bu bölüm iyidir.

t = []; // array to note the repeated values
// t[x] == [
//           subarray holding value x, 
//           position of value x (I care zero or nonzero)
//         ]
n = a.length // counter start, must reach 0
// remember part just in case, because this check will destroy it 
result = part.join(';') // a string representation for return value
do
{
  // in the golfed code there is a forr loop
  // all this body is inside the for condition
  c = 0; // init c to a falsy, if a pair is found c becomes truthy
  part.forEach(b=> // b: array, current partition
    [0,1].forEach(q=> ( // exec for 0 (start), 1 (end)
      q *= b.length-1, // now q is the correct index
      x = b[q]) // x is the value at start or end
      x && ( // b could be empty, check that x is not 'undefined'
        t[x] ? // is there a value in t at position x?
           ( // yes, remove the pair
             n-=2, // pair found, decrement counter
             [c, p] = t[x], // get stored array and position
             p ? c.pop() : c.shift(), // remove from c at start or end
             q ? b.pop() : b.shift()  // remove twin value from b
           )
           : // no, remember the value in t
             t[x] = [b, q]
    )) // end [0,1].forEach
  ) // end part.forEach
}
while (c) // repeat until nothing can be removed
if(!n) return 1 // wow, result found (in 'result' variable)

Ardından, eksik olan kısım, G sayısını bölümleme sayısını arttıran G işlevini calop eden bir döngüdür. Bir sonuç bulunduğunda döngüden çıkar.

Hepsini bir araya getirmek

F=a=>{
  G=(v,i,u=v)=>{
    if (i--)
    {
      for(; r[i]=--u; )
        if (G(u,i)) 
          return 1;
    }
    else
    {
      w = [...r,n=l].map((x,i)=>a.slice(z, z = x-~i), z = 0);
      y = w.join`;`;
      for(; // almost all the for body is inside the condition
        w.map(b=>
          [0,1].map(q=>
            (x=b[q*=~-b.length])
             &&(t[x]
                ?([c,p]=t[x],n-=2,
                   p?c.pop():c.shift(),
                   q?b.pop():b.shift())
                :t[x]=[b,q])) // end [0,1].map
          ,c=0,t=[] // init variables for w.map
        ),c; // the loop condition is on c
      )
        if(!n)return 1 // this is the for body
    }
  };
  for(l = a.length, r = [], k = 0; !G(l-k-1, k); k++);
  return y
}

Ölçek

F=a=>{G=(v,i,u=v)=>{if(i--){for(;r[i]=--u;)if(G(u,i))return 1;}else for(w=[...r,n=l].map((x,i)=>a.slice(z,z=x-~i),z=0),y=w.join`;`;w.map(b=>[0,1].map(q=>(x=b[q*=~-b.length])&&(t[x]?([c,p]=t[x],n-=2,p?c.pop():c.shift(),q?b.pop():b.shift()):t[x]=[b,q])),c=0,t=[]),c;)if(!n)return 1};for(l=a.length,r=[],k=0;!G(l-k-1,k);k++);return y}

console.log=x=>O.textContent+=x+'\n'

TestData=[[1,1],[1,2,1,2],[1,3,2,4,3,2,1,4],[1,2,3,4,3,4,1,2],[1,1,2,2,3,3],[4,3,4,2,2,1,1,3]]

TestData.forEach(t=>console.log(t+' -> '+F(t)))

function RandomTest() {
  var l=I.value*2
  var a=[...Array(l)].map((_,i)=>1+i/2|0)
  a.map((v,i)=>a[a[i]=a[j=0|i+Math.random()*(a.length-i)],j]=v) // shuffle
  Q.textContent=a+''+'\n\n'+F(a).replace(/;/g, ';\n') // better readability
}
Base test
<pre id=O></pre>
Random test. Number of pairs: <input id=I value=15><button onclick="RandomTest()">-></button>
<pre id=Q></pre>

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.