Vérification de la chaîne ordinale

17

La description :

Étant donné une chaîne en entrée, vérifiez s'il s'agit d'un nombre ordinal valide en anglais ou non. Si elle est valide, renvoyez la valeur véridique, sinon retournez la valeur fausse. (Suggéré par @Arnauld. Merci. Aussi par @JoKing)

Pour les utilisateurs qui souhaitent connaître les nombres ordinaux, cliquez ici:

https://www.mathsisfun.com/numbers/cardinal-ordinal-chart.html (Suggestion de: qwr)

Entrées possibles:

21st ---> true
12nd ---> false
1nd ---> false
....

Il s'agit d'un défi de golf de code, donc le code le plus court dans chaque langue sera le gagnant.

Exemples :

console.log('12th' , true) // This evaluates to true
console.log('1st' , true) // also evaluates to true
console.log('21nd' , false) // returns false
console.log('11st' , false) // returns false
console.log('111199231923819238198231923213123909808th' , true) // true

Étant donné que de nombreuses personnes ont posé la question de savoir si la saisie ne sera que des chaînes valides:

Toutes les entrées seront toujours valides. c'est-à-dire qu'ils seront sous forme de chaîne et se composeront d'un chiffre (ou nombre de chiffres) avec l'un des quatre suffixes:

st, nd, rd,th

Muhammad Salman
la source
Pouvez-vous clarifier les règles des nombres ordinaux? Ou au moins mettre un lien vers les règles que vous suivez.
qwr
Ce sont des règles normales. Je n'ai rien changé. Mais merci pour la contribution, j'ai ajouté un lien
Muhammad Salman
@Jonathan Allan Les nombres ordinaux commencent à partir 1st, les ordinaux négatifs n'existent pas - english.stackexchange.com/questions/309713/…
Oliver Ni
@JonathanAllan OP dit "L'entrée va être un modèle ordinal valide." ce qui signifie aucun négatif
Oliver Ni
2
Vous dites que les entrées seront toujours valides mais je pense qu'un meilleur terme serait bien formé . Les 12e et 12e sont bien formés mais seul le premier est valide .
David Conrad

Réponses:

3

Utilitaires Bash + GNU , 54

L'appariement des expressions rationnelles semble être un moyen simple de procéder. Je suis sûr que cette expression pourrait être raccourcie davantage:

egrep '((^|[^1])(1st|2nd|3rd)|(1.|(^|[^1])[^1-3])th)$'

Entrée de STDIN. Sortie sous forme de code retour shell - 0 est véridique et 1 est falsey.

Essayez-le en ligne!

Traumatisme numérique
la source
Quelle ? cela ne produit pas la bonne réponse.
Muhammad Salman
@MuhammadSalman C'est parce que c'est une suite de tests. Jetez un œil aux codes de sortie pour 1stet 1th.
Dennis
egrepest capable de tests d'addition et de primalité (en unaire), donc je pense que vous pouvez en faire une réponse egrep.
Dennis
Je suis désolé mais mon bash est nul, je n'ai aucune idée de quelque chose dedans. Je me suis ennuyé alors j'ai utilisé un vérificateur de différence pour vérifier la différence entre l'entrée et la sortie. Je vois ce que tu veux dire. J'ai donc une question maintenant @Dennis: Bash a-t-il des booléens?
Muhammad Salman
Peut-être que les cas de test seraient plus clairs s'ils egrepétaient exécutés séparément pour chaque entrée pour obtenir le code de sortie correspondant pour chacun: Essayez-le en ligne! .
manatwork
3

c'est sous l'hypothèse que l'entrée est un modèle ordinal valide. si ce n'est pas le cas, des modifications doivent être apportées

JavaScript (Node.js) , 97 92 78 octets

s=>("tsnr"[~~((n=(o=s.match(/(\d{1,2})(\D)/))[1])/10%10)-1?n%10:0]||'t')==o[2]

Essayez-le en ligne!

Explication

s=>
   ("tsnr"                                // all the options for ordinal - 4-9 will be dealt afterwards    
      [~~(                                //floor the result of the next expression
        (n=(                              //save the number (actually just the two right digits of it into n
          o=s.match(/(\d{1,2})(\D)/))[1]) //store the number(two digits) and the postfix into o (array)
        /10%10)-1                         //if the right most(the tenths digit) is not 1 (because one is always 'th')
          ?n%10:0]                        //return n%10 (where we said 0-3 is tsnr and afterwards is th
            ||'t')                        // if the result is undefined than the request number was between 4 and 9 therefor 'th' is required
    ==o[2]                                // match it to the actual postfix  

_____________________________________________________________________

port de @Herman Lauenstein

JavaScript (Node.js) , 48 octets

s=>/1.th|(^|[^1])(1st|2nd|3rd|[^1-3]th)/.test(s)

Essayez-le en ligne!

DanielIndie
la source
Si la solution reg d'hypothèse peut également être***.
l4m2
S'il n'est pas supposé qu'il s'agit de / \ d * (st | nd | rd | th) / input, 1stapassez le test reg; si supposé, /1.th|(^|[^1])(1s|2n|3r|[^1-3]t)/travaux
l4m2
3

Python ,  56  53 octets

-3 grâce à (utiliser l'inclusion d'une lettre unique au lieu de l'avant-dernière égalité de caractère)

lambda v:'hsnrhhhhhh'[(v[-4:-3]!='1')*int(v[-3])]in v

Une fonction sans nom.

Essayez-le en ligne!

Comment?

Depuis toutes les entrées (ici v) est garanti de la forme que \d*[st|nd|rd|th]nous pouvons simplement tester si un caractère existe dans vlequel nous nous attendons à être là si elle était correcte ( s, n, rou h, respectivement) - c'est <getExpectedLetter>in v.

Le dernier chiffre détermine généralement ceci:

v[-3]: 0 1 2 3 4 5 6 7 8 9
v[-2]: h s n r h h h h h h

... sauf lorsque l'avant-dernier chiffre est un 1, quand tout doit se terminer par thet donc notre caractère attendu doit être h; pour évaluer cela, nous pouvons prendre une tranche (pour éviter qu'une erreur d'index ne se produise pour les entrées sans -4 ème caractère) v[-4:-3]. Puisque 0mappe hdéjà, nous pouvons obtenir l'effet souhaité en utilisant la multiplication avant l'indexation dans 'hsnrhhhhhh'.

Jonathan Allan
la source
st, nd, rd et th ont tous une lettre unique afin que vous puissiez simplement tester si elle se produit dans la chaîne 53 octets
Asone Tuhid
@AsoneTuhid nice golf - merci!
Jonathan Allan
@AsoneTuhid - également économisé trois sur ma réponse Jelly, alors doublez les remerciements!
Jonathan Allan
3

Java 8, 54 51 octets

s->s.matches(".*1.th|(.*[^1])?(1s|2n|3r|[^1-3]t).")

Explication:

Essayez-le en ligne.

s->  // Method with String parameter and boolean return-type
  s.matches(".*1.th|(.*[^1])?(1s|2n|3r|[^1-3]t).")
     //  Validates if the input matches this entire regex

Les correspondances String # de Java s'ajoutent implicitement ^...$.

Explication de l'expression régulière:

^.*1.th|(.*[^1])?(1s|2n|3r|[^1-3]t).$
^                                          Start of the regex
 .*1.                                       If the number ends in 11-19:
     th                                      it must have a trailing th
       |                                    If not:
        (.*    )?                            Optionally it has leading digits,
           [^1]                              excluding a 1 at the end
                 (1s|2n|3r         .      followed by either 1st, 2nd, 3rd,
                          |[^1-3]t).      0th, 4th, 5th, ..., 8th, or 9th
                                    $   End of the regex
Kevin Cruijssen
la source
2

Pyth, 49 60 octets SBCS

Js<2zK%J100I||qK11qK12qK13q>2z"th".?qz+J@c."dt8¸*£tÎðÎs"2J

Suite de tests

SE a mangé des éléments non imprimables dans le code (et dans l'explication ci-dessous) mais ils sont présents dans le lien.

Explication:
Js<2zK%J100I||qK11qK12qK13q>2z"th".?qz+J@c."dt8¸*£tÎðÎs"2J # Code
Js<2z                                                         # J= the integer in the input
     K%J100                                                   # K=J%100
           I||qJ11qJ12qJ13                                    # IF K is 11, 12, or 13:
                          q>2z"th"                            #  Print whether the end of the input is "th"
                                  .?                          # Otherwise:
                                    qz                        #  Print whether the input is equal to
                                      +J                      #   J concatenated with
                                        @                   J #    The object at the Jth modular index of
                                          ."dt8¸*£tÎðÎs"   #     The string "thstndrdthththththth"
                                         c                 2  #      Chopped into strings of length 2 as a list
Traduction Python 3:
z=input();J=int(z[:-2]);K=J%100
if K==11or K==12or K==13:print(z[-2:]=="th")
else:print(z==str(J)+["thstndrdthththththth"[2*i:2*i+2] for i in range(10)][J%10])
hakr14
la source
2

Python 2, 92 82 74 68 octets

-8 grâce à Chas Brown
-6 grâce à Kevin Cruijssen

lambda s:(a+'t'*10+a*8)[int(s[-4:-2]):][:1]==s[-2:-1]
a='tsnr'+'t'*6

Construit une grande chaîne de ths, sts, nds et rds pour les fins 00de 99. Vérifie ensuite si cela correspond.

Oliver Ni
la source
2

Rétine , 35 31 octets

-4 octets grâce à @Asone Tuhid

Merci à @Leo d'avoir trouvé un bug

1.th|(^|[^1])(1s|2n|3r|[04-9]t)

Sorties 1pour vrai et 0pour faux. Cela suppose l'entrée est au format ordinal avec un suffixe valide (extrémités avec st, nd, rdou th).

Essayez-le en ligne!

Herman L
la source
1

Gelée ,  25  22 octets

-3 octets grâce à une observation faite dans un commentaire fait par sur mon entrée Python.

ḣ-2VDṫ-’Ạ×ɗ/«4ị“snrh”e

Un lien monadique.

Essayez-le en ligne! Ou consultez la suite de tests .

Comment?

ḣ-2VDṫ-’Ạ×ɗ/«4ị“snrh”e - Link: list of characters   e.g. "213rd" or "502nd" or "7th"
ḣ-2                    - head to index -2                "213"      "502"      "7"
   V                   - evaluate                         213        502        7
    D                  - cast to decimal list            [2,1,3]    [5,0,2]    [7]
     ṫ-                - tail from index -1                [1,3]      [0,2]    [7]
           /           - reduce with:                                          (no reduction since already length 1)
          ɗ            -   last 3 links as a dyad:                           
       ’               -     decrement (the left)           0         -1        x
        Ạ              -     all? (0 if 0, 1 otherwise)     0          1        x
         ×             -     multiply (by the right)        0          2        x
            «4         - minimum of that and 4              0          2        4
              ị“snrh”  - index into "snrh"                 'h'        'n'      'h'
                     e - exists in? (the input list)        0          1        1
Jonathan Allan
la source
0

05AB1E , 24 octets

0ìþR2£`≠*.•’‘vê₅ù•sèsáнQ

Essayez-le en ligne! ou comme suite de tests

Explication

0ì                         # prepend 0 to input
  þ                        # remove letters
   R                       # reverse
    2£                     # take the first 2 digits
      `≠                   # check if the 2nd digit is false
        *                  # and multiply with the 1st digit
         .•’‘vê₅ù•         # push the string "tsnrtttttt"
                  sè       # index into this string with the number calculated
                    sáн    # get the first letter of the input
                       Q   # compare for equality
Emigna
la source
0

Rubis , 42 39 octets

Lambda:

->s{s*2=~/1..h|[^1](1s|2n|3r|[4-90]t)/}

Essayez-le en ligne!

Entrée utilisateur:

p gets*2=~/1..h|[^1](1s|2n|3r|[4-90]t)/

Essayez-le en ligne!

Allumettes:

  • 1(anything)(anything)h - 12th
  • (not 1)1s - (1st)
  • (not 1)2n - (2nd)
  • (not 1)3r- ( 3rd)

Parce que [^1]( not 1) ne correspond pas au début d'une chaîne, l'entrée est dupliquée pour s'assurer qu'il y a un caractère avant le dernier.


Rubis -n , 35 octets

p~/1..h|([^1]|^)(1s|2n|3r|[4-90]t)/

Essayez-le en ligne!

Même idée que ci-dessus mais au lieu de dupliquer la chaîne, cela correspond également au début de la chaîne ( ^).

Asone Tuhid
la source
0

Excel, 63 octets

=A1&MID("thstndrdth",MIN(9,2*RIGHT(A1)*(MOD(A1-11,100)>2)+1),2)

(MOD(A1-11,100)>2)retourne FALSEquand A1se termine par 11-13

2*RIGHT(A1)*(MOD(A1-11,100)>2)+1retours 1si elle est en 11- 13et 3, 5, 7, etc. autrement

MIN(9,~)modifie les retours ci-dessus 9en 9tirant thde la chaîne

MID("thstndrdth",MIN(~),2)extrait le premier thpour les entrées se terminant par 11- 13, stpour 1, ndpour 2, rdpour 3et le dernier thpour tout ce qui est supérieur.

=A1&MID(~) ajoute le numéro d'origine à l'ordinal.


Publier en tant que wiki car je n'en suis pas l'auteur. ( Source )

2 tours
la source
0

Wolfram Language (Mathematica) , 122 octets

Contrairement à la plupart des autres réponses ici, cela retournera en fait faux lorsque l'entrée n'est pas un "modèle ordinal valide", donc il retournera correctement faux en entrée comme "3a23rd", "singe" ou "╚§ +!". Je pense donc que cela fonctionne pour l'ensemble des chaînes d'entrée possibles.

StringMatchQ[((d=DigitCharacter)...~~"1"~(e=Except)~d~~(e["1"|"2"|"3",d]~~"th")|("1st"|"2nd"|"3rd"))|(d...~~"1"~~d~~"th")]

Essayez-le en ligne!

Kelly Lowder
la source
0

Wolfram Language (Mathematica) , 65 59 octets

SpokenString@p[[#]]~StringTake~{5,-14}&@@ToExpression@#==#&

Essayez-le en ligne!

Bien sûr, Mathematica a un module intégré (bien que non documenté) pour la conversion en nombre ordinal. Source .

(pour la version 65 octets: selon cela, il semble que la v9 et les versions antérieures n'ont pas besoin d'appeler Speakavant, il peut donc être possible d'enregistrer d'autres octets)

Consultez également la réponse de KellyLowder pour une version non intégrée.

user202729
la source
0

PHP, 60 octets

ennuyeux: regexp une fois de plus la solution la plus courte

<?=preg_match("/([^1]|^)(1st|2nd|3rd|\dth)$|1\dth$/",$argn);

sortie vide pour faux, 1pour vrai.

Exécuter en tant que pipe avec -nFou l' essayer en ligne . (TiO enveloppé comme fonction pour plus de commodité)

Titus
la source
0

code machine x86, 65 octets

00000000: 31c0 4180 3930 7cfa 8079 0161 7ef4 8079  1.A.90|..y.a~..y
00000010: ff31 7418 31db 8a19 83eb 308a 9300 0000  .1t.1.....0.....
00000020: 0031 db43 3851 010f 44c3 eb0a 31db 4380  .1.C8Q..D...1.C.
00000030: 7901 740f 44c3 c374 736e 7274 7474 7474  y.t.D..tsnrttttt
00000040: 74                                       t

Assemblée:

section .text
	global func
func:					;the function uses fastcall conventions
					;ecx=first arg to function (ptr to input string)
	xor eax, eax			;reset eax to 0
	read_str:
		inc ecx			;increment ptr to string

		cmp byte [ecx], '0'
		jl read_str		;if the char isn't a digit, get next digit
		cmp byte [ecx+1], 'a'
		jle read_str		;if the char after the digit isn't a letter, get next digit
		cmp byte [ecx-1], '1'
		je tens 		;10-19 have different rules, so jump to 'tens'
		xor ebx, ebx		;reset ebx to 0
		mov bl, byte [ecx]  	;get current digit and store in bl (low byte of ebx)
		sub ebx, 0x30		;convert ascii digit to number
		mov dl, [lookup_table+ebx] ;get correct ordinal from lookup table
		xor ebx, ebx		;reset ebx to 0
		inc ebx			;set ebx to 1
		cmp byte [ecx+1], dl	;is the ordinal correct according to the lookup table?
		cmove eax, ebx		;if the ordinal is valid, set eax (return reg) to 1 (in ebx)
		jmp end			;jump to the end of the function and return

		tens:
		xor ebx, ebx		;reset ebx to 0
		inc ebx			;set ebx to 1
		cmp byte [ecx+1], 't'	;does it end in th?
		cmove eax, ebx		;if the ordinal is valid, set eax (return reg) to 1 (in ebx)

	end:
	ret				;return the value in eax
section .data
	lookup_table db 'tsnrtttttt'

Essayez-le en ligne!

Logern
la source
-1

Expression régulière compatible Perl, 29 octets

1.th|(?<!1)(1s|2n|3r)|[4-90]t

Nous acceptons thaprès tout numéro "adolescent" ou après tout chiffre autre que 1..3. Pour 1..3, nous utilisons un lookbehind de négatif à accepter st, ndou rdseulement lorsqu'ils ne sont pas Précédé par 1.

Programme de test

#!/usr/bin/bash

ok=(✓ ❌)

for i
do grep -Pq '1.th|(?<!1)(1s|2n|3r)|[4-90]t' <<<"$i"; echo $i ${ok[$?]}
done 

Résultats

1st ✓
1th ❌
2nd ✓
2th ❌
3rd ✓
3th ❌
4st ❌
4th ✓
11th ✓
11st ❌
12nd ❌
12th ✓
13th ✓
13rd ❌
112nd ❌
112th ✓
21nd ❌
32nd ✓
33rd ✓
21th ❌
21st ✓
11st ❌
111199231923819238198231923213123909808th ✓
Toby Speight
la source