Rzeźby magnetyczne

14

Jest to luźna kontynuacja mojego wcześniejszego wyzwania dotyczącego konstruowania grafów .

tło

Ekscentryczny artysta zatrudnił cię do oceny integralności strukturalnej swoich rzeźb. Tworzy swoje dzieła sztuki, biorąc wiązkę magnesów w kształcie sześcianu i upuszczając je jeden po drugim na ogromny stos. Aby lepiej przeanalizować jego metodę, używamy następującego dwuwymiarowego modelu. Zaczynamy od pustej podłogi i upuszczamy magnes #przy dowolnej współrzędnej całkowitej, powiedzmy 0:

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

Jeśli upuści się inny magnes 0, kończy się on na poprzednim:

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

Teraz upuśćmy jeszcze jeden magnes na 0, a następnie jeden na 1:

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

Jak widać powyżej, spadający magnes przyczepia się do drugiego magnesu, który mija (pierwszy tylko go spowalnia). Drugi magnes nie musi znajdować się bezpośrednio pod pierwszym, a magnes po obu stronach nadal liczy się jako jeden magnes:

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

Artyści chcą, abyś obliczył maksymalną pionową przerwę w ostatecznej rzeźbie, czyli maksymalną liczbę pustych przestrzeni między dwoma magnesami na tej samej kolumnie lub magnesem i ziemią pod nim. Na powyższym obrazku liczba ta wynosiłaby 3 (w kolumnie 2).

Wejście

Lista liczb całkowitych reprezentujących współrzędne, w których artysta upuszcza magnesy, odczytywana od lewej do prawej. Możesz założyć, że współrzędne są spełnione -1024 <= i < 1024i że długość listy wynosi co najwyżej 1024, jeśli to pomaga.

Wynik

Maksymalna pionowa przerwa w ostatecznej rzeźbie. Pusta rzeźba ma szczelinę -1i ten przypadek musi zostać uwzględniony, ponieważ nasz rzeźbiarz jest dadaistą.

Dodatkowe zasady

Możesz podać funkcję lub pełny program. Wygrywa najkrótsza liczba bajtów, a standardowe luki są niedozwolone. Preferowany jest kod z objaśnieniami.

Przypadki testowe

[] -> -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
Zgarb
źródło

Odpowiedzi:

1

Dyalog APL, 73 70 znaków

{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
ngn
źródło
Uwaga: Ma on długość 122 bajtów (wyzwanie jest w bajtach), przy założeniu UTF-8.
MtnViewMark
Jestem bardzo sympatyczny: często miałem obsesję na punkcie używania znaków spoza ASCII w moim golfowym Haskell. Od tego czasu uważałem, czy Q określa liczbę według znaków lub bajtów.
MtnViewMark
@MtnViewMark Punktacja według bajtów nie oznacza punktacji według bajtów UTF-8. Takie postępowanie w przypadku APL karze go za to, że jest za stary, aby uznać ASCII za ważny standard. Zestaw znaków APL łatwo mieści się w jednobajtowej stronie kodowej i ta strona kodowa istnieje . Tak więc używając tej strony kodowej do kodowania, każdy znak jest bajtem. Z drugiej strony, jeśli użyjesz znaków innych niż ASCII w Haskell, będziesz musiał użyć kodowania, które zawiera zarówno znaki ASCII, jak i znaki spoza ASCII - i to zwykle UTF-8.
Martin Ender
@ngn - przeczytawszy większość postów na ten temat, wydaje się, że, niestety, wciąż są mętne. Być może jednak najlepiej byłoby, gdyby wyzwanie było oceniane w bajtach, aby APL było oceniane w bajtach, ale należy podać gdzieś zastosowane kodowanie.
MtnViewMark
4

Haskell - 217 185 182 bajtów

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(-))))

Stosowanie:

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

Ta funkcja tworzy kolejną funkcję, która zwraca listę pozycji y magnesu dla danej pozycji x. Za jego pomocą oblicza luki dla wszystkich pozycji x -1024 .. 1024 i przyjmuje maksimum (Edytuj: teraz biorę minimum, ponieważ luki są ujemne: im niższa liczba, tym większa luka).

nimi
źródło
Sprytne podejście! Mam nadzieję, że nie przeszkadza ci to, że trochę to polubiłem.
MtnViewMark
@MtnViewMark: Wcale nie. Znalazłem 3 kolejnych bajtów zapisać: nie , iść z liczb ujemnych i podjąć . flip-minimum
nimi
W moim repozytorium można znaleźć ten kod, 42997-Magnetic.hs, który zawiera również uprząż testową dla przypadków testowych oraz wizualizator, który wyświetla rzeźby.
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,2,1]) === 2

Lub wersja do odczytu

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;
};
zabalajka
źródło
2

Python 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)])

Przed golfem w białej przestrzeni wygląda to tak:

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)])

Oto wyjaśnienie bardziej skomplikowanych linii, głównie dla mojej korzyści.

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

To konstruuje tablicę pustych list o długości max (drop) -min (drop) +1 plus symbol zastępczy po obu stronach. Zawsze chcę napisać [[]] * K, aby zbudować tablicę pustych list, ale dzięki temu wskaźniki K do tej samej pustej listy.

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

Funkcja izip_longest z itertools jest jak zip, ale wypełnia krótszą listę None, aby spakować listy razem. Krojenie [:: - 1] odwraca listę zer i jedynek z porównania „lub”. Lista jest odwrócona, aby użyć metody index w następnym wierszu, który znajduje pierwszą instancję elementu. Ponieważ ostatnim elementem niepustej kolumny musi być 1, jest to pierwszy element na odwróconej liście i jest ignorowany przez plasterek [1:].

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

Najpierw oblicz różnicę między długością kolumny i a pozycją drugiego 1 w sąsiednich kolumnach. Jeśli różnica jest dodatnia, dodaj tyle zer do kolumny i, zanim dodasz 1. Dowolna liczba dodatnia razy [0] jest pustą listą.

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

Grupa funkcji przez itertools dzieli listę na podsekwencje kolejnych elementów. Ta linia znajduje maks. Długości wszystkich podsekwencji zer we wszystkich kolumnach. Konieczne jest rzutowanie każdej podsekwencji q na listę, ponieważ groupby zwraca generator (podobnie jak wszystkie funkcje itertools), który naturalnie nie obsługuje metody len.

użytkownik2487951
źródło
1

Java - 281 bajtów

Całkiem prosto.

Najpierw konstruuje rzeźbę w szeregu

Następnie znajduje największą lukę.

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;
    }

mały -

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;}
Stretch Maniac
źródło
Można zapisać bajt zastępując pierwszy ||z |. Zwracając yzamiast drukowania oszczędza 9 bajtów.
Ypnypn,
@Ypnypn, Thanks! BTW, Twoja pierwsza instrukcja wydaje się zgłaszać wyjątek ArrayIndexOutOfBounds (-1). (Nie mam dużego doświadczenia z bitowymi operatorami)
Stretch Maniac
Minęło około 1,5 roku, ale można golf to trochę więcej ( 272 bajtów ) 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;}. Podsumowanie zmian: z=9999zostało dodane i wykorzystane; inti int[][]inicjalizacji pola zostały połączone w jeden; drugi ||otrzymuje brzmienie |; for(r=9998;r>=0;r--)został zmieniony nafor(r=z;--r>-2;)
Kevin Cruijssen