Skyline'ı fırça darbeleriyle kaplama


43

Negatif olmayan bir tamsayı silueti yükseklik listesi göz önüne alındığında, onu kaplamak için ne kadar kesintisiz 1 birim yüksekliğinde yatay fırça darbesi gerektiğini yanıtlayın.

[1,3,2,1,2,1,5,3,3,4,2], görselleştirildi:

      5    
      5  4 
 3    5334 
 32 2 53342
13212153342

dokuz fırça darbesi gerekiyor:

      1    
      2  3 
 4    5555 
 66 7 88888
99999999999

Örnekler

[1,3,2,1,2,1,5,3,3,4,2]9

[5,8]8

[1,1,1,1]1

[]0

[0,0]0

[2]2

[2,0,2]4

[10,9,8,9]11


İlgi çok tekrarlı kullanıcıları için: dayanarak bu uyarınca bu .
Adám

2
Yani tüm fırça darbeleri yatay mı?
tsh

1
@tsh İyi nokta. Eklendi.
Adám

Codegolf değildi, ama yaklaşık bir yıl önce bir görüşme kodu testi için bu sorum vardı.
luizfzs

Yanıtlar:


35

JavaScript (Node.js) , 38 bayt

a=>a.map(v=>(n+=v>p&&v-p,p=v),p=n=0)|n

Çevrimiçi deneyin!

Basitçe soldan sağa tarama yapan açgözlü bir algoritma, yalnızca gerektiğinde çizgiler çizer ve mümkün olduğunca uzun süre çizer.

Teşekkürler Arnauld, 2 3 bayt kurtar


@Arnauld güzel yakalamak. tamamen unuttum.
tsh

Bunu nasıl anladın?
Ad'm

@ Adám Hiçbir şey sihir. Soruyu ilk kez okuduğumda, tüm çizgilerin sadece yatay olduğunu fark edene kadar nasıl arayacağımı kafam karıştı. Ve sonra bu formül doğal olarak aklıma geldi ...
tsh

4
sihir , bu süreci tanımlamak için uygun bir kelime gibi görünüyor.
Ad'm

1
Bu, şu anda yaygın olarak kullanılan algoritmanın kaynağı olsa da, burada açıklanmaktadır .
14'te

28

05AB1E ,  8 7  5 bayt

@Adnan sayesinde 2 bayt kaydedildi

0š¥þO

Çevrimiçi deneyin!

Nasıl?

Bu ilk önce @ tsh tarafından bulunan algoritmayı kullanıyor . Bu cevabı beğenirseniz, cevaplarını da arttırdığınızdan emin olun !

Bir gökdelen bir öncekinden daha düşük veya daha yüksek olduğunda, sadece fırça darbelerini uzatarak 'ücretsiz' boyanabilir.

Örneğin, aşağıdaki şekilde gökdelenler ve boyamak hiçbir maliyeti yoktur.BC

Öte yandan, gökdelen boyamak için 2 yeni fırça darbesine ihtiyacımız var, ondan sonra tekrar kullanılıp kullanılmayacakları önemli değil.E

binalar

İlk gökdelen için, her zaman içinde katlar olduğu kadar çok darbeye ihtiyaç duyarız.

Bunu matematiğe dönüştürmek:

S=h0+i=1nmax(hihi1,0)

Listeye hazırlarsak , bu basitleştirilebilir:0

S=i=1nmax(hihi1,0)

Yorumlananlar

0š¥þO     # expects a list of non-negative integers  e.g. [10, 9, 8, 9]
0š        # prepend 0 to the list                    -->  [0, 10, 9, 8, 9]
  ¥       # compute deltas                           -->  [10, -1, -1, 1]
   þ      # keep only values made of decimal digits
          # (i.e. without a minus sign)              -->  ["10", "1"]
    O     # sum                                      -->  11

Bence 0š¥ʒd}Oseni bir bayt kurtarıyor.
Bay Xcoder,

@ Don'tbeax-tripledot Yorumunuzu gördüğümde cevabımı aynen şöyle demiştim;)
Arnauld

4
Güzel açıklama.
Ad'm

1
Değiştirme ʒd}ile þsana iki bayt kaydetmek gerekir.
Adnan

@Adnan Ah, güzel. Teşekkürler!
Arnauld,


7

Haskell , 32 bayt

(0%)
p%(h:t)=max(h-p)0+h%t
p%_=0

Çevrimiçi deneyin!

Bir sonraki öğeye bakmak yerine önceki öğeyi izleyen Lynn'in çözümünde bir gelişme p. Bu, temel durumu ve özyinelemeli çağrıyı, çağrıya ihtiyaç duyma karşılığında kısaltır (0%).

max(h-p)0max h p-paynı uzunluk için olabilir .



5

K (oK) , 12 7 bayt

Ngn sayesinde -5 bayt!

Arnauld'un 05AB1E çözümünün bir k (OK) limanı (ve tsh'ın JavaScript çözümü):

+/0|-':

Çevrimiçi deneyin!

J , 15 bayt

Arnauld'un 05AB1E çözümünün AJ portu (ve tsh'ın JavaScript çözümü):

1#.0>./2-~/\0,]

Çevrimiçi deneyin!

Saf çözümüm:

J , 27 bayt

1#.2(1 0-:])\0,@|:@,~1$~"0]

Çevrimiçi deneyin!


2
OK: her prior ( ':) , listeden önce ( 0for -) örtük bir kimlik elemanı kullanır , bu yüzden 0,gereksizdir. { x}bir kompozisyon yapmak için ihmal edebilirsiniz :+/0|-':
ngn

@ ngn Teşekkürler! Görünüşe göre bunu unuttum:Some primitive verbs result in a different special-cased initial value: +, *, - and & are provided with 0, 1, 0 or the first element of the sequence, respectively
Galen Ivanov

5

Haskell , 34 32 bayt

Lynn tarafından kesilmiş 2 bayt

g x=sum$max 0<$>zipWith(-)x(0:x)

Çevrimiçi deneyin!

Yani başlamak için biz varız zipWith(-). Bu iki liste alır ve ikili farklılıklarının yeni bir listesini oluşturur. Daha sonra xve ile birleştiririz (0:x). (0:)bir listenin önüne sıfır ekleyen bir fonksiyondur ve onu bir araya zipWith(-)getirerek, o listenin ardışık elemanları arasındaki farkı sıfır ile önlüyoruz. Sonra tüm negatif olanları sıfıra çeviririz (max 0<$>). Bu, her bir öğenin her bir kulede başlatılması gereken yeni vuruş sayısının olduğu yeni bir liste oluşturur. Toplamı elde etmek için bunları sadece özetliyoruz sum.


2
g x=sum$max 0<$>zipWith(-)x(0:x)32 bayt :)
Lynn

Olduğu gibisum.zipWith((max 0.).(-))<*>(0:)
Lynn

@Lynn İkinciniz, .öncekinden daha yüksek olduğu için ekstra parantez gerekir <*>.
Buğday Sihirbazı

3

Japt , 8 bayt

@Shaggy'den -2 bayt

mîT Õ¸¸è

açıklama

mîT Õ¸¸è      Full program. Implicit input U
                e.g. U = [2,0,2]
mîT             Map each item X and repeat T(0) X times
                     U = ["00","","00"]
    Õ           Transpose rows with columns
                     U = ["0 0","0 0"]
     ¸¸         Join using space and then split in space
                     U = ["0","0","0","0"]
        è       Return the count of the truthy values

Çevrimiçi deneyin!


8 bayt:mîT Õ¸¸è
Shaggy,

1
Bu arada sopayı çok iyi kullanmışsın A.y().
Shaggy,

3

MATL , 8 bayt

0whd3Y%s

Çevrimiçi deneyin!

Hemen hemen @ Arnauld'un algoritması. Olumlu girişleri uint64seçmek yerine, bir bayt (teşekkürler @LuisMendo) yazarak kaydedildi ).


3

Jöle , 5 bayt

05AB1E cevabımın , @tsh JS yanıtına benzeyen bir bağlantı noktası .

ŻI0»S

Çevrimiçi deneyin!

Yorumlananlar

ŻI0»S    - main link, expecting a list of non-negative integers  e.g. [10, 9, 8, 9]
Ż        - prepend 0                                             -->  [0, 10, 9, 8, 9]
 I       - compute the deltas                                    -->  [10, -1, -1, 1]
  0»     - compute max(0, v) for each term v                     -->  [10, 0, 0, 1]
    S    - sum                                                   -->  11

3

Japt , 7 6 bayt

änT fq

Dene

Oliver sayesinde 1 bayt kaydedildi.

änT xwT    :Implicit input of integer array
än         :Consecutive differences / Deltas
  T        :  After first prepending 0
    f      :Filter elements by
     q     :  Square root (The square root of a negative being NaN)
           :Implicitly reduce by addition and output


Güzel olan, @Oliver; bunu düşünemezdim.
Shaggy,


2

Retina 0.8.2 , 21 bayt

\d+
$*
(1+)(?=,\1)

1

Çevrimiçi deneyin! Link, test durumlarını içerir. Açıklama:

\d+
$*

Birliğe dönüştür.

(1+)(?=,\1)

Tüm üst üste binmeleri, yeni bir darbeye gerek duymayan sonraki kuleyle silin.

1

Kalan vuruşları say.


2

Ortak Lisp, 88 87 bayt

(lambda(s)(let((o 0))(dolist(c s)(incf o(max 0 c))(mapl(lambda(y)(decf(car y)c))s))o))

olmayan küçültülmüş

(lambda (skyline)
  (let ((output 0))
    (dolist (current-skyscraper-height skyline)
      (incf output (max 0 current-skyscraper-height))
      (mapl (lambda (skyscraper)
              (decf (car skyscraper) current-skyscraper-height))
            skyline))
    output)))

Dene

Bir kule boyandığında, yüksekliğine eşit sayıda fırça darbesi alır. Bu fırça darbeleri, şu anki kulenin yüksekliğini tüm diğer kulelerden (ve kendisinden çekerek ancak bunun önemi yoktur) burada belirtilen tüm bunlara çevrilir. Eğer bir sonraki kule daha kısa ise, o zaman negatif bir sayıya itilir ve bu negatif sayı daha sonra izleyen kulelerden çıkarılır (önceki bir kuleden diğerine çevrilemeyen fırça darbelerini gösterir). Aslında sadece öncekiler de dahil olmak üzere tüm kule yüksekliklerinden sayıyı çıkarır , ancak bu önemli değil çünkü öncekilere bir daha bakmayız.


PPCG'ye Hoşgeldiniz. Doğrulama kolaylığı için çevrimiçi bir test ortamına bir bağlantı verebilir misiniz?
Jonathan Frech

Evet kesinlikle. rextester.com/TKBU14782 Cevap kısa bir süre içinde güncellenecek
Charlim

Aferin. Güzel, ilk çalışan yazı için +1. Golf eğlenin.
Jonathan Frech

1

05AB1E , 13 10 bayt

Z>Lε@γPO}O

Çevrimiçi deneyin veya tüm test durumlarını doğrulayın .

Açıklama:

Z            # Get the maximum of the (implicit) input-list
 >           # Increase it by 1 (if the list only contains 0s)
  L          # Create a list in the range [1, max]
   ε         # Map each value to:
    @        #  Check if this value is >= for each value in the (implicit) input
     γ       #  Split into chunks of adjacent equal digits
      P      #  Take the product of each inner list
       O     #  Take the sum
        }O   # And after the map: take the sum (which is output implicitly)

1

Bayrak /u:System.Math, 47 bayt ile C # (Visual C # Etkileşimli Derleyici)

n=>n.Select((a,i)=>i<1?a:Max(a-n[i-1],0)).Sum()

Çevrimiçi deneyin!

Eski versiyon, bayraklı /u:System.Math, 63 byte

n=>n.Aggregate((0,0),(a,b)=>(a.Item1+Max(0,b-a.Item2),b)).Item1

Bu çözümün ilk çözümden daha zarif olduğunu hissediyorum. Başlangıç ​​değeri olarak iki değerli bir dizgiye sahip diziden geçer, değerleri toplar ve değerin önündeki değeri dizinin ikinci bölümünde saklar.

Çevrimiçi deneyin!


1

Pyth, 8 bayt

s>#0.++0

@ Tsh'ın muhteşem cevabının başka bir limanı . Girdilerin deltasındaki (. +) sPozitif değerlerinin ( >#0) toplamını 0 önceden hazırlanmış ( +0Q, sonuçta Q çıkarımlı olarak) alır.

Online Deneyin burada ya bir kerede tüm test durumları doğrulamak burada .

Dize birleştirme yöntemi, 10 bayt

Diğer cevaplara göz atmadan önce yazdığım çözüm buydu.

lcj.t+d*LN

Test odası.

lcj.t+d*LNQ   Implicit: Q=eval(input()), b=<newline>, N=<quote mark>
              Trailing Q inferred
        L Q   Map each element of Q...
       * N    ... to N repeated that many times
     +b       Prepend a newline
   .t         Transpose, padding with spaces
  j           Join on newlines
 c            Split on whitespace
l             Take the length, implicit print

1

Clojure, 50 bayt

#((reduce(fn[[s n]i][(+(max(- i n)0)s)i])[0 0]%)0)

Çevrimiçi deneyin! (Bu neden hiçbir şey yazdırmıyor?)

#( ; begin anonymous function
    (reduce
        (fn [[s n] i] ; internal anonymous reducing function, destructures accumulator argument into a sum and the previous item
            [(+ (max (- i n) 0) s ; the sum part of the accumulator becomes the previous sum plus the larger of zero and the difference between the current number and the last one, which is how many new strokes need to be started at this point
            i]) ; ...and the previous item part becomes the current item
        [0 0] ; the initial value of the accumulator gives no strokes yet, and nothing for them to cover yet
        %) ; reduce over the argument to the function
    0) ; and get the sum element of the last value of the accumulator.

PPCG'ye Hoşgeldiniz! Clojure hakkında hiçbir şey bilmiyorum, ancak hızlı bir arama döngü için tembel değerlendirmek gerekeceğini göstermektedir. Çevrimiçi Deneyin! (İpucu: Yanıtınızı otomatik olarak biçimlendirmek için bağlantı düğmesini kullanabilirsiniz). Umarım takıl ve eğlenirsin!
Jo King,


0

MATL , 15 14 13 bayt

ts:<~"@Y'x]vs

Giriş, ;ayırıcı olarak kullanan bir sütun vektörüdür .

Çevrimiçi deneyin! Veya tüm test durumlarını doğrulayın .

açıklama

t       % Implicit input: column vector. Duplicate
s       % Sum
:       % Range from 1 to that. Gives a row vector
<~      % Greater or equal? Element-wise with broadcast
"       % For each column
  @     %   Push current columnn
  Y'    %   Run-length encoding. Gives vector of values (0, 1) and vector of lengths
  x     %   Delete vector of lengths
]       % End
v       % Vertically concatenate. May give an empty array
s       % Sum. Implicit display

0

Perl 5, 21 bayt

$\+=$_>$'&&$_-$';//}{

TIO

Nasıl

  • -p+ }{+ $\numara
  • //boş dize ile eşleşir, böylece sonraki satır için postmatch $'önceki satırı içerir
  • $\+=$_>$'&&$_-$'Eğer mevcut öncekinden daha büyükse, şimdiki satır ile önceki arasında fark biriktirmek, (ayrıca yazılabilir $\+=$_-$' if$_>$', ancak perl $\+=$_-$'if$_>$'aynı şekilde ayrılmaz )


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.