Automatizza il tuo esercizio di conteggio di prima elementare


36

CodeGolf Challenge

PWSSHHHH! Ti svegli in un laboratorio criogenico nel 3000. Dopo essere stato scortato all'ufficio incarichi per ricevere il tuo chip di carriera, presumibilmente quello di un ragazzo delle consegne, una sonda rileva che sei del 2000. Per questo motivo, e alcuni stereotipi, sei considerato stupido rispetto all'umano moderno di oggi e sei costretto a ripetere la scuola elementare.

Si entra nella tua classe di prima elementare e l'insegnante sta dando un compito. Dirà o scriverà un numero fino a 50. Se scrive il numero sulla lavagna (per esempio: 25), allora devi dire i numeri fino a quel numero "uno, due, tre, ..., venticinque ". Se pronuncia il numero ad alta voce (ad esempio: "sei"), sul tablet devi scrivere i numeri fino a quel numero "1, 2, 3, 4, 5, 6"

Questo diventa molto noioso e decidi di automatizzare il processo con le tue conoscenze di programmazione del 21 ° secolo ancora funzionanti, ma arcaiche.


Obbiettivo:

Il tuo programma dovrebbe ricevere un input. Questo input sarà un numero decimale ( 1 thru 50) o un numero scritto ( one thru fifty).

• Se l'input è un numero decimale, l'output dovrebbe contare da uno a detto numero, usando lo stile scritto. (ad es. trentadue )

• Se l'input è un numero scritto, l'output dovrebbe contare da 1 a detto numero, usando lo stile decimale. (es. 32 )


Regole:

Input e Output possono essere in qualsiasi caso di tua scelta (quindi puoi creare un programma che accetta solo lettere maiuscole se lo desideri).

I numeri decimali di input non devono essere di tipo numerico (ad es. Int), possono essere una stringa di input contenente numeri (25 vs "25"). Entrambi vanno bene e puoi scegliere quale vuoi che il tuo programma accetti. (Il tuo programma non deve accettare entrambi)

Lo stile scritto NON richiede un trattino tra parole composte, ma è possibile se lo si desidera.

I valori di output devono essere separati in qualche modo, qualsiasi separatore va bene 1,2,3 1 2 3 etc

Non è possibile aggiungere ulteriori librerie come num2words (python) ecc. (Tuttavia le librerie di sistema vanno bene)

Anche se il retroscena dice che sei del 2000, puoi usare le lingue create dopo quella data (lol)


Questo è , quindi vince il programma con il byte più breve!


1
Ci è permesso usare librerie come num2words in caso di Python.
Gurupad Mamadapur,

1
@AlbertRenshaw ma per quanto riguarda i builtin che lo fanno? (Mathematica)
Pavel

1
@coredump Significa che puoi scegliere l'uno o l'altro o entrambi. Non deve essere in grado di gestire entrambi i tipi di input
Albert Renshaw,

2
"Mordimi il culo di metallo lucido!" Non mi conto
RaisingAgent

1
Continuo a pensare che il titolo sia "il tuo primo (conteggio dei voti)" non "il tuo (conteggio dei voti)"
CAD97

Risposte:


32

Perl 6 , 119 113 byte

{my \n=<①     ㊿>.map:{|map *.uniname.words[2..*].join,$^a..$^b}
/\d/??n[^$_]!!1..1+first $_,n,:k}

Database Unicode FTW!

Utilizza numeri scritti in maiuscolo senza hypen, ad es TWENTYTWO.
Restituisce un elenco di stringhe o un intervallo di numeri. (Entrambi usano lo spazio come separatore quando stampati con put.)


3
Ahahaha molto intelligente! Lo adoro
Albert Renshaw il

13

Python3, 276 271 269 243 237 235 232 217 byte

Prendendo spunto dall'invio di @smls perl ...

from unicodedata import*
o=[name(chr(k)).split(' ',2)[-1]for j in['①⑴','㉑㉠','㊱㋀']for k in range(ord(j[0]),ord(j[1]))]
i=input()
w=i in o
for i in range(w and o.index(i)+1or int(i)):print(w and i+1or o[i])

Ho il sospetto che potrebbe essere ulteriormente migliorato.

Fa uso della libreria di sistema unicodedataper cercare i nomi per i numeri. Richiede nomi di numeri maiuscoli (separati da spazio FORTY TWO:) o numeri interi decimali come input.

(Questa è la mia prima presentazione di golf in codice.)

(Ho anche notato che stavo contando male la lunghezza (codifica), quindi è di qualche byte in meno di quanto si pensasse in precedenza. Ho comunque aggiornato solo il conteggio dei byte più recente. Oops.)


Benvenuti in PPCG!
AdmBorkBork,

In difesa: unicodedataè una libreria di sistema fornita con l'installazione predefinita, non una libreria "extra" che deve essere installata separatamente.
preavviso il

Benvenuti nel sito! Puoi rimuovere molti spazi dal tuo codice .
xnor

1
Benvenuti in PPCG. È possibile perdere 3 byte inserendo la stampa in un forciclo e avendo nuove righe tra ogni output. print()non importa se è un numero intero o una stringa allora. Provalo online!
ElPedro,

1
Penso che puoi import*invece di import namesalvare un paio di byte
Wheat Wizard,

10

Lisp comune, 297 253 243 242 144 128

(lambda(s)(#1=dotimes(u(or(#1#(i 51)(if(equal(#2=format()"~R"i)s)(return i)))s))(#2#t"~[~:;, ~]~:[~R~;~D~]"u(stringp s)(1+ u))))

Dettagli

(lambda (s) 
  (dotimes                         ; iterate...                                                                          
      (u                           ; for u from zero below ...                
       (or                         ; if s is a string, then                   
        (dotimes (i 51)            ;   parse s by iterating from 0 to 50      
          (if (equal               ;   until we find a match between          
               (format nil "~R" i) ;   the English word(s) for i              
               s)                  ;   and the given s                        
              (return i)))         ;   (exit loop)                            
        s))                        ; otherwise, use s, which is a number      
    (format t                      ; for each U, print to standard output     
            "~[~:;, ~]~:[~R~;~D~]" ; (see below for details)                  
            u                      ; ...                                      
            (stringp s)            ; ... arguments to format                  
            (1+ u))))              ; ...                                      
  • ~[ 0 ~; 1 ~; ... ~:; else ~]è uno switch, basato sul valore dell'argomento disponibile successivo, che passa al formato di controllo secondario appropriato. Qui ho solo un caso di "0" e per "else". Questo è usato per inserire un separatore prima di ogni numero tranne il primo, grazie a U che parte da zero.

  • ~:[ FALSE ~; TRUE ~]è un formato condizionale; qui produciamo le cose diversamente se l'input s è una stringa o no.

  • ~Rscrivere un numero come un numero cardinale inglese, mentre ~Dsemplicemente stampa il numero.

Esempi

CL-USER> (test "five")
1, 2, 3, 4, 5

CL-USER> (test 32)
one, two, three, four, five, six, seven, eight, nine, ten, eleven, twelve, thirteen, fourteen, fifteen, sixteen, seventeen, eighteen, nineteen, twenty, twenty-one, twenty-two, twenty-three, twenty-four, twenty-five, twenty-six, twenty-seven, twenty-eight, twenty-nine, thirty, thirty-one, thirty-two

Da quello che ho capito della domanda, devi essere in grado di analizzare entrambi gli stili, non solo uno, quindi la tua soluzione a 55 byte potrebbe non essere valida. "Il tuo programma non deve accettare entrambi" si riferisce a 25 vs "25", il decimale come un numero o come una stringa.
Tom,

@TomDevs Grazie. Questo è decisamente confuso. A dire il fvero , se definisco in modo che "(f 2)" stampa "uno, due" e (f "two")stampa "1, 2", ti sembrerà bello?
coredump,

Sì, penso che sia giusto.
Tom,

@TomDevs Grazie, l'ho risolto
coredump

1
@AlbertRenshaw No, solo inglese; questa funzionalità potrebbe essere già considerata gonfia, ma poiché è già stata implementata in alcuni Lisps, è stata standardizzata.
coredump,

8

JavaScript ES6, 559 526 381 368 364 358 332 327 315 byte

a="one0two0three0four0five0six0seven0eight0nine0ten0eleven0twelve0thir10four10fif10six10seven10eigh10nine1".replace(/1/g,'teen').split(0),b="twenty0thirty0forty0fifty".split(0),c=(n,d=Array,e=b.forEach(i=>a=a.concat(i,a.slice(0,9).map(x=>i+x))))=>1/n?a.slice(0,n).join():d.from(d(a.indexOf(n)+1),(x,i)=>i+1).join();

Grazie a Lithos Kritixi per l'idea di dividere l'array e Arnauld per il trucco 1 / n.

a="one0two0three0four0five0six0seven0eight0nine0ten0eleven0twelve0thir10four10fif10six10seven10eigh10nine1".replace(/1/g,'teen').split(0),b="twenty0thirty0forty0fifty".split(0),c=(n,d=Array,e=b.forEach(i=>a=a.concat(i,a.slice(0,9).map(x=>i+x))))=>1/n?a.slice(0,n).join():d.from(d(a.indexOf(n)+1),(x,i)=>i+1).join();

console.log(c("twentyfive"));
console.log(c("fifty"));
console.log(c(50));


1
Puoi rimuovere vare puoi cambiare l'array ['one,'two',..]in"one0two0three0...".split(0)
Kritixi Lithos

Spazi ridondanti a null, Array(n).
Yytsi,

2
Puoi sostituirlo !isNaN(n)con 1/n. Questo ti dà NaNper una stringa (falsy), un float diverso da zero per un numero intero diverso da zero (verità) o Infinityper 0 (anche verità).
Arnauld,

Aggiungi 4 spazi davanti a ogni riga di codice
sagiksp

@sagiksp Sì, devo aver sbagliato qualcosa durante la modifica del post, ora dovrebbe essere risolto :)
Tom

6

Python 2 , 503 499 494 490 479 byte

-5 grazie a @JonathanAllan

l='one two three four five six seven eight nine ten eleven twelve thir#four#fif#six#seven#eigh#nine#'.replace('#','teen ').split()
m='twenty','thirty','forty','fifty'
i,z,R=raw_input(),' ',range
try:n=int(i);p=(n/10)-2;o=(l+sum([[m[x]]+[m[x]+z+l[y]for y in R(9)]for x in R(p)],[])+[m[p]]+[m[p]+z+l[y]for y in R(n%10)],l[:n])[n<20]
except:j=i.split();o=map(str,R(1,(m.index(j[0])+2)*10+l.index(j[1])+2if z in i else l.index(i)+2if i in l else(m.index(i)+2)*10+1))
print','.join(o)

Provalo online!

Immettere un numero o uno spazio ortografico separato da spazio di un numero.

Versione leggermente meno giocata e più leggibile:

l='one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen'.split()
m='twenty','thirty','forty','fifty'
i=raw_input()
try:
 n=int(i)
 if n<20:
  o=l[0:n]
 else:
  o=l
  for x in range((n/10)-2):
   o+=[m[x]]+[m[x]+' '+l[y]for y in' '*9]
  p=m[(n/10)-2]
  o+=[p]+[p+' '+l[y]for y in' '*n%10]
except:
 if' 'in i:
  t=i.split()
  s=((m.index(t[0])+2)*10)+l.index(t[1])+2
 else:
  s=l.index(i)+2 if i in l else((m.index(i)+2)*10)+1
 r=range(1,s)
 o=map(str,r)
print','.join(o)

1
Risparmio di 6 byte conl="one two three four five six seven eight nine ten eleven twelve thir#four#fif#six#seven#eigh#nin#".replace("#","teen ").split()
Jonathan Allan

... oops 5, mancato il eda nineteen.
Jonathan Allan,

C'è un motivo per cui devi usare Python 2, senza di essa la stampa sarebbe più lunga, ma il raw_input potrebbe essere semplicemente inserito? (Stessa domanda per l'altra risposta)
nedla2004

@ nedla2004 - Nessun motivo diverso da quello che non ho ancora avuto modo di installare Python 3 sul mio ultimo laptop :-)
ElPedro

6

Schema, 161 , 152 , 149

(define (c x)(let((r(string->number x)))(let l((i 1))(let((n (format #f "~r" i)))(display(if r n i))(newline)(or(eq? r i)(equal? x n)(l (+ i 1)))))))

Non compresso:

(define (count limit)
  (let ((numerical-limit (string->number limit)))
    (let l ((i 1))
      (let ((current-number (format #f "~r" i)))
        (display (if numerical-limit current-number i))
        (newline)
        (or (eq? numerical-limit i)
            (equal? limit current-number)
            (l (+ i 1)))))))

Come si converte, ad esempio, da "quattro" a 4? Non sono sicuro di string->numberaverlo fatto, ho controllato rapidamente e sembra essere usato per convertire, ad esempio, da stringa "4"a numero 4.
coredump

@coredump Questo è corretto. (string->number "four")ritorna #f.
Michael Vehrs,

Quale schema stai eseguendo?
coredump,

1
@coredump guile 2.0.9
Michael Vehrs,

6

PHP - 397 372 349 344 329 byte

Ispirato alla soluzione JS di TomDevs

25 byte salvati sostituendoli $a=[...]con$a=explode(...)

Salvati altri 23 byte tornando a un array senza delimitatori di stringa e memorizzandoli teenin una variabile, grazie a @ user59178

Salvati altri 5 byte rimuovendo il (int)typecasting

Salvati altri 15 byte rilasciando $b, $inelle fordichiarazioni e tra parentesi graffe, grazie ancora a @ user59178

$a=[one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thir.$t=teen,four.$t,fif.$t,six.$t,seven.$t,eigh.$t,nine.$t];foreach([twenty,thirty,forty,fifty] as$c){$a[]=$c;for($i=0;$i<9;)$a[]=$c.'-'.$a[$i++];}if($argv[1]!=0)for($i=0;$i<$argv[1];)echo$a[$i++].' ';else for($i=1;$i<=array_search($argv[1],$a)+1;)echo$i++.' ';

Ungolfed:

$a =[one,two,three,four,five,six,seven,eight,nine,ten,eleven,‌​twelve,thir.$t=teen,‌​four.$t,fif.$t,six.$‌​t,seven.$t,eigh.$t,n‌​ine.$t];
foreach ([twenty,thirty,forty,fifty] as $c){
    $a[] = $c;
    for ($i=0;$i<9;)
        $a[] = $c . '-' . $a[$i++];
}
if( $argv[1] !=0 )
    for ($i=0;$i<$argv[1];)
        echo $a[$i++] . ' ';
else
    for ($i=1;$i<=array_search($argv[1], $a)+1;)
        echo $i++ . ' ';

Provalo per una stringa di input o per un numero di input


1
Quando giochi a golf puoi usare molte stringhe direttamente senza virgolette, incluso tutto il numero che usi. Ciò provoca un avviso ma può essere ignorato. Inoltre, è più breve (di 2 byte interi) archiviare teenin una variabile anziché ripeterla ogni volta. Come tale sarebbe diventato:$a=[one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thir.$t=teen,four.$t,fif.$t,six.$t,seven.$t,eigh.$t,nine.$t];
user59178

Non ci avevo pensato, grazie;)
roberto06

Puoi salvare altri 7 byte rilasciando $be inserendo il secondo array direttamente nel foreach, altri 6 byte rilasciando tutte le parentesi graffe (anche se devi inserire $a=$cil setup del ciclo for) e altri 6 byte post-incrementando $iquando lo usi piuttosto che nel bit 'dopo' dei cicli for.
user59178

Salva sei byte (due per ciclo) spostando il post-incremento dalla riga alla seguente:for ($i=0;$i<9;)$a[]=$c.'-'.$a[$i++];
Alex Howansky

Spiacenti, ho appena notato che @utente59178 ha suggerito la stessa cosa ...
Alex Howansky

6

Python 2, 262 byte

x="one two three four five six seven eight nine ten eleven twelve thir#four#fif#six#seven#eigh#nine#".replace("#","teen ").split()
x+=[a+"ty"+b for a in"twen","thir","for","fif"for b in['']+x[:9]]
v=input()
for s in range(1,x.index(v)+2)if v>50else x[:v]:print s

repl.it

Le stringhe di input e output sono minuscole e concatenate *, quindi per testare un input di stringa immettere, ad esempio, "thirtyfive"al prompt.

Costruisce l'elenco di tutte le parole (più "fiftyone"a "fiftynine"), xquindi verifica se inputè una parola con il proxy v>50(le stringhe sono maggiori dei numeri in Python 2 e tutti i numeri nell'intervallo di input valido dalla specifica sono <=50) ed printè appropriato I valori di entrambi i affettare la lista, x[:v]o la costruzione di una serie di numeri interi, range(1,x.index(v)+2).

* L'aggiunta della sillabazione su entrambi costa 11 byte, sostituendola a+"ty"bcon a+"ty"+'-'*(b>'')+b.


5

Wolfram Language, 92 bytes

If[NumberQ@#, Do[Print@IntegerName@i, {i, #}], 
  Do[Print@i, {i, Interpreter["SemanticNumber"]@#}]] &

(I'm new to this, let me know if I did something wrong)


2
-10 bytes: Do[Print@If[#>0,i,,IntegerName@i],{i,If[#>0,#,,Interpreter["SemanticNumber"]@#]}]&
JungHwan Min

5

JavaScript (ES6), 261 bytes

Note: the string assigned to z is encoded with atob. In the encoded string there are 11 bytes that I can not post to this site, even if they are valid characters in a javascript string. So I used an hex escape in the form \xHH. Each one of these escapes is counted as 1 byte.
The original uncompressed string is the less golfed version.

x=>(z=btoa('ö\x89ÞöÜ(öØkyï_¢êý~+Þöȱöǯz\x7f^\x8a\x08möx§{Û^\x9f×¥z÷§öÜ\x1e\x96÷½¶\x18«÷×â\x7fß}z(!÷Ûpz\x7f}~\x8aý').split(9),o=(0+z.map((v,i)=>i<20?i<13?v:(v||z[i-10])+'teen':z.slice(0,10).map(d=>(z[i]||z[i-8]||z[i-18])+'ty'+d))).split`,`,p=o.indexOf(x),o.slice(1,-~x+p+!~p).map((x,i)=>~p?i+1:x))

Less golfed

x => (
  z = '9one9two9three9four9five9six9seven9eight9nine9ten9eleven9twelve9thir99fif999eigh99twen99for9'
      .split(9),
  o = (0 + // 0 + array to build a comma separated string
       z.map( (v, i) => 
         i < 20 
         ? i < 13 
           ? v // 1 to 13 are 'as is'
           : (v||z[i-10])+'teen' // compose for 14 to 19
         : z.slice(0,10).map(d=>(v||z[i-8]||z[i-18])+'ty'+d)) // 20s, 30s, 40s, 50s
      ).split`,`, // from comma separated to array again
  // o contains strings from one to fiftynine
  p = o.indexOf(x), // look for input
  o.slice(1, -~x+p+!~p).map((x,i) => ~p?i+1:x)
)

Test

F=
x=>(z=btoa('ö\x89ÞöÜ(öØkyï_¢êý~+Þöȱöǯz\x7f^\x8a\x08möx§{Û^\x9f×¥z÷§öÜ\x1e\x96÷½¶\x18«÷×â\x7fß}z(!÷Ûpz\x7f}~\x8aý').split(9),o=(0+z.map((v,i)=>i<20?i<13?v:(v||z[i-10])+'teen':z.slice(0,10).map(d=>(v||z[i-8]||z[i-18])+'ty'+d))).split`,`,p=o.indexOf(x),o.slice(1,-~x+p+!~p).map((x,i)=>~p?i+1:x))

function update() {
  var i=I.value
  O.textContent = F(i)
}  

update()
<input id=I value=25 oninput='update()'><pre id=O></pre>


ö\x89ÞöÜ(öØ... this stuff is great hahaa
Albert Renshaw


5

Python 3, 305 303 bytes

Converted to Python 3 after advice from @nedla2004. Now also has no space between written numbers on input or output e.g. enter twentytwo

l='one two three four five six seven eight nine ten eleven twelve thir#four#fif#six#seven#eigh#nine#'.replace('#','teen ').split()
m='twenty','thirty','forty','fifty'
i,R=input(),range
l+=sum([[m[x]]+[m[x]+l[y]for y in R(9)]for x in R(3)],[])
for x in R(1,l.index(i)+2)if i in l else l[:int(i)]:print(x)

Try it online 3!

Python 2, 327 320 313 308 bytes

l='one two three four five six seven eight nine ten eleven twelve thir#four#fif#six#seven#eigh#nine#'.replace('#','teen ').split()
m='twenty','thirty','forty'
i,R=raw_input(),range
l+=sum([[m[x]]+[m[x]+l[y]for y in R(9)]for x in R(3)],[])+['fifty']
for x in R(1,l.index(i)+2)if i in l else l[:int(i)]:print x

Try it online 2!

163 170 177 bytes shorter than my original answer so I am posting it as an alternative. This uses for on the two lists to build up a complete list of all of the string representations of the numbers then identifies the right one in the list and prints everything up to it either by value or by index. Outputs a new line for each value.


5

Python 2, 432 422 416 403 bytes

I'm sure this can be improved on. At the very least if I can get away with hardcoding the value to be worked on and not needing a function I can save 20. It needs a space to separate words in text input. Saved 6 bytes thanks to JonathanAllan's comment on ElPedro's answer, 4 for rearranging maths.

def z(f):
 a,b,i,d="one two three four five six seven eight nine ten eleven twelve thir#four#fif#six#seven#eigh#nine#".replace("#","teen ").split()+[""],"twenty thirty forty fifty".split(),1,f>50
 if d:f=f.split();f=a.index(f[-1])+21+b.index(f[-2])*10 if len(f)>1 else b.index(f[-1])*10+20 if f[-1]in b else a.index(f[-1])+1
 while i<=f:s=i if d else a[i-1]if i<20 else b[i//10-2]+a[i%10-1];print s;i+=1

(NB: The actual version of this uses tabs to indent instead of spaces. QPaysTaxes added a single space because that wasn't rendering properly, to ensure that the given code compiles. It shouldn't change the byte count.)


@JonathanAllan's comment on ElPedro's answer works here too for -6
Chris H

1
len(`f`)>2 can be ...`f`[2:] for another 3 I believe. (ignore the ... can't seem to get the backticks working properly)
Jonathan Allan

In fact in python 2 you could go for f>50 for 6. (and another one by not using d)
Jonathan Allan

@JonathanAllan that doesn't work for passing numbers as integers, which I currently do: TypeError: 'int' object has no attribute '__getitem__'. If I pass numeric input as a string, f[2:] gets closer but still fails when trated as a boolean (print f[2:] and True prints a blank line if len(f)<2, not True or False)
Chris H

@JonathanAllan f>50 works, thank you. Dropping d isn't so simple as I always put the end value of the loop into f so line 8 can't be changed to if f>50 as it will never be true.
Chris H

4

C++11, 484 480 477 bytes

#import<iostream>
#import<cstdlib>
#import<vector>
using namespace std;f(){int j,i=2;string s="teen";vector<string>v={"","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve"};for(;i++<9;)v.push_back(v[i]+s);v[13]="thir"+s;v[15]="fif"+s;v[18]="eigh"+s;for(i=19;i++<50;){string n[4]={"twenty","thirty","forty","fifty"};v.push_back(n[i/10-2]+v[i%10]);}cin>>s;if(i=atoi(s.c_str()))for(j=0;j++<i;)cout<<v[j]<<" ";else while(v[i++]!=s)cout<<i<<" ";}

Text input in lower-case without hyphens.


3

PowerShell, 362 bytes

$z=0..50|%{("0twenty0thirty0forty0fifty"-split0)[+(($b="$_"[0])-gt49)*($_-gt19)*(+"$b"-1)]+($x=(("0one0two0three0four0five0six0seven0eight0nine0ten0eleven0twelve"-split0)+(-split'thir four fif six seven eigh nine'|%{$_+'teen'})))[($_%10)*($_-gt19)]+$x[$_*($_-le19)]}
if(($n=-split$args)[0][0]-in48..57){$z[$n[0]..$n[2]]}else{$z.IndexOf($n[0])..$z.IndexOf($n[2])}

Try it online! words input or numbers input

This is a right mess, and I'm not terribly happy with it, but here it is. Golfing suggestions welcome.

The first line sets $z to be an array of the full English words. You can see the -split0 for numbers 1 to 12, and the loop to construct all the teens, and then there's a bunch of logic to put everything together right. Try it online!

The second line starts with some logic. We take the input $args (as a string), -split it on whitespace, store it into $n for use later, take the first [0] word, and the first [0] character of that, and check if it is -in a range 48..57 (i.e., ASCII 0 to 9). So, we're checking if we have decimal input or English input. Try it online!

In the first case, we build a range based on the decimal inputs $n[0]..$n[2] and use that to index into $z[...]. In the other case, we find the .indexOf() the first word and the last word, and build just a numerical range from that. In either situation, we now have an array of objects on the pipeline (either strings or integers), and an implicit Write-Output at program completion gives us a newline between elements.


3

Swift3, 402 bytes

let f=["one","two","three","four","five","six","seven","eight","nine"]
let g=["twenty","thirty","forty","fifty"]
let v=[f,["ten","eleven","twelve"],["thir","four","fif","six","seven","eigh","nine"].map{$0+"teen"},[g[0]],f.map{g[0]+$0},[g[1]],f.map{g[1]+$0},[g[2]],f.map{g[2]+$0},[g[3]]].flatMap{$0}
func c(s:String){if let i=Int(s){print(v.prefix(upTo:i))}else{for j in 1...v.index(of:s)!+1{print(j)}}}

Ungolfed:

let f = ["one","two","three","four","five","six","seven","eight","nine"]
let g = ["twenty","thirty","forty","fifty"]

let values = [f,["ten","eleven","twelve"],["thir","four","fif","six","seven","eigh","nine"].map{$0+"teen"},
              [g[0]], f.map{g[0]+$0},
              [g[1]], f.map{g[1]+$0},
              [g[2]], f.map{g[2]+$0},
              [g[3]]].flatMap{$0}

func count(s:String){
    if let i = Int(s) {
        print(values.prefix(upTo: i))
    } else {
        for j in 1...values.index(of: s)!+1{
            print(j)
        }
    }
}

count(s:"29")
count(s:"twentyeight")

Nothing special here, just using an array to back up the written-out numbers.

I originally thought this solution using this other way to calculate the values array:

let values = f + ["eleven","twelve"]
    + ["thir","four","fif","six","seven","eigh","nine"].map{$0+"teen"}
    + [g[0]] + f.map{g[0]+$0}
    + [g[1]] + f.map{g[1]+$0}
    + [g[2]] + f.map{g[2]+$0}
    + [g[3]]

Which could be golfed to:

let v=f+["eleven","twelve"]+["thir","four","fif","six","seven","eigh","nine"].map{$0+"teen"}+[g[0]]+f.map{g[0]+$0}+[g[1]]+f.map{g[1]+$0}+[g[2]]+.map{g[2]+$0}+[g[3]]

replacing the 3rd line in the golfed code

I could have scored 381 bytes, but, there is a compiler error that says: "expression was too complex to be solved in reasonable time", more info on the error can be found here


LOVE seeing swift in here, I'll have to check this out more when I get back
Albert Renshaw

3

R, 452 430 424 bytes

o=c("","one","two","three","four","five","six","seven","eight","nine") 
t=gsub(0,"teen",c("ten","eleven","twelve","thir0","four0","fif0","six0","seven0","eigh0","nine0"))
s=c("twenty","thirty","forty") 
p=""
for(i in s){for(j in o){p=paste0(p,i,j," ")}}
as.data.frame(t(d<-1:50))
names(d)=c(o[-1],t,as.vector(strsplit(p," ")[[1]]),"fifty")
f=function(x){if(is.numeric(x)){names(d)[1:x]}else{matrix(d[1:d[x]],dimnames=NULL)}}

#> f(5)
#[1] "one"   "two"   "three" "four"  "five" 

#> f('five')
#     [,1]
#[1,]    1
#[2,]    2
#[3,]    3
#[4,]    4
#[5,]    5

Places the numbers in a data.frame with written-out numbers as column names, making the translation between the two (and subsequent printing) pretty easy.

Main attempt at golfing was in creating the written-out numbers for 20-49, probably much more to golf here.

I made an attempt with as.matrix to print the data.frame with just the numbers, but am still left with a matrix header. Hopefully that's ok.

Ungolfed:

ones <- c("","one","two","three","four","five","six","seven","eight","nine") 
teens <- c("ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen")
tens <- c("twenty","thirty","forty") 

p=""
for(i in tens){
  for(j in ones){
    p=paste0(p, i, j," ")
  }
}

nums <- 1:50
as.data.frame(t(nums))
names(nums) <- c(ones[-1], teens, as.vector(strsplit(p, " ")[[1]]), "fifty")
f <- function(x){
  if(is.numeric(x)){
    names(nums)[1:x]
  } else {
    matrix(nums[1:nums[x]], dimnames = NULL)
  }
}

Slight improvement to 359 Bytes: o=c("","one","two","three","four","five","six","seven","eight","nine") ; v=c("ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"); w=c("twenty","thirty","forty"); a=data.frame(0:50, c(o,v, sapply(w[1:3],function(y) sapply(o,function(x) paste0(y,x))),"fifty")); b=which(a==i); a[if(b<52) 2:b else 2:(b-51),ifelse(b<52,2,1)]
count

@count looks like a big improvement! I can't seem to figure out where the function is, though, or where you'd take an argument.
BLT

2

C, 342 331 bytes

char*x[]={"teen","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thir","four","fif","twenty","thirty","fourty","fifty"};void main(int z,char**i){for(z=1;z<=atoi(i[3]);z++)printf("%s%s%s\n",z<16?x[z]:z<20?z^18?x[z-10]:"eigh":x[z/10+14],z>20&&z%10?"-":z>12&&z<20?*x:"",z>20&&z%10?x[z%10]:"");}

Try it online!


My favorite language :)
Albert Renshaw

1
You actually don't need the 1 thru or one thru; all this codegolf requires is your third argument. The first two will always be "1 and thru" (or "one and thru")
Albert Renshaw

@AlbertRenshaw Good call! Thanks :)
Ahemone

1

SAS, 179

%macro c(n);%let f=words.;%if%length(&n)>2%then%do;%do c=1%to 50;%if%qsysfunc(putn(&c,&f))=&n%then%let n=&c;%end;%let f=2.;%end;%do i=1%to &n;%put%sysfunc(putn(&i,&f));%end;%mend;

Output is written to the log separated by newlines. SAS has a built-in format for converting digits to words, which is a major advantage for this challenge, but annoyingly it lacks an informat for doing the reverse.

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.