Kéo dài một mảng


13

Trước đó tôi đã xác định quá trình nghiền một mảng

Trong một lòng, chúng tôi đọc các mảng từ trái sang phải. Nếu tại một thời điểm chúng ta bắt gặp hai phần tử giống nhau liên tiếp, chúng ta sẽ loại bỏ phần tử thứ nhất và nhân đôi phần tử thứ hai.

Ví dụ ở đây là quá trình nghiền mảng sau

[5,2,2,4]
 ^
[5,2,2,4]
   ^
[5,2,2,4]
     ^
[5,4,4]
   ^
[5,4,4]
     ^
[5,8]
   ^

Lưu ý rằng cùng một yếu tố có thể được thu gọn nhiều lần. Trong ví dụ 2,2,4đã được thu gọn 8trong một lần duy nhất.

Bây giờ nghiền nát các mảng là dễ dàng, những gì khó khăn là làm mờ chúng. Nhiệm vụ của bạn là lấy một mảng các số nguyên dương làm đầu vào và đầu ra mảng lớn nhất có thể tạo thành đầu vào khi bị nghiền nát nhiều lần. Ví dụ, mảng [4]được hình thành bằng cách nghiền [2,2]mà lần lượt được hình thành bằng cách nghiền [1,1,1,1]. Vì chúng ta không thể có các giá trị không nguyên [1,1,1,1]không thể bị xóa thêm nữa và đó là câu trả lời của chúng tôi.

Bạn sẽ không bao giờ nhận được một 0trong mảng đầu vào của bạn bởi vì các mảng như vậy có thể được mở rộng vô thời hạn. Bạn cũng sẽ không bao giờ nhận được một trường hợp có hai số lẻ giống nhau cạnh nhau, những trường hợp như vậy không thể là kết quả của việc nghiền nát.

Đây là vì vậy các câu trả lời sẽ được ghi với kích thước của nguồn được đo bằng byte với ít byte hơn.

Trước khi bạn bắt đầu đưa ra câu trả lời của mình, tôi chỉ muốn nói rằng thử thách này khó khăn hơn đáng kể. Kiểm tra trực giác của bạn khi bạn đi cùng và đảm bảo câu trả lời của bạn vượt qua tất cả các trường hợp kiểm tra.

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

[] -> []
[5] -> [5]
[6] -> [3,3]
[8] -> [1,1,1,1,1,1,1,1]
[4,8] -> [1,1,1,1,1,1,1,1,1,1,2]
[2,8] -> [1, 1, 1, 1, 2, 1, 1, 1, 1]
[4,4] -> [1,1,1,1,1,1,1,1]

1
Xin lỗi nhưng tôi vẫn không thể hiểu quy tắc. Tại sao [1,1,1,1,1,1,1,1,1,1,2]sản xuất [4, 8]thay vì [8, 4]? điều này nên được [1,>1,1,1,1,1,1,1,1,1,2], [2,1,>1,1,1,1,1,1,1,2], [2,>2,1,1,1,1,1,1,2], [4,1,>1,1,1,1,1,2], [4,2,1,>1,1,1,2], [4,2,>2,1,1,2], [4,>4,1,1,2], [8,1,>1,2], [8,2,>2], [8,4]?
tsh

2
@tsh Tôi nghĩ bạn có một quan niệm sai lầm trong cách nghiền nát hoạt động. Đây là con đường phải mất đầu tiên vượt qua: [1,>1,1,1,1,1,1,1,1,1,2], [2,>1,1,1,1,1,1,1,1,2], [2,1,>1,1,1,1,1,1,1,2], [2,2,>1,1,1,1,1,1,2], [2,2,1,>1,1,1,1,1,2], [2,2,2,>1,1,1,1,2], [2,2,2,1,>1,1,1,2], [2,2,2,2,>1,1,2], [2,2,2,2,1,>1,2], [2,2,2,2,2,>2], [2,2,2,2,4>], thứ hai vượt qua: [2,>2,2,2,4], [4,>2,2,4], [4,2,>2,4], [4,4,>4], [4,8>]. Hy vọng rằng sẽ xóa nó lên. Nếu bạn muốn một số mã để xem câu hỏi trước đó có câu trả lời thực hiện chức năng nghiền.
Đăng Rock Garf Hunter

Có ổn không nếu tôi xuất số, mỗi số được phân tách bằng một dòng mới?
scottinet

@scottinet Đó là một cách hợp lý để xuất danh sách. Đi về phía trước.
Đăng Rock Garf Hunter

Trường hợp kiểm tra [4, 4]nên được loại bỏ, vì chúng ta không bao giờ có thể có được mảng đó sau một chuỗi kéo dài => chuỗi, vì điều này sẽ kết thúc với[8]
scottinet

Câu trả lời:


2

JavaScript (Node.js) , 237 221 213 186 byte

f=a=>a.map(b=>{for(i=1;~b%2;b/=2)i*=2;return Array(i).fill(b)}).reduce((t,c,i,s)=>{b=c.slice();if(i)r=2*s[--i].length,b.length>=r&&b[0]==s[i][0]?b[r-2]+=b.pop():b;return t.concat(b)},[])

Hãy thử trực tuyến!

Thuật toán này tính toán các mảng được kéo dài tối ưu, bằng cách kéo dài từng số đến mức tối đa, và sau đó, nếu cần, nó sẽ nghiền nát một cặp số ở đúng vị trí, tạo ra một "trình chặn nghiền" một cách hiệu quả, làm gián đoạn chuỗi nghiền của số trước đó.

Ví dụ:

[1, 1, 1, 1, 1, 1]cho [4,2]một lần bị nghiền nát, nhưng [1, 1, 1, 1, 2]kết quả trong[2, 4]

Thách thức là xác định chính xác vị trí của một trình chặn khối phải được đặt sao cho việc nghiền mảng kết quả cho kết quả đúng:

  • Một trình chặn khối chỉ cần được đặt nếu số kéo dài trước bằng với số hiện tại và nếu trình tự kéo dài hiện tại lớn hơn số trước. Ví dụ, [2, 4]đòi hỏi phải có một chặn lòng (số kéo dài được 1, lặp đi lặp lại, và [1, 1]ngắn hơn [1,1,1,1]), nhưng [4, 2][2, 6]không đòi hỏi một
  • nếu chúng ta gọi nchuỗi kéo dài trước đó và nếu điều kiện trên được xác minh, thì chuỗi hiện tại là sự lặp lại của nchuỗi. Để làm gián đoạn chuỗi nghiền của số trước đó, chúng ta cần đặt trình chặn nghiền ở cuối nchuỗi thứ hai của số hiện tại để kéo dài. Ví dụ : [2, 8] => [(1, 1)=n, (1, 1) + (2) + (1, 1) + ...], hoặc[4, 8] => [(1, 1, 1, 1)=n, (1, 1, 1, 1) + (1, 1, 2) + ...]


1

Python 2 , 230 228 226 byte

Hoạt động bằng cách lặp lại tất cả các danh sách có thể có cùng số tiền với danh sách đầu vào. Loại bỏ những cái không bằng mảng đầu vào trong một số trạng thái bị nghiền nát, chọn cái dài nhất.

Chỉnh sửa: -2 byte bằng cách loại bỏ ifchức năng chính

Chỉnh sửa: -2 byte bằng cách xóa hai dấu ngoặc vuông không cần thiết

lambda x:max((c(z[:],x),len(z),z)for z in b(sum(x)))[2]
def c(x,y):
 i=e=1
 while x[i:]:
	if x[~-i]==x[i]:del x[i];i-=1;x[i]*=2;e=2
	i+=1
 return x==y or~-e and c(x,y)
b=lambda s:[z+[-~i]for i in range(s)for z in b(s+~i)]+[[]]

Hãy thử trực tuyến!

Giải trình

Chức năng chính, chịu trách nhiệm tìm kiếm tất cả các giải pháp có thể và chọn giải pháp dài nhất

lambda x:max((c(z[:],x),len(z),z)for z in b(sum(x)))[2]

Hàm nghiền, kiểm tra xem y có bằng một trong các khối không.

def c(x,y):
 i=e=1
 while x[i:]:
	if x[~-i]==x[i]:del x[i];i-=1;x[i]*=2;e=2
	i+=1
 return x==y or~-e and c(x,y)

Tạo tất cả các hoán vị có thể có với tổng đã cho

b=lambda s:[z+[-~i]for i in range(s)for z in b(s+~i)]+[[]]

0

05AB1E , 41 37 byte

vy[DÉ#2÷]DYQX©NoDU‹&sDV¸X∍sić·®·Íǝ}»,

Hãy thử trực tuyến!

Cổng giải pháp Javascript của tôi.

Giải thích:

vy                   for each member of the list
[DÉ#2÷]              divide by 2 until odd: stack = stretched value, N = iterations
DYQ                  stetched value equal to the previous one?
X©NoDU‹              previous size < current one? (+store the new size in X)
&                    AND on the 2 previous tests
sDV¸X∍s              build a list of the new stretched value repeated X times
                      (+store the new stetched value in Y)
ić·®·Íǝ}             if the previous tests are true:
                       reduce the result list size by 1
                       multiply by 2 the number at the crush block position
»,                   join by newline + print the list
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.