Manyetik Heykeller


14

Bu, grafik oluşturma konusundaki önceki zorluklarımın gevşek bir devamıdır .

Arka fon

Eksantrik bir sanatçı, heykellerinin yapısal bütünlüğünü tahmin etmenizi sağladı. Bir grup küp şeklindeki mıknatıs alıp tek tek büyük bir kazığa bırakarak sanat eserlerini yaratır. Yöntemini daha iyi analiz etmek için aşağıdaki iki boyutlu modeli kullanıyoruz. Boş bir zeminle başlıyoruz ve #herhangi bir tamsayı koordinatına bir mıknatıs bırakıyoruz 0:

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

Başka bir mıknatıs atılırsa, bir öncekinin 0üstüne gelir:

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

Şimdi bir mıknatıs daha 0sonra da bir mıknatıs bırakalım 1:

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

Yukarıda görüldüğü gibi, düşen bir mıknatıs geçtiği ikinci mıknatısa yapışır (birincisi sadece yavaşlar). İkinci mıknatısın doğrudan ilk mıknatısın altında olması gerekmez ve her iki taraftaki bir mıknatıs hala bir mıknatıs olarak sayılır:

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

Sanatçılar, son heykeldeki maksimum dikey boşluğu, yani aynı sütundaki iki mıknatıs veya bir mıknatıs ve altındaki zemin arasındaki maksimum boş alanı hesaplamanızı istiyor. Yukarıdaki resimde, bu sayı 3 (sütun üzerinde 2) olacaktır.

Giriş

Soldan sağa okuyarak sanatçının mıknatıslarını düşürdüğü koordinatları temsil eden bir tamsayı listesi. Eğer yardımcı olursa, koordinatların tatmin edici -1024 <= i < 1024olduğunu ve listenin uzunluğunun en fazla olduğunu varsayabilirsiniz 1024.

Çıktı

Son heykelde maksimum dikey boşluk. Boş heykelin boşluğu vardır -1ve heykeltraşımız bir dadaist olduğu için bu dava dahil edilmelidir.

Ek kurallar

Bir işlev veya tam bir program verebilirsiniz. En kısa bayt sayısı kazanır ve standart boşluklara izin verilmez. Açıklamaları olan kod tercih edilir.

Test senaryoları

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

Yanıtlar:


1

Dyalog APL, 73 70 karakter

{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

Not: UTF-8 varsayarsak, bu 122 bayt uzunluğundadır (zorluk bayt cinsindendir).
MtnViewMark


Oldukça sempatikim: Golf Haskell'imde ASCII olmayan karakterler kullandığım için sık sık ölüyordum. O zamandan beri Q'nun karakter veya bayt cinsinden sayımını belirtirse oldukça dikkatli davranıyorum.
MtnViewMark

@MtnViewMark Baytlara göre puanlama, UTF-8 baytlarına göre puanlama anlamına gelmez. APL için bunu yapmak, ASCII'yi önemli bir standart olarak tanıyamayacak kadar yaşlı olduğu için cezalandırıyor. APL'nin karakter seti tek baytlık bir kod sayfasına kolayca sığar ve bu kod sayfası vardır . Yani bu kod sayfasını her karakteri kodlamak için kullanmak bir bayttır. Öte yandan, Haskell'de ASCII olmayan karakterler kullanıyorsanız, hem ASCII hem de ASCII olmayan karakterleri içeren bir kodlama kullanmanız gerekir ve bu genellikle UTF-8'dir.
Martin Ender

@ngn - şimdi bu konudaki meta yayınların çoğunu okuduktan sonra, şeylerin hala çamurlu olduğu görülüyor. Bununla birlikte, meydan okuma bayt olarak puanlandığında, bayt cinsinden APL'yi puanlamak, ancak kullanılan kodlamanın bir yere değinmek belki de en iyisi olacaktır.
MtnViewMark

4

Haskell - 217 185 182 Bayt

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

Kullanımı:

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

Bu işlev, belirli bir x konumu için mıknatıs y konumlarının listesini döndüren başka bir işlev oluşturur. Bununla birlikte, tüm x -1024 .. 1024 konumları için boşlukları hesaplar ve maksimumu alır (Düzenleme: şimdi minimum değeri alıyorum, çünkü boşluklar negatif: sayı ne kadar düşükse boşluk da o kadar büyük olur).


Akıllı yaklaşım! Umarım biraz golf oynadığım umrumda değil.
MtnViewMark

@MtnViewMark: Hiç de değil. Ben kurtarmak için 3 daha fazla bayt buldum: yok , negatif sayılarla gidip almak . flip-minimum
nimi

Repo'mda , test senaryoları için bir test koşum takımı ve heykelleri görüntüleyen bir görselleştirici içeren 42997-Magnetic.hs kodunu bulabilirsiniz .
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

Veya okunabilir versiyon

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

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

Beyaz alan golfünden önce şöyle görünür:

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

İşte, çoğunlukla kendi yararım için, daha karmaşık hatların bir açıklaması.

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

Bu, max (damla) -min (damla) +1 artı her iki tarafta bir yer tutucu uzunluğunda boş listeler dizisi oluşturur. Her zaman boş listeler dizisi oluşturmak için [[]] * K yazmak istiyorum, ancak bu K işaretçileri aynı boş listeye yapar.

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

İtertools'tan izip_longest işlevi zip gibidir, ancak listeleri bir araya getirmek için daha kısa listeyi Yok ile doldurur. Dilimleme [:: - 1], "veya" karşılaştırmasından 0'ların ve 1'lerin listesini tersine çevirir. Bir sonraki satırda, bir elemanın ilk örneğini bulan dizin yöntemini kullanmak için liste tersine çevrilir. Boş olmayan bir sütunun son öğesi 1 olması gerektiğinden, bu, ters listedeki ilk öğedir ve dilim [1:] aracılığıyla yok sayılır.

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

İlk olarak, i sütununun uzunluğu ile bitişik sütunlardaki ikinci 1'in konumu arasındaki farkı hesaplayın. Fark pozitifse, 1'i eklemeden önce i sütununa bu sıfırları ekleyin. Pozitif olmayan sayıların herhangi biri [0] boş listedir.

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

İtertools içindeki groupby işlevi bir listeyi ardışık elemanların alt dizilerine böler. Bu satır, tüm sütunlardaki sıfırların tüm alt dizilerinin maksimum uzunluklarını bulur. Her bir q alt listesini bir listeye dökmek gerekir, çünkü groupby doğal olarak bir len yöntemini desteklemeyen bir üreteci (tüm itertools işlevleri gibi) döndürür.


1

Java - 281 bayt

Oldukça düz ileri.

İlk önce heykeli bir dizi halinde inşa eder

Sonra en büyük boşluğu bulur.

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

küçük -

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

Önce değiştirerek byte kaydedebilirsiniz ||ile |. Ayrıca, yyazdırmak yerine geri dönmek 9 bayt tasarruf sağlar.
Ypnypn

@Ypnypn, Teşekkürler! BTW, İlk deyiminiz bir ArrayIndexOutOfBounds istisnası (-1) atıyor gibi görünüyor. (Bitsel operatörlerle çok fazla deneyimim yok)
Stretch Maniac

1,5 yıl kadar oldu, ama golf can o biraz daha: ( 272 bayt ): 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;}. Değişikliklerin özeti: z=9999eklendi ve kullanıldı; intve int[][]alanın başlatılması bir araya getirildi; ikincisi ||ile değiştirilir |; for(r=9998;r>=0;r--)olarak değiştirildifor(r=z;--r>-2;)
Kevin Cruijssen
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.