地平线问题(The Skyline Problem‍​​)

2019-06-24 14:02发布

我只是碰到这个小问题来了UVA的在线法官 ,并认为,它可能是一小码高尔夫球一个很好的候选人。

问题:

你要设计一个方案,以协助建筑师在绘制给在城市建筑物的位置一个城市的天际线。 为了使问题易于处理,所有的建筑是长方形的,他们都有一个共同的底部(它们是建在城市是很平)。 这个城市也被看作是二维的。 建筑物是由一个有序三元组(李,嗨,日),其中LiRi分别向左和右坐标,建设我和Hi是建筑物的高度规定。

在建筑物下面的图中示出在左侧与三元

(1,11,5), (2,6,7), (3,13,9), (12,7,16), (14,3,25), (19,18,22), (23,13,29), (24,4,28) 

和天际线,在右侧示出,是由序列表示:

1, 11, 3, 13, 9, 0, 12, 7, 16, 3, 19, 18, 22, 3, 23, 13, 29, 0 

输出应包括描述如图上面的例子中天际线的矢量的。 在天际线矢量(V1,V2,V3,... VN),vi使得i是偶数表示的水平线(高度)。 在vi使得i是奇数表示的垂直线(x坐标)。 天际线载体应在最低表示“路径”采取,例如,由一个错误的起始X坐标和在所有定义的天际线的线水平和垂直行进。 因此,在天际线向量的最后一个条目将是一个0坐标必须用一个空格分开。

如果我将不计入规定(试验)建筑物的声明,并包括所有的空格和制表符,我的解决方案,在Python,长223个字符。

这里是浓缩版:

B=[[1,11,5],[2,6,7],[3,13,9],[12,7,16],[14,3,25],[19,18,22],[23,13,29],[24,4,28]]

# Solution.

R=range
v=[0 for e in R(max([y[2] for y in B])+1)]
for b in B:
   for x in R(b[0], b[2]):
      if b[1]>v[x]:
         v[x]=b[1]
p=1
k=0
for x in R(len(v)):
   V=v[x]
   if p and V==0:
      continue
   elif V!=k:
      p=0
      print "%s %s" % (str(x), str(V)),
   k=V

我想,我也没有作出任何的错误,但如果是这样 - 随意批评我。

我没有太多的声誉,所以我只需要支付100赏金 - 我很好奇,如果任何人都可以尝试在不到解决这个..可以说,80个字符。 解决方案发表cobbal是101个字符长 ,目前这是最好的一个。

我想,这80个字符是这类问题一个生病的限制。 cobbal,与他的性格46解决方案完全以让我吃惊-尽管我必须承认,我花了一些时间去阅读他的解释我才明白部分他所编写的。

Answer 1:

我刚开始学习Ĵ ,所以在这里不用我第一次尝试在高尔夫球:

103 62 49
46个字符

   b =: 8 3 $ 1 11 5 2 6 7 3 13 9 12 7 16 14 3 25 19 18 22 23 13 29 24 4 28
   ,(,.{&s)I.s~:_1|.s=:0,~>./(1&{*{.<:[:i.{:)"1 b
1 11 3 13 9 0 12 7 16 3 19 18 22 3 23 13 29 0

虽然我敢肯定有人究竟是谁知道语言以及可以通过颇有几分缩短这个

代码的解释:

   NB. list numbers up to right bound of the building
   ([: i. {:) 14 3 25  
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   NB. compare to left bound of building and then multiply by height
   (1&{ * {. <: [: i. {:) 14 3 25 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 3 3 3 3 3 3 3 3 3
   NB. apply to each row of b, note how shorter entries are padded with 0s
   (1&{ * {. <: [: i. {:)"1 b
0 11 11 11 11  0  0  0  0 0 0 0 0 0 0 0 0 0 0  0  0  0 0  0  0  0  0  0  0
0  0  6  6  6  6  6  0  0 0 0 0 0 0 0 0 0 0 0  0  0  0 0  0  0  0  0  0  0
...
   NB. collapse to find max, add a 0 to the end for rotate later, assign to s
   ] s =: 0 ,~ >./ (1&{ * {. <: [: i. {:)"1 b
0 11 11 13 13 13 13 13 13 0 0 0 7 7 7 7 3 3 3 18 18 18 3 13 13 13 13 13 13 0
   NB. rotate s right 1 and then compare to s to find where height changes
   s ~: _1 |. s
0 1 0 1 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 1 1 0 0 0 0 0 1
   NB. find indices of all differences
   I. s ~: _1 |. s
1 3 9 12 16 19 22 23 29
   NB. pair each index with the height of the building there
   (,. {&s) I. s ~: _1 |. s
 1 11
 3 13
 9  0
...
   NB. and finally flatten the list
   , (,. {&s) I. s ~: _1 |. s
1 11 3 13 9 0 12 7 16 3 19 18 22 3 23 13 29 0


Answer 2:

Python中,89个字符,也使用三联的5001备忘:

B=[[1,11,5],[2,6,7],[3,13,9],[12,7,16],[14,3,25],[19,18,22],[23,13,29],[24,4,28]]

x=o=0
while x<5001:
 n=max([H for L,H,R in B if L<=x<R]+[0])
 if n-o:print x,n,
 o=n;x+=1

更换5001通过max(map(max,B))+1 ,以允许(几乎)任意大城市叶102个字符。

修订记录:

  • 挽救了两个字符,如约翰·皮里的评论描述
  • 保存一个字符为MahlerFive建议


Answer 3:

Python的:115个字符

像OP,我不包括数据的声明,但我指望空白。

D = [(1,11,5), (2,6,7), (3,13,9), (12,7,16), 
 (14,3,25), (19,18,22), (23,13,29), (24,4,28)]

P=[max([0]+[h for s,h,e in D if s<=x<e])for x in range(5001)]
for i,x in enumerate(P[1:]):
   if x!=P[i]:print i+1,x,

请注意,我使用由OP作为问题的确切定义的链接。 举例来说,我骗了一下假设有没有建筑物坐标超过5000,所有的坐标是正整数。 原帖没有严格的限制不够这很有趣,在我看来。

编辑 :感谢约翰·皮里约崩清单建设成循环印刷尖端。 你怎么我错过?

编辑 :我改变range(1+max(zip(*D)[2]))range(5001)决定使用在原来的问题所给定的确切定义之后。 第一个版本将处理任意正整数的建筑物(假设全部放入到内存)。

编辑 :意识到我是过于复杂的事情。 检查我的修订。

顺便说一句 - 我有一种预感,有一个更优雅,也可能更短,方式做到这一点。 有人打我!



Answer 4:

一个176字节的WinXP .COM可执行文件:

vQoAgMYQjsKO2jPAM / + 5AIDzq7QLzSE8 / 751AXQDvoQB6DkAi / noNACL2egvACn5A / 87HXYCiR2D xwLi9eviM8mZ9 / VSQQvAdfeI + rQCzSG3LFqAwjC0As0h4vbD / 9Y8CnP6D7bI / 9Y8CnPwtACR9 yOvxtAvNITz UD + / + dRO0CM0hLDDDtAHNITwadfW kAHDM /½/ 7cgrTn4dA + L + I1E / tHo6Jr / i8folf8L 9nXozSA =

Base64编码的,我用这个网站来进行编码 。 解码为.com文件。 该程序读取标准输入直到一个EOF,从控制台读取时,然后将结果输出到stdout其是按Ctrl-Z。

编辑:源代码:

    mov bp,10
    add dh,10h
    mov es,dx
    mov ds,dx
    xor ax,ax
    xor di,di
    mov cx,8000h
    rep stosw
    mov ah,0bh
    int 21h
    cmp al,255
    mov si,offset l9
    je l1
    mov si,offset l11
l1:
    call l7
    mov di,cx
    call l7
    mov bx,cx
    call l7
    sub cx,di
    add di,di
l2:
    cmp bx,[di]
    jbe l3
    mov [di],bx
l3:
    add di,2
    loop l2
    jmp l1
l4:
    xor cx,cx
l5:
    cwd
    div bp
    push dx
    inc cx
    or ax,ax
    jnz l5
    mov dl,bh
    mov ah,2
    int 21h
    mov bh,44
l6:
    pop dx
    add dl,48
    mov ah,2
    int 21h
    loop l6
    ret
l7:
    call si
    cmp al,10
    jae l7
    db 0fh, 0b6h, 0c8h
l8:
    call si
    cmp al,10
    jae ret
    mov ah,0
    xchg cx,ax
    mul bp
    add cx,ax
    jmp l8
l9:
    mov ah,0bh
    int 21h
    cmp al,255
    jne l12
    mov ah,8
    int 21h
l10:
    sub al,48
    ret
l11:
    mov ah,1
    int 21h
    cmp al,26
    jne l10
    mov si,offset l12
    ret
l12:
    xor si,si
    xor di,di
    mov bh,32
l13:
    lodsw
    cmp ax,di
    je l14
    mov di,ax
    lea ax,[si-2]
    shr ax,1
    call l4
    mov ax,di
    call l4
l14:
    or si,si
    jne l13
    int 20h

编译,像往常一样对我来说,使用A86。



Answer 5:

Python和133个字符 ,内存和时间高效的,对数据输入没有任何限制

D = [(1,11,5), (2,6,7), (3,13,9), (12,7,16), (14,3,25), (19,18,22), (23,13,29), (24,4,28)]

l,T=0,zip(*D)
for x,h in map(lambda x:(x,max([y for a,y,b in D if a<=x<b]or[0])),sorted(T[0]+T[2])):
    if h!=l: print x,h,
    l=h

说明:

lambda x:(x,max([y for a,y,b in D if a<=x<b]or[0])

返回的位置和位置x处的高度。

现在在排序坐标列表循环由编译sorted(zip(*D)[0]+zip(*D)[2])和输出如果高度变化。

第二版本是不与上述一个高效和具有坐标限制,但只使用115个字符

for x in range(100):
    E=[max([y for a,y,b in D if a<=(x-i)<b]+[0])for i in(0,1)]
    if E[0]-E[1]:print x,E[0],


Answer 6:

的98个字符Ĵ ,默认定义(没有变量名!):

,@(([:(1:,{:"1)}.~:}:)#])@((],[:>./(1&{@[*(]>:{.@[)*]<{:@[)"1)"2 0(([:<./{."1)}.[:i.@>:[:>./{:"1))

在行动:

$ jconsole
   s =: ,@(([:(1:,{:"1)}.~:}:)#])@((],[:>./(1&{@[*(]>:{.@[)*]<{:@[)"1)"2 0(([:<./{."1)}.[:i.@>:[:>./{:"1))
   |:b =: 8 3 $ 1 11 5 2 6 7 3 13 9 12 7 16 14 3 25 19 18 22 23 13 29 24 4 28
 1 2  3 12 14 19 23 24
11 6 13  7  3 18 13  4
 5 7  9 16 25 22 29 28
   s b
1 11 3 13 9 0 12 7 16 3 19 18 22 3 23 13 29 0

只有86与最左边的坐标假设字符始终为1。

,@(([:(1:,{:"1)}.~:}:)#])@((],[:>./(1&{@[*(]>:{.@[)*]<{:@[)"1)"2 0([:>:[:i.[:>./{:"1))

只有76与附加假设最右边的坐标为至多99。

,@(([:(1:,{:"1)}.~:}:)#])@((],[:>./(1&{@[*(]>:{.@[)*]<{:@[)"1)"2 0&(>:i.99))

借用cobbal一些技巧,我可以得到68。

[:,@({:"1#>:@i.@#,.{."1)[:1&|.[:(,.(~:_1&|.))[:>./(1&{*{.<:[:i.{:)"1

默认定义就不能使用抗衡s=:…消除冗余,虽然。


每当我回答的J一个问题,我尽量花时间来解释这是怎么回事,因为我觉得别人可能会喜欢看看到一个陌生的语言的工作。

   NB. The first, second, and last element of a vector
   ({. 0{b), (1 { 0{b), ({: 0{b)
1 11 5
   NB. Count from 0 to (last element of vector)-1
   i. {: 0{b
0 1 2 3 4
   NB. Booleans: first element of vector less than or equal to (above)?
   ({. <: [:i.{:) 0{b
0 1 1 1 1
   NB. Multiply by second element of vector
   (1&{ * {.<:[:i.{:) 0{b
0 11 11 11 11
   NB. Stack up results for each vector, then find maximum by column
   >./ (1&{*{.<:[:i.{:) " 1 b
0 11 11 13 13 13 13 13 13 0 0 0 7 7 7 7 3 3 3 18 18 18 3 13 13 13 13 13 13
   NB. Identify leaders and make table
   |: (,. (~: _1 & |.)) >./(1&{*{.<:[:i.{:)"1 b
0 11 11 13 13 13 13 13 13 0 0 0 7 7 7 7 3 3 3 18 18 18 3 13 13 13 13 13 13
1  1  0  1  0  0  0  0  0 1 0 0 1 0 0 0 1 0 0  1  0  0 1  1  0  0  0  0  0
   NB. Rotate left
   |: 1 |. (,.(~:_1&|.))>./(1&{*{.<:[:i.{:)"1 b
11 11 13 13 13 13 13 13 0 0 0 7 7 7 7 3 3 3 18 18 18 3 13 13 13 13 13 13 0
 1  0  1  0  0  0  0  0 1 0 0 1 0 0 0 1 0 0  1  0  0 1  1  0  0  0  0  0 1
   NB. 1-based index and first element, when last element is true
   |: ({:"1 # >: @ i. @ # ,. {."1) 1&|.(,.(~:_1&|.))>./(1&{*{.<:[:i.{:)"1 b
 1  3 9 12 16 19 22 23 29
11 13 0  7  3 18  3 13  0
   NB. Flatten
   , ({:"1#>:@i.@#,.{."1)1&|.(,.(~:_1&|.))>./(1&{*{.<:[:i.{:)"1 b
1 11 3 13 9 0 12 7 16 3 19 18 22 3 23 13 29 0
   NB. Rearrange for tacit verb
   ([:,@({:"1#>:@i.@#,.{."1)[:1&|.[:(,.(~:_1&|.))[:>./(1&{*{.<:[:i.{:)"1) b
1 11 3 13 9 0 12 7 16 3 19 18 22 3 23 13 29 0
share
  • like the tacit, very nice explanation too – cobbal Jul 3 '09 at 4:33
5
votes

2 C# answers - way too long, but I'd love to see better?

LINQ approach (135 chars excluding array line):

var a=new[]{new[]{1,11,5},new[]{2,6,7},new[]{3,13,9},new[]{12,7,16},new[]{14,3,25},new[]{19,18,22},new[]{23,13,29},new[]{24,4,28}};    
int l=0,y,x=-1;while(++x<5001){var b=a.Where(c=>c[0]<=x&&c[2]>x);if((y=b.Any()?b.Max(c=>c[1]):0)!=l)Console.Write(x+", "+(l=y)+", ");}

Or a non-LINQ answer (179 185 chars excluding array line):

var a={1,11,5,2,6,7,3,13,9,12,7,16,13,3,25,19,18,22,23,13,29,24,4,28};
var b=new int[5000];int i=-1,j,z;while(++i<a.Length)for(j=a[i*3];j<a[i*3+2];j++)if((z=a[i*3+1])>b[j])b[j]=z;i=-1;z=0;while(++i<5000)if(b[i]!=z)Console.Write(i+", "+(z=b[i])+", ");
share
  • if((y=a.Where(c=>c[0]<=x&&c[2]>x).Max(c=>(int?)c[1])??0)!=l) saves you a few characters – Jimmy Jul 6 '09 at 22:20
  • "Console.Write" c#'s achilles heal of golf :) You have 3 references to [x,y] in the latter solution. replacing with [x*3+y] costs 6 characters but a.GetLength(0) becomes a.Length. the first [i*3+0] can lose th plus zero though so you net save ywo characters. you can lift the definition of j to where you define z. – ShuggyCoUk Jul 18 '09 at 2:46
  • not sure if you allow yourself var in the non Linq version, shaves one character of the declaration of b. – ShuggyCoUk Jul 18 '09 at 2:51
  • Nice; feel free to hack either/both in ;-p – Marc Gravell Jul 18 '09 at 7:05
3
votes

Code is condensed (few lines to code) which is good for the tournament (time is the scarcest resource), and seems correct (I don't know python, but I think I understand the code).

Your solution basically paints the city skyline in a buffer and then outputs the contents of the buffer in the required format.

The extra info you ommited from the problem is that there will be at most 5000 buildings and the horizontal positions will smaller than 10.000. That implies that memory does not seem a problem in your case (40kb for the skyline assuming 32bit architecture, plus 45kb for the building description - optional, you could paint the skyline in the read loop). The algorithm is linear in the number of buildings so it is fast.

With toughter memory constraints you could go for a one-pass algorithm, but I believe that in this case it would perform slower and be much more complex to implement (more of your time, more CPU time)

Now you should consider really reading the input in the given format and using that data for your computations instead of a prestored data array.

BTW, is python a valid language now in ACM contests?

share
  • it wasn't last year. – Victor Jun 30 '09 at 23:15
  • 1
    Valid Languages = Java, C, C++, C#. As of 2008, problems may not have a judge-written C# solution. – glasnt Jul 1 '09 at 3:02
  • 2
    TomatoSandwich is right - Python is not a supported language for ACM contests - I just used it, because with it, I could write condensed code. I also omitted information about test cases, because SO doesn't have means of providing them automatically, so I assumed, that algorithm written for test data will work for all data – zeroDivisible Jul 1 '09 at 4:05
  • 2
    The info about test data is important. If your skyline coordinates instead of ranging to 10.000 could range to 2^32-1 (max 32bit integer) then your algorithm would be flawed as it would require 2^34 bytes or 16Gb of memory to store the v variable (array from 0 to 2^32-1 of 32bit integers). The same goes for buildings, if the number was big enough you would have to refactor into a one-pass algorithm. Those are really important items to evaluate an algorithm, not only correctness but viability of the implementation. – David Rodríguez - dribeas Jul 1 '09 at 5:29
  • what happened with Pascal? have they dropped it? – fortran Jul 9 '09 at 9:42
3
votes

Here's a quick one in Perl

( by quick I mean less than two hours )

Perl in only 327 characters

( excluding " #/" to improve highlighting )

use 5.010;
$/=undef;
@s=map{[split',',$_]}grep{$_}split/\)\s*(?:$|,\s*\()|^\s*\(/,<>; #/
for$s(@s){($l,$y,$r)=@$s;
for$x($l..$r){$c=$p[$x];$p[$x]=$c>$y?$c:$y;}}
for($x=1;$x<=@p;$x++){$y=$p[$x]||0;
if(!defined$z){$l=$x;$z=$y;
}elsif($y!=$z){push@n,[$l,$z,$x-1];$z=$y;$l=$x;}}
push@n,[$l,$z];
say join', ',map{($_->[0],$_->[1])}@n;

Original testing version 853 characters

#! /usr/bin/env perl
use strict;
use warnings;
use 5.010;
use YAML;
use List::Util 'max';


my $file;
{
  local $/ = undef;
  $file = <>;
}

my @sections = map { [split ',', $_] } grep {$_} split m'
  \)\s* (?:$|,\s*\() |
  ^ \s* \(
'x, $file;

#my $max_x = max map{ $_->[2] } @sections;
#say $max_x;

my @points;
for my $reg( @sections ){
  my($l,$y,$r) = @$reg;
  for my $x ( $l .. $r ){
    my $c = $points[$x] || 0;
    $points[$x] = max $c, $y;
  }
}


my @new;
my($l,$last_y);
for( my $x=1; $x <= @points; $x++ ){
  my $y = $points[$x] || 0;

  # start
  if( ! defined $last_y ){
    $l = $x;
    $last_y = $y;
    next;
  }

  if( $y != $last_y ){
    push @new, [$l,$last_y,$x-1];
    $last_y = $y;
    $l = $x;
    next;
  }
}
push @new, [$l,$last_y];


say Dump \@sections, \@points, \@new;

say join ', ', map { ($_->[0],$_->[1]) } @new;

Initial minified version 621 characters

( excluding " #/" to improve highlighting )

#! /usr/bin/env perl
use strict;
use warnings;
use YAML;
use 5.010;

$/=undef;

my@s=map{[split',',$_]}grep{$_}split/\)\s*(?:$|,\s*\()|^\s*\(/,<>; #/

my@p;
{
  no strict; no warnings 'uninitialized';

  for$s(@s){
    ($l,$y,$r)=@$s;
    for$x($l..$r){
      $c=$p[$x];
      $p[$x]=$c>$y?$c:$y;
    }
  }
}

# $last_y => $z
my @n;
{
  no strict;

  #my($l,$z);
  for($x=1;$x<=@p;$x++){
    $y=$p[$x]||0;
    if(!defined$z){
      $l=$x;
      $z=$y;
    }elsif($y!=$z){
      push@n,[$l,$z,$x-1];
      $z=$y;
      $l=$x;
    }
  }
  push@n,[$l,$z];
}

say Dump \@s, \@p, \@n;

say join', ',map{($_->[0],$_->[1])}@n;

I used YAML to make sure I was getting the right data, and that the different versions worked the same way.

share
3
votes

Assuming the input:

b=[(1,11,5),(2,6,7),(3,13,9),(12,7,16),(14,3,25),(19,18,22),(23,13,29),(24,4,28)]

Haskell: 105 characters

h x=maximum$0:[y|(l,y,r)<-b,l<=x,x<r]
main=putStr$unwords[show x++" "++show(h x)|x<-[1..9999],h x/=h(x-1)]

String formatting seems to be where Haskell falls behind the Python solutions. Having to use an extra 5 characters to write 'main=' doesn't help either, but perhaps it shouldn't be included, the C#/Java solutions would be massive if their code had to demonstrate the complete program :)

Haskell: 76 characters (no string formatting & no main)

h x=maximum$0:[y|(l,y,r)<-b,l<=x,x<r]
print[(x,h x)|x<-[1..9999],h x/=h(x-1)]

Looking back at the original problem it requires that you to read the input from a file, so I thought it would be interesting to see how many characters that adds.

Haskell: 149 characters (full solution)

main=interact f
f i=unwords[show x++" "++show(h x)|x<-[1..9999],h x/=h(x-1)] where
 h x=maximum$0:[y|[l,y,r]<-b,l<=x,x<r]
 b=map(map read.words)$lines i

Below is what the full solution looks like with more descriptive variable names and type signatures where possible.

main :: IO ()
main = interact skyline

skyline :: String -> String
skyline input =

  unwords [show x ++ " " ++ show (heightAt x) |
           x <- [1..9999], heightAt x /= heightAt (x-1)]

  where heightAt :: Int -> Int
        heightAt x = maximum $ 0 : [h | [l,h,r] <- buildings, l <= x, x < r]

        buildings :: [[Int]]
        buildings = map (map read . words) $ lines input
share
2
votes

Here's my attempt in Perl. 137 characters, of which 33 are dedicated to finding the end of the skyline.

@a = ([1,11,5],[2,6,7],[3,13,9],[12,7,16],[14,3,25],[19,18,22],[23,13,29],[24,4,28]);
($x)=sort{$b<=>$a}map{$$_[2]}@a;
for(;$c<=$x;$c++){$n=0;map{$n=$$_[1]if$c>=$$_[0]&&$c<$$_[2]&&$n<$$_[1]}@a;print"$c $n "if$n!=$h;$h=$n;}
share
  • It's even shorter than mine :P How long did this take you to create? – Brad Gilbert Jul 9 '09 at 22:25
  • About 30 minutes. – Eric Jul 10 '09 at 7:16
2
votes

Rereading the UVA rules, we're not limited to a max X of 5000, but rather 5000 buildings. X and Y values up to (and including) 9999 are allowed.

Also, apparently only C, C++, C#, and Java are officially recognized languages, so I did mine up in Java. The numbers are only space separated, but commas could be put back in (at a cost of two more total chars). Totalling 153 chars (excluding the array line):

int[][]b=new int[][]{{1,11,5},{2,6,7},{3,13,9},{12,7,16},{14,3,25},{19,18,22},{23,13,29},{24,4,28}};
int[]y=new int[10000];int i;for(int[]o:b)for(i=o[0];i<o[2];y[i]=Math.max(y[i++],o[1]));for(i=0;i<9999;)if(y[i++]!=y[i])System.out.print(i+" "+y[i]+" ");

The logic is pretty straightforward. The only things that make the flow a little wonky are variable reuse and nonstandard placement of post-increment. Generates:

1 11 3 13 9 0 12 7 16 3 19 18 22 3 23 13 29 0 
share
2
votes

Apart from the challenge.

Is the result set correct? At position 22 the highest point is 18 and at 23 is 13, so 3 is not the highest point.

I also tried to make a php version and it gives me a diferent final vector. It is not optimized for speed.

<?php
$buildings = array(
    array(1,11,5), 
    array(2,6,7), 
    array(3,13,9), 
    array(12,7,16), 
    array(14,3,25), 
    array(19,18,22), 
    array(23,13,29), 
    array(24,4,28)
);

$preSkyline = array();
for( $i = 0; $i<= 30; $i++){
    foreach( $buildings as $k => $building){
        if( $i >= $building[0] && $i<= $building[2]){
            $preSkyline[$i][$k] = $building[1];
        } else{
            $preSkyline[$i][$k] = 0;
        }
    }
}
foreach( $preSkyline as $s =>$a){
    $skyline[$s] = max( $a );
}
$finalSkyline = array();
foreach( $skyline as $k => $v){
    if( $v !== $skyline[ $k-1]){
        $finalSkyline[$k] =  $v;
    }
}
echo "<pre>";
print_r( $finalSkyline );
?>

this returns:

Array
(
    [0] => 11
    [2] => 13
    [9] => 0
    [11] => 7
    [16] => 3
    [18] => 18
    [22] => 13
    [29] => 0
)

which are the inflexion points and the max height.

share
2
votes

ruby, 80 chars

B=[[1,11,5],[2,6,7],[3,13,9],[12,7,16],[14,3,25],[19,18,22],[23,13,29],[24,4,28]]
o=0;1.upto(5001){|x|y=(B.map{|b|x>=b[0]&&x<b[2]&&b[1]||0}.max);o!=(o=y)&&p(x,y)}
share
2
votes

C

int main(int arc, char **argv) {
  int B[][3]={{1,11,5},{2,6,7},{3,13,9},{12,7,16},{14,3,25},{19,18,22},{23,13,29},{24,4,28}},o=0,y=0,x=0,blen=8,bs=0,b;
  for (;x<9001;x++,o=y,y=0) {
    for (b=bs;b<blen;b++) {
      if (x >= B[b][0] && x < B[b][2] && B[b][1] > y) y=B[b][1];
      if (x > B[b][2]) bs = b;
    }
    if (y-o) printf("%d %d ", x, y);
  }
}
share