건축가가 스카이 라인을 시각화하도록 지원


29

도시 계획 프로젝트의 일환으로 건축가의 의견을 수렴하여 도시 스카이 라인을 표시하는 프로그램이나 기능을 만들 수 있습니다. 프로젝트는 시작 단계에만 있으므로 매우 대략적인 스케치로 충분합니다. 물론 가장 쉬운 방법은 단순히 ASCII 아트로 스카이 라인을 그리는 것입니다.

모든 건물은 강 옆에 있으므로 모두 정렬되어 있습니다. 건축가는 각 건물의 높이를 입력으로 제공하며 코드에는 스카이 라인이 표시되어야합니다.

아키텍트의 입력은 정수 또는 반정 수입니다. 숫자가 정수인 경우 건물에는 평평한 지붕이 있고 반정 수는 지붕이 삐걱 거리게됩니다. 0은 평평한 접지입니다. 건물 벽의 간격은 3 자이며 0은 1 자입니다. 인접한 건물은 벽을 공유합니다.

출력에 대한 자세한 내용과 설명은 아래 예를 참조하십시오.

N = 3
 ___
|   |
|   |
|___|

N = 3.5
  _      
 / \
|   |
|   |
|___|

N = 6
 ___
|   |
|   |
|   |
|   |
|   |
|___|

n = 0
_

입력 예 : 3 3.5 0 2

      _
 ___ / \  
|   |   |  ___
|   |   | |   |
|___|___|_|___|

입력 예 : 0 0 2.5 3 0 4 1

             ___
    _  ___  |   |
   / \|   | |   |
  |   |   | |   |___
__|___|___|_|___|___|

루이빌 ,0 2 1 3.5 0 4 2 4 2 4 6 1 6 0 5 1

                                    ___     ___
                                   |   |   |   |  ___
           _    ___     ___     ___|   |   |   | |   |
          / \  |   |   |   |   |   |   |   |   | |   |
  ___    |   | |   |___|   |___|   |   |   |   | |   |
 |   |___|   | |   |   |   |   |   |   |___|   | |   |___
_|___|___|___|_|___|___|___|___|___|___|___|___|_|___|___|

사용되는 ASCII 문자는 개행, 공백 및 /\_|(코드 포인트 10, 32, 47, 92, 95, 124)입니다.

규칙 :

  • 모든 숫자에 2를 곱하여 정수만 입력으로하는 프로그램을 만드는 것은 선택 사항입니다. 따라서을 복용하는 대신 3 3.5 2프로그램이 걸릴 수 있습니다 6 7 4. 두 번째 입력 형식을 선택하면 6을 입력하면 3 층 건물이되며 7은 지붕이 뾰족한 3 층 건물이어야합니다.
  • 출력은 위에서 설명한대로 정확하게 이루어져야하지만 후행 공백과 줄 바꾸기는 정상입니다.
  • 입력의 정확한 형식은 선택 사항입니다. 귀하의 언어에서 가장 좋은 것이 무엇이든.
  • 건축가가 결과를 볼 수 있도록 결과가 화면에 표시되어야합니다.
  • 적어도 하나의 정수가 제공되고 유효한 입력 만 제공된다고 가정 할 수 있습니다.

이것은 codegolf이므로 바이트 단위의 가장 짧은 코드가 이깁니다.


1
높이 0.5의 건물은 어떻게 생겼습니까?
톰 카펜터

정말로 생각하지 않았습니다. 가장 확실한 선택은 당신에게 거의 호빗 집 같은 단지 피치의 지붕, 수 :-)하지만해도 될까요, 또는 입력이 0.5하지 않습니다 가정 할 수있다 자유롭게 선택할 수 ...
스튜이 그리핀

1
현재 벽이 없기 때문에 이상한 일이 발생합니다 (0.5 높이가 존재하지 않는다고 가정). 그래서 나는 약간의 대답을해야합니다.
톰 카펜터

방금 높이 0.5로 코드를 시험해 보았습니다. "이상한"은 매우 설명적인 단어 = PI가 자세히 설명하지 않았으므로 무슨 일이 일어나고 있는지 잘 모르겠습니다. 완벽하게 유효합니다, 당신은 0.5 건물이 없다고 가정 할 수 있습니다 ...
Stewie Griffin

답변:


5

Python 2, 199 193 1188 바이트

a=map(int,raw_input().split())
l=max(a)+1|1
while~l:print''.join((x%2*'/  _\\ '[x<l::2]*(x<=l<x+4)or'_ '[x|1!=l>1]*3)[x<1:x+2]+'| '[x<=l>=y]*(x+y>0)for x,y in zip([0]+a,a+[0]))[1:];l-=2

이것은 정수를 입력으로 받아들이는 전체 프로그램입니다. 입력 예 .


훌륭한!
나는

5

MATLAB, 219209203 바이트

i=input('');x=1;c=0;m(1:4*numel(i))='_';for a=i;b=fix(a);m(1:b,x)='|';s=95;if a~=b;m(b+2,x+2)=95;s='/ \';end;m(b+1,x+(1:3))=s;x=x+(a>0)*3+1;m(1:b,x)='|';x=x+(a<1&c>0);c=a;end;disp(flipud(m(:,1:x-(a<1))))

불행히도 Octave 에서는 작동하지 않습니다 . 왜 그런지 완전히 알지 못하고 깨지는 disp / flipud 비트와 관련이있는 것 같습니다.

또한 현재 0.5 높이 건물이 어떻게 보이는지에 대한 정의가 없으며 언급이 없으므로이 코드에서는 허용되지 않는다고 가정합니다.

다음은 약간 더 읽기 쉬운 코드입니다.

i=input(''); %e.g. [0 0 2 1 3.5 0 4 2 4 2 4 6 1 6 0 5 1 0 0 1 0]
x=1;
c=0;
m(1:4*numel(i))='_';
for a=i;
    b=fix(a);
    m(1:b,x)='|';
    s=95;
    if a~=b;
        m(b+2,x+2)=95;
        s='/ \';
    end;
    m(b+1,x+(1:3))=s;
    x=x+(a>0)*3+1;
    m(1:b,x)='|';
    x=x+(a<1&c>0);
    c=a;
end;
disp(flipud(m(:,1:x-(a<1))))

먼저 입력을 배열로 가져 와서 변수 초기화를 수행합니다.

i=input(''); %e.g. [0 0 2 1 3.5 0 4 2 4 2 4 6 1 6 0 5 1]
x=1;
c=0;

높이가 0 인 건물은 고통이기 때문에 기본적으로 옆에있는 것 (인쇄 된 내용은 변경되지 않음)에 따라 너비가 결정됩니다. 모든 건물에 충분한 땅을 그려서 물건을 단순화합니다. 우리는 각 건물의 너비가 4 자 (인접한 건물이 합쳐지기 때문에)라고 가정합니다.

m(1:4*numel(i))='_';

이제 각 건물을 차례로 그립니다.

for a=i

먼저 우리는 얼마나 많은 '|' 우리는 필요합니다.

    b=fix(a);

이제이 건물의 벽을 그립니다. 인접한 두 건물이있는 경우이 새 건물의 벽은 마지막 건물의 벽과 같은 기둥에 있습니다.

    m(1:b,x)='|';

이 건물이 절반 높이인지 확인하십시오. 그렇다면 지붕이 달라집니다. 절반 높이의 경우 지붕은 / \전체 높이가 될 것입니다 ___(Matlab은 단일 밑줄에서 암시 적으로 이것을 복제하므로 몇 바이트를 절약하십시오). 반 높이 건물에는 한 줄 더 높은 지붕이 추가되어 추가됩니다.

    s=95;
    if a~=b;
        m(b+2,x+2)=95;
        s='/ \';
    end;

지붕에서 그리기

    m(b+1,x+(1:3))=s;

이제 다음 건물의 시작으로 이동하여 공유 벽을 그립니다 (이 시점에서 벽이 너무 짧으면 다음 건물을 그릴 때 벽이 더 커집니다). 높이가 0 인 건물은 너비가 1이고, 일반 건물은 너비가 4이므로 (a> 0)을 부울이 아닌 10 진수로 처리하여 if-else가되는 것을 단순화합니다.

    x=x+(a>0)*3+1;
    m(1:b,x)='|';

다음은 높이가 0 인 건물에서 작동하는 약간의 해커입니다. 기본적 으로이 건물의 높이가 0이고 그 이전의 것이 아닌 경우 다른 두 건물 사이에 샌드위치 된 0 높이 건물의 너비가 사실상 두 배이기 때문에 다음 건물의 위치가 1 씩 증가해야 함을 의미합니다. 추가 벽은 일반적으로 인접한 건물과 공유됩니다. 또한 다음에이 점검을 수행하기 위해이 건물 높이를 추적합니다.

    x=x+(a<1&c>0);
    c=a;
end;

완료되면 빌딩 매트릭스를 뒤집어 올바른 방법으로 표시하십시오. 우리는 또한 여기에서 초과 접지를 제거합니다.

disp(flipud(m(:,1:x-(a<1))))

따라서이 스크립트를 실행할 때 다음과 같이 입력을 요청합니다.

[0 0 2 1 3.5 0 4 2 4 2 4 6 1 6 0 5 1 0 0 1 0]

그런 다음 건물을 생성하고 결과를 표시합니다. 위의 입력에 대해 다음이 생성됩니다.

                                     ___     ___                   
                                    |   |   |   |  ___             
            _    ___     ___     ___|   |   |   | |   |            
           / \  |   |   |   |   |   |   |   |   | |   |            
   ___    |   | |   |___|   |___|   |   |   |   | |   |            
  |   |___|   | |   |   |   |   |   |   |___|   | |   |___    ___  
__|___|___|___|_|___|___|___|___|___|___|___|___|_|___|___|__|___|_

잘 했어요!
Stewie Griffin

4

코 틀린, 447 442 바이트

val a={s:String->val f=s.split(" ").map{it.toFloat()}.toFloatArray();val m=(f.max()!!+1).toInt();for(d in m downTo 0){var l=0f;for(c in f){val h=c.toInt();print(if(h==d&&d!=0)if(h<l-0.5)"|" else{" "}+if(c>h)"/ \\" else "___" else if(h<d)if(d<l-0.5)"|" else{" "}+if(h==0)" " else if((c+0.5).toInt()==d)" _ " else "   " else{if(h==0)if(l<1)"  " else "| " else "|   "}.replace(' ',if(d==0)'_' else ' '));l=c;};if(d<l-0.5)print("|");println();}}

언 골프 버전 :

val ungolfed: (String) -> Unit = {
    s ->

    val floats = s.split(" ").map { it.toFloat() }.toFloatArray()
    val maxH = (floats.max()!! + 1).toInt()

    for (drawHeight in maxH downTo 0) {
        var lastBuildingH = 0f
        for (f in floats) {
            val buildingH = f.toInt()
            if (drawHeight == 0) {
                // Baseline
                if (buildingH == 0)
                    if (lastBuildingH.toInt() == 0) print("__")
                    else print("|_")
                else print("|___")
            } else if (buildingH == drawHeight) {
                // Ceiling
                if (buildingH < lastBuildingH - 0.5) print("|")
                else print(" ")
                if (f > buildingH) print("/ \\")
                else print("___")
            } else if (buildingH < drawHeight) {
                // Above building
                if (drawHeight < lastBuildingH - 0.5) print("|")
                else print(" ")
                if (buildingH == 0) print(" ")
                else {
                    if ((f + 0.5).toInt() == drawHeight) print(" _ ")
                    else print("   ")
                }
            } else {
                if (buildingH == 0) print("| ")
                else print("|   ")
            }
            lastBuildingH = f;
        }
        if (drawHeight < lastBuildingH - 0.5) print("|")
        println()
    }
}

3

파이썬 2, 357 306 299 294 287 281 276 바이트

def s(l):
 d=len(l)+1;l=[0]+l+[0];h=(max(l)+3)/2;o=''
 for i in range(d*h):
  a=l[i%d+1];c=l[i%d];b=2*(h-1-i/d);o+="|"if(a>b+1)+(c>b+1)else" "*(a+c>0);o+=" _/__  _\\"[a-b+1::3]if b*(1>=abs(a-b))else" "*(1+2*(a>0))
  if b==0:o=o.replace(" ","_")
  if i%d==d-1:print o[:-1];o=''

이것은 "이중"인코딩을 사용하여 함수로 목록으로 전달됩니다. 편집 : 큰 조건부 중 일부를 배열 선택기로 다시 실행하고 이중 인코딩으로 전환하여 바이트를 줄였습니다. 조건부를 훨씬 더 재정렬하고 더 많은 논리를 산술로 변환하여 더 많은 바이트를 면도했습니다.

편집 : xsot가 더 좋습니다

설명:

d=len(l)+1;l=[0]+l+[0];m=max(l);h=m/2+m%2+1;o=''

d두 번째 요소부터 끝에 추가 한 0까지 목록의 각 끝에 0을 추가하기 때문에 배열의 길이보다 1이 더 큽니다. h도면의 높이입니다. (이 계산에서는 두 배의 표현을 사용하기 때문에이 계산에서 2로 나눠야합니다. 두 배의 표현을 사용합니다.이 표현은 특히 모든 곳에서 정수를 플로트로 변환하지 않기 위해 사용됩니다. 일반 종류보다 약간 더 여유를 얻으십시오.) o출력 문자열입니다.

 for i in range(d*h):

이중 for 루프를 단일 for 루프로 접는 표준 트릭입니다. 일단 우리가 :

  a=l[i%d+1];c=l[i%d];b=2*(h-1-i/d)

우리는 이제 다음과 같은 성과를 달성했습니다.

for b in range(2*h-2,-2,-2):
 for j in range(d):
  a=l[j+1];c=l[j]

그러나 10 바이트가 절약되는 방식으로 (다음 줄의 공백 포함).

  o+="|"if(a>b+1)+(c>b+1)else" "*(a+c>0)

여기에 하나 이상의 건물 경계가있는 한 현재 건물 또는 이전 건물의 높이가 현재 선보다 키가 큰 벽을 붙입니다. 다음 조건에 해당합니다.

  o+=("|" if a>b+1 or c>b+1 else " ") if a or c else ""

여기서 b는 현재 스캔 높이이고, a는 현재 건물 높이이며, c는 이전 건물 높이입니다. 조건부 후자는 벽을지면 공간 사이에 두는 것을 방지합니다.

  o+=" _/__  _\\"[a-b+1::3]if b*(1>=abs(a-b))else" "*(1+2*(a>0))

건물의 높이와 현재 스캔 높이를 비교하여 지붕 부품을 선택하여 올바른 지붕을 그리는 부품입니다. 지붕이 여기에 가지 않으면 적절한 수의 공간을 인쇄합니다 (실제 건물 인 경우 3, 예를 들어 a> 0, 그렇지 않으면 1). 우리가 지상에있을 때 지붕을 그리려고 시도하지 않습니다. 즉 0.5 크기의 건물에는 뾰족한 지붕이 없습니다. 오 잘

  if b==0:o=o.replace(" ","_")

우리가 지상에있을 때 공백 대신 밑줄을 원합니다. 우리는 여기서 한 번에 모두 교체합니다.

  if i%d==d-1:print o[:-1];o=''

다음 행 처리를 시작하기 직전에 현재 행을 인쇄하고 출력 행을 지우십시오. 마지막 문자는 함수 시작 부분에 0을 추가하여 추가 한지면 공간에 해당하는 "_"이므로 잘립니다. (우리는 오른쪽 벽을 삽입하기 위해 특별한 경우를 추가 할 필요가 없으므로 0을 추가했습니다. 0을 추가하고 "_"를 잘라서 추가 한 것보다 훨씬 많은 코드를 추가합니다.


자동차 골프. 와우. (또한 +1)
박수 :

2

파이썬 3

725 바이트

608 바이트

골프 코드 :

import sys,math;
m,l,w,s,bh,ls,ins,r,a="|   |","___","|"," ",0,[],[],range,sys.argv[1:]
def ru(n):return math.ceil(n)
def bl(h,n):
    if(n>ru(h)):return(s*5,s)[h==0]
    if(h==0):return"_"
    if(n==0):return w+l+w
    if(n<h-1):return m
    return("  _  "," / \ ")[n==ru(h)-1]if(h%1)else(s+l+s,m)[n==h-1]
for arg in a:
    f=ru(float(arg))
    if(bh<f):bh=f
for i in r(bh,-1,-1):
    ln=""
    for bld in a:ln+=bl(float(bld),i)
    ls.append(ln)
for i in r(len(ls[-1])-1):
    if(ls[-1][i]==ls[-1][i+1]==w):ins.append(i-len(ins))
for ln in ls:
    for i in ins:ln=(ln[:i]+ln[i+1:],ln[:i+1]+ln[i+2:])[ln[i]==w]
    print(ln)

ungolfed 코드는 다음과 같습니다. 몇 가지 의견이 있지만 기본 아이디어는 이중 벽으로 건물을 만드는 것이므로 결론은 다음과 같습니다.

_|___||___|_|___||___|

그런 다음 이중 벽의 색인을 얻고 해당 열을 제거하여 다음을 얻습니다.

_|___|___|_|___|___|

암호:

import sys
import numbers
import math

mid="|   |";
l="___";
w="|";
s=" ";

def printList(lst):
    for it in lst:
        print(it);

# h = height of building
# l = line numeber starting at 0
def buildingline(h,n):
    #if (h==0):
    #   return " " if(n>math.ceil(h)) else "   ";
    if(n>math.ceil(h)):
        return s if(h == 0) else s*5;
    if(h==0): return "_";
    if(n==0): return w+l+w;
    if(n<h-1): return mid;
    if(h.is_integer()):
        return mid if(n==h-1) else  s+l+s;
    else:
        return " / \ " if (n==math.ceil(h)-1) else "  _  "; 
# max height
bh=0;

for arg in sys.argv[1:]:
    f = math.ceil(float(arg));
    if(bh<f):bh=f;

# lines for printing
lines = []

for i in range(bh,-1,-1):
    line="";
    for bld in sys.argv[1:]:
        bld=float(bld);
        line += buildingline(bld,i);
        #lh = bld;
    lines.append(line);

#for line in lines:
#   print(line);
#printList(lines);


# column merging
#find indexes for merging (if there are | | next to each other)
indexes = [];
for i in range(len(lines[-1])-1):
    if (lines[-1][i]=='|' and lines[-1][i+1] == '|'):
        indexes.append(i-len(indexes));

#printList(indexes);

#index counter
for line in lines:
    newLine = line;
    for i in indexes:
        if newLine[i] == '|' :
            newLine=newLine[:i+1] + newLine[i+2:];
        else : newLine = newLine[:i] + newLine[i+1:];
    print(newLine);

골프를 할 시간이다!


당신은 여기를 보고 싶을 수도 있습니다 . 나는 여기에 많은 골프 잠재력이 있다고 생각한다. =) 나는 기본 파이썬 만 알고 있기 때문에, 내가 두려워하는 것을 제안 할 수는 없다 ...
Stewie Griffin

공백을 제거하고 변수 이름을 단축했지만 나머지는 변경하지 않은 것처럼 보입니다. 예를 들어, 일부 루프를 제거하고, 더 적은 비교를 사용하는 등 영리한 방법을 찾아야합니다. 물론, ru(n):return math.ceil(n)골프 와 같은 수는 있지만 여전히 .. 부정적인 방법으로 사용하지 마십시오. 좋은 골퍼 자신, 그리고 좋은 프로그래머가 아니라고 확신합니다. 나는 당신이 그것을 약간 개선하려고 제안합니다 ... 당신이 그것을 단축 관리한다는 사실을 알게되면 실제로 일종의 재미입니다. 며칠 전에 많은 사람들이 120에서 55로갔습니다. 그래서 당신이 그것에 새로운 경우에도 가능합니다.
Stewie Griffin

@StewieGriffin 해당 링크에 감사드립니다! 저는 실제로 코드 골프 초보자입니다. 그래서 코드 골프를하는 대신 실제 작업을 완료하는 것에 관한 것입니다. 그러나 다양한 언어의 가능성을 발견하는 놀라운
Cajova_Houba

FTR : 이와 같은 좀 더 복잡한 과제에 대해서는 스스로 마무리하는 것이 좋을 것입니다. =)
Stewie Griffin

2

PHP, 307 297 293 바이트

<?$r=str_pad("",$p=((max($argv)+1)>>1)*$w=4*$argc,str_pad("\n",$w," ",0));for(;++$i<$argc&&$r[$p++]=_;$m=$n)if($n=$argv[$i]){$q=$p+=!$m;eval($x='$r[$q-1]=$r[$q]=$r[$q+1]=_;');for($h=$n>>1;$h--;$q-=$w)$r[$q-2]=$r[$q+2]="|";$n&1?($r[$q-1]="/")&($r[$q-$w]=_)&$r[$q+1]="\\":eval($x);$p+=3;}echo$r;

명령 행에서 인수 * 2를 가져옵니다. 파일로 저장하고로 실행하십시오 php <filename> <parameters>.

고장

// initialize result    
$r=str_pad("",              // nested str_pad is 3 bytes shorter than a loop
    $p=                     // cursor=(max height-1)*(max width)=(start of last line)
    ((max($argv)+1)>>1)     // max height-1
    *
    $w=4*$argc              // we need at least 4*($argc-1)-1, +1 for newline
    ,
    // one line
    str_pad("\n",$w," ",0)  // (`str_pad("",$w-1)."\n"` is one byte shorter,
);                          // but requires `$w+1`)

// draw skyline
for(;
    ++$i<$argc              // loop through arguments
    &&$r[$p++]=_                // 0. draw empty ground and go one forward
    ;
    $m=$n                       // 7. remember value
)
    if($n=$argv[$i])            // if there is a house
    {
        $q=                         // 2. copy $p to $q
        $p+=!$m;                    // 1. go one forward if there was no house before this
        // offset all further positions by -2 (overwrite empty ground, share walls)
        eval($x=                    // 3. draw floor
        '$r[$q-1]=$r[$q]=$r[$q+1]=_;'
        );
        for($h=$n>>1;$h--;$q-=$w)   // 4. draw walls
            $r[$q-2]=$r[$q+2]="|";
        $n&1                        // 5. draw roof
            ?($r[$q-1]="/")&($r[$q-$w]=_)&$r[$q+1]="\\"
            :eval($x)               // (eval saved 7 bytes)
        ;                           // (ternary saved 6 bytes over `if`)
        $p+=3;                      // 6. go three forward (5-2)
    }

// output
echo$r;

1

C ++, 언 골프

(또는 어쩌면 돌이킬 수없는)

요소가 100 개 미만이고 각 요소가 100보다 작다고 가정하면 s건물 수 (입력에 필요)입니다.

#include <iostream>
using namespace std;
int main()
{
float a[100];
int i,j,s;
cin>>s;
for(i=0;i<s;++i)
 cin>>a[i];
for(i=100;i>=1;--i)
{
for(j=0;j<s;++j)
{
if((a[j]>=i)||(a[j-1]>=i))
 cout<<"|";
else
 cout<<" ";
if(i==1)
 cout<<"___";
else if(a[j]+1==i)
 cout<<"___";
else if(a[j]+1.5==i)
 cout<<" _ ";
else if(a[j]+0.5==i)
 cout<<"/ \\";
else cout<<"   ";
}
if(a[s-1]>=i)
 cout<<"|";
cout<<endl;
}
}

출력에 약간의 오류가 있습니다 ...지면의 폭은 3 자 (1 자 여야 함)이며 마지막 벽이 없습니다.
Stewie Griffin

@StewieGriffin 나는 이것을 게시 할 때 여전히 오류를 분류하고있었습니다. 1. 마지막 벽을 추가했습니다. 2. 경사 지붕 / _ \의 너비가 3 자이므로지면의 너비는 3 자 여야합니다.
ghosts_in_the_code

1
* 내부가 아닌 건물 사이 의 접지 .
Stewie Griffin

여전히 작업 중이라면 기다릴 수도 있지만 줄 바꿈과 들여 쓰기를 제거하면 많은 바이트를 제거 할 수 있습니다 . 나는 땅의 문제를 해결하지 않은,하지만 이 작품 0.346 바이트 대신 401
스튜이 그리핀

@StewieGriffin 어쨌든 너무 길어서 실제로 골프 답변을 제출하려고하지 않습니다. 100 바이트 미만으로 더 나은 언어가 존재할 수 있습니다. 그래서 내 코드는 다른 사람들에게 더 많은 참조 솔루션입니다.
ghosts_in_the_code
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.