Emoticon facial expression recognition

Write a program that accepts as input an emoticon and ouputs if the emoticon is happy or sad.

The program accepts a string as input or parameter, and should display the string "happy" if the input is in the happy emoticon list, or "sad" if the input is in the sad emoticon list.

You can assume the input is always a valid (happy or sad) emoticon, with no space or tabs around.

Here is a space separated list of happy emoticons:

:-) :) :D :o) :] :3 :c) :> =] 8) =) :} :^) :-D 8-D 8D x-D xD X-D XD =-D =D =-3 =3 B^D (-: (: (o: [: <: [= (8 (= {: (^:


Here is a space separated list of sad emoticons:

>:[ :-( :( :-c :c :-< :< :-[ :[ :{ 8( 8-( ]:< )-: ): >-: >: ]-: ]: }: )8 )-8


This is code-golf, so the shortest program wins.

• You forgot about :'D, :') (happy) and :@ (angry) – Ismael Miguel Sep 13 '15 at 0:11

Python, 86 bytes

I should be sent to prison.

x=lambda c: ["happy","sad"][c[0]+c[-1:]in open(__file__).read(88)[::-1]]#<][><:>{:}(:)


The shortest I could come up with was equivalent to Martin's CJam answer, so I decided I'd hide all the sad emojis (minus the middle character if any) in the reverse of my code and use Python's __file__ quine cheat.

Muahahaha.

• Very well thought – edc65 Sep 12 '15 at 15:56
• Actually, now that I look at your code, will removing the space after the colon help anything, or will it just break the program? – Beta Decay Sep 12 '15 at 17:54
• I love that the program contains its own emoticon: c: – Alex A. Sep 12 '15 at 22:31
• @BetaDecay it'll break it heheh – cjfaure Sep 13 '15 at 19:10
• @AlexA. it also has these, if you look carefully: 8) (8 :] [: – cjfaure Sep 13 '15 at 19:11

CJam, 33 32 bytes

Thanks to Dennis for saving 1 byte.

q)"[(c<{"&\"])>}"&|"sad""happy"?


Looks like it's shorter to do the same thing without a regex...

Test it here.

Explanation

This based on the same observation as the Retina answer, but this time matching happy faces doesn't have any benefit, so we'll match sad faces instead (because there's one less mouth to take into account). The solution is otherwise exactly the same, except that it's not implemented via regex substitution:

q)             e# Read input and split off last character.
"[(c<{"&       e# Set intersection with the sad right-hand mouths.
\              e# Pull up remaining emoticon.
"])>}"&        e# Set intersection with the sad left-hand mouths.
|              e# Set union, which amounts to a logical OR in this case.
"sad""happy"?  e# Pick the correct string.

• Woah, give the rest of us a chance Martin :D – Beta Decay Sep 12 '15 at 10:31

Retina, 38 36 bytes

.+[])D3>}]|[<[({].+
happy
^...?$sad  We can recognise all emoticons by their mouths, because none of the mouths is used as a hat or eyes in the other set (only in the same set). The happy ones have one more mouth to take into account, but they have the benefit that the mouths don't appear in the other set at all, not even as noses (the opposite is not true: c is both a sad mouth and a happy nose). This means we can avoid using anchors but instead just ensure that there are more characters on the other side of the mouth. So the valid mouths for happy faces are ] ) D 3 > } on the right or < [ ( { on the left. We match those with .+[])D3>}]|[<[({].+ and replace them with happy. If we didn't match there will be two or three characters in the string (the emoticon), but if we did there will be five (happy). So in a second step we replace two or three characters with sad. • We can recognise all emoticons by their mouths, because none of the mouths is used as a hat. Well, the ]:< emoticon uses a mouth as a hat, just saying. – Loovjo Sep 12 '15 at 10:47 • @Loovjo except there is no . after "hat" in my answer. ;) "... as a hat or eyes in the other set (only in the same set)." – Martin Ender Sep 12 '15 at 10:50 JavaScript (ES6), 46 Using a regexp to find sad emoticons, that are those beginning with >)]} or ending with <([{c. Side note: other regexps here may be shorter but I'm not sure to understand them. Usual note: test running the snippet on any EcmaScript 6 compliant browser (notably not newest Chrome but not MSIE. I tested on Firefox, Safari 9 could go) Big news It seems arrow functions finally arrived to Chrome land! Rel 45, august 2015 F=s=>/^[\])}>]|[[({<c]$/.test(s)?'sad':'happy'

//Same length

Y=s=>s.match].|[)}>].|.[[({<c]?'sad':'happy'

//TEST
out=x=>O.innerHTML+=x+'\n';

sad='>:[ :-( :( :-c :c :-< :< :-[ :[ :{ 8( 8-( ]:< )-: ): >-: >: ]-: ]: }: )8 )-8'.split
happy=':-) :) :D :o) :] :3 :c) :> =] 8) =) :} :^) :-D 8-D 8D x-D xD X-D XD =-D =D =-3 =3 B^D (-: (: (o: [: <: [= (8 (= {: (^:'.split

sad.forEach(x=>out(x + ' is ' + F(x)))
out('\nThe happy faces')
happy.forEach(x=>out(x + ' is ' + F(x)))
<pre id=O></pre>

• works great on chrome – Glycerine Sep 12 '15 at 13:39
• @Glycerine so now Chrome recognize => ? I missed that news – edc65 Sep 12 '15 at 13:45

Julia, 87 69 bytes - saved 18 bytes thanks to Alex A.

s=readline();print(s[end-1] in")D]3>}"||s[1] in"([<{"?"happy":"sad")

• You can save a bunch by using a ternary instead of the if/else and putting the ternary inside of print to avoid having to assign t. – Alex A. Sep 12 '15 at 16:52

Python 3, 7775747261 55 bytes

lambda e:('happy','sad')[e[-1]in'[(c<{'or e[0]in'])>}']


Try it online!

How does it work

If a face string starts with ])>} or ends with [(c<{, it is sad, otherwise it is happy. Tuple indexing is used as if.

• Welcome to Programming Puzzles & Code Golf! – Dennis Sep 14 '15 at 22:30
• Using a function is perfectly fine. In contrast, assuming the input is already stored in x is not allowed. – Dennis Mar 24 '18 at 15:34

Brachylog, 50 bytes

(rh{,"[(c<{":Im?};?h{,"])>}":Im?}),"sad".;"happy".


Explanation

(                              ),"sad".;"happy".  § If what's in the parentheses is true,
§ output "sad", else output "happy".

rhA                                              § Unify A with the last char of the input
,"[(c<{":ImA                                  § True if A is a char of "[(c<{"
;                                 § OR
?hA                              § Unify A with the first char of the input
,"])>}":ImA                   § True if A is a char of "])>}"


Python, 159 bytes.

i,e=raw_input(),0
for c in i:e=(e,i.index(c))[c in":=8xXB"]
f,s,h=i[:e],i[e+1:],0
for c in f:h+=c in"[(c<{"
for c in s:h+=c in")]}>D"


MATLAB, 85 83 bytes

There must be a way to reduce the size here.

e=input('');if any([e(end)=='[(c<{',e(1)=='])>}']),'sad';else 'happy';end,disp(ans)


Input is a smiley string. First and last characters will be compared to determine whether it's sad. If not, it's happy.

I was able to save 2 bytes by not displaying either, but assigning them to MATLAB's default variable (ans) instead and then displaying ans after the if-statement. But I'm convinced it can be improved somehow.

2 bytes improvement by changing function s(e), to e=input('');.

PowerShell, 92 Bytes

param([char[]]$a)if("<[({".IndexOf($a[0])+"})D3]>".IndexOf($a[-1])-eq-2){"sad"}else{"happy"}  A little wordy, but as a bonus, it doesn't use regex! This takes advantage of the .NET <string>.IndexOf() function that returns -1 if the character isn't found in the string. So, if the first character isn't a "happy" character, the first IndexOf() will be -1 -- likewise for the last character. So, if it's a sad face, the IndexOf()s will always sum to -2, meaning the -eq-2 is $TRUE, and thus sad gets printed.

Bonus variant: PowerShell with Regex, 95 bytes

param([char[]]$a)if(($a[0]-match"[<$$$\{]")-or(a[-1]-match"[\}$$D3$>]")){"happy"}else{"sad"}


lambda y:"sad"if re.match("(.*[[(c<{]$)|(^[\])>}])",y)else"happy" import re  Try it online The regex import makes it a bit too long, as well as the inability to use None as an array index. But I like regex :) Java 8, 52 bytes e->e.matches(".+[\$(c<{]|[)>$$/extract_itex]}].+")?"sad":"happy"  Try it online. Explanation: e-> // Method with String as both parameter return-type e.matches( ".+[\$(c<{]|[)>\$}].+") // Checks if the input matches the regex ?"sad" // If it does: output "sad" :"happy" // Else: output "happy"  Java's String#matches implicitly adds ^... to match the entire String, which is why it is shorter to check for sad faces instead of checking for happy faces like most other answers do with .+[\$$)D3>}]|[<\$({].+ (because my regex would fail in @MartinEnder's Retina answer for example, due to the happy test case :c)). Regex explanation: ^.+[\\[(c<{]|[)>\$}].+$
^                           Start of the string
.+                          One or more characters,
[\$(c<{] followed by one of "[(c<{" | Or [)>\$}]        One of ")>]}",
.+      followed by one or more characters
\$    End of the string