Pemeriksaan string ordinal

17

Deskripsi:

Diberikan string sebagai input, periksa apakah itu nomor urut yang valid dalam bahasa Inggris atau tidak. Jika valid mengembalikan nilai kebenaran, sebaliknya mengembalikan nilai palsu. (Disarankan oleh @Arnauld. Terima kasih. Juga oleh @JoKing)

Untuk pengguna yang ingin tahu tentang nomor urut, buka di sini:

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

Input yang mungkin:

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

Ini adalah tantangan kode golf sehingga kode terpendek di setiap bahasa akan menjadi pemenangnya.

contoh:

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

Karena banyak orang mengajukan pertanyaan mengenai apakah input hanya berupa string yang valid atau tidak:

Semua input akan selalu valid. yaitu mereka akan dalam bentuk string dan terdiri dari digit (atau jumlah digit) bersama dengan salah satu dari empat sufiks:

st, nd, rd,th

Muhammad Salman
sumber
Bisakah Anda mengklarifikasi aturan nomor urut? Atau setidaknya pasang tautan ke apa aturan yang Anda ikuti.
qwr
Itu adalah aturan normal. Saya tidak mengubah apa pun. Tapi terima kasih atas masukannya, saya menambahkan tautan
Muhammad Salman
@Jonathan Allan Nomor urut ordinal mulai dari 1st, ordinal negatif tidak ada - english.stackexchange.com/questions/309713/…
Oliver Ni
@JonathanAllan OP mengatakan "Input akan menjadi pola ordinal yang valid." yang berarti tidak ada yang negatif
Oliver Ni
2
Anda mengatakan input akan selalu valid tetapi saya pikir istilah yang lebih baik akan terbentuk dengan baik . Baik ke-12 dan ke-12 terbentuk dengan baik tetapi hanya yang pertama yang valid .
David Conrad

Jawaban:

3

Utilitas Bash + GNU , 54

Pencocokan Regex tampaknya merupakan cara yang mudah untuk dilakukan. Saya cukup yakin ungkapan ini dapat dipersingkat lebih:

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

Masukan dari STDIN. Output sebagai kode pengembalian shell - 0 benar dan 1 palsu.

Cobalah online!

Trauma Digital
sumber
Apa ? ini bukan menghasilkan jawaban yang benar.
Muhammad Salman
@MuhammadSalman Itu karena itu adalah test suite. Lihatlah kode keluar untuk 1stdan 1th.
Dennis
egrepmampu melakukan pengujian penjumlahan dan primality (dalam unary), jadi saya pikir Anda dapat membuat ini jawaban egrep.
Dennis
Saya minta maaf tetapi bash saya menyebalkan karena saya tidak tahu tentang sesuatu di dalamnya. Saya bosan jadi menggunakan checker diff untuk memeriksa perbedaan antara input dan output. Saya mengerti maksud Anda. Jadi saya punya satu pertanyaan sekarang @ Dennis: Apakah Bash punya boolean?
Muhammad Salman
Mungkin kasus uji akan lebih jelas jika egrepakan dieksekusi secara terpisah untuk setiap input untuk mendapatkan kode keluar yang cocok untuk masing-masing: Coba online! .
manatwork
3

ini dengan asumsi bahwa input adalah pola ordinal yang valid. jika itu bukan perubahan kasus perlu dilakukan

JavaScript (Node.js) , 97 92 78 byte

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

Cobalah online!

Penjelasan

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  

_____________________________________________________________________

pelabuhan @Herman Lauenstein

JavaScript (Node.js) , 48 byte

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

Cobalah online!

DanielIndie
sumber
Jika asumsi solusi reg juga bisa***.
14m2
Jika tidak diasumsikan / \ d * (st | nd | rd | th) / input, 1stalulus tes reg; jika diasumsikan, /1.th|(^|[^1])(1s|2n|3r|[^1-3]t)/bekerja
14m2
3

Python ,  56  53 byte

-3 terima kasih kepada (gunakan penyertaan huruf yang unik alih-alih kesetaraan karakter kedua dari belakang)

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

Fungsi yang tidak disebutkan namanya.

Cobalah online!

Bagaimana?

Karena semua masukan (di sini v) dijamin menjadi bentuk yang \d*[st|nd|rd|th]kita dapat hanya menguji apakah karakter ada di vmana kami berharap untuk berada di sana jika itu benar ( s, n, r, atau h, masing-masing) - yang <getExpectedLetter>in v.

Digit terakhir biasanya menentukan ini:

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

... kecuali jika digit kedua dari belakang adalah a 1, ketika semua harus diakhiri thdan karenanya karakter yang kita harapkan haruslah h; untuk mengevaluasi ini kita dapat mengambil sepotong (untuk menghindari kesalahan indeks terjadi untuk input tanpa -4 th karakter) v[-4:-3]. Sejak 0peta hsudah kita dapat mencapai efek yang diinginkan menggunakan perkalian sebelum pengindeksan ke 'hsnrhhhhhh'.

Jonathan Allan
sumber
st, nd, rd dan th semua memiliki huruf yang unik sehingga Anda dapat menguji apakah itu terjadi dalam string 53 byte
Asone Tuhid
@AsoneTuhid golf yang bagus - terima kasih!
Jonathan Allan
@ AsoneTuhid - juga menyimpan tiga jawaban Jelly saya, jadi gandakan terima kasih!
Jonathan Allan
3

Java 8, 54 51 byte

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

Penjelasan:

Cobalah online.

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

String Java # cocok ditambahkan secara implisit ^...$.

Penjelasan regex:

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

Pyth, 49 60 byte SBCS

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

Suite uji

SE memakan beberapa unsintables dalam kode (dan dalam penjelasan di bawah) tetapi mereka ada di tautan.

Penjelasan:
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
Terjemahan 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
sumber
2

Python 2, 92 82 74 68 byte

-8 Terima kasih kepada Chas Brown
-6 terima kasih kepada Kevin Cruijssen

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

Membangun string besar ths, sts, nds, dan rds untuk akhiran 00untuk 99. Kemudian periksa untuk melihat apakah cocok.

Oliver Ni
sumber
2

Retina , 35 31 byte

-4 byte terima kasih kepada @Asone Tuhid

Terima kasih kepada @ Leo untuk menemukan bug

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

Output 1untuk benar dan 0salah. Ini mengasumsikan input dalam format ordinal dengan akhiran valid (berakhir dengan st, nd, rdatau th).

Cobalah online!

Herman L.
sumber
1

Perl 5 -n , 57 byte

/..$/;say$&eq(th,st,nd,rd,(th)x6)[$_%100-$_%10-10&&$_%10]

Cobalah online!

Xcali
sumber
1

Jelly ,  25  22 byte

-3 byte berkat pengamatan yang dibuat dalam komentar yang dibuat pada entri Python saya.

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

Tautan monadik.

Cobalah online! Atau lihat test-suite .

Bagaimana?

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

05AB1E , 24 byte

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

Cobalah online! atau sebagai Test suite

Penjelasan

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

Ruby , 42 39 byte

Lambda:

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

Cobalah online!

Input pengguna:

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

Cobalah online!

Cocok:

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

Karena [^1]( not 1) tidak cocok dengan awal string, input diduplikasi untuk memastikan ada karakter sebelum yang terakhir.


Ruby -n , 35 byte

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

Cobalah online!

Gagasan yang sama seperti di atas tetapi alih-alih menduplikasi string, ini juga cocok dengan awal string ( ^).

Asone Tuhid
sumber
0

Excel, 63 byte

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

(MOD(A1-11,100)>2)kembali FALSEsaat A1diakhiri dengan 11-13

2*RIGHT(A1)*(MOD(A1-11,100)>2)+1kembali 1jika dalam 11- 13dan 3, 5, 7, dll. jika tidak

MIN(9,~)mengubah pengembalian apa pun di atas 9ke dalam 9untuk menarik thdari string

MID("thstndrdth",MIN(~),2)mengeluarkan yang pertama thuntuk input yang diakhiri dengan 11- 13, stuntuk 1, nduntuk 2, rduntuk 3, dan yang terakhir thuntuk sesuatu yang lebih tinggi.

=A1&MID(~) menambahkan nomor asli ke ordinal.


Posting sebagai wiki karena saya bukan penulisnya. ( Sumber )

Engineer Toast
sumber
0

Bahasa Wolfram (Mathematica) , 122 byte

Tidak seperti kebanyakan jawaban lain di sini, ini sebenarnya akan mengembalikan false ketika input bukan "pola ordinal yang valid", jadi itu akan benar mengembalikan false pada input seperti "3a23rd", "monyet" atau "+§ +!". Jadi saya pikir ini berfungsi untuk seluruh rangkaian string input yang mungkin.

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

Cobalah online!

Kelly Lowder
sumber
0

Bahasa Wolfram (Mathematica) , 65 59 byte

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

Cobalah online!

Tentu saja Mathematica memiliki built-in (walaupun tidak berdokumen) untuk mengkonversi ke nomor urut. Sumber .

(untuk versi 65-byte: menurut itu tampaknya v9 dan sebelumnya tidak perlu memanggil Speaksebelumnya sehingga mungkin untuk menyimpan lebih banyak byte)

Lihat juga jawaban KellyLowder untuk versi yang bukan bawaan .

pengguna202729
sumber
0

PHP, 60 byte

membosankan: regexp sekali lagi solusi terpendek

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

output kosong untuk kepalsuan, 1untuk kebenaran.

Jalankan sebagai pipa dengan -nFatau coba online . (TiO dibungkus sebagai fungsi untuk kenyamanan)

Titus
sumber
0

kode mesin x86, 65 byte

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

Majelis:

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'

Cobalah online!

Logern
sumber
-1

Ekspresi reguler yang kompatibel dengan Perl, 29 byte

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

Kami menerima thsetelah nomor "remaja", atau setelah angka apa pun selain 1..3. Untuk 1..3, kita menggunakan lookbehind negatif untuk menerima st, ndatau rdhanya ketika tidak didahului oleh 1.

Program uji

#!/usr/bin/bash

ok=(✓ ❌)

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

Hasil

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
sumber