Questo è un numero?


17

Preludio:

Volevo allenarmi a creare casi di test, quindi li proverò su qualcosa di semplice.

Sfida:

Prendi qualsiasi dato input (stringa) (all'interno dell'intervallo ASCII visibile) e deduci se è un numero e genera qualcosa che potrebbe essere usato per valutare.

Regole:

  • Un numero conterrà solo i caratteri -0123456789,.
  • Le risposte sono necessarie solo per riconoscere numeri compresi tra -1000000000 e 1000000000 (esclusivo), ma possono riconoscere numeri arbitrariamente grandi.
  • È possibile scrivere un programma completo o una funzione.
  • Se un numero, restituisce tutto ciò che potrebbe essere utilizzato per discernerlo e documentare l'output nella descrizione (es. My program outputs T if a number, F if not.).
  • L'input sarà qualsiasi quantità di caratteri all'interno dell'intervallo ASCII o vuoto (se vuoto restituisce qualunque cosa tu abbia emesso se non un numero).
  • I numeri potrebbero includere un punto decimale (es. 3.14). In tal caso, devono avere almeno una cifra prima del punto decimale e almeno una cifra dopo di essa.
  • I numeri possono avere zeri iniziali o finali (es. 000001.00000).
  • La parte intera di un numero può essere divisa per essere leggibile in blocchi di tre cifre con virgole (es. 1,000.23456). In questo caso devono essere divisi ogni tre cifre da destra a sinistra (es. 1,234,567, 10,000.202, 123,234.00, 0,123.293).
  • I numeri negativi sono indicati da un segno iniziale -(es. -1.23). Un +indizio per indicare un numero positivo non è consentito e dovrebbe comportare un risultato errato.
  • Le eccezioni NON vengono conteggiate come output valide e riconoscibili (tranne quando possono passare output allo stream di uscita standard (es. Exception on line N [...]Possono essere inserite come output per un numero / non numero se la stringa viene messa nello stream di uscita standard.

Casi test:

(assumendo la My program outputs T if a number, F if not.versione)

123 -> T [on integer]
-123 -> T [negative numbers need to be handled]
0 -> T [on zero]
123.456 -> T [on floating point]
123,456.789 -> T [on evenly divided by 3 digits with comas]
123456789 -> T [thousand separators are not required]
0000001.00000 -> T [on leading/trailing zeros]
00.00 -> T [on zero and leading/trailing zeros]
999999999.9999999999999999999999999999999999999999999999999999 -> T [on close to the maximum value]
-999999999.9999999999999999999999999999999999999999999999999999 -> T [on close to the minimum value]
 -> F [on empty]
lolz -> F [on non-number value]
n4melyh4xor -> F [on non-number with digits]
  1.2 -> F [on space-padded]
9.3 1.3 -> F [on anyhow separated multiple numbers]
1e5 -> F [no scientific notation]
50cl05e.buty3ts0f4r -> F [on input with letters obscuring the number]
1,2,3,4.5678 -> F [on badly readability-divided number]
1,234.5,678 -> F [on readability-divided floating point part]
.234 -> F [on no leading zero]
+1 -> F [no leading + sign]
1.234.3 -> F [only one decimal point]
12345,678 -> F [on separator stopping mid-way]

, il numero minimo di caratteri è il vincitore.


Possiamo supporre che l'ingresso sia sempre ASCII?
Brad Gilbert b2gills

@ BradGilbertb2gills, sì.
n4melyh4xor

Se -123è OK, che dire +456-> buono o cattivo. O viene +lasciato fuori dalla festa?
chux - Ripristina Monica il

@chux, il treno del partito è partito prima che il + arrivasse. Buona fortuna la prossima volta, +.
n4melyh4xor

2
Quando le persone chiedono chiarimenti nei commenti, è necessario modificare la domanda. Non dovrebbe mai essere necessario leggere i commenti per conoscere le specifiche. Ho modificato per includere le risposte e alcuni casi di test.
Peter Taylor,

Risposte:


10

Retina , 28 29 31 40 34 byte

^-?\d{1,3}((,\d{3})*|\d*)(\.\d+)?$

Output 1se vero, 0altrimenti. Per quanto ho capito, in questo caso Retina emette il numero di corrispondenze che il regex ha sull'input.

Provalo online!

Test Suite

Le modifiche

  • Risolto per rispettare la regola "ci dovrebbero essere cifre dopo il decimale"
  • Risolto il problema per rispettare le regole "gestire i negativi"
  • Risolto per rispettare i separatori di virgola opzionali
  • Corretto errore con migliaia di separatori come notato da @MartinEnder
  • Golfato rimuovendo lookahead condizionale

RegExplanation

^-?\d{1,3}((,\d{3})*|\d*)(\.\d+)?$
^                                $  This marks the start and end of regex
 -?                                 Optional hyphen for negative number
   \d{1,3}                          Matches between 1 and 3 digits
          (             )           Capturing group
           (,\d{3})*                 Matches at least zero of comma and three numbers (in the case of separators)
                    |                OR
                     \d*             Matches at least zero digits (in the case of no separators)
                        (\.\d+)?    Matches an optional . and at least one digit (for decimal numbers)

@MartinEnder Risolto! Inoltre, come si specificano i flag (diciamo flag per me g) in Retina?
Kritixi Lithos,

Metti un `davanti al regex e poi i modificatori vanno davanti a quello, ad es m`^.$. gnon esiste in .NET, le corrispondenze sono globali per impostazione predefinita.
Martin Ender,

3

JavaScript, 46 49 byte

Questa è una porta diretta della mia risposta Retina. L'unico motivo per cui ho usato JS è che esiste un modo semplice per testare il regex usando lo snippet di snack qui sotto

f=s=>/^-?\d{1,3}((,\d{3})*|\d*)(\.\d+)?$/.test(s)

f=s=>/^-?\d{1,3}((,\d{3})*|\d*)(\.\d+)?$/.test(s)
<input oninput=p.innerText=f(value)><p id=p></p>


Se non fosse per alcune delle regole (come la virgola), si potrebbe semplicemente fare isNaN(+prompt())per 16 caratteri. Questa è la vita, suppongo
Matheus Avellar il

2

Perl 6 , 42 byte

{?/^\-?[\d**1..3[\,\d**3]+|\d+][\.\d+]?$/}

Provalo

Allargato:

{  # bare block lambda with implicit parameter 「$_」

  ? # turn the following into a Bool result

  /  # match implicitly against 「$_」

    ^                 # beginning of string

    \- ?              # optional leading 「-」

    [

      \d ** 1..3      # 1 to 3 digits
      [
        \,            # comma
        \d ** 3       # three digits
      ]+              # repeat at least once

    |                 # or

      \d+             # at least one digit

    ]

    [ \. \d+ ]?       # 「.」 followed by at least one digit optionally

    $  # end of string

  /
}

1

PHP, 62 byte

<?=preg_match("#^-?(\d+|\d{1,3}(,\d{3})*)(\.\d+)?$",$argv[1]);

Il builtin non può gestire le virgole e accetta la notazione scientifica; quindi ho dovuto percorrere la via regex. <?=is_numeric($argv[1]);sarebbe stato di 24 byte.


0

strumenti bash / Unix, 64 byte

egrep -c '^-?([0-9]+|[0-9]{1,3}(,[0-9]{3})+)(\.[0-9]+)?$'<<<"$1"

Salvarlo come file e passare la stringa da testare come primo argomento del comando.

L'output è 0 per un non numero, 1 per un numero.

Se sei disposto ad accettare input da stdin e se puoi garantire che l'input è costituito da una sola riga, puoi rimuovere <<< "$ 1" alla fine, risultando in 57 byte .

Per quanto riguarda il codice stesso, l'opzione -c per egrep conta il numero di righe corrispondenti (che sarà 0 o 1).



0

C89, 195 byte

b,d,c,i;f(char*s){b=*s;for(d=c=i=0;i++,*(s++),d+=*s=='.',c+=*s==',',b=c?i&(i%4!=3)&*s==','?0:b:b;)if(*s==45&!i);else if((*s==32)|(*s==46)|*s==43|!isdigit(*s)&*s!=46&*s!=44)||!(d-1))b=0;return b;}

Ungolfed:

bool is_base10_number (const char* const str) {

  if(!str[0])return false;

  size_t
    dpts = 0,
    cmas = 0;

  for (size_t i = 0; i < strlen(str); i++) {

    if ((str[i] == '-') && (!i)){
      continue;
    }

    if (
      (str[i] == ' ')
      || (str[0] == '.')
      || (str[0] == '+')
      ||
      (
        (!isdigit(str[i]))
        && (str[i] != '.')
        && (str[i] != ',')
      )
    ) {
      return false;
    }

    dpts += str[i] == '.';
    cmas += str[i] == ',';

    if (cmas) {
      if (i & ((i % 4) != 3) & str[i] == ',') {
        return false;
      }
    }

  }

  if (dpts > 1) { return false; }

  return true;
}

0

Python 2, 79 byte

Soluzione Regex

import re
lambda s:[s]==re.findall('-?(?:\d{1,3}(?:,\d{3}\d+)(?:\.?\d+)?',s)


-?                                          | Starts with 0-1 dashes
  (?:\d{1,3}(?:,\d{3})+                     | Have 1-3 digits and 1+ (comma followed by 3 digits)
                       |\d+)                | or 1+ digits
                            (?:\.?\d+)?     | Ends with dot and 1+ digits or nothing

Provalo online


0

c #, 75 byte

bool t(string n){double v;return double.TryParse(n.Replace(",",""),out v);}
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.