You are given two strings, each consisting of the English word for a number between 1 and 13:
one, two, three, four, five, six, seven, eight, nine, ten, eleven, twelve, thirteen
Your program or function must find out whether it's possible to spell at least one other word from the same list without using any of the letters used in the two input words.
You can follow this link to see a naive, ungolfed implementation along with the table of all possible I/O.
Examples
If the input is
['six', 'four'], we can spell'ten','eleven'or'twelve'so the answer is yes.If the input is
['five', 'seven'], we can only spell'two'but the answer is still yes.If the input is
['one', 'six'], we cannot spell any other number so the expected answer is no.
Rules
- You may take the words in any reasonable format. They can be in either lower case (
'one'), upper case ('ONE') or title case ('One'), but it must be consistent. - You may be given twice the same word.
- The order of the words is not guaranteed (i.e. your code must support both
['four', 'six']and['six', 'four']). - You may return either truthy / falsy values (inverting the meaning is permitted) or two distinct and consistent values of your choice.
- This is code-golf.
21 Answers 21
J, 19 bytes
Takes input as six four. As the input range is limited, I just deleted characters while the output stayed the same. :-) Reads like "if there is no e in the input, or if there are no t and o in the input, ... then we can spell another number."
e.e`to`for`si-.~&><
e.e`to`for`si-.~&><
&>< boxing stuff
e`to`for`si for each e, to, for, si:
-.~ delete from the input any character from the list
e. is the input still in the results, i.e. is there any
case were no character got deleted?
-
8\$\begingroup\$ Nice answer! ;-) \$\endgroup\$Arnauld– Arnauld2020年12月04日 18:04:11 +00:00Commented Dec 4, 2020 at 18:04
Jelly, 15 bytes
"Œ}İs~#2ð»Ḳḟ@€i
Adaptation of xash's J answer. Returns a non-zero integer (truthy) for yes and 0 (falsey) for no. The footer generates all test cases and tests them (mapping truthy and falsey to 1 and 0 for readability)
My original answer was 38 bytes:
"}ICẸƁÄĊ}¿ȥ~ṢṄO44ƓX9Ỵ9ÑẠỤẠḣ|¿;»ḲiⱮ€Q§Ạ
Returns a falsey value if the answer is yes and a truthy value otherwise
Basic naive compression approach, (削除) I'm sure there's a shorter answer out there that exploits some property that's shorter (削除ここまで)
Both input in the form six four
How they work
"Œ}İs~#2ð»Ḳḟ@€i - Main link. Takes s on the left
"Œ}İs~#2ð» - "e to for si"
Ḳ - ["e", "to", "for", "si"]
€ - Over each k of these:
ḟ@ - Yield s with characters in k removed
i - Index of s in this list or 0
And the 38 byte compression version:
"}ICẸƁÄĊ}¿ȥ~ṢṄO44ƓX9Ỵ9ÑẠỤẠḣ|¿;»ḲiⱮ€Q§Ạ - Main link. Takes s on the left
"}ICẸƁÄĊ}¿ȥ~ṢṄO44ƓX9Ỵ9ÑẠỤẠḣ|¿;» - "one two ... twelve thirteen"
Ḳ - Split on spaces
Q - s deduplicated
€ - Over each number n:
Ɱ - Over each character c in s:
i - Index of c in n else 0
§ - Sums
Ạ - Does not contain 0
Retina 0.8.2, 23 bytes
G`t|o
G`f|o|r
G`s|i
G`e
Try it online! Link includes all 169 possible inputs. Leaves the input unchanged if no numbers are possible, but outputs nothing if other numbers are possible. Explanation:
G`t|o
The input must contain t or o in order to prevent two from being possible; only two and twelve contain w, so if there's a w then t is already present.
G`f|o|r
The input must contain f, o or r in order to prevent four from being possible; only four contains u, so if there's a u then f, o and r are already present.
G`s|i
The input must contain s or i in order to prevent six from being possible; only six contains x, so if there's an x then s and i are already present.
G`e
The input must contain e in order to prevent eleven from being possible; only eleven and twelve contain l, only five, seven, eleven and twelve contain v, and only one, seven, nine, ten, eleven and thirteen contain n, so if there's an l, a v or an n then e is already present. Additionally, only two, four and six do not contain an e, so no other letters need to be tested.
-
\$\begingroup\$ You followed the exact same chain of logic I used, just seven hours earlier than me. I don't think I can beat this Retina solution with this approach, so I'll just settle for upvoting yours. \$\endgroup\$Silvio Mayolo– Silvio Mayolo2020年12月05日 03:29:13 +00:00Commented Dec 5, 2020 at 3:29
-
\$\begingroup\$ @SilvioMayolo It looks as if xash beat me to it anyway. (I didn't understand his program, so I didn't realise it at the time, but XCali ported it, so it must be the same.) \$\endgroup\$Neil– Neil2020年12月05日 07:22:00 +00:00Commented Dec 5, 2020 at 7:22
05AB1E, (削除) 35 (削除ここまで) 34 bytes
J"€μ‚•„í†ìˆÈŒšï¿Ÿ ̄\Š—¿áÓÁÏ"#€SåO0å
You must compress, if not, be distressed.
Inputs as lowercase.
How?
J # Join the two input numbers into a string
"€μ‚•„í†ìˆÈŒšï¿Ÿ ̄\Š—¿áÓÁÏ" # Push the number words from "one" to "thirteen"
Så # Are each character in the input?numbers? 1 if yes, 0 if not
€ O # Sum the results for each word
0å # Is there a 0 on a word?
# (implicitly) Print the answer
-
\$\begingroup\$ You'll save a byte by taking input as a single string already (see comments to question). \$\endgroup\$Dominic van Essen– Dominic van Essen2020年12月05日 10:22:08 +00:00Commented Dec 5, 2020 at 10:22
-
\$\begingroup\$ You can save a byte by changing
#€StoS#. \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2020年12月07日 08:23:14 +00:00Commented Dec 7, 2020 at 8:23
Japt -x, 14 bytes
Adaptation of xash's J solution so be sure to upvote them, too.
Input as a single lowercase delimited string, outputs a positive integer for true and 0 for false.
`èJ-n£`qÍ£¶kX
Try it or try all possible pairs (with 1 used for true)
C (gcc), (削除) 130 (削除ここまで) (削除) 128 (削除ここまで) 102 bytes
Saved 2 bytes thanks to ceilingcat!!!
Saved a whopping 26 bytes thanks to AZTECCO!!!
a,b,i;f(s,j)char*s,*j;{for(a=b=0,i=11;i--;i%3||(b+=!a,a=0))for(j=s;*j;)a+="e..to.forsi"[i]==*j++;b=b;}
Uses xash's idea from his J answer.
Inputs a string of two words separated by a space and returns a truthy value if it's possible to spell at least one other word from the given list without using any of the letters used in the two input words or a falsy value otherwise.
-
-
\$\begingroup\$ @AZTECCO Very nice - thanks! :D \$\endgroup\$Noodle9– Noodle92020年12月06日 10:28:18 +00:00Commented Dec 6, 2020 at 10:28
-
\$\begingroup\$ What is the purpose of the
b=b;? I don't see it. \$\endgroup\$EasyasPi– EasyasPi2020年12月27日 04:40:28 +00:00Commented Dec 27, 2020 at 4:40 -
\$\begingroup\$ @EasyasPi Because gcc uses the same register for assignment and return value, so this saves bytes over
return b;. \$\endgroup\$Noodle9– Noodle92020年12月27日 12:20:44 +00:00Commented Dec 27, 2020 at 12:20
Perl 5 -p, (削除) 83 (削除ここまで) (削除) 28 (削除ここまで) 26 bytes
Credit to @NahuelFouilleul for saving 2 bytes
$_=/e/&/t|o/&/[for]/&/i|s/
Switched to @xash's method. This script inverts the output: 0 means that another number can be formed; 1 means that another number cannot be made.
-
\$\begingroup\$ 26 bytes \$\endgroup\$Nahuel Fouilleul– Nahuel Fouilleul2020年12月05日 10:11:23 +00:00Commented Dec 5, 2020 at 10:11
-
\$\begingroup\$ @NahuelFouilleul Might as well use
f|o|rfor consistency (I did that in my Retina answer). \$\endgroup\$Neil– Neil2020年12月06日 11:12:21 +00:00Commented Dec 6, 2020 at 11:12
Python 2, 56 bytes
lambda s:all(set(x)&set(s)for x in"e to for si".split())
Take inputs like two four, outputs negated. Checks whether the string has an e, and intersects the non-e numbers of two, four, and six.
52 bytes in Python 3 using {*x} for set(x).
-
1
Bash, (削除) 85 (削除ここまで) (削除) 74 (削除ここまで) (削除) 61 (削除ここまで) 53 bytes
Supply the input as an argument of the program. Output is via exit code.
[[ -z `for i in e to for si;{ grep -v [$i]<<<1ドル;}` ]]
Python 3.8 (pre-release), (削除) 175 (削除ここまで) (削除) 164 (削除ここまで) 146 bytes
def f(x):w="oe two tre for fie si se eit ie te e twe tire".split();return[[(w:=[*filter(lambda a:c not in a,w)])for c in i]for i in x][-1][-1]!=[]
saved 8 bytes with the help of member SunnyMoon
saved 18 bytes with the help of member Neil
normal version of the code:
def f(x):
w="oe two tre for fie si se eit ie te e twe tire".split()
for i in x:
for c in i:
w = [*filter(lambda a:c not in a, w)]
return w != []
-
2\$\begingroup\$ You can improve this by removing duplicate characters, i.e
one,two,thre,four,five,six,sevn,eight,nie,ten,elvn,twelv,thiren, I guess \$\endgroup\$SunnyMoon– SunnyMoon2020年12月04日 17:52:18 +00:00Commented Dec 4, 2020 at 17:52 -
3\$\begingroup\$ @SunnyMoon You can also remove
u,xandgsince they never appear in other words. \$\endgroup\$Neil– Neil2020年12月04日 18:51:51 +00:00Commented Dec 4, 2020 at 18:51 -
3\$\begingroup\$ @SunnyMoon Also the letters
h,l,nandvonly appear in words withe, andwonly appears in words witht, so they don't make any difference. \$\endgroup\$Neil– Neil2020年12月04日 18:56:42 +00:00Commented Dec 4, 2020 at 18:56
Charcoal, 19 bytes
⊙⪪"&↓εg⌕8¡="a⬤ι¬Noθλ
Try it online! Port of my Retina answer, but I was able to output a Charcoal boolean, i.e. - for possible, nothing for impossible. Explanation:
"&↓εg⌕8¡=" Compressed string `eatoaforasi`
⪪ a Split on `a`
⊙ Any substring satisfies
⬤ι All characters of substring satisfy
¬Noθλ Character not present in input
Implicitly print
Ruby 2.7 -n, 45 bytes
+1 to the idea of xash in his J's answer!
p %w[e to for si].any?{$_.chars&_1.chars==[]}
Ruby 2.7 + gem install humanize, 61 bytes
require'humanize'
f=->v{(1..13).any?{_1.humanize.count(v)<1}}
Ruby 2.7 -n, (削除) 104 (削除ここまで) 90 bytes
Saved 10 bytes by removing duplicate chars from number names.
p %w[one two thre four five six sevn eight nie ten elvn twelv thiren].any?{_1.count($_)<1}
TIO uses an older version of Ruby, while in Ruby 2.7, we've numbered parameters, i.e., _1, which saves 2 bytes.
Jelly, (削除) 39 (削除ここまで) 37 bytes
ị"1⁄2ĠWufṠ`ßṡƝ0:Ƒ’bȷ¤æ»
OUḅ96%191%5)ç/Ḃ
-2 bytes thanks to @xigoi
Takes input as a list of two words in lowercase.
How it works
Uses a lookup table for all pairs. Instead of a ×ばつ13 lookup table, this uses a ×ばつ10 table because a few number/words (1&3, 2&4, 7&9, 10&12) have the same table values, so I engineered a hash with very specific collisions using a brute force script.
A ×ばつ9 table is theoretically possible, but I doubt that it will save bytes due to a more complex hash function.
Lookup table generator after computing the hashes.
OUḅ96%191%5 # hash function
OUḅ96 # character codepoints interpreted in reverse as a base 96 number
%191%5 # mod 191 then mod 10
ị"1⁄2ĠWufṠ`ßṡƝ0:Ƒ’bȷ¤æ» # lookup table
ị"1⁄2ĠWufṠ`ßṡƝ0:Ƒ’bȷ¤ # get the correct row from a list of 10 rows corresponding to the hash of the first word
# (base-250 compression then interpret as base 1000)
æ» # bitshift by the amount corresponding to the hash of the second word
Ñ€ç/Ḃ # apply the lookup table and hash. For some reason I couldn't get ÑçÑḂ to work.
-
\$\begingroup\$
ÑçÑ}Ḃworks, not that it saves any bytes \$\endgroup\$2020年12月04日 19:45:00 +00:00Commented Dec 4, 2020 at 19:45 -
Husk, (削除) 14 (削除ここまで) 12 bytes
Edit: -2 bytes thanks to Razetime
Λn0w ̈toƒr1∫e
Outputs falsy (0) if we can spell another letter without the input letters, truthy (non-zero) otherwise.
Uses approach of checking whether any of the input letters are present in "to", "for", "is" or "e", as pioneered by xash's answer.
Λ # are all these elements truthy?
n # are there intersecting elements of
0 # input
# in each of
w ̈toƒr1∫e # "to","for","is","e"
-
\$\begingroup\$ You can use
Λhere: Try it online! \$\endgroup\$Razetime– Razetime2020年12月07日 08:32:29 +00:00Commented Dec 7, 2020 at 8:32 -
\$\begingroup\$ -2 bytes with
n: Try it online! \$\endgroup\$Razetime– Razetime2020年12月07日 08:33:15 +00:00Commented Dec 7, 2020 at 8:33 -
\$\begingroup\$ @Razetime - Thanks & thanks! Really nice! I was hoping that it would be possible for Husk to be the shortest answer (at least so far), but just needed those extra tips! \$\endgroup\$Dominic van Essen– Dominic van Essen2020年12月07日 09:10:23 +00:00Commented Dec 7, 2020 at 9:10
Zsh -Fe, 30 bytes
for i (e to for si)grep [$i] f
Try it online! (includes all combinations)
Takes input from a file named f, outputs via exit code (0 = we can't spell a third word, 1 = we can).
The option -F disables globbing; without it, we would have to escape the square-brackets. -e makes zsh exit on the first command that fails - it's like a short-circuiting NOR over all the commands executed, similar to the approach in this great J answer. Also takes inspiration from this Bash answer.
R, 87 bytes
function(x,u=utf8ToInt)all(sapply(c('to','for','si','e'),function(m)any(u(m)%in%u(x))))
Reversed output: TRUE if we cannot spell another number without the input letters.
Started with the full vector "one","two","three" ... "thirteen","fourteen", then removed the duplicate letters, then removed the only-in-one-number letters, then removed the letters in words that consistently had another letter. This brought the vector to "oe","to","tre" ... "e","te","tire". At this point it was obvious that we can delete all numbers containing an "e" except "e" (which is what's left of "eleven").
And then I realised that I'd just re-created xash's answer.
Well done, xash!
-
1\$\begingroup\$ I'd also re-created xash's answer, but I didn't realise until I read XCali's port, as I was sadly unable to understand xash's explanation. (On the other hand I needed no explanation to read XCali's code.) \$\endgroup\$Neil– Neil2020年12月06日 11:12:35 +00:00Commented Dec 6, 2020 at 11:12
05AB1E, 14 bytes
"e€‡€ˆ€„"#€мQà
Port of @xash' J answer, so make sure to upvote him!
Also takes the input as a single (space-delimited) string.
Try it online or verify all test cases.
Explanation:
"e€‡€ˆ€„" # Push dictionary string "e for is to"
# # Split it on spaces: ["e","for","is","to"]
€м # For each: remove all those characters from the (implicit) input
Q # Then check for each if they're still equal to the (implicit) input
à # And check if any of the four were truthy by taking the maximum
# (after which this result is output implicitly)
See this 05AB1E tip of mine (section How to use the dictionary?) to understand why "e€‡€ˆ€„" is "e for is to".
JavaScript (Node.js), (削除) 99 (削除ここまで) (削除) 95 (削除ここまで) 78 bytes
x=>y=>!'e to for si'.split` `.filter(m=>![...m].some(k=>(x+y).includes(k)))[0]
Uses xash's idea from his J answer.
Returns false for yes and true for no (counterintuitive I know, deal with it). Uses currying syntax - (x)(y).
Explanation:
x=> //declare function
y=> //declare function 2
! // necessary for consistent result
'e to for si' //see xash's J answer
.split` ` // to array
.filter( //keep value only if following true
m=> //function with value m
! //if following is false
[...m] //m into array of letters
.some( //replace each with
k=> //function of k
(x+y).includes(k) //if includes true (input contains one of word
)
) // array now has any items only if it contains something
[0] //0th item, undefined if no answers, one of strings above if does, then negated by ! at top.
There's got to be a better way to do all the .includes.
Regex (any)
^([^e]*|[^to]*|[^for]*|[^si]*)$
Just using @xash's trick again. Takes a single string.
Javascript, 44 bytes (using regex)
x=>/^([^e]*|[^to]*|[^for]*|[^si]*)$/.test(x)
I mean it works, but I like the other one because it took more than 2 minutes. Takes a single string.
six four? \$\endgroup\$