Tasteless and other bugs

52

2

Some versions of the standard Android calculator app allow you to press a key, like 'sin' and then the 'del' key to make it 'si'. Probably just a bug which they can't be bothered with removing.

Screenshot of Android calculator

The following letters/letter groupings are typable:

 

sin
si
s
cos
co
c
tan
ta
t
ln
l
log
lo
e

So, 'tasteless' is typable, because ta-s-t-e-l-e-s-s and so is 'clogs' because 'c-log-s'. However 'got' is not typable, neither is 'an' or 'xyz'.

Write a program that takes a single word (or sequence of letters, only a-z in input) as input and produces output to indicate if a word is typable or not.

Output may be a single character/letter/digit/etc. or it may be larger. All typable words should produce the same output. All non-typable words should also produce the same output.

P.S. Just out of curiosity, is 'tasteless' the longest dictionary word that is typable?

ghosts_in_the_code

Posted 2016-12-04T16:08:37.073

Reputation: 2 907

1Just to be clear: We output a single, consistent digit or letter of our choice to indicate the word is typeable, and a different, single, consistent digit or letter of our choice to indicate the word is not typeable. Is that correct? – Dennis – 2016-12-04T16:36:10.403

3

The longest word I could find is 10 letters, coelostats.

– Conor O'Brien – 2016-12-04T21:48:10.623

1So, is "πe" not a word? – Mr Lister – 2016-12-05T09:15:37.713

@Dennis Ya, more or less. – ghosts_in_the_code – 2016-12-05T14:43:19.773

@MrLister To make the problem simpler, only a-z are allowed in input. – ghosts_in_the_code – 2016-12-05T14:44:05.420

@Dennis Though there's probably nothing wrong in outputting something bigger, like 'true' and 'false' or something like that. Basically it shud be obvious from the output as to what the result is. Ok, I'll edit the question – ghosts_in_the_code – 2016-12-05T14:49:04.290

1Another 11: sissinesses – Chris H – 2016-12-06T13:29:44.233

Answers

20

Perl, 47 43 41 + 1 = 42 bytes

-4 bytes thanks to @Sunny Pun. -2 bytes thanks to @Brad Gilbert b2gills and @Downgoat

Run with the -n flag.

say!/^(s(in?)?|co?|t(an?)?|ln?|log?|e)+$/

It can definitely be golfed futher, but in the spirit of competition, I'm leaving the mostly-original regex I came up with at the beginning. Returns nothing if true, 1 if false.

Try it online!

I downloaded a dictionary file, and the longest word I found was 11 letters -- tattletales

Gabriel Benamy

Posted 2016-12-04T16:08:37.073

Reputation: 2 827

1I think co? should be sufficient since sin will take care of the s :) Nice playing with /log?/! – Sunny Pun – 2016-12-04T16:49:21.653

1It doesn't say that it needs to be case insensitive (remove i), or that the single result has to make sense (remove one !) – Brad Gilbert b2gills – 2016-12-04T18:19:26.453

Do you need i flag at very end since input is only a-z? – Downgoat – 2016-12-05T15:04:58.270

You can make this simpler: -2: /^(s|sin?|co?|t|tan?|ln?|log?|e)+$/ or if you prefer: /^([celst]|sin?|co|tan?|ln|log?)+$/ – Not that Charles – 2016-12-05T22:49:27.677

ETHProductions´ regex is 4 bytes shorter: /^((si|ta|l)n?|co?|log?|[ste])+$/ – Titus – 2016-12-06T12:58:55.020

1Enjoy your bounty! – ghosts_in_the_code – 2016-12-13T17:03:06.377

16

JavaScript (ES6), 44 bytes

s=>/^((si|ta|l)n?|co?|log?|[ste])+$/.test(s)

I think this is the shortest regex possible, but of course I may be wrong.

Explanation

An obvious first place to start would be a regex that simply includes all options separately:

s=>/^(sin|si|s|cos|co|c|tan|ta|t|log|lo|l|ln|e)+$/.test(s)

First, we can observe that cos can be formed from co and s, making it unnecessary:

s=>/^(sin|si|s|co|c|tan|ta|t|log|lo|l|ln|e)+$/.test(s)

Some of these, such as sin and si, can be combined by making the last letter optional:

s=>/^(sin?|s|co?|tan?|t|log?|ln?|e)+$/.test(s)

This works because sin? matches si with or without an n on the end, thus covering both sin and si.

There seems to be a lot of n?s as well. What if we put them all together?

s=>/^((si|ta|l)n?|s|co?|t|log?|e)+$/.test(s)

One more way to golf this would be to combine the remaining single-char options into a character range, but this comes out at the same length:

s=>/^((si|ta|l)n?|co?|log?|[ste])+$/.test(s)

And that's how you golf a simple regex. I believe this is the shortest possible regex that matches every string correctly, but perhaps not. I will award a +100 bounty to anyone who manages to improve upon this regex.

ETHproductions

Posted 2016-12-04T16:08:37.073

Reputation: 47 880

The one that I used in my answer is sort of similar: ^(s|t|co?|(l|ta|si)n?|log?|e)+$ – Mama Fun Roll – 2016-12-04T21:23:50.997

Firstly, I count 44 bytes. Secondly, here's an alternate but longer solution: / /.test.bind(/^((si|ta|l)n?|co?|log?|[ste])+$/). – Conor O'Brien – 2016-12-04T21:41:26.070

@ConorO'Brien Whoops, don't know how I miscounted that... – ETHproductions – 2016-12-04T22:48:59.483

You can do a=/^((si|ta|l)n?|co?|log?|[ste])+$/;a.test for 42 bytes. I believe this is allowed, because a.test is an anonymous function. – NoOneIsHere – 2016-12-06T01:39:07.560

@SeeOneRhino It is, but it's not really allowable because f=a.test doesn't work. I wonder if it's acceptable to call with the alternate name a.test though... – ETHproductions – 2016-12-06T01:52:34.903

@ETHproductions I tried it on Chrome Dev Console. It worked. – NoOneIsHere – 2016-12-06T02:59:35.627

@SeeOneRhino Does f=/abc/.test; f("abc") work? – ETHproductions – 2016-12-06T03:06:01.043

You could do s|t|e instead of [ste]; might be faster. But I bet there´s nothing shorter. – Titus – 2016-12-06T13:16:32.677

@ETHproductions No. Sorry, I thought it worked. It keeps giving an "incompatible type reciever" error. – NoOneIsHere – 2016-12-06T19:58:22.527

@SeeOneRhino That's OK, thanks for suggesting it anyway. I've tried that in the past, but while it works in some other languages, it does not in JS... – ETHproductions – 2016-12-07T21:38:00.320

You can add your bounty to http://meta.codegolf.stackexchange.com/q/5243/40929

– ghosts_in_the_code – 2016-12-11T07:17:29.263

@ETH Are you still awarding a bounty? – ghosts_in_the_code – 2017-01-04T05:45:45.863

7

Pyth, 37 33 29 28 bytes

The code contains an unprintable character, so here is an xxd hexdump.

00000000: 737d 5173 4d5e 733c 5252 6336 2e22 6174  s}QsM^s<RRc6."at
00000010: 14d0 69ba 76f1 ac59 6422 346c            ..i.v..Yd"4l

Try it online.

Extremely Astronomically inefficient. The time and space complexity is O(16n) O(24n).

Explanation

First, a Q is implicitly appended.

s}QsM^s<RRc6."…"4lQ     Implicit: Q = input
            ."…"        Generate "logsincostanlnee"
          c6            Split in 6 parts: ["log", "sin", "cos", "tan", "ln", "ee"]
         R      4       For each n from 0 to 3
       <R               Take the first n chars from each string
      s                 Flatten the results
                 lQ     Get length of input
     ^                  Take that Cartesian power of the list
   sM                   Join each resulting list
 }Q                     Check if the input is found
s                       Cast to integer

PurkkaKoodari

Posted 2016-12-04T16:08:37.073

Reputation: 16 699

The OP has clarified; you don't need the s. – Dennis – 2016-12-05T20:07:15.620

6

Jelly, 32 31 30 28 26 bytes

ŒṖw@€€“¡Ṡ[ẈKœịḲ-¢ȧ?-»’%3ḌẠ

Outputs 0 if the word is typeable, 1 if not. Thanks to @JonathanAllan for golfing off 1 byte!

Try it online!

How it works

ŒṖw@€€“¡Ṡ[ẈKœịḲ-¢ȧ?-»’%3ḌẠ  Main link. Argument: s (string of lowercase letters)

ŒṖ                          Yield all partitions of s.
      “¡Ṡ[ẈKœịḲ-¢ȧ?-»       Yield "sine  logcostanln". Every third character
                            marks the start of a typeable word.
  w@€€                      Find the indices of all substrings in the partitions
                            in the string to the right (1-based, 0 if not found).
                     ’      Decrement. "Good" indices are now multiples of 3.
                      %3    Modulo 3. "Good" indices are mapped to 0, "bad"
                            indices are mapped to 1 or 2.
                        Ḍ   Convert from decimal to integer. A partition will
                            yield 0 iff all indices are "good".
                         Ạ  All; yield 0 if one or more integers are falsy (0), 1
                            if all integers are truthy (non-zero).

Dennis

Posted 2016-12-04T16:08:37.073

Reputation: 196 637

6

Brachylog, 33 bytes

Fixed a bug thanks to @Synoli.

~c:1a
,"sincostanloglneeee"@6e@[?

Try it online!

Outputs true. if typeable or false. otherwise.

Explanation

We try deconcatenations of the input until we find one for which all strings that we concatenate are a prefix of one of ["sin", "cos", "tan", "log", "lne", "eee].

~c                          A list of strings which when concatenated results in the Input
  :1a                       All strings of this list satisfy the predicate below:

,"sincostanloglneeee"@5           The list ["sin", "cos", "tan", "log", "lne", "eee"]
                       e          Take one element of that list
                        @[?       The input is a prefix of that element

Fatalize

Posted 2016-12-04T16:08:37.073

Reputation: 32 976

Why the . after true? – user41805 – 2016-12-04T18:22:56.593

1@KritixiLithos In SWI-Prolog when a query is true it prints true. and false. otherwise. i just reimplemented this: if the output is ignored (as it is here) and there is no writing to STDOUT, then it will print true. or false. depending on whether the main predicate succeeds or fails. It has a dot in SWI-Prolog because true. and false. are actually valid programs which always succeeds/always fails. – Fatalize – 2016-12-04T18:26:38.033

How does this solution work without tan explicitly appearing in the list? – Synoli – 2016-12-11T23:49:10.897

2@Synoli It doesn't. I fixed it at the cost of 3 bytes, thanks. – Fatalize – 2016-12-12T07:53:09.603

4

Perl 6,  60 50  44 bytes

first attempt (60)

put +?(get~~/^<{<sin cos tan ln log e>».&{|m:ex/^.+/}}>*$/)

translation of the Perl 5 answer (50)

put +?(get~~/^[s[in?]?|co?|t[an?]?|ln?|log?|e]*$/)

using -n switch (43+1)

put +?/^[s[in?]?|co?|t[an?]?|ln?|log?|e]*$/

The first ? converts the result to Boolean, and the first + converts that to a number (1 for True, 0 for False)

Brad Gilbert b2gills

Posted 2016-12-04T16:08:37.073

Reputation: 12 713

3

Mathematica, 101 bytes

If[StringMatchQ[#,("sin"|"si"|"s"|"cos"|"co"|"c"|"tan"|"ta"|"t"|"ln"|"l"|"log"|"lo"|"e")..],"T","F"]&

It seems that the hard parts of this challenge are coming up with the shortest regex and choosing the most concise language to match the regex. I don't have anything to contribute to the former, and Mathematica isn't good candidate for the latter since you have to use StringMatchQ and RegularExpression. What I can do is answer your P.S.: is "tasteless" the longest word that you can type?

In[1]:= f=StringMatchQ[#,("sin"|"si"|"s"|"cos"|"co"|"c"|"tan"|"ta"|"t"|"ln"|"l"|"log"|"lo"|"e")..]&;

In[2]:= Select[EntityList@"Word",f@#[[2,1]]&][[All,2,1]]//SortBy[StringLength]//DeleteDuplicates
Out[2]= {c,e,l,s,t,cc,cl,el,et,lo,si,sl,ta,te,ccc,col,cos,cot,eel,ell,eta,etc,lee,let,log,lot,sec,see,set,sic,sin,sit,tae,tan,tat,tec,tee,cell,clog,clot,coco,cole,colt,coss,cost,cote,else,less,loco,loge,loll,lose,loss,lota,sect,seel,sell,sess,seta,sett,sill,silo,silt,sine,sise,siss,site,sloe,slog,slot,stet,taco,tact,tael,talc,tale,tall,tect,tell,test,cello,close,cosec,costa,cotan,eccle,elect,elsin,ettle,loess,lotte,secle,setee,since,sleet,stale,stall,state,steel,stele,tasse,taste,tatee,teest,telco,testa,tetel,tsine,cellco,closet,coleta,collet,coltan,cosine,cosset,costal,ecesis,estate,lessee,scelet,select,sellee,sestet,settee,settle,siesta,silole,stacte,stance,stasis,tallet,tallot,taslet,tassel,tasset,tattle,tectal,teetan,tellee,testee,tsetse,celesta,cessile,cocotte,collect,costate,ecolect,ectasis,electee,sessile,sinless,sitelet,statant,tassell,tastant,testate,coestate,colessee,colocolo,cosiness,costless,electant,lossless,sceletal,siletane,statelet,tactless,tallness,telltale,telocoel,coelostat,sissiness,stateless,tasteless,tattletale}

So "tattletale" seems to be the longest by one character.

ngenisis

Posted 2016-12-04T16:08:37.073

Reputation: 4 600

Why is this non-competing? Does the function f you define not comply with the rules of the challenge? – Dennis – 2016-12-04T17:23:36.323

No, it outputs True or False rather than a single character. – ngenisis – 2016-12-04T17:25:46.320

Posts tagged with decision-problem are about determining True/False, so I think this is competing. – FlipTack – 2016-12-04T17:29:29.633

Non-competing status is reserved for submissions that use a language or language feature that didn't exist or had a bug when the challenge was posted. – Dennis – 2016-12-04T17:29:40.523

Fair enough. I edited my answer to have an actual solution. – ngenisis – 2016-12-04T17:36:33.960

You can save a few bytes by replacing If[...,"T","F"] with Boole@.... – Greg Martin – 2016-12-04T20:39:29.693

2

Wonder, 41 bytes

!.(mstr"^(s|t|co?|(l|ta|si)n?|log?|e)+$")

Usage:

(!.(mstr"^(s|t|co?|(l|ta|si)n?|log?|e)+$")) "tasteless"

Totally misunderstood the question before, but now it's all fixed. Outputs F for match and T for no match.

Noncompeting, 35 bytes

!.`^(s|t|co?|(l|ta|si)n?|log?|e)+$`

Usage:

(!.`^(s|t|co?|(l|ta|si)n?|log?|e)+$`) "tasteless"

This makes use of applicable regexes, which was implemented after this challenge.

Mama Fun Roll

Posted 2016-12-04T16:08:37.073

Reputation: 7 234

2From my understanding, you can only delete the last character in the calculator, which means n in not typable but sin and ln are. – Sunny Pun – 2016-12-04T16:23:19.520

This regex detects sa as true – user41805 – 2016-12-04T16:27:17.860

1This fails the test case got. – Dennis – 2016-12-04T16:30:19.747

I believe it's fixed. – Mama Fun Roll – 2016-12-04T16:57:06.830

The ? make the sub expression docile; see http://www.rexegg.com/regex-quantifiers.html#cheat_sheet. But even making it greedy with ?? or possessive with ?+ doesn´t work for some reason (at least in PHP). coelostats triggers the trap (at lo and ta).

– Titus – 2016-12-06T12:19:35.380

Is there a... problem? I'm pretty sure coelostats is typable. If there is another test case that this code fails on, let me know. – Mama Fun Roll – 2016-12-06T14:35:34.403

2

Processing, 223 bytes

int d(String b){for(String p:"tan0log0sin0cos0ln0e".split("0"))if(p.startsWith(b))return 1;return 0;}

int l(String p){String b="";int t=1;for(char c:p.toCharArray()){b+=c;if(d(b)<1){b=c+"";t=d(b);}if(t<1)return t;}return t;}

Finally decided to do an answer without regex. To call the function, use l("tasteless");. Returns 0 for false and 1 for true.

Expanded code with explanation

int d(String b){
  for(String p:"tan0log0sin0cos0ln0e".split("0"))
    if(p.startsWith(b))
      return 1;
  return 0;
}
//main function
int l(String p){
  String b="";
  int t=1;
  for(char c:p.toCharArray()){
    b+=c;
    if(d(b)<1){
      b=c+"";
      t=d(b);
    }
    if(t<1)return t;
  }
  return t;
}

Basically, we iterate over the given string, building up b char by char. We check using d() if any of the tan,log,... start with b. If it does, then it is valid. Else, we check if the char at that position is valid and we reset b. Now if it is invalid, 0 will be returned, or else it will still be valid. At the end, if the program hasn't already returned something, then return 1.

user41805

Posted 2016-12-04T16:08:37.073

Reputation: 16 320

Can't the d function return a bool? – Roman Gräf – 2016-12-05T13:55:14.087

@RomanGräf It is more bytes to use boolean than int. Also true and false require more bytes than 1 and 0 – user41805 – 2016-12-05T14:03:54.407

2

Scala, 49 bytes

s=>s.matches("(s(in?)?|co?|t(an?)?|ln?|log?|e)+")

Returns true if the given string matches the regex, false otherwise.

corvus_192

Posted 2016-12-04T16:08:37.073

Reputation: 1 889

2

Python 3, 154 bytes

r=1;i=input()
while r:
 r=0
 for s in'sin,cos,tan,log,ln,co,lo,si,ta,s,c,t,l,e'.split(','):
  if i.startswith(s):r=i=i.replace(s,'',1);break
print(i=='')

Try it online!

Henke

Posted 2016-12-04T16:08:37.073

Reputation: 41

1You might need to check indentation, I had to edit the code to make it work – george – 2016-12-05T10:02:37.170

@george, weird, I tried in IDLE and the online compiler, and both seem to work – Henke – 2016-12-05T17:38:31.793

2

Python 3, 149 130 bytes

i=input()
for a in 'tan,sin,cos,log,si,co,ta,lo,lo,ln,s,c,t,l,e'.split(','):
    if a in i:
        i=i.replace(a,"")
print(not i)

edit #1: shaved 19 bytes using @Henke solution

Dillanm

Posted 2016-12-04T16:08:37.073

Reputation: 158

0

PHP, 60 bytes

<?=preg_match("#^((si|ta|l)n?|co?|log?|s|e|t)+$#",$argv[1]);

regex stolen from ETHproductions:
takes input from command line argument; prints 1 for typable, 0 for not typeable.

older versions, 75 73 69 bytes

<?=!preg_replace("#co|log|ln|lo|sin|si|tan|ta|[celst]#","",$argv[1]);

replaces all possible words with empty string, returns the result, negates.

<?=!preg_split("#co|log|ln|lo|sin|si|tan|ta|[celst]#",$argv[1],-1,1);

splits input by regex matches. Flag 1 stands for PREG_SPLIT_NO_EMPTY and tells preg_split to only return non-empty results. If input is typable, preg_split will only have empty results, so it will return an empty array, which is falsy. ! negates the result.

Both versions take input from command line argument
and print 1 if result is empty (input is typable), else nothing.

Notes:
Packing the regex using ? does not work here; it renders the expressions ungreedy; probably due to backtracking. And the order of the alternatives is important: ta has to stand before t or the engine will stop matching when it finds t.

I found a quantifier cheat sheet, thought ?? or ?+ might help; but they did not work for me.

Titus

Posted 2016-12-04T16:08:37.073

Reputation: 13 814

0

Python 2, 124 bytes

f=lambda w:any(f(w[len(s):])if w[:len(s)]==s else 0for s in'sin,cos,tan,log,ln,co,lo,si,ta,s,c,t,l,e'.split(','))if w else 1

TFeld

Posted 2016-12-04T16:08:37.073

Reputation: 19 246

0

Java 8, 55 bytes

s->return s.matches("^((si|ta|l)n?|co?|log?|[ste])+$");

Disclamer: I used ETHproductions' regex because it was many bytes shorter than mine. Full credit on the Regex to him. What I did was add 24 bytes to make it a Java function.

Returns false if the word did not fit into the Regex, else true.

RudolfJelin

Posted 2016-12-04T16:08:37.073

Reputation: 853