Mostra un conteggio (in basi diverse)


16

Il conteggio è un semplice sistema di conteggio che funziona nella base 5. Esistono diversi sistemi di conteggio utilizzati in tutto il mondo, ma quello utilizzato nella maggior parte dei paesi di lingua inglese è forse il più semplice: contare le unità contrassegnando le linee verticali, quindi per ogni 5 ° segno inserisce una linea orizzontale attraverso la precedente raccolta di quattro. Questo raggruppa i segni di conteggio in gruppi di 5 (e li rende più facili da contare rapidamente).

Stai per scrivere un programma che visualizza i segni di conteggio fino a un determinato valore. Ma contare solo nella base 5 è noioso! Pertanto, il tuo programma dovrebbe anche essere in grado di visualizzare i conteggi in diverse basi.

Ingresso

L'input sarà uno o due valori interi non negativi separati da una virgola (ad esempio 9o 8,4). Il primo numero è il valore che dovrebbe essere visualizzato dal conteggio. Il secondo valore è la base del conteggio. Se il secondo valore non viene fornito, utilizzare la base 5 .

Produzione

L'output sarà il valore immesso rappresentato come tally art ASCII. Ecco alcuni esempi su cui puoi testare il tuo programma: il tuo output dovrebbe corrispondere esattamente a loro!

Input: 12o12,5

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

Ingresso: 7,3

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

Ingresso: 4,2

 |   |
-+- -+-
 |   |

Input: 6,1o 6,10(notare gli spazi iniziali)

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

Si noti inoltre che la base 1 è considerata incoerente: devono essere utilizzate solo linee verticali.

Se uno dei valori immessi è 0, non dovrebbe esserci alcun output (e il tuo programma dovrebbe terminare con grazia).

Regole

  • Questo è , quindi vince l'implementazione corretta (in byte) più breve.
  • L'input / output può essere su qualsiasi supporto adatto (es. Stdin / stdout, file ...).
  • L'input può essere sotto forma di più argomenti della riga di comando o separato da spazi, ecc. Se è più adatto alla lingua di destinazione.
  • Le nuove righe finali sono consentite nell'output. Gli spazi finali non lo sono. Questa regola si applica solo quando c'è un output (cioè non quando il valore immesso è 0).
  • Il codice deve essere impostato sulla base 5 per impostazione predefinita quando non viene inserita alcuna base.

3
L'output di non dovrebbe 6,1apparire più simile -+- -+- -+- -+- -+- -+-?
Peter Taylor,

3
Se si indica "L'input sarà uno o due valori interi positivi separati da una virgola (ad esempio 9 o 8,4)." allora dovremmo essere in grado di prenderlo come un dato di fatto e non dovremmo preoccuparci di "Il tuo programma dovrebbe essere robusto - dovresti convalidare l'input ..." oltre a gestire uno o due numeri.
AndoDaan,

1
@PeterTaylor -+-rappresenterebbe due, perché c'è una linea verticale e un punteggio orizzontale attraverso di essa. La base 1 avrebbe solo linee verticali. @AndoDaan ammended.
Sean Latham,

Ok --- --- --- --- --- ---allora. Per coerenza con le altre basi, dovresti eseguire uno sciopero orizzontale attraverso b-1linee verticali. Se si intende che sia incoerente, è necessario dichiararlo esplicitamente.
Peter Taylor,

L'ho fatto. Scusa, pensavo fosse implicito.
Sean Latham,

Risposte:


4

CJam 103 85 72 caratteri

Provalo su http://cjam.aditsu.net/ .

originale

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

Funziona definendo un insieme di riscontri con spazi, linee e una l per gli spazi che dovrebbero rimanere spazi. Quindi sfrutta la funzione er (tranliteration) per creare la seconda riga. La parte più inefficiente riguarda i casi speciali 1 e 0. Modificherò quando lo migliorerò. Suggerimento Ho impiegato troppo tempo per rendermene conto: poiché il secondo input è 1 è uguale all'infinito o il primo input +1, la ridefinizione quando è uguale a 1 consente di risparmiare un sacco di lavoro.

più migliorato finora con delimitato da virgole

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

più migliorato finora con input delimitati da spazio

Naturalmente come CJam è davvero progettato per input delimitati da spazio. Posizionare l'input su 20 3 invece di 20,3 è un enorme vantaggio.

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

5

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

Ok, proviamo:

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)

Modifica: ho trascurato che non dovrebbe esserci output se n==0o b==0. Questo mi costa 11 caratteri. :(

Modifica: Ok, dopo aver risolto il secondo problema menzionato nei commenti, la mia soluzione è sostanzialmente convergente a quella di BeetDemGuise.


Questo stampa nuove righe quando uno degli ingressi (o entrambi) sono zero, che secondo la sfida non è desiderato. Inoltre, cosa succede se nel programma viene inserito un solo numero?
BeetDemGuise

1
Ciò fallisce quando viene omesso il secondo valore ( bin questo caso dovrebbe essere 5). Lo renderò più chiaro nella domanda. Modifica: oh, non importa, l'hai corretto proprio come ho fatto questo commento!
Sean Latham,

Quale Python è questo?
Decadimento beta

È Python 2.7.8. - Oh, c'è stato un piccolo errore alla fine ...
Falko,

1
Se è Python 2.x non puoi salvare un altro personaggio usando n/binvece di n//b?
Emil,

5

bash, 239 228 199 189 188

Ecco il mio tentativo, potrebbe essere molto giocato a golf.

Nota: la seconda riga non sottrae 5 da 2, imposta un valore predefinito se $2è vuoto!

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"

Funziona {1..$n}invece di `seq $n`?
FUZxxl,

@FUZxxl purtroppo no, h=8;echo {1..$h}uscite{1..8}

Questo non è buono.
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

Il programma è piuttosto semplice:

  • Ottieni l'input e prova a decomprimerlo t,b. Se fallisce, basta semplicemente assegnare i valori corretti.
  • Se la base era 1, cambia il suo valore in qualcosa che possa gestire facilmente tutte le linee verticali ( t+1).
  • Imposta alcune variabili e crea le sezioni inferiore e superiore dei conteggi.
  • Stampa i conteggi se entrambi te bsono diversi da zero.

EDIT 1: Usa la inputfunzione invece di raw_inputdopo aver giocato un po '.

EDIT 2: Grazie a Falko per aver segnalato un piccolo bug con il mio controllo diverso da zero. Ora il nostro codice è sostanzialmente identico, meno alcuni nomi di variabili e qualche piccola logica.

EDIT 3: Grazie a come Python confronta sequenze e tipi diversi , possiamo confrontarci icon a listper ottenere una versione più breve del nostro try...exceptblocco.

Ecco la versione ungolfed:

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

Penso che t&bsia Falseper 10,5. Altrimenti le nostre soluzioni stanno convergendo! ;)
Falko,

@Falko Hai ragione su entrambi i fronti! Sai cosa dicono delle grandi menti.
BeetDemGuise

Sarebbe davvero fantastico se potessimo trovare un modo breve per verificare se iè scalare o un elenco. Quindi potremmo far cadere il try ... exceptmostro.
Falko,

@Falko Penso di aver trovato un controllo migliore di 1 byte. A listè sempre maggiore di un int. Inoltre, le lists vengono confrontate in ordine lessicografico. Quindi, se confrontiamo, [0]<iquesto restituirà sempre Falseif iè un numero e Trueif iè un elenco (con un primo elemento diverso da zero).
BeetDemGuise

1
Grande! Ho ulteriormente abbreviato il tuo approccio. Bel lavoro di squadra! :)
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);}}

Meno golf:

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);
  }
}

Puoi salvarne un po 'facendo iun longcosì da non doverlo dichiarare separatamente. Qualche altro facendo i++%b>0nei tuoi loop invece di incrementarlo separatamente (e i++<n%bnel terzo loop). Un altro 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

ungolfed

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

visualizza le linee orizzontali anziché quelle verticali per la base 1 :(
cinese perl goth

@chineseperlgoth sì, questo è uno dei requisiti. Si prega di leggere i commenti su Q.
Fozi

3

C - 193

Sono così dispiaciuto. Trattare il caso speciale per 1 è stato un po 'un brutto trucco, quindi immagino che questo possa essere giocato di più con un approccio migliore. Inoltre, questo codice include una nuova riga all'inizio dell'output, quindi se ciò non è consentito, per favore fatemelo sapere.

Certo, l'aspetto molto brutto definisce sempre aiuto :)

Il conteggio dei caratteri include solo gli spazi necessari e le nuove linee.

#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;}
}

Il tuo codice sembra stampare newline quando uno dei valori è zero. Questo è esplicitamente vietato. La tua soluzione non è conforme.
FUZxxl,

@FUZxxl Hai ragione, mi sono perso! Questa cattiva soluzione rapida dovrà fare per ora. Spero di avere presto tempo per trovare un modo migliore.
Allbeert,

Sono abbastanza sicuro che è possibile salvare alcuni caratteri, sostituendo printfcon puts, e la sua sostituzione returncon un operatore ternario.
millinon

@millinon Il problema putsè che aggiunge una nuova riga ogni volta :(. E per l'operatore ternario, non è possibile aggiungere returns o fors al loro interno !. Il tuo commento mi ha dato l'idea di salvare qualche altro personaggio molto rimuovendo facilmente il return
pensiero

2

C # 271 byte

Non il più breve, non ho potuto golfare la lettura dell'input a causa della necessità di accettare 0 come input.

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;}}

Codice formattato:

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;
    }
}

1

Lua - 219 203 byte

Sono andato a fare copie d di b copie di "|", quindi ho aggiunto r copie di "|" alla fine. Sento che forse avrei dovuto andare con il "tally up" i "|" s alla stringa uno alla volta.

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!

Campione:

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


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


c:\Programming\AnarchyGolfMine>lua test.lua
18,1
 | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | |

1
Potresti pubblicare una versione leggermente più leggibile e ungolfed? Giocare a golf a Lua sembra interessante!

@Alessandro fatto. E grazie, ha fatto trovare un paio di cose che mi mancavano.
AndoDaan,

1

JavaScript (193)

Questo potrebbe essere eccessivamente complesso.

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)

Versione commentata

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)

1

Python - 127 123 122

Basta intrufolarsi con una versione in pitone leggermente più corta.

modifica: risolto 0 che non stampava nulla e non si riavviava, finiva per avere la stessa lunghezza

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

0

C (207 caratteri)

La nuova riga prima exitè solo per leggibilità.

#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 spudorato rubato da Allbeert. Si noti che questa soluzione non viene compilata con gcc mentre tenta di imporre un prototipo inesistente per exit. Compilare con un compilatore C funzionante cometcc . Inoltre, questa funzione può o meno funzionare su piattaforme a 64 bit. Usare con cura.

Ecco l'implementazione originale non modificata su cui si basa:

#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);
}

0

Python 2 , 134 126 123 114 byte

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)

Provalo online!

Vecchia domanda che conosco ma divertente da provare comunque. Possibilità di provare alcuni trucchi che ho imparato da quando mi sono unito.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.