Giúp tôi sắp xếp tất của tôi!


30

Tôi có một đống vớ sạch mà tôi muốn sắp xếp thành cặp. Thật không may, tôi chỉ có thể đi tất từ ​​hai đầu của đống, không phải giữa. Hơn nữa, tôi chỉ có thể tháo vớ ra khỏi đống một đôi phù hợp tại một thời điểm. Chiến lược của tôi là đầu tiên chia cọc thành một hoặc nhiều cọc nhỏ hơn. Tôi nghĩ rằng một số ví dụ sẽ làm rõ điều này. Tôi sẽ đại diện cho mỗi chiếc vớ là một số nguyên dương (số nguyên phù hợp cho biết tất bằng nhau).

Nếu đống vớ ban đầu là

1 2 3 3 2 1

sau đó tôi không phải thực hiện bất kỳ chia tách. Tôi có thể tháo cả hai 1vớ, rồi cả 2vớ, rồi cả 3vớ.

Nếu thay vào đó, cọc ban đầu là

1 2 3 2 3 1

sau đó tôi phải tách nó ra trước vì tôi sẽ không thể ghép tất cả các vớ bằng cách chỉ tháo chúng ra khỏi cuối. Một khả năng là chia nó thành hai đống

1 2 3 and 2 3 1

Bây giờ tôi có thể loại bỏ 1tất, rời đi 2 3 and 2 3, tiếp theo là 3tất, rời đi 2 and 2, và cuối cùng là 2tất.

Công việc của bạn

Đưa ra đống vớ ban đầu, hãy viết một chương trình sẽ chia nó thành các đống nhỏ hơn cho phép tôi phân loại vớ. Chương trình của bạn nên chia cọc thành số lượng cọc ít nhất có thể (nếu có nhiều giải pháp tốt nhất, bạn chỉ cần tìm một giải pháp).

Đầu vào sẽ được cung cấp dưới dạng danh sách, chuỗi phân tách hoặc hình thức thuận tiện khác. Nó sẽ chỉ chứa các số nguyên giữa 1và một số giá trị tối đa n, với mỗi số nguyên xảy ra chính xác hai lần.

Đầu ra phải bao gồm danh sách đầu vào được chia thành các danh sách nhỏ hơn, được đưa ra dưới bất kỳ hình thức thuận tiện nào.

Ví dụ

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

Lưu ý rằng đây không phải là đầu ra được phép duy nhất cho hầu hết các đầu vào này. Đối với trường hợp thứ hai, ví dụ, các đầu ra 1 2; 1 2hoặc 1 2 1; 2cũng sẽ được chấp nhận.

Cảm ơn Sp3000 cho một số gợi ý kiểm tra!

Tôi ghét dành thời gian dài để phân loại quần áo của tôi, vì vậy hãy làm cho mã của bạn càng ngắn càng tốt. Câu trả lời ngắn nhất trong byte chiến thắng!

Ghi chú

  • Tôi không muốn phải nhìn vào phía sau một chiếc tất để xem có phải đôi phù hợp của nó ở đó không, vì vậy việc mang cả hai chiếc vớ vào một đôi từ cùng một đầu là không được phép. Ví dụ, nếu là đống 1 1 2 2thì bạn sẽ không thể để nó thành một đống và lấy cả hai 1vớ từ đầu bên trái.

5
Tôi có thể nói chào mừng đến PPCG Carmeister. Đây là một thử thách đầu tiên rất tốt +1.
Logic Knight

1
Chào mừng đến với PPCG! Đây là một câu hỏi đầu tiên rất tốt. Mặc dù câu hỏi này dường như không có bất kỳ vấn đề lớn nào, chúng tôi khuyến khích người dùng sử dụng Hộp cát để nhận phản hồi về các thách thức của họ trước khi đăng chúng.
Mego

Vì vậy, 123213có thể được chia thành 1; 23; 213( 1; 23; 213-> 1; 2; 21-> ; 2; 2)?
R. Kap

@Mego Cảm ơn! Tôi chắc chắn sẽ làm điều đó trong tương lai. @ R.Kap Đó sẽ là một cách hợp lệ để phân tách nó, nhưng câu trả lời sẽ đưa ra một phân tách tách nó thành số lượng cọc nhỏ nhất có thể. Vì có thể phân tách 123213chỉ bằng hai cọc, câu trả lời của bạn sẽ phải đưa ra một trong hai lần chia hai cọc.
Carmeister

1
@ven Tôi không hoàn toàn chắc chắn tôi hiểu câu hỏi của bạn, nhưng những đôi tất có sẵn là những cái ở đầu mỗi cọc và những cái ở cuối mỗi cọc.
Carmeister

Câu trả lời:


6

Bình thường, 25 byte

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

Bộ kiểm tra

Giải trình:

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

Không phải là một nhiệm vụ dễ dàng cho một ngôn ngữ không có nội dung kết hợp.

Có lẽ là chơi golf nhiều hơn.

Lưu ý: tất cả các phân vùng đều có kích thước tối thiểu là 2, vì một phân vùng có một phần tử duy nhất luôn ít hữu ích hơn.

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}

Giải thích trong các phần

(đó là quá dài dòng, nhưng tôi thấy thật khó để giải thích - cuối cùng bỏ qua để "đặt tất cả lại với nhau")

Hàm đệ quy để liệt kê tất cả các phân chia có thể có của một mảng

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

Bây giờ, tôi cần các phân vùng có kích thước từ 2 trở lên, vì vậy tôi phải sử dụng chức năng này với các tham số khác nhau. Tham số v là "kích thước mảng - số phân vùng mong muốn - 1". Sau đó, tôi phải xây dựng các phân vùng theo một cách hơi khác.

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

Vì vậy, tôi có thể liệt kê danh sách các phân vùng không phân chia, 1 phân tách, 2 phân chia, v.v. Khi tôi tìm thấy một phân vùng làm việc, tôi sẽ dừng lại và đưa ra kết quả tìm thấy.

Để kiểm tra, quét danh sách phân vùng, lưu ý các giá trị ở đầu và cuối của mỗi giá trị, nếu tìm thấy giá trị được lặp lại thì hãy xóa nó. Lặp lại cho đến khi không có gì có thể được gỡ bỏ, cuối cùng: nếu tất cả các cặp đã bị xóa thì phân vùng này là tốt.

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)

Sau đó, phần còn thiếu chỉ là một vòng lặp làm dịu chức năng G làm tăng số lượng phân vùng. Lối ra vòng lặp khi tìm thấy kết quả.

Đặt nó tất cả cùng nhau

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
}

Kiểm tra

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>

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.