Narysuj mój wykres słupkowy

24

Zostałeś wybrany do stworzenia programu, który tworzy ładne wykresy słupkowe ASCII . Oto format wejściowy:

[List of words (they can have spaces)] [an integer >= 0]
Bar 3
This is so cool 4
IDK-Why 6

Dane wejściowe będą miały wiele wierszy w tym formacie, z których każdy reprezentuje jeden pasek na wykresie. Format wyjściowy wykresu będzie taki:

 _ _ _ _
|_|_|_|_|
 | | | |
 | | | + [name of 4th bar]
 | | + [name of 3rd bar]
 | + [name of 2nd bar]
 + [name of 1st bar]

Oto kilka przykładów:

In:
Cool 4
Kool 6

Out:
   _
  | |
 _| |
| | |
| | |
| | |
|_|_|
 | |
 | + Kool
 + Cool

In:
Graph 5
Bar 3

Out:
 _
| |
| |_
| | | 
| | |
|_|_|
 | |
 | + Bar
 + Graph

In:
Very 4
Large 5
Bar 3
Graph 5

Out:
   _   _
 _| | | | 
| | |_| |
| | | | |
| | | | |
|_|_|_|_|
 | | | |
 | | | + Graph
 | | + Bar
 | + Large
 + Very

In:
Bars can be 0 0
Large-bars_are$nice2 6
average)(@#$ 3
neato 5

Out:
   _
  | |  _
  | | | | 
  | |_| |
  | | | |
  | | | |
 _|_|_|_|
 | | | |
 | | | + neato
 | | + average)(@#$
 | + Large-bars_are$nice2
 + Bars can be 0

Funkcje lub pełne programy są dozwolone.

J Atkin
źródło
1
Czy liczba całkowita jest pojedynczą cyfrą, czy może być> 9?
edc65
> 9 jest dozwolone, po prostu nie podałem tego jako przykładu, ponieważ byłby tak duży.
J Atkin
Czy w każdej linii mogą znajdować się spacje końcowe? Czy to znaczy, że wyjście jest prostokątne?
Stewie Griffin
Tak, dozwolone są spacje końcowe
J Atkin
1
Spójrz na historię, @Doorknob usunął ją, nie jestem pewien, dlaczego ...
J Atkin

Odpowiedzi:

15

sh + awk + tac, 173

Głównie awkskrypt, który drukuje wykres od dołu do góry, a następnie jest odwracany tac.

awk '{n[NR]=$NF;$NF="";$0=p" + "$0;p=" |"p}1;END{for(print p;p~/\|/;print p (k>($0=0)?"|":""))for(i=k=p="";i<NR;p=p (j>0||k>0?"|":" ")(!k||$0?"_":" ")){j=k;k=n[++i]--}}'|tac

Opis

awk, pierwsza część, wykonywana dla każdej linii wejściowej

{
  n[NR]=$NF;         # store the value, here n[1]=0, n[2]=6, n[3]=3, n[4]=5
  $NF="";            # remove the value from the label
  $0=p" + "$0;       # add a prefix (initially empty) and a " + " in the front
  p=" |"p            # grow the prefix for the next string
}1;                  # implicitly print $0

Wydajność

 + Bars can be 0 
 | + Large-bars_are$nice2 
 | | + average)(@#$ 
 | | | + neato 

awk, druga część, wykonana raz na końcu

END{
  for(print p;p~/\|/;print p (k>($0=0)?"|":""))
    for(i=k=p="";i<NR;p=p (j>0||k>0?"|":" ")(!k||$0?"_":" "))
      {j=k;k=n[++i]--}}

bez golfa:

END{
  print p;           # print the prefix again
  for(;p~/\|/;)      # for each line, bottom up. no more "|" -> we're done
  {
    p="";            # string to be built
    i=k=0;           # i: bar index, k: heigth of the previous bar
    for(;i<NR;)      # for each bar, left to right
    {
      j=k;           # store the previous bars heigth in j
      k=n[++i]--;    # get the current bars remaining height and decrement it
      p=p (j>0||k>0?"|":" ")(!k||$0?"_":" ");
                     # if the bar to the left or this one have some height
                       remaining, draw a border in between them, else a space
                     # if this bars remaining heigth is exactly 0, draw a top
                     # if $0 is set, draw the bottom
    }
    print p (k>0?"|":"");
                     # draw (or not) the rightmost border, finally print
    $0=0;            # unset $0, only to detect first run
  }
}

Wydajność

 | | | |             # the prefix
 _|_|_|_|            # the strings built by the nested loops
  | | | |            |
  | | | |            v
  | |_| |
  | | | |
  | |  _
   _                 # no more "|" in the string, we're done

tac odwraca linie

   _    
  | |  _
  | | | |
  | |_| |
  | | | |
  | | | |
 _|_|_|_|
 | | | |
 | | | + neato 
 | | + average)(@#$ 
 | + Large-bars_are$nice2 
 + Bars can be 0 
Rainer P.
źródło
8

JavaScript (ES6), 270 262 270 287

Naprawiono błąd, dodając brakujący wiersz „|” pod kratami

l=>{t=p=o='';l=l.split`
`.map(r=>([,b,c]=r.match(/(.*) (\d+)/),[' + '+b,+c>t?t=c:c]));for(++t;t--;o+=`
`)l.map(x=>o+=x[1]<t?'y y':x[1]>t?t?'x x':'x_x':'y_y');return o.replace(/(yx)|(xy)|(xx?)/g,'|').replace(/y+/g,' ')+[...l,' '].map(x=>p+x[p+=' |',0]).reverse().join`
`}

Testuj Test w przeglądarce Firefox, ponieważ Chrome nie obsługuje przypisania Destrukturyzacji ES6

F=l=>{
  t=p=o='';l=l.split`\n`.map(r=>([,b,c]=r.match(/(.*) (\d+)/),[' + '+b,+c>t?t=c:c]));
  for(++t;t--;o+=`\n`)l.map(x=>o+=x[1]<t?'y y':x[1]>t?t?'x x':'x_x':'y_y');
  return o.replace(/(yx)|(xy)|(xx?)/g,'|').replace(/y+/g,' ')
  +[...l,' '].map(x=>p+x[p+=' |',0]).reverse().join`\n`
}

function test()
{
  var i=I.value
  O.textContent=F(i)
}  
  
test()
textarea { display:block; width:50%; height:5em}
Input
<textarea id=I>Bars can be 0 0
Large-bars_are$nice2 6
average)(@#$ 3
neato 5</textarea>
<button onclick='test()'>go</button><br>
Output
<pre id=O></pre>

edc65
źródło
W mojej odpowiedzi Jolfa, nad którą pracuję, użyłem i.match(/.+ |./g). Może to się przyda?
Conor O'Brien
„Uncaught ReferenceError: Nieprawidłowa lewa strona w przypisaniu”, a następnie kilka „Uncaught ReferenceError: test nie jest zdefiniowany”, ponieważ pierwszy błąd uniemożliwił deklarację testu ()
x13
@ThisNameBetterBeAvailable Używając jakiej przeglądarki? ES6 nie jest w pełni obsługiwany w Chrome i całkowicie nieobsługiwany w większości wersji MSIE
edc65
@TenNameBetterBeDostępny w tym przypadku problem nie obsługuje Chrome destructuring assignment: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… . Wypróbuj lepszą przeglądarkę, np. Firefox
edc65
2

421 bajtów - Python 2

import sys
l=sys.stdin.read().split('\n')
b=[(' '.join(x[:-1]),int(x[-1])) for x in map(str.split,l[:-1])]
a=len(b)
e=enumerate
m=[' '*(a+1)+'|'*x[1] for i,x in e(b)]+[' '*(len(b)+1)+'|'*b[-1][1]]
h=[' '*i+'+'+'|'*(a-i)+'_'+' '*(x[1]-1)+'_' for i,x in e(b)]
c=m+h
c[::2]=m
c[1::2]=h
c=[''.join(' ' if not x else x for x in l) for l in map(None,*c)]
for i,(n,_) in e(b):
 c[a-i-1]+='\b'*i*2+n
c='\n'.join(c[::-1])
print(c)

Testy

a 1
b 2
c 3
     _
   _| |
 _| | |
|_|_|_|
 | | |
 | | + c
 | + b
 + a
Tuomas Laakkonen
źródło
Dla mnie nie daje właściwej mocy wyjściowej dla zerowych wysokości (np. a 0 b 3) I schodzących słupków (np a 5 b 3 c 0.). Moja wersja Python to Python 2.7.10.
nimi
1

Java, 613 dla funkcji drukowania

Możliwe jest zaoszczędzenie kilku bajtów dzięki „zwykłym” przekształceniom for(i=0;i<n;i++)na for(;i++<n;), upraszczając trójkowe warunki warunkowe lub bardziej eleganckie obliczenia „etykiet” i „wysokości”, ale to dopiero początek.

package stackoverflow.codegolf.barchart;

import static java.util.stream.Stream.of;

import java.util.stream.IntStream;


public class BarChartTest
{
    public static void main(String[] args)
    {
        String input0[] = {
            "Cool 4",
            "Kool 6",
        };
        String input1[] = {
            "Graph 5",
            "Bar 3",
        };
        String input2[] = {
            "Very 4",
            "Large 5",
            "Bar 3",
            "Graph 5",
        };
        String input3[] = {
            "Bars can be 0 0",
            "Large-bars_are$nice2 6",
            "average)(@#$ 3",
            "neato 5",
        };
        runTest(input0);
        runTest(input1);
        runTest(input2);
        runTest(input3);
    }

    private static void runTest(String input[])
    {
        System.out.println("In:");
        for (String string : input)
        {
            System.out.println(string);
        }
        System.out.println("Out:");
        BarChartTest b = new BarChartTest();
        b.print(input);
    }

    void p(String a[]){int h[]=of(a).map(this::s).mapToInt(Integer::parseInt).toArray(),M=IntStream.of(h).max().getAsInt(),C=a.length,r,c,y;Object t[]=of(a).map(this::p).toArray();String s="",p=" + ",w="";char n=10,v='|',i=32,u=95,e;for(r=0;r<=M;r++){e=r==M?'_':' ';y=M-r;for(c=0; c<C; c++){s+=h[c]>y?v:c>0?h[c-1]>y?v:e:r==0?e:i;s+=h[c]==y?u:e;}s+=h[C-1]>y?v:e;s+=n;}for(r=0;r<C;r++){for(c=0;c<C-r;c++){s+=" |";}s+=r>0?p+t[C-r]:w;s+=n;}s+=p+t[0];System.out.println(s);}int b(String s){return s.lastIndexOf(" ");}String p(String s){return s.substring(0,b(s));}String s(String s){return s.substring(b(s)+1,s.length());}
}
Marco13
źródło
1

Haskell, 323 bajty

f x|(p,q)<-unzip$map((\l->(unwords$init l,(read$last l))).words)$lines x=unlines(reverse$init.(zip((zipWith max=<<tail)$0:q++[0])(q++[0])>>=).(!)<$>[0..maximum q])++v p++'\n':(0#p)
v=(>>" |")
_#[]=""
l#(h:t)=(l+1)#t++v[1..l]++" + "++h++"\n"
0!(0,_)=" _"
0!_="|_"
i!(j,k)|i<j=(i==k)?'|'|1<2=(i==k)?' '
i?c|i=c:"_"|1<2=c:" "

Przykład użycia:

*Main> putStr $ f "Bars can be 0 0\nLarge-bars_are$nice2 6\naverage)(@#$ 3\nneato 5"
   _     
  | |  _ 
  | | | |
  | |_| |
  | | | |
  | | | |
 _|_|_|_|
 | | | |
 | | | + neato
 | | + average)(@#$
 | + Large-bars_are$nice2
 + Bars can be 0

Jak to działa (ogólny przegląd, szczegóły może później):

(p,q)<-unzip$map((\l->(unwords$init l,(read$last l))).words)$lines x
           -- breaks the input into a list of labels (-> p), e.g.
           -- ["Bars can be 0","Lagerge-basr_asr$niche",...] and a list of heights
           -- (-> q), e.g. [0,6,3,5]

unlines(reverse$init.(zip((zipWith max=<<tail)$0:q++[0])(q++[0])>>=).(!)<$>[0..maximum q])
           -- builds the bars
v p++"\n"
           -- builds the first row of "|" underneath the zero line
(0#p)
           -- build the label section

Część parsująca ( (p,q)<-unlines...) zajmuje dużo bajtów, być może mogę zagrać w golfa dalej.

nimi
źródło
1

Python 2, 345 bajtów

B,H=zip(*[(a,int(b))for a,b in[x.rsplit(' ',1)for x in input().split('\n')]])
h=max(H)
L=len(B)
b=['|'*H[0]]*(L*2+1)
for i in range(L):b[2+i*2]='|'*max(H[i],H[min(i+1,L-1)]);b[1+i*2]=('_'+' '*(H[i]-1)+'_')[:H[i]+1]
b=[x.ljust(h+1)for x in b]
for l in zip(*b)[::-1]:print ''.join(l)
print' |'*L
for i in range(-1,-L-1,-1):print' |'*(L+i),'+',B[i]
TFeld
źródło