g | x | w | all
Bytes Lang Time Link
108AWK250820T140819Zxrs
084Retina240627T210102Zmbomb007
074Perl 5 + pl060F240627T123532ZDom Hast
040Japt240626T195155ZShaggy
085Zsh240626T214608ZGammaFun
099R240626T162046ZGlory2Uk
123Python220909T225423Z97.100.9
057Brachylog220909T213551ZDLosc
150Java JDK170519T090203ZOlivier
008Vyxal220909T012121Zlyxal
120Retina170518T222030Zeush77
155Python 2170523T080941ZGáb
198C170521T083250ZKhaled.K
254Java170521T071832ZKhaled.K
099Javascript ES6170519T010312Znderscor
060Ruby + to_words170518T231106ZValue In
028Jelly170518T220705ZJonathan
163Bash170519T130143Zmarcosm
087PHP>=7.0170518T224838ZJör
041Pyth170519T095604ZKarlKast
052Japt170519T093609ZLuke
148Python170518T230646ZJonathan
083Mathematica170518T220651ZGreg Mar
121Javascript170519T041136ZSteve Be
128PHP170518T232348ZTitus
121JavaScript ES6170519T000738ZNeil
111Haskell170518T230916Znimi
02605AB1E170518T220749ZAdnan
150Python 3170518T213824Z0WJYxW9F

AWK, 108 bytes

{a="ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE"
gsub(/[A-Z]/,"&.*",a)
for(;i++<split(a,b);)$1~b[i]&&$0=i}1

Attempt This Online!

Prints your digit, or it prints the word back to you for falsey. You could add a ,$0+=0 to the end to get a zero instead.

Retina, 84 bytes

K`ONE1TWO2THREE3FOUR4FIVE5SIX6SEVEN7EIGHT8NINE9
[A-Z]
.$*$0.$*
\d
¶$0¶
"$+"~`¶$
¶\D¶

Try it online!

Explanation

This discards the input and generates the program to use

K`ONE1TWO2THREE3FOUR4FIVE5SIX6SEVEN7EIGHT8NINE9  # K (constant): discard input, use the string
[A-Z]                               # Replace each letter
.$*$0.$*                            # With ".*" before and after the match
\d                                  # Replace each digit
¶$0¶                                # With a newline before and after the match
¶$                                  # Replace the final newline/end
¶\D¶                                # With "¶\D¶"

Generates this:

.*O.*.*N.*.*E.*
1
.*T.*.*W.*.*O.*
2
.*T.*.*H.*.*R.*.*E.*.*E.*
3
.*F.*.*O.*.*U.*.*R.*
4
.*F.*.*I.*.*V.*.*E.*
5
.*S.*.*I.*.*X.*
6
.*S.*.*E.*.*V.*.*E.*.*N.*
7
.*E.*.*I.*.*G.*.*H.*.*T.*
8
.*N.*.*I.*.*N.*.*E.*
9
\D

Then this configuration on the last Eval ~ stage evaluates that program using the initial input, gotten with "$+".

"$+"~`

Perl 5 + -pl060F, 74 bytes

$"="*";$\||=/^@F*$/*++$-for ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE}{

Try it online!

Japt, 40 bytes

Ò`ÆRtwodÈ(‚fÆfivÀ£xç P ightdÍÂ`qd a!øUà

Try it

Ò`...`qd a!øUà     :Implicit input of lowercase string U
Ò                  :Negate the bitwise NOT of
 `...`             :  Compressed string of lowercase digit names, delimited with "d"
      qd           :  Split on "d"
         a         :  0-based index of first element (or -1 if no element)
          !ø       :    Contained in
            Uà     :      Combinations of U

Zsh, 85 bytes

for d (ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE);((++i,${#1:#${~d///*}*}))||bye i

Try it online!

The magic happens at ${~d///*}*, which turns ONE into *O*N*E*, etc. The :# operator removes the whole string if it matches, so if it's length is zero, (( )) is falsy and we exit with $i as the retcode.

If there's no matches, it will exit with 0, since the last command run was a truthy (( )).

Zsh, 96 bytes

local -A A
for d (ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE);A[${d///*}*]=$[++i]
<<<$A[(k)$1]

Try it online!

A much cooler variant imo, using the k subscript flag. It's unfortunate that associative arrays have to be declared with local -A, unlike normal arrays.

k: If used in a subscript on an associative array, this flag causes the keys to be interpreted as patterns, and returns the value for the first key found where exp is matched by the key. Note this could be any such key as no ordering of associative arrays is defined. This flag does not work on the left side of an assignment to an associative array element. If used on another type of parameter, this behaves like r.

R, 103 102 99 bytes

\(s)grep("^[MI]*$",attr(adist(scan(,s,t="ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE"),s,,T),"t"))

Attempt This Online!

Once again, a solution that relies upon the Levenshtein distances. Here as the output from the adist function the trafos patterns are used. These patterns are strings with the lengthes corresponding either to the input or to the output string, with 4 possible code letters: M- if the character has not been changed, I - a new character inserted, D - deleted, S - substituted. We only need to filter the trafos having neither substitutions nor deletions.

Conveniently, grep gives the position of the matched digit. If no digit was matched, the output is integer(0).

Python, 125 123 bytes

f=lambda b,x=9,i=0:x and f(b,x-1)+x*all(i:=b.find(c,i)+1for c in"NINE EIGHT SEVEN SIX FIVE FOUR THREE TWO ONE".split()[-x])

Attempt This Online!

-2 bytes from @xnor, also fixing a misalignment with the spec

Brachylog, 57 bytes

∧"ONE
TWO
THREE
FOUR
FIVE
SIX
SEVEN
EIGHT
NINE"ṇi₁Ph⊆?∧Pt

Try it online!

Explanation

I think this could be shorter if i were reversible, but it doesn't appear to be.

∧"..."ṇi₁Ph⊆?∧Pt
∧                  Break unification with input
 "..."             String containing words ONE through NINE, newline-separated
      ṇ            Split on newlines
       i₁          [item, index] pair for some item in that list (1-based index)
         P         Call that pair P
          h        Its first element (the word)
           ⊆       is a non-contiguous substring of
            ?      the input
             ∧     And
               Pt  P's last element (the index) is the output

Java (JDK), 150 bytes

s->{for(var i=0;i<9;)if(s.matches("."+"ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE".split(" ")[i++].replaceAll(".","*$0.")+"*"))return i;return"NO";}

Try it online!

Saves

Vyxal, 9 8 bytes

9'∆ċ?ṗṠc

Try it Online!

-1 thanks to EmanresuA

9 bytes but faster:

9'∆ċ:?Þ∩=

Try it Online!

The joys of having number to word built-ins!

Explained

9'∆ċ:?Þ∩=
9'        # From the range [1, 9], keep only items n where:
  ∆ċ      #   n as a word
     ?Þ∩  #   under multiset intersection with the input
    :   = #   is the same. 

Retina, 160 126 120 bytes

O.*N.*E
1
T.*W.*O
2
T.*H.*R.*E.*E
3
F.*O.*U.*R
4
F.*I.*V.*E
5
S.*I.*X
6
S.*E.*V.*E.*N
7
E.*I.*G.*H.*T
8
N.*I.*N.*E
9
\D

Try it online!

Returns an empty string if the input does not contain a digit.

-6 bytes thanks to @CalculatorFeline.

Python 2, 155 bytes

import re;lambda k:next((i for i,j in enumerate([re.search('.*'.join(list(s)),k)for s in'ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE'.split()])if j),-1)+1

An anonymous function searching for regex group. Not the best solution here in Python but an alternative way.

C, 198 bytes

Try Online

char*T[]={"ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN","EIGHT","NINE"};
g(char*a,char*b){while(*a&*b)a+=(*b++==*a);return!*a;}
i;char*f(char*b){for(i=0;i<9;i++)if(g(T[i],b))return T[i];return"NO";}

Java, 254 bytes

int g(String a,String b){int i=0,p=0;for(char c:a.toCharArray()){p=i;i=b.indexOf(c);if(i<=p)return 0;}return 1;}
String f(String a){String[]T={"ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN","EIGHT","NINE"};for(String t:T)if(g(t,a)>0)return t;return"NO";}

Try Online

boolean g(String a,String b)
{
    int i = 0, p = 0;
    for(char c:a.toCharArray())
    {
        p = i;
        i = b.indexOf(c);
        if(i <= p) return false;
    }
    return true;
}

String f(String a)
{
    String[]T={"ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN","EIGHT","NINE"};
    for(String t:T)if(g(t,a))return t;
    return"NO";
}

Javascript (ES6), 101 99 bytes

f=
s=>-~'ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE'.split` `.findIndex(x=>s.match([...x].join`.*`))
<!-- snippet demo: -->
<input list=l oninput=console.log(f(this.value))>
<datalist id=l><option value=BOUNCE>
<option value=ENCODE>
<option value=EIGHT>
<option value=BLACKJACK>
<option value=FABULOUS>
<option value=EXERCISE>
<option value=DRIFTWOOD>
<option value=SERVICEMAN>
<option value=INSIGNIFICANCE>
<option value=THROWDOWN>
<option value=ZERO>
<option value=OZNERO>

Ruby + to_words: 49 48+12 = 61 60 bytes

Uses the flags -rto_words -n. Takes lowercase words. Returns nil if no "digit" found.

-1 byte now that lowercase input is allowed, allowing for the removal of the i flag on the regex.

p (1..9).find{|i|$_=~/#{i.to_words.chars*".*"}/}

For a more pure Ruby answer without external gems, 91+1 = 92 bytes:

p (1..9).find{|i|$_=~/#{%w"0 ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE"[i].chars*".*"}/}

Jelly, 31 28 bytes

-2 bytes now that lowercase input is acceptable

“¡¦ẇṆb~ṇjṚØ%ĖġṘḥḞṾṇJḌ»Ḳe€ŒPT

A full program that expects lowercase input and prints the result, using 0 for the falsey case.

As a monadic link taking a list of characters it actually returns a list of integers which contains a single 0 in the falsey case, a single integer between 1 and 9 inclusive in the expected use cases and multiple such entries in cases where more than one number exists in the word.

Try it online!

How?

“¡¦ẇṆb~ṇjṚØ%ĖġṘḥḞṾṇJḌ»Ḳe€ŒPT - Main link: list of characters, s
“¡¦ẇṆb~ṇjṚØ%ĖġṘḥḞṾṇJḌ»       - dictionary lookup of "one two three four five six seven eight nine"
                      Ḳ      - split on spaces
                         ŒP  - partitions of s
                       e€    - exists in? for €ach
                           T - truthy indexes

Bash, 163 bytes

a=NO;case $1 in *O*N*E*)a=1;;*T*W*O*)a=2;;*T*H*R*E*E*)a=3;;*F*O*U*R*)a=4;;*F*I*V*E*)a=5;;*S*I*X*)a=6;;*S*E*V*E*N*)a=7;;*E*I*G*H*T*)a=8;;*N*I*N*E*)a=9;;esac;echo $a

Try it online!

a=NO;
case $1 in
 *O*N*E*)a=1;;
 *T*W*O*)a=2;;
 *T*H*R*E*E*)a=3;;
 *F*O*U*R*)a=4;;
 *F*I*V*E*)a=5;;
 *S*I*X*)a=6;;
 *S*E*V*E*N*)a=7;;
 *E*I*G*H*T*)a=8;;
 *N*I*N*E*)a=9;;
esac;
echo $a

Don't know RETINA but seems a straight port of that answer.

PHP>=7.0, 87 Bytes

<?for(;$i++<9;)levenshtein(IntlChar::charName("$i"),"DIGIT $argn",0,1,1)?:die("$i")?>NO

If only insertions of chars from one digit as word to the input is done exit the program with the digit. Or change the order to levenshtein("DIGIT $argn",IntlChar::charName("$i"),1,1,0) to count not the deletions of chars

levenshtein

IntlChar::charName

PHP>=7.0, 112 Bytes

for(;$i<9;)$r+=++$i*preg_match("#".chunk_split(substr(IntlChar::charName("$i"),6),1,".*")."#",$argn);echo$r?:NO;

IntlChar::charName

PHP, 128 Bytes

foreach([ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE]as$v)$r+=++$k*preg_match("#".chunk_split($v,1,".*")."#",$argn);echo$r?:NO;

Try it online!

143 Bytes for more then 1 digit

foreach([ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE]as$v)$r.=++$k*preg_match("#".chunk_split($v,1,".*")."#",$argn);echo+$r?strtr($r,[""]):NO;

Try it online!

Pyth, -44- 41 bytes

+1xm}dyQc."EX%~)Û#lº,îQÓCe¯4Aô4"\P1

Takes a quoted string, outputs 0 for NO.

Try it!

explanation

+1xm}dyQc."EX%~)Û#lº,îQÓCe¯4Aô4"\P1
         ."EX%~)Û#lº,îQÓCe¯4Aô4"      # Compressed string: "ONEPTWOPTHREEPFOURPFIVEPSIXPSEVENPEIGHTPNINE" (P is close to the other letters, makes the compression better)
        c                       \P    # split on P: ['ONE', 'TWO', 'THREE', 'FOUR', 'FIVE', 'SIX', 'SEVEN', 'EIGHT', 'NINE']
   m                                  # map over this list (variable: d)
    }dyQ                              # is d a (ordered) subset of the input (Q)? (= element of the powerset)
  x                                1  # get the index of the first true
+1                                    # add one, because the list was indexed at 0 and conveniently -1 (not found) becomes 0 

Japt, 52 bytes

1+`e two È(e fŒr five £x  v eight ͍`¸a@v fX¬q".*

Try it online!

Python, 148 bytes

from itertools import*
lambda s:[tuple(w)in combinations(s,len(w))for w in("x ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE "+s).split()].index(1)%10

An unnamed function taking an uppercase only word and returning the integer (1 to 9), or 0 for NO.

Try it online!

How?

For an input string s the function traverses through a list of the strings: "x", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT" , "NINE", and s itself looking for any matches.*

The comparison used is whether this string, w, is one that may be formed from a combination of letters in order from the input. The function combinations gets these for us (and only the ones of the required length using len(w)), but they are in the form of tuples, so the strings are cast to tuples for the comparison.

Of the eleven results the one for "x" will always be False, while the one for s itself will always be True. The "x" is there to ensure the index of a match with ONE through NINE are the values required (since Python lists are 0-indexed), the s is there to ensure the call to index(1) (synonymous with index(True)) wont fail when no digit word was found, whereupon the resulting 10 is converted to a 0 with a modulo of ten using %10.

* If s contains spaces for some reason, the list of ws will be longer, but the process will still work since the digit word matches will work the same way, and if none match the first space-split substring from s will match, once again giving 10 and returning 0.

If multiple digit words exist the function will return the minimal one.

Mathematica, 83 bytes (WindowsANSI encoding)

±w_:=Rest@Position[Subsets@w~Cases~#&/@Characters@*IntegerName~Array~9,Except@{},1]

Defines a unary function ± that takes a list of lowercase characters as input and returns either a digit, in a form like {{7}}, or else an empty list {}. I don't feel like I did a ton of golfy things here, except that Characters@*IntegerName~Array~9 generates the number-name matches to look for without hard-coding them.

Example usage:

±{"i", "n", "s", "i", "g", "n", "i", "f", "i", "c", "a", "n", "c", "e"}

yields {{9}}.

Javascript, 121 bytes

(s,a=0)=>'ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE'.split``.map((p,i)=>RegExp(p.split``.join`.*`).exec(s)?a=i+1:0)&&a

or 116

(s,a=0)=>' ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE'.split` `.map((p,i)=>a|=~s.search(p.split``.join`.*`)&&i)&&a

But just recycling material at this point.

PHP, 134 132 128 bytes

<?=preg_match(strtr(chunk_split("#(ONE0TWO0THREE0FOUR0FIVE0SIX0SEVEN0EIGHT0NINE",1,".*"),[")|("]).")#",$argn,$m)?count($m)-1:NO;

run as pipe with -nF or try it online.

Creates a regex with the words in parentheses; i.e. each word N is in the Nth sub-expression.
If a word is found, the matched string will be in $m[0] and in the the Nth element, with the elements between them empty and no empty string behind; i.e. $m has N+1 elements.

JavaScript (ES6), 121 bytes

f=
s=>[...s].map(c=>a=a.map(s=>s.slice(s[0]==c)),a=`ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE`.split` `)&&1+a.indexOf(``)
<input oninput=o.textContent=f(this.value)><pre id=o>0

Returns the lowest detected digit or 0 if no digit was detected (+6 if NO is required).

Haskell, 113 111 bytes

import Data.List
last.((`elemIndices`([]:words"ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE"))=<<).subsequences

Try it online!

Returns 0 if no digit is found.

Find all subsequences of the input word in the list of digits. Prepend an empty string [] at index 0 which is part of every subsequence. elemIndices returns a list of indices and =<< flattens them into a single list. Pick the last index.

05AB1E, 26 bytes

The falsy value here is 0.

æ‘€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š‘#å1k>

Explanation:

æ                           # Compute the powerset of the input
 ‘€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š‘       # Push "ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE"
                     #      # Break on spaces
                      å     # Check each for membership
                       1k   # Get the index of 1 in the array (-1 if not found)
                         >  # Increment by one

Uses the 05AB1E encoding. Try it online! or Verify all test cases!

Python 3, 150 bytes

from itertools import*;lambda x:([i for i in range(10)if(*' OTTFFSSENNWHOIIEIIEORUVXVGN  ERE EHE  E   NT '[i::9],)in[*combinations(x+'  ',5)]]+[0])[0]

combinations returns all the combinations of things in order. It would be simpler to have a set number for the second parameter of combinations, so spaces are added onto the end of the original string that is a parameter of my lambda. That's a simple description of how my entry works. Ask if you would like any more clarification.