スカイラインをブラシストロークで覆う


43

負でない整数のスカイラインの高さリストが与えられた場合、それをカバーするために必要な連続した1ユニットの高さの水平ブラシストロークの数を答えます。

[1,3,2,1,2,1,5,3,3,4,2]として視覚化:

      5    
      5  4 
 3    5334 
 32 2 53342
13212153342

9つのブラシストロークが必要です。

      1    
      2  3 
 4    5555 
 66 7 88888
99999999999

[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


興味を持った高担当者のユーザーの場合:に基づいて、このあたりとしてこれ
アダム

2
だから、すべてのブラシストロークは水平ですか?
TSH

1
@tsh良い点。追加されました。
アダム

コードゴルフではありませんでしたが、約1年前にインタビューコードテストでこの質問がありました。
luizfzs

回答:


35

JavaScript(Node.js)、38バイト

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

オンラインでお試しください!

左から右にスキャンし、必要な場合にのみ線を描画し、できるだけ長く描画する貪欲なアルゴリズム。

Arnauldに感謝、2 3バイト節約


@Arnauldすてきなキャッチ。完全に忘れました。
tsh

どうやってこれを実現しましたか?
アダム

@Adám魔法は何もない。最初に質問を読んだとき、すべての行が水平方向のみであることに気付くまで、検索方法に戸惑いました。そして、この式はちょうど....自然に私の心に来た
TSHを

4
魔法は、そのプロセスを説明するのにぴったりの言葉のようです。
アダム

1
これが現在広く使用されているアルゴリズムの起源ですが、ここで説明されています
アダム

28

05AB1E 8 7  5バイト

@Adnanのおかげで2バイト節約

0š¥þO

オンラインでお試しください!

どうやって?

これは、最初に@tshによって検出されたアルゴリズムを使用しています。この回答が気に入ったら、彼らの回答も必ず投票してください!

超高層ビルが以前のものよりも低いか高い場合は、ブラシストロークを延長するだけで「無料」でペイントできます。

たとえば、下の図の高層ビルBC塗装には費用はかかりません。

一方、高層ビルをペイントするには、その後再利用するかどうかに関係なく、2つの新しいブラシストロークが必要です。E

建物

最初の高層ビルでは、床にあるのと同じ数のブラシストロークが常に必要です。

これを数学に変える:

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

リストの先頭にを追加すると、次のように簡略化できます。0

S=i=1nmax(hihi1,0)

コメント済み

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

1 0š¥ʒd}Oバイト節約できたと思います。
Xcoder氏

@ Don'tbeax-tripledot私はあなたのコメントを見たとき、まさにその答えを編集していた;)
アーナルド

4
美しい説明。
アダム

1
に置き換えるʒd}と、þ2バイト節約できます。
アドナン

@アドナンああ、いいね。ありがとう!
アーナルド

7

Python 3、37バイト

lambda a:sum(a)-sum(map(min,a[1:],a))

オンラインでお試しください!

サリエンのおかげで、Python 3に切り替えて-5バイト


パイソン247の 43 42バイト

lambda a:sum(a)-sum(map(min,a[1:],a[:-1]))

オンラインでお試しください!

Alt:

lambda a:sum(a)-sum(map(min,zip(a[1:],a)))

オンラインでお試しください!


Python 3では、[:-1]を捨てて5バイト節約できます。
サリエン

@Sarienありがとう:D、私はマップを知らなかったのpython 2と3で異なる
TFeld



5

K(oK)12 7バイト

ngnのおかげで-5バイト!

Arnauldの05AB1Eソリューション(およびtshのJavaScriptソリューション)の k( OK ポート:

+/0|-':

オンラインでお試しください!

J、15バイト

Arnauldの05AB1Eソリューション(およびtshのJavaScriptソリューション)のAJポート:

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

オンラインでお試しください!

私の素朴な解決策:

J、27バイト

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

オンラインでお試しください!


2
oK:各事前(':)は、リストの前に暗黙のID要素(0for -)を使用するため0,、不要です。あなたは、省略することができます{ x}:それ構図にするために+/0|-':
NGN

@ngnありがとう!どうやらこれを忘れてしまったようです: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
ガレン・イワノフ

5

Haskell34 32バイト

Lynnによってトリミングされた2バイト

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

オンラインでお試しください!

それで、始めるためにzipWith(-)。これは2つのリストを取り、それらのペアごとの違いの新しいリストを作成します。私たちは、その後でそれを組み合わせるx(0:x)(0:)リストの先頭にゼロを追加する関数であり、それを組み合わせることzipWith(-)で、リストの連続する要素間の差異を取得し、先頭にゼロを付けます。次に、ですべての負の値をゼロにし(max 0<$>)ます。これにより、各要素が各タワーで開始する必要がある新しいストロークの数である新しいリストが作成されます。合計を取得するには、これらを合計しsumます。


2
g x=sum$max 0<$>zipWith(-)x(0:x)は32バイトです:)
Lynn

ようであるsum.zipWith((max 0.).(-))<*>(0:)
リン・

@Lynnの.方がより優先順位が高いため、2番目の括弧には追加の括弧が必要になり<*>ます。
ウィートウィザード

3

Japt、8バイト

@Shaggyから-2バイト

mîT Õ¸¸è

説明

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

オンラインでお試しください!


8バイト:mîT Õ¸¸è
シャギー

1
A.y()ちなみに、のパディングをうまく使用しています。
シャギー



3

Japt7 6バイト

änT fq

それを試してみてください

Oliverのおかげで1バイト節約されました。

ä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


素晴らしいもの、@ Oliver。それを考えていなかっただろう。
シャギー



2

Common Lisp、88 87バイト

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

縮小されていない

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

試して

1つのタワーをペイントすると、その高さに等しい数のブラシストロークがかかります。これらのブラシストロークは、次のすべてのブラシストロークに変換されます。ここでは、他のすべてのタワーから現在のタワーの高さを引いて示します(それ自体は重要ではありません)。次の塔が短い場合、それは負の数にプッシュされ、この負の数はその後に続く塔から減算されます(前の塔から次の塔に変換できなかったブラシストロークを示します)。実際には、前のものを含むすべてのタワーの高さから数値を減算しますが、前のものを再び見ないため、これは重要ではありません。


PPCGへようこそ。検証を容易にするために、オンラインテスト環境へのリンクを提供していただけますか?
ジョナサンフレッチ

そのとおり。rextester.com/TKBU14782回答はまもなく更新されます
チャーリム

よくやった。素晴らしく、最初の投稿のための+1。ゴルフをお楽しみください。
ジョナサンフレッチ

1

05AB1E13 10 バイト

Z>Lε@γPO}O

オンラインそれを試してみたり、すべてのテストケースを確認してください

説明:

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

C#(Visual C#Interactive Compiler)、フラグ付き/u:System.Math、47バイト

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

オンラインでお試しください!

古いバージョン、フラグ付き/u:System.Math、63バイト

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

このソリューションは最初のソリューションよりもエレガントだと思います。開始値として2値タプルを使用して配列を調べ、値を取得し、その前の値をタプルの2番目の部分に格納します。

オンラインでお試しください!


1

Pyth、8バイト

s>#0.++0

@tshのすばらしい回答のもう1つの移植。入力のデルタ(。+)のs正の値(>#0)の合計()に、先頭に0を付けた(+0Q、末尾のQを推測)を取ります。

ここでオンライン試すか、ここですべてのテストケースを一度に確認してください

文字列結合メソッド、10バイト

これは、他の回答を参照する前に書いた解決策でした。

lcj.t+d*LN

テストスイート。

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バイト

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

オンラインでお試しください!(なぜこれは何も印刷しないのですか?)

#( ; 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へようこそ!Clojureについては何も知りませんが、簡単な検索では、遅延ループを評価する必要があることがわかります。オンラインでお試しください!(ヒント:回答を自動フォーマットするためにリンクボタンを使用できます)。どうぞお楽しみに!
ジョーキング


0

MATL15 14 13バイト

ts:<~"@Y'x]vs

入力は、;セパレータとして使用する列ベクトルです。

オンラインでお試しください!または、すべてのテストケースを確認します

説明

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バイト

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

TIO

どうやって

  • -p+ }{+ $\トリック
  • //空の文字列に一致するため、次の行のポストマッチ$'には前の行が含まれます
  • $\+=$_>$'&&$_-$'currentがpreviousよりも大きい場合、現在の行とpreviousの差を累積します(書き込むこともできますが$\+=$_-$' if$_>$'、perlは$\+=$_-$'if$_>$'同じものを解析しません)


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.