Điêu khắc từ tính


14

Đây là sự tiếp nối lỏng lẻo của thử thách trước đây của tôi về việc xây dựng đồ thị .

Lý lịch

Một nghệ sĩ lập dị đã thuê bạn để ước tính tính toàn vẹn cấu trúc của tác phẩm điêu khắc của anh ta. Ông tạo ra các tác phẩm nghệ thuật của mình bằng cách lấy một loạt nam châm hình khối, và thả từng viên một vào một đống lớn. Để phân tích tốt hơn phương pháp của mình, chúng tôi sử dụng mô hình hai chiều sau. Chúng tôi bắt đầu với một sàn trống và thả một nam châm #ở bất kỳ tọa độ nguyên nào, nói 0:

       |
       v
       #
===============
       0

Nếu một nam châm khác bị rơi tại 0, nó sẽ nằm trên đỉnh của cái trước đó:

       |
       v
       #
       #
===============
       0

Bây giờ, chúng ta hãy thả thêm một nam châm tại 0, và sau đó một 1:

        |
       #v
       ##
       #
===============
       0

Như đã thấy ở trên, một nam châm rơi xuống dính vào nam châm thứ hai mà nó đi qua (cái thứ nhất chỉ làm nó chậm lại). Nam châm thứ hai không cần trực tiếp bên dưới nam châm thứ nhất và nam châm ở cả hai bên vẫn được tính là một nam châm:

      #   #
      ##|##
      # v #
      ### #
      #   #
===============
       0

Các nghệ sĩ muốn bạn tính toán khoảng cách dọc tối đa trong tác phẩm điêu khắc cuối cùng, nghĩa là, số lượng khoảng trống tối đa giữa hai nam châm trên cùng một cột hoặc nam châm và mặt đất bên dưới nó. Trong hình trên, con số này sẽ là 3 (trên cột 2).

Đầu vào

Một danh sách các số nguyên, đại diện cho tọa độ nơi nghệ sĩ thả nam châm, đọc từ trái sang phải. Bạn có thể giả định rằng các tọa độ thỏa mãn -1024 <= i < 1024và độ dài của danh sách là nhiều nhất 1024, nếu điều đó có ích.

Đầu ra

Khoảng cách dọc tối đa trong tác phẩm điêu khắc cuối cùng. Các tác phẩm điêu khắc trống có khoảng cách -1, và trường hợp này phải được bao gồm, vì nhà điêu khắc của chúng tôi là một nghệ sĩ múa.

Quy tắc bổ sung

Bạn có thể cung cấp một chức năng hoặc một chương trình đầy đủ. Số byte ngắn nhất sẽ thắng và các sơ hở tiêu chuẩn không được phép. Mã với giải thích được ưa thích.

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

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

Câu trả lời:


1

APL Dyalog, 73 70 ký tự

{y←⍬⋄⌈/¯1,,¯1-2-/0,x⊢⌸{y,←⌈/(1+y/⍨0=⍵),Y⊃⍨2⊃⍒Y←1 1,∪y/⍨1=⍵}¨|x-¯1↓¨,\x←⍵}

{y←⍬⋄¯1⌈⌈/,¯1-2-/¯1,⍵⊢⌸{y,←⌈/(1+y/⍨0=⍵),⊃1↓{⍵[⍒⍵]}∪y/⍨1=⍵}¨|⍵-¯1↓¨,\⍵}

First statement:
       y←⍬  initialize semi-global variable y with an empty vector
Second statement, from right to left:
         ⍵  the vector of x coordinates
       ,\⍵  concat-scan: all prefixes of ⍵ of length 1, 2, ..., ≢⍵
   ¯1↓¨,\⍵  drop the last element of each prefix, lengths are 0, 1, ..., (≢⍵)-1
|⍵-¯1↓¨,\⍵  for each x: magnitudes of differences between x and its predecessors
 {...}¨...  execute the code in parens for each item of the argument
         ⍵  is now a single vector of differences from those described above
       1=⍵  boolean mask, where are our neighbouring xs?
    y/⍨1=⍵  select the ys corresponding to our neighbouring xs
   ∪y/⍨1=⍵  unique ys
   {⍵[⍒⍵]}  sort descending
       ⊃1↓  first of one-drop, i.e. get the second element if it exists, otherwise 0
       0=⍵  which previous xs are the same as our x?
  1+y/⍨0=⍵  select the corresponding ys and add 1 to them
        ⌈/  maximum of all the ys described so far
       y,←  append to the semi-global y
            the result from {} will be identical to y
  ⍵⊢⌸{...}  a matrix of ys, grouped in rows by x (which is now in ⍵) and zero-padded
       ¯1,  prepend ¯1 to the left of each row
       2-/  differences between consecutive horizontal elements, result is a matrix
       ¯1-  negative one minus each element of the matrix
         ,  ravel the matrix (linearize it to a vector)
        ⌈/  maximum; if the vector is empty, return ¯1.8e308, a very small number
     ¯1⌈⌈/  greater of ¯1 and the ⌈/  to avoid the very small number

Lưu ý: Cái này dài 122 byte (thử thách tính bằng byte), giả sử UTF-8.
MtnViewMark


Tôi khá thông cảm: Tôi thường xuyên bị sử dụng các ký tự không phải ASCII trong Haskell trong golf của mình. Kể từ đó, tôi đã khá chú ý nếu Q chỉ định đếm theo ký tự hoặc byte.
MtnViewMark

@MtnViewMark Ghi điểm theo byte không có nghĩa là chấm điểm theo byte UTF-8. Làm như vậy đối với APL là trừng phạt vì quá già để nhận ra ASCII là một tiêu chuẩn quan trọng. Bộ ký tự của APL phù hợp dễ dàng trong một codepage một byte và codepage đó tồn tại . Vì vậy, sử dụng codepage đó làm mã hóa mỗi ký tự một byte. Mặt khác, nếu bạn sử dụng các ký tự không phải ASCII trong Haskell, bạn sẽ phải sử dụng một mã hóa chứa cả ASCII và các ký tự không phải ASCII - và đó thường là UTF-8.
Martin Ender

@ngn - bây giờ đã đọc hầu hết các bài đăng meta về điều này, dường như mọi thứ, than ôi, vẫn còn lầy lội. Tuy nhiên, có lẽ sẽ là tốt nhất, khi thử thách được tính bằng byte, để ghi điểm APL theo byte, nhưng đề cập đến một nơi nào đó mã hóa được sử dụng.
MtnViewMark

4

Haskell - 217 185 182 byte

import Data.List
r g n m|m==n=max(head(g m)+1)((reverse.(0:).nub.sort$g(m-1)++g(m+1))!!1):g m|1<3=g m
j x=(-1)-minimum(0:(map(foldl r(\_->[0])x)[-1024..1024]>>=(tail>>=zipWith(-))))

Sử dụng:

j [1,2,1,2,1,2,1,2,2,2,2,1,0]

Hàm này xây dựng một hàm khác trả về danh sách các vị trí nam châm cho vị trí x đã cho. Với nó, nó tính toán các khoảng trống cho tất cả các vị trí x -1024 .. 1024 và lấy mức tối đa (Chỉnh sửa: hiện tại tôi đang lấy mức tối thiểu, bởi vì các khoảng trống là âm: số càng thấp thì khoảng cách càng lớn).


Cách tiếp cận thông minh! Hy vọng bạn không bận tâm rằng tôi chơi golf một chút.
MtnViewMark

@MtnViewMark: Không hề. Tôi đã tìm thấy 3 byte hơn nữa để tiết kiệm: không flipnhững -, đi với số âm và lấy minimum.
nimi

Trong repo của tôi, bạn có thể tìm thấy mã này, 42997-Magnetic.hs cũng bao gồm một khai thác thử nghiệm cho các trường hợp thử nghiệm và một trình hiển thị hiển thị các tác phẩm điêu khắc.
MtnViewMark

3

Javascript, 201 193

F=P=>{m=[];for(p of P){s=2;c=m[p]=m[p]||[];for(i=1e4;~i&&s;i--){if((m[p-1]||[])[i]||(m[p+1]||[])[i])s--;if(c[i-1]) s=0}c[++i]=1}g=-1;m.map(c=>{ d=0;for(i in c){g=i-d>g?i-d:g;d=++i} });return g}

F ([1,1,2,2,2,2,2,1,1)) === 2

Hoặc phiên bản có thể đọc được

F=P=>{
  m=[];  // magnet positions
  for(p of P){ // every dropped magnet
    s=2; // initial speed
    c=m[p]=m[p]||[]; // column where magnet is dropping
    for(i=1e4;~i&&s;i--){ // continue until at floor or zero speed
      if((m[p-1]||[])[i]||(m[p+1]||[])[i])s--;  // magnet on either side, decrease speed
      if(c[i-1]) s=0; // magnet is directly below
    }
    c[++i]=1;
  }
  g=-1; // maximum gap
  m.map(c=>{ 
          d=0;for(i in c){g=i-d>g?i-d:g;d=++i;} 
       });
  return g;
};

2

Con trăn 2.7, 327

from itertools import * 
s=input()
if s:m=min(s);l=[[] for _ in range(max(s)-m+3)]
for t in s:
    i=t-m+1;r=l[i];c=[x or y for x,y in izip_longest(l[i-1],l[i+1])][::-1][1:];j=len(c)-c.index(1)-1-len(r) if any(c) else 0;l[i]=r+[0]*j+[1]
print -1 if not s else max([len(list(q)) if b==0 else 0 for k in l for b,q in groupby(k)])

Trước khi chơi golf trắng, nó trông như thế này:

from itertools import * 
s=input()
if s:
    m=min(s)
    l=[[] for _ in range(max(s)-m+3)]
for t in s:
    i=t-m+1;r=l[i]
    c=[x or y for x,y in izip_longest(l[i-1],l[i+1])][::-1][1:]
    j=len(c)-c.index(1)-1-len(r) if any(c) else 0
    l[i]=r+[0]*j+[1]
print -1 if not s else max([len(list(q)) if b==0 else 0 for k in l for b,q in groupby(k)])

Đây là một lời giải thích về các dòng phức tạp hơn, chủ yếu là vì lợi ích của riêng tôi.

l=[[] for _ in range(max(s)-m+3)] 

Điều này xây dựng một mảng các danh sách trống có độ dài tối đa (giọt) -min (giọt) +1 cộng với một trình giữ chỗ ở hai bên. Tôi luôn muốn viết [[]] * K để xây dựng một mảng các danh sách trống, nhưng điều đó làm cho các con trỏ K vào cùng một danh sách trống.

c=[x or y for x,y in izip_longest(l[i-1],l[i+1])][::-1][1:] 

Hàm izip_longest từ itertools giống như zip, nhưng điền vào danh sách ngắn hơn bằng Không để nén các danh sách lại với nhau. Việc cắt [:: - 1] đảo ngược danh sách 0 và 1 so với so sánh "hoặc". Danh sách được đảo ngược để sử dụng phương thức chỉ mục trong dòng tiếp theo, tìm thấy phiên bản đầu tiên của một phần tử. Vì phần tử cuối cùng của cột không trống phải là 1, đây là phần tử đầu tiên trong danh sách đảo ngược và bị bỏ qua qua lát [1:].

j=len(c)-c.index(1)-1-len(r) if any(c) else 0 
l[i]=r+[0]*j+[1]

Đầu tiên tính toán sự khác biệt giữa chiều dài của cột i và vị trí của cột thứ hai trong các cột liền kề. Nếu sự khác biệt là dương, hãy thêm nhiều số không vào cột i trước khi thêm 1. Bất kỳ số lần không cố ý nào [0] là danh sách trống.

max([len(list(q)) if b==0 else 0 for k in l for b,q in groupby(k)])

Hàm nhóm từ itertools chia một danh sách thành các phần tử liên tiếp. Dòng này tìm tối đa độ dài của tất cả các số 0 trong tất cả các cột. Cần phải truyền từng chuỗi q vào danh sách, bởi vì nhóm sẽ trả về một trình tạo (giống như tất cả các hàm itertools) mà tự nhiên không hỗ trợ phương thức len.


1

Java - 281 byte

Khá thẳng về phía trước.

Đầu tiên, nó xây dựng các tác phẩm điêu khắc trong một mảng

Sau đó, nó tìm thấy khoảng cách lớn nhất.

int a(int[]b){
        int[][]d=new int[9999][9999];
        int g,r,t,y=-1;
        for(int c:b){
            c+=5000;
            g=0;
            for(r=9998;r>=0;r--){
                if(r==0||d[c][r-1]==1){d[c][r]=1;break;}
                if((d[c-1][r]==1||d[c+1][r]==1)&&++g==2){d[c][r]=1;break;}
            }
        }
        for(int[] k:d){
            t=0;
            for(int i:k){
                if(i==0)t++;
                else{if(t>y)y=t;t=0;}
            }
        }
        return y;
    }

nhỏ -

int a(int[]b){int[][]d=new int[9999][9999];int g,r,t,y=-1;for(int c:b){c+=5000;g=0;for(r=9998;r>=0;r--){if(r==0||d[c][r-1]==1){d[c][r]=1;break;}if((d[c-1][r]==1||d[c+1][r]==1)&&++g==2){d[c][r]=1;break;}}}for(int[] k:d){t=0;for(int i:k){if(i==0)t++;else{if(t>y)y=t;t=0;}}}return y;}

Bạn có thể lưu một byte bằng cách thay thế đầu tiên ||bằng |. Ngoài ra, trở lại ythay vì in nó tiết kiệm 9 byte.
Ypnypn

@Ypnypn, Cảm ơn! BTW, Tuyên bố đầu tiên của bạn dường như đưa ra một ngoại lệ ArrayIndexOutOfBound (-1). (Tôi không có nhiều kinh nghiệm với các nhà khai thác bitwise)
Stretch Maniac

Đã khoảng 1,5 năm, nhưng bạn có thể đánh gôn thêm: ( 272 byte ) : int a(int[]b){int z=9999,d[][]=new int[z][z],g,r,t,y=-1;for(int c:b){c+=z/2;g=0;for(r=z;--r>-2;){if(r==0||d[c][r-1]==1){d[c][r]=1;break;}if((d[c-1][r]==1|d[c+1][r]==1)&&++g==2){d[c][r]=1;break;}}}for(int[]k:d){t=0;for(int i:k){if(i==0)t++;else{if(t>y)y=t;t=0;}}}return y;}. Tóm tắt các thay đổi: z=9999đã được thêm và sử dụng; intint[][]khởi tạo trường đã được hợp nhất thành một; thứ hai ||được thay thế bởi |; for(r=9998;r>=0;r--)đã được đổi thànhfor(r=z;--r>-2;)
Kevin Cruijssen
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.