Comprobación de cadena ordinal

17

Descripción:

Dada una cadena como entrada, verifique si es un número ordinal válido en inglés o no. Si es válido, devuelva el valor verdadero de lo contrario, devuelva el valor falso. (Sugerido por @Arnauld. Gracias. También por @JoKing)

Para usuarios que quieran saber sobre números ordinales, haga clic aquí:

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

Posibles entradas:

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

Este es un desafío de código de golf, por lo que el código más corto en cada idioma será el ganador.

Ejemplos:

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

Dado que muchas personas hicieron la pregunta sobre si las entradas serán solo cadenas válidas o no:

Todas las entradas siempre serán válidas. es decir, estarán en forma de cadena y constarán de un dígito (o número de dígitos) junto con uno de los cuatro sufijos:

st, nd, rd,th

Muhammad Salman
fuente
¿Puedes aclarar las reglas de los números ordinales? O al menos ponga un enlace a las reglas que está siguiendo.
qwr
Son reglas normales. No cambié nada Pero gracias por el aporte, agregué un enlace
Muhammad Salman
@Jonathan Allan Los números ordinales comienzan 1st, los ordinales negativos no existen - english.stackexchange.com/questions/309713/…
Oliver Ni
@JonathanAllan OP dice "La entrada será un patrón ordinal válido". lo que significa que no hay negativos
Oliver Ni
2
Usted dice que las entradas siempre serán válidas, pero creo que un mejor término estaría bien formado . Tanto el 12 como el 12 están bien formados, pero solo el primero es válido .
David Conrad el

Respuestas:

3

Bash + utilidades GNU , 54

La combinación de expresiones regulares parece ser una forma sencilla de hacerlo. Estoy bastante seguro de que esta expresión podría acortarse más:

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

Entrada de STDIN. Salida como un código de retorno de shell: 0 es verdadero y 1 es falso.

Pruébalo en línea!

Trauma digital
fuente
Qué ? Esto no está dando la respuesta correcta.
Muhammad Salman
@MuhammadSalman Eso es porque es un conjunto de pruebas. Eche un vistazo a los códigos de salida para 1sty 1th.
Dennis
egrepes capaz de realizar pruebas de suma y primalidad (en unario), por lo que creo que puede hacer de esto una respuesta egrep.
Dennis
Lo siento, pero mi golpe apesta, ya que no tengo idea de nada. Me aburrí, así que usé un verificador de diferencias para verificar la diferencia entre entrada y salida. Te entiendo. Entonces tengo una pregunta ahora @Dennis: ¿Bash tiene booleanos?
Muhammad Salman
Tal vez los casos de prueba serían más claros si egrepse ejecutaran por separado para cada entrada para obtener el código de salida correspondiente para cada uno: ¡ Pruébelo en línea! .
manatwork
3

esto se da por supuesto que la entrada es un patrón ordinal válido. si no es el caso, se deben hacer cambios

JavaScript (Node.js) , 97 92 78 bytes

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

Pruébalo en línea!

Explicación

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  

_____________________________________________________________________

puerto de @Herman Lauenstein

JavaScript (Node.js) , 48 bytes

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

Pruébalo en línea!

DanielIndie
fuente
Si la solución de supuestos reg también puede ser***.
l4m2
Si no se supone que es / \ d * (st | nd | rd | th) / input, 1stapase la prueba de registro; si se supone, /1.th|(^|[^1])(1s|2n|3r|[^1-3]t)/trabajo
l4m2
3

Python ,  56  53 bytes

-3 gracias a (use la inclusión de letras únicas en lugar de la penúltima igualdad de caracteres)

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

Una función sin nombre.

Pruébalo en línea!

¿Cómo?

Dado que todas las entradas (en este caso v) se garantiza que sea de la forma \d*[st|nd|rd|th]sólo podemos probar si existe un personaje en vel que esperamos estar allí si fuese correcto ( s, n, r, o h, respectivamente) - que es <getExpectedLetter>in v.

El último dígito generalmente determina esto:

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

... excepto cuando el penúltimo dígito es a 1, cuando todo debería terminar con thy, por lo tanto, nuestro carácter esperado debe ser h; para evaluar esto podemos tomar una rebanada (para evitar un error de índice que ocurren para entradas sin -4 ° carácter) v[-4:-3]. Ya que los 0mapas hya podemos lograr el efecto deseado usando la multiplicación antes de indexar 'hsnrhhhhhh'.

Jonathan Allan
fuente
st, nd, rd y th tienen una letra única, por lo que puede probar si ocurre en la cadena de 53 bytes
Asone Tuhid
@AsoneTuhid bonito golf - ¡gracias!
Jonathan Allan
@AsoneTuhid: también guardé tres en mi respuesta de Jelly, ¡así que el doble de gracias!
Jonathan Allan
3

Java 8, 54 51 bytes

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

Explicación:

Pruébalo en línea.

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

Java String # coincide implícitamente agrega ^...$.

Explicación de expresiones regulares:

^.*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
fuente
2

Pyth, 49 60 bytes SBCS

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

Banco de pruebas

SE comió algunos no imprimibles en el código (y en la explicación a continuación) pero están presentes en el enlace.

Explicación:
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
Traducción de 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
fuente
2

Python 2, 92 82 74 68 bytes

-8 gracias a Chas Brown
-6 gracias a Kevin Cruijssen

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

Construye una cadena grande de ths, sts, nds, y rdcomo terminaciones 00a 99. Luego verifica si coincide.

Oliver Ni
fuente
2

Retina , 35 31 bytes

-4 bytes gracias a @Asone Tuhid

Gracias a @Leo por encontrar un error

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

Salidas 1para verdadero y 0para falso. Esto supone que la entrada está en formato ordinal con un sufijo válido (con extremos st, nd, rdo th).

Pruébalo en línea!

Herman L
fuente
1

Jalea ,  25  22 bytes

-3 bytes gracias a una observación realizada en un comentario realizado en mi entrada de Python.

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

Un enlace monádico.

Pruébalo en línea! O vea el conjunto de pruebas .

¿Cómo?

ḣ-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
fuente
0

05AB1E , 24 bytes

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

Pruébalo en línea! o como un conjunto de pruebas

Explicación

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
fuente
0

Ruby , 42 39 bytes

Lambda

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

Pruébalo en línea!

Entrada del usuario:

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

Pruébalo en línea!

Partidos:

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

Debido a que [^1]( not 1) no coincide con el comienzo de una cadena, la entrada se duplica para asegurarse de que haya un carácter antes del último.


Ruby -n , 35 bytes

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

Pruébalo en línea!

La misma idea que la anterior, pero en lugar de duplicar la cadena, esto también coincide con el inicio de la cadena ( ^).

Asone Tuhid
fuente
0

Excel, 63 bytes

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

(MOD(A1-11,100)>2)regresa FALSEcuando A1termina con11 -13

2*RIGHT(A1)*(MOD(A1-11,100)>2)+1regresa 1si está en 11- 13y 3,5 , 7, etc. de otra manera

MIN(9,~)cambia cualquier retorno anterior 9en9 tirar de la thde la cadena

MID("thstndrdth",MIN(~),2)extrae el primero thpara las entradas que terminan en 11- 13, stpara 1, ndpara 2, rdpara3 y el último thpara cualquier cosa más alta.

=A1&MID(~) antepone el número original al ordinal.


Publicar como wiki ya que no soy el autor de esto. ( Fuente )

tostadas de ingeniero
fuente
0

Wolfram Language (Mathematica) , 122 bytes

A diferencia de la mayoría de las otras respuestas aquí, esto en realidad devolverá falso cuando la entrada no sea un "patrón ordinal válido", por lo que correctamente devolverá falso en entradas como "3a23rd", "monkey" o "╚§ +!". Así que creo que esto funciona para todo el conjunto de posibles cadenas de entrada.

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

Pruébalo en línea!

Kelly Lowder
fuente
0

Wolfram Language (Mathematica) , 65 59 bytes

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

Pruébalo en línea!

Por supuesto, Mathematica tiene una función incorporada (aunque no documentada) para convertir a un número ordinal. Fuente .

(para la versión de 65 bytes: según parece, v9 y antes no necesitan llamar Speak antes, por lo que es posible guardar algunos bytes más)

Consulte también la respuesta de KellyLowder para una versión no incorporada.

usuario202729
fuente
0

PHP, 60 bytes

aburrido: regexp una vez más la solución más corta

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

salida vacía para falsedad, 1 para verdad.

Ejecutar como tubería con -nFo probarlo en línea . (TiO envuelto como función para mayor comodidad)

Tito
fuente
0

código de máquina x86, 65 bytes

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

Montaje:

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'

Pruébalo en línea!

Logern
fuente
-1

Expresión regular compatible con Perl, 29 bytes

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

Aceptamos thdespués de cualquier número "adolescente", o después de cualquier dígito que no sea 1..3. Para 1..3, se utiliza una búsqueda hacia atrás negativa a aceptar st, ndo rdsólo cuando no precedida de 1.

Programa de prueba

#!/usr/bin/bash

ok=(✓ ❌)

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

Resultados

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
fuente