Est-ce un chiffre?

17

Prélude:

Je voulais m'entraîner à faire des cas de test, donc je vais les essayer sur quelque chose de facile.

Défi:

Prenez n'importe quelle entrée (chaîne) donnée (dans la plage ASCII visible) et déduisez s'il s'agit d'un nombre et sortez quelque chose qui pourrait être utilisé pour évaluer.

Règles:

  • Un nombre ne contiendra que les caractères -0123456789,.
  • Les réponses ne sont nécessaires que pour reconnaître les nombres compris entre -1000000000 et 1000000000 (exclusif), mais peuvent reconnaître des nombres arbitrairement grands.
  • Vous pouvez écrire un programme complet ou une fonction.
  • S'il s'agit d'un nombre, renvoyez tout ce qui pourrait être utilisé pour le discerner et documenter la sortie dans la description (ex. My program outputs T if a number, F if not.).
  • L'entrée sera n'importe quelle quantité de caractères dans la plage ASCII ou vide (si vide retournez tout ce que vous sortiriez sinon un nombre).
  • Les nombres peuvent inclure un point décimal (ex. 3.14). S'ils le font, ils doivent avoir au moins un chiffre avant la virgule décimale et au moins un après.
  • Les nombres peuvent avoir des zéros en tête ou en fin (ex. 000001.00000).
  • La partie entière d'un nombre pourrait être divisée pour la lisibilité en morceaux de trois chiffres avec des virgules (ex. 1,000.23456). Dans ce cas , ils doivent être divisés tous les trois chiffres de droite à gauche (ex. 1,234,567, 10,000.202, 123,234.00, 0,123.293).
  • Les nombres négatifs sont indiqués par un début -(ex. -1.23). Un début +pour indiquer un nombre positif n'est pas autorisé et devrait entraîner une sortie falsifiée.
  • Les exceptions ne sont PAS comptées comme des sorties valides et discernables (sauf lorsqu'elles peuvent transmettre des sorties au flux de sortie standard (par exemple, Exception on line N [...]peuvent être mises en sortie pour un nombre / n ° de nombre si la chaîne est placée dans le flux de sortie standard).

Cas de test:

(en supposant la My program outputs T if a number, F if not.version)

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]

, le moins de caractères est le gagnant.

n4melyh4xor
la source
Pouvons-nous supposer que l'entrée est toujours ASCII?
Brad Gilbert b2gills
@ BradGilbertb2gills, oui.
n4melyh4xor
Si ça -123va, qu'en est-il de +456-> bon ou mauvais. Ou est- +il exclu de la fête?
chux
@chux, le train du parti est parti avant l'arrivée du +. Plus de chance la prochaine fois, +.
n4melyh4xor
2
Lorsque les gens demandent des clarifications dans les commentaires, vous devez modifier la question. Il ne devrait jamais être nécessaire de lire les commentaires pour connaître la spécification. J'ai édité pour inclure les réponses et certains cas de test.
Peter Taylor

Réponses:

10

Rétine , 28 29 31 40 34 octets

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

Sorties 1si véridique, 0sinon. Pour autant que je comprends, dans ce cas, Retina génère le nombre de correspondances de l'expression régulière sur l'entrée.

Essayez-le en ligne!

Suite de tests

Modifications

  • Correction pour respecter la règle "il devrait y avoir des chiffres après la décimale"
  • Correction pour se conformer aux règles "gérer les négatifs"
  • Correction pour se conformer aux séparateurs de virgule en option
  • Correction d'un bug avec des milliers de séparateurs comme indiqué par @MartinEnder
  • Golfé en supprimant l'anticipation conditionnelle

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)
Kritixi Lithos
la source
@MartinEnder Fixed! De plus, comment spécifiez-vous les drapeaux (par exemple, les drapeaux pour met g) dans Retina?
Kritixi Lithos
Mettez un `devant l'expression régulière, puis les modificateurs vont devant cela, par exemple m`^.$. gn'existe pas dans .NET, les correspondances sont globales par défaut.
Martin Ender
3

JavaScript, 46 49 octets

Ceci est un port direct de ma réponse Retina. La seule raison pour laquelle j'ai utilisé JS est qu'il existe un moyen simple de tester l'expression régulière à l'aide de l'extrait de snack ci-dessous

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>

Kritixi Lithos
la source
S'il n'y avait pas certaines règles (comme la règle de virgule), on pourrait simplement le faire isNaN(+prompt())pour 16 caractères. Telle est la vie, je suppose
Matheus Avellar
2

Perl 6 , 42 octets

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

Essayez-le

Étendu:

{  # 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

  /
}
Brad Gilbert b2gills
la source
1

PHP, 62 octets

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

Le builtin ne peut pas gérer les virgules et il accepte la notation scientifique; j'ai donc dû marcher sur le chemin des regex. <?=is_numeric($argv[1]);aurait été de 24 octets.

Titus
la source
0

outils bash / Unix, 64 octets

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

Enregistrez-le en tant que fichier et passez la chaîne à tester comme premier argument à la commande.

La sortie est 0 pour un non-nombre, 1 pour un nombre.

Si vous êtes prêt à accepter l'entrée de stdin et si vous pouvez garantir que l'entrée se compose d'une seule ligne, vous pouvez supprimer le <<< "$ 1" à la fin, ce qui donne 57 octets .

Quant au code lui-même, l'option -c pour egrep compte le nombre de lignes correspondantes (qui sera soit 0 soit 1).

Mitchell Spector
la source
0

C89, 195 octets

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

Non golfé:

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;
}
chat
la source
0

Python 2, 79 octets

Solution 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

Essayez-le en ligne

Possum mort
la source
0

c #, 75 octets

bool t(string n){double v;return double.TryParse(n.Replace(",",""),out v);}
Johan du Toit
la source