用笔触覆盖天际线


43

给定一个非负整数天际线高度列表,请回答需要多少不间断的1个单位高的水平画笔笔划来覆盖它。

[1,3,2,1,2,1,5,3,3,4,2],可视为:

      5    
      5  4 
 3    5334 
 32 2 53342
13212153342

需要九个笔触:

      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好点。添加。
亚当

它不是codegolf,但大约一年前,我有这个问题要进行面试代码测试。
luizfzs

Answers:


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

我想0š¥ʒd}O可以为您节省一个字节。
Xcoder先生

@ Don'tbeax-tripledot我正在编辑我的答案,确切地看到了您的评论;)
Arnauld

4
美丽的解释。
亚当

1
替换ʒd}þ将节省两个字节。
阿德南

@Adnan啊,很好。谢谢!
Arnauld

7

Python 3,37个字节

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

在线尝试!

感谢Sarien,通过切换到Python 3可实现-5字节


Python 2中47个 43 42字节

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

在线尝试!

替代:

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字节

-5个字节,感谢ngn!

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
确定:每个在先(':)在列表之前都使用隐式标识元素(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
Galen Ivanov

5

Haskell34 32字节

Lynn修剪了2个字节

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

在线尝试!

所以我们开始吧zipWith(-)。这将获得两个列表,并生成一个两两差异的新列表。然后,我们将其与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您的第二个将需要额外的括号,因为其.优先级高于<*>
麦向导

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

MATL,8字节

0whd3Y%s

在线尝试!

@Arnauld的算法差不多。通过强制转换为uint64而不是选择)肯定的条目来节省一个字节(感谢@LuisMendo)。


3

果冻,5个字节

我的05AB1E答案的端口,其本身类似于@tsh JS答案

ŻI0»S

在线尝试!

已评论

Ż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

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

视网膜0.8.2,21字节

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

1

在线尝试!链接包括测试用例。说明:

\d+
$*

转换为一元。

(1+)(?=,\1)

删除下一个塔的所有重叠部分,这些重叠不需要新的笔触。

1

计算剩余的笔画。


2

通用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)))

测试一下

当绘制一个塔时,需要花费与其高度相等的笔触数。这些笔触转换为以下所有笔触,在此通过从所有其他塔楼(及其本身减去当前塔楼的高度)中减去来表示。如果随后的塔楼较短,则将其推为负数,然后此负数将从随后的塔楼中减去(表示无法从前一塔楼转换为下一塔楼的笔触)。实际上,它只是从所有塔高(包括先前的高度)中减去该数目,但这无关紧要,因为我们不再关注先前的高度。


欢迎来到PPCG。您能否提供到在线测试环境的链接以简化验证?
Jonathan Frech

是的,一点没错。rextester.com/TKBU14782答案将很快更新
Charlim

做得好。+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#交互式编译器)/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

我觉得这个解决方案比第一个解决方案更优雅。它以两个值的元组作为起始值遍历数组,拾取值,然后将其之前的值存储在元组的第二部分。

在线尝试!


1

Pyth,8个字节

s>#0.++0

@tsh出色的回答的另一个方面。取输入的增量(。+)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一无所知,但是快速搜索显示您需要评估lazy for循环。在线尝试!(提示:您可以使用链接按钮自动设置答案的格式)。希望您能在这里玩得开心!
乔·金


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个字节

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

蒂奥

怎么样

  • -p+ }{+ $\技巧
  • //匹配空字符串,以便下一行后匹配$'将包含上一行
  • $\+=$_>$'&&$_-$'如果当前的电流大于先前的行,则累积当前行与先前的行之间的差异(也可以写入$\+=$_-$' if$_>$',但perl不会解析$\+=$_-$'if$_>$'相同的行)


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.