Exibir um registro (em várias bases)

16

Tallying é um sistema simples de contagem que funciona na base 5. Existem vários sistemas diferentes de cálculo usados ​​em todo o mundo, mas o que é usado na maioria dos países de língua inglesa é talvez o mais simples - contar unidades marcando linhas verticais e, em seguida, para cada quinta marca coloca uma linha horizontal na coleção anterior de quatro. Isso agrupa as marcas de contagem em grupos de 5 (e facilita a contagem rápida).

Você vai escrever um programa que exibe marcas de registro até um determinado valor. Mas calcular apenas na base 5 é chato! Portanto, seu programa também deve poder exibir registros em diferentes bases.

Entrada

A entrada será um ou dois valores inteiros não negativos separados por vírgula (por exemplo, 9ou 8,4). O primeiro número é o valor que deve ser exibido pelo registro. O segundo valor é a base da contagem. Se o segundo valor não for fornecido, use a base 5 .

Resultado

A saída será o valor inserido representado como marcas de registro de arte ASCII. Aqui estão alguns exemplos contra os quais você pode testar seu programa - sua saída deve corresponder exatamente a eles!

Entrada: 12ou12,5

 | | | |   | | | |   | |
-+-+-+-+- -+-+-+-+-  | |
 | | | |   | | | |   | |

Entrada: 7,3

 | |   | |   |
-+-+- -+-+-  |
 | |   | |   |

Entrada: 4,2

 |   |
-+- -+-
 |   |

Entrada: 6,1ou 6,10(observe os espaços iniciais)

 | | | | | |
 | | | | | |
 | | | | | |

Observe também que a base 1 deve ser inconsistente - somente linhas verticais devem ser usadas.

Se um dos valores inseridos for 0, não haverá saída alguma (e seu programa deve terminar normalmente).

Regras

  • Isso é , portanto a implementação correta mais curta (em bytes) vence.
  • A entrada / saída pode estar em qualquer meio adequado (por exemplo, stdin / stdout, arquivo ...).
  • A entrada pode ser na forma de vários argumentos de linha de comando ou separados por espaços, etc., se for mais adequado para o idioma de destino.
  • Novas linhas à direita são permitidas na saída. Os espaços à direita não são. Esta regra se aplica somente quando há uma saída (ou seja, não quando o valor inserido é 0).
  • Seu código deve ter como padrão a base 5 quando nenhuma base for inserida.
Sean Latham
fonte
3
A saída de não deveria 6,1parecer mais -+- -+- -+- -+- -+- -+-?
Peter Taylor
3
Se você declarar "A entrada será um ou dois valores inteiros positivos separados por vírgula (por exemplo, 9 ou 8,4)." então, devemos considerar isso como um dado e não ter que nos preocupar com "Seu programa deve ser robusto - você deve validar a entrada ..." além de manipular um ou dois números.
AndoDaan
11
@PeterTaylor -+-representaria dois, porque há uma linha vertical e uma pontuação horizontal através dela. A base 1 teria apenas linhas verticais. @AndoDaan ammended.
Sean Latham
Ok --- --- --- --- --- ---então. Para obter consistência com as outras bases, você deve fazer um ataque horizontal através de b-1linhas verticais. Se pretende ser inconsistente, você deve declarar isso explicitamente.
Peter Taylor
Eu já fiz isso. Desculpe, eu pensei que estava implícito.
Sean Latham

Respostas:

4

CJam 103 85 72 caracteres

Experimente em http://cjam.aditsu.net/ .

original

q","/(i:A\_,{~i}{;5}?:B_@*{(_{" |"*S"l"++AB/*AB%}{;MA}?\:J" |l""-+ "er\" |"*N+_J\+@2$+@J\+++"l"Ser}{;}?

Trabalha definindo um conjunto de tallys com espaços, linhas e l para espaços que devem permanecer espaços. Em seguida, aproveita a função er (tranliteração) para criar a segunda linha. A parte mais ineficiente é lidar com os 1 e 0 casos especiais. Editará à medida que eu a melhorar. Dica: Demorei muito para perceber: como a segunda entrada sendo 1 é igual ao infinito ou a primeira entrada +1, redefini-la quando for igual a 1 economiza muito trabalho.

melhorado até agora com delimitação por vírgula

l",":G/(i:A\_5a?~i:B_@*{(_" |":K*\{SG++AB/*AB%}{A}?\_KG+"-+ "er[\GSer_@@M]\K*N+*}{;}?

melhorado até agora com entrada delimitada por espaço

Naturalmente, o CJam foi realmente projetado para entrada delimitada por espaço. Colocar a entrada em 20 3 em vez de 20,3 é um grande benefício.

ri:Aq_5s?S-i(_)A)?:B*{B(" |":K*STs++ABmd@@*_K"-+"er[\_@@M]\K*N+*TsSer}M?
Kaine
fonte
5

Python 2 - 111 108 119 144 140 136 135 134 - Experimente

Ok, vamos tentar:

i=input()
n,b=[(i,5),i][i>[]]
o=b-1
a=[n,n%b][b>1]*' |'
m=(b>1)*n/b
s=(' |'*o+'  ')*m+a
print(s+'\n'+('-+'*o+'- ')*m+a+'\n'+s)*(b*n>0)

Edit: Eu esqueci que não deve haver saída se n==0ou b==0. Isso me custa 11 caracteres. :(

Edit: Ok, depois de corrigir o segundo problema mencionado nos comentários, minha solução basicamente convergiu para a do BeetDemGuise.

Falko
fonte
Isso imprime novas linhas quando uma das entradas (ou ambas) é zero, o que de acordo com o desafio é indesejável. Além disso, e se apenas um número for inserido no programa?
BeetDemGuise
11
Isso falha quando o segundo valor é omitido ( bnesse caso, deve ser 5). Vou deixar mais claro na pergunta. Edit: oh, não importa, você corrigiu isso assim como eu fiz esse comentário!
Sean Latham
Qual Python é esse?
Beta Decay
É o Python 2.7.8. - Ah, houve um pequeno erro no final ...
Falko
11
Se for o Python 2.x, você não poderá salvar mais um caractere usando em n/bvez de n//b?
Emil
5

Bater, 239 228 199 189 188

Aqui está a minha tentativa, poderia ser muito jogado.

Nota: a segunda linha não subtrai 5 de 2, define um valor padrão se $2estiver vazio!

n=$1
b=${2-5}
((n<1&b<1))&&exit
while ((n>b&b>1));do
n=$[n-b]
x+=\
y+=-
for i in `seq $[b-1]`;{
x+='| '
y+=+-
}
x+=\
y+=\
done
for j in `seq $n`;{
x+=' |'
y+=' |'
}
echo -e "$x\n$y\n$x"

fonte
Funciona em {1..$n}vez de `seq $n`?
FUZxxl
@FUZxxl infelizmente não, h=8;echo {1..$h}outputs{1..8}
Isso não é bom.
FUZxxl
3

Python - 171 143

i=input();t,b=i if[0]<i else(i,5);b=[b,t+1][b==1];l,d,m,o=' |',t/b,t%b,b-1;r=(l*o+'  ')*d+l*m
if t*b>0:print r,'\n',('-+'*o+'- ')*d+l*m,'\n',r

O programa é bem direto:

  • Obtenha a entrada e tente descompactar t,b. Se isso falhar, simplesmente atribua os valores corretos.
  • Se a base era 1, altere seu valor para algo que possa manipular todas as linhas verticais facilmente ( t+1).
  • Defina algumas variáveis ​​e crie as seções inferior e superior das notas.
  • Imprima os registros se ambos te bforem diferentes de zero.

EDIT 1: Use a inputfunção em vez de raw_inputdepois de algumas brincadeiras.

EDIT 2: Obrigado a Falko por apontar um pequeno bug com minha verificação diferente de zero. Agora nosso código é basicamente idêntico, menos alguns nomes de variáveis ​​e alguma lógica pequena.

EDIT 3: Graças a como o Python compara seqüências e tipos diferentes , podemos comparar icom a listpara obter uma versão mais curta do nosso try...exceptbloco.

Aqui está a versão não destruída:

i=input()

# If True, `i` must be a list
if [0]<i:
    t,b=i
# Otherwise, we know its a number (since `list` comes after `int` lexicographically.)
else:
    b=5
    t=i

b = b if b==1 else t+1
l=' |'
d=t/b
m=t%b
o=b-1

r=(l*o+'  ')*d+l*m
if t and b:
    print r,'\n',('-+'*o+'- ')*d+l*m,'\n',r
BeetDemGuise
fonte
Eu acho que t&bé Falsepor 10,5. Caso contrário, nossas soluções estão convergindo! ;)
Falko
@ Falko Você está certo em ambos os aspectos! Você sabe o que eles dizem sobre grandes mentes.
BeetDemGuise
Seria ótimo se pudéssemos encontrar uma maneira curta de testar se ié escalar ou uma lista. Então poderíamos largar o try ... exceptmonstro.
Falko
@ Falko Acho que encontrei uma verificação de 1 byte melhor. A listé sempre maior que um int. Além disso, lists são comparados em ordem lexicográfica. Portanto, se compararmos, [0]<iisso sempre retornará Falsese ifor um número e Truese ifor uma lista (com um primeiro elemento diferente de zero).
BeetDemGuise
11
Ótimo! Encurtei ainda mais sua abordagem. Bom trabalho em equipe! :)
Falko
3

Java, 343

class C{public static void main(String[]a){long n=new Long(a[0])+1,b=a.length>1?new Long(a[1]):5;if(b>0){if(b<2)b=(int)2e9;int i;for(i=1;i<n;i++)p(i%b>0?" |":"  ");p("\n");for(i=1;i<n-n%b;i++)p(i%b>0?"-+":"- ");if(n>b)p("- ");for(i=1;i<n%b;i++)p(" |");p("\n");for(i=1;i<n;i++)p(i%b>0?" |":"  ");}}static void p(String s){System.out.print(s);}}

Menos golfe:

class C {
  public static void main(String[] a) {
    long n=new Long(a[0])+1, b=a.length>1 ? new Long(a[1]) : 5;
    if(b>0) {
      if(b<2) b=(int)2e9; // if the base is 1, pretend the base is 2 billion
      int i;
      for(i=1;i<n;i++) p(i%b>0 ? " |" : "  ");
      p("\n");
      for(i=1;i<n-n%b;i++) p(i%b>0 ? "-+" : "- ");
      if(n>b) p("- ");
      for(i=1;i<n%b;i++) p(" |");
      p("\n");
      for(i=1;i<n;i++) p(i%b>0 ? " |" : "  ");
    }
  }
  static void p(String s) {
    System.out.print(s);
  }
}
Ypnypn
fonte
Você pode economizar alguns fazendo ium, longpara não precisar declará-lo separadamente. Um pouco mais, fazendo i++%b>0seus loops em vez de incrementá-lo separadamente (e i++<n%bno terceiro loop). Outro usando b=b<2?(int)2e9:b.
Geobits
3

Perl - 167 165 156

my($n,$b)=($ARGV[0]=~/(\d+)(?:,(\d+))?/,5);print$b>1?map{join(" ",($_ x($b-1))x int($1/$b)," | "x($1%$b))."\n"}(" | ","-+-"," | "):join" ",("---")x$1if$1*$b

destroçado

my($n,$b) = ($ARGV[0] =~ /(\d+)(?:,(\d+))?/, 5);
print($b>1 ?
    map{ 
        join(" ",($_ x ($b-1)) x int($1/$b)," | " x ($1%$b))."\n"
    } (" | ","-+-"," | ") :
    join " ", ("---") x $1
) if $1 * $b
Fozi
fonte
exibe linhas horizontais em vez dos verticais para a base 1 :(
perl chinês gótico
@chineseperlgoth sim, esse é um dos requisitos. Por favor, leia os comentários sobre Q.
Fozi
3

C - 193

Eu sinto muito. Lidar com o caso especial de 1 foi um truque ruim, então acho que isso poderia ser melhorado com uma abordagem melhor. Além disso, este código inclui uma nova linha no início da saída; portanto, se isso não for permitido, entre em contato.

Claro, define muito feio sempre ajuda :)

A contagem de caracteres inclui apenas os espaços necessários e novas linhas.

#define P printf(
#define L P" |")
#define A P"\n");for(i=0;i<a;)b==1?i++,L:i++&&i%b==0?P
i;
main(a,b)
{
    scanf("%d,%d",&a,&b)<2?b=5:!b?a=0:a;
    if(a){
    A"  "):L;
    A"- "):a%b&&i>a/b*b?L:P"-+");
    A"  "):L;}
}
Allbeert
fonte
Seu código parece imprimir novas linhas quando um dos valores é zero. Isso é explicitamente proibido. Sua solução não está em conformidade.
FUZxxl
@FUZxxl Você está certo, eu perdi isso! Essa má solução rápida terá que ser feita por enquanto. Espero ter tempo em breve para encontrar uma maneira melhor.
Allbeert
Tenho certeza de que você pode salvar alguns caracteres substituindo printfpor putse substituindo returnpor um operador ternário.
millinon
@millinon O problema putsé que ela adiciona uma nova linha sempre :(. E para o operador ternário, não é possível adicionar returns ou fors dentro deles! Seu comentário me deu a idéia de salvar mais alguns caracteres facilmente, removendo o returnque Obrigado.!
Allbeert
2

C # 271bytes

Não é o mais curto, não consegui jogar a leitura de entrada devido à necessidade de aceitar 0 como entrada.

using C=System.Console;class P{static void Main(){var L=C.ReadLine().Split(',');int t=int.Parse(L[0]),f=L.Length>1?int.Parse(L[1]):5,r=3,i;for(var R="";t*f>0&r-->0;C.WriteLine(R.TrimEnd()))for(R="",i=0;i<t;R+=r==1&i++<t-t%f?(i%f<1?"- ":"-|"):i%f<1?"  ":" |")f+=f<2?t:0;}}

Código formatado:

using C=System.Console;

class P
{
    static void Main()
    {
        var L=C.ReadLine().Split(',');
        int t=int.Parse(L[0]),f=L.Length>1?int.Parse(L[1]):5,r=3,i;

        for(var R="";t*f>0&r-->0;C.WriteLine(R.TrimEnd()))
            for(R="",i=0;i<t;R+=r==1&i++<t-t%f?(i%f<1?"- ":"-|"):i%f<1?"  ":" |")
                f+=f<2?t:0;
    }
}
VisualMelon
fonte
1

Lua - 219 203 bytes

Fui para fazer d cópias de b cópias de "|" e adicionar r cópias de "|" no fim. Eu sinto que talvez eu devesse ter subido a contagem dos "|" para a corda, uma de cada vez.

l=' |'s=string.rep _,_,a,b=io.read():find'(%d+)%D*(%d*)'b=tonumber(b)or 5 d=(a-a%b)/b f=b>1 and s(s(l,b-1)..'  ',d)g=b>1 and s(s('-+',b-1)..'- ',d)r=b>1 and a%b or a e=s(l,r)..'\n'print(f..e..g..e..f..e)

ungolfed:

l=' |'          --the base string
s=string.rep    --string.rep will be used a lot, so best shorten it

_,_,a,b=io.read():find'(%d+)%D*(%d*)' --reads a,b I'm probably way of the mark with this one

b=tonumber(b)or 5

d=(a-a%b)/b -- shorter than math.floor(a/b), d equal the vertical mark

f=b>1 and s(s(l,b-1)..'  ',d) or '' --creates d multiples of b multiples of "|" more or less
g=b>1 and s(s('-+',b-1)..'- ',d)or''--same as above but with the middle "-+-"

r=b>1 and a%b or a --idk maybe i should set r before d(a- a%b )/b

e=s(l,r)..'\n'  -- makes the remainder string, notice that if b==1  then e will output all the "|" 

print(f..e..g..e..f..e) -- here's where the real magic happens!

Amostra:

c:\Programming\AnarchyGolfMine>lua test.lua
13,5
 | | | |   | | | |   | | |
-+-+-+-+- -+-+-+-+-  | | |
 | | | |   | | | |   | | |


c:\Programming\AnarchyGolfMine>lua test.lua
6,2
 |   |   |
-+- -+- -+-
 |   |   |


c:\Programming\AnarchyGolfMine>lua test.lua
18,1
 | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | |
AndoDaan
fonte
11
Você poderia postar uma versão ligeiramente mais legível e não-destruída? Golfe em Lua parece interessante!
@Alessandro done. E obrigado, fez encontrar algumas coisas que eu perdi.
precisa saber é o seguinte
1

JavaScript (193)

Isso pode ser excessivamente complexo.

s=prompt().split(",");a=+s[0];b=s[1];b=b?+b:5;o=b>1;v=" | ";q=w="";for(g=~~(a/b),c=o?a-g:a;g+1;g--,q+=" ",w+=" ")for(i=o;c&&i<b;i++)c--,q+=v,w+=g&&o?"-+-":v;if(a&&b)console.log(q+'\n'+w+'\n'+q)

Versão comentada

s=prompt().split(",");
a=+s[0];
b=s[1];
b=b?+b:5;   // convert b to int and default to 5
o=b>1;      // special handling for b0 and b1
v=" | ";
q=w="";
// calculate number of lines and number of groups
for(g=~~(a/b),c=o?a-g:a;g+1;g--,q+=" ",w+=" ")
    for(i=o;c&&i<b;i++)
        c--,  // decrease line count
        q+=v,
        w+=g&&o?"-+-":v; // use " | " for last group and "-+-" for others
if(a&&b) // handle b0
    console.log(q+'\n'+w+'\n'+q)
Mika Lammi
fonte
1

Python - 127 123 122

Apenas entrando com uma versão python um pouco mais curta.

edit: Corrigido 0 não imprimindo nada e rejeitador, terminou com o mesmo comprimento

k=input()
k=i,j=((k,5),k)[k>[]]
for m in[' |','-+',' |']*all(k):
 print(m*(j-1)+m[0]+' ')*(i/j*(j>1))+' |'*(i%(j+(j<2)*i))
Bizangles
fonte
0

C (207 caracteres)

A nova linha logo antes exité apenas para legibilidade.

#define P printf(
#define t(v)for(a=c;b<=a;a-=b)a-c&&P" "),P v+1),q(b,v);q(a," |");P"\n");
q(n,c){while(n--)P c);}a;b;c;main(){scanf("%d,%d",&c,&b)<2?b=5:0;b&&c||
exit();b==1?b=32767:0;t("| ")t("+-")t("| ")}

scanfuso descaradamente roubado da Allbeert. Observe que esta solução não é compilada com o gcc, pois tenta impor um protótipo inexistente para exit. Compile com um compilador C funcional, comotcc . Além disso, essa função pode ou não funcionar em plataformas de 64 bits. Use com cuidado.

Aqui está a implementação original não-baseada em que isso se baseia:

#include <stdio.h>
#include <stdlib.h>

static void
tally_line(int base, int count, const char *str)
{
     int follower = 0, i;

     /* full tallies first */
     for (; count >= base; count -= base) {
          if (follower++)
               putchar(' ');

          /* only print second character */
          printf(str + 1);

          for (i = 0; i < base; i++)
               printf(str);
     }

     /* partial tally */
     for (i = 0; i < count; i++)
          printf(" |");

     /* newline */
     puts("");
}

extern int
main(int argc, char **argv)
{
     int base, count;

     /* do away with program name */
     count = atoi(*++argv);

     base = argc - 3 ? 5 : atoi(*++argv);

     /* remove 0 later */
     base | count || exit(0);

     /* a crossed-out tally never appears for large numbers */
     if (base == 1)
          base = 32767;

     tally_line(base, count, "| ");
     tally_line(base, count, "+-");
     tally_line(base, count, "| ");

     return (EXIT_SUCCESS);
}
FUZxxl
fonte
0

Python 2 , 134 126 123 114 bytes

lambda i,j=5,a=" |":"\n".join(("",(a*~-j+"  ","-+"*~-j+"- ")[x%2]*(i/j))[j>1]+a*(i,i%j)[j>1]for x in(0,1,2)if i*j)

Experimente online!

Velha pergunta que eu conheço, mas divertido de qualquer maneira. Chance de experimentar alguns truques que aprendi desde que entrei.

ElPedro
fonte