Emoticon facial expression recognition

25

1

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.

Arnaud

Posted 2015-09-12T10:10:52.183

Reputation: 8 231

1You forgot about :'D, :') (happy) and :@ (angry) – Ismael Miguel – 2015-09-13T00:11:16.507

Answers

19

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.

cjfaure

Posted 2015-09-12T10:10:52.183

Reputation: 4 213

Very well thought – edc65 – 2015-09-12T15:56:36.673

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 – 2015-09-12T17:54:15.790

6I love that the program contains its own emoticon: c: – Alex A. – 2015-09-12T22:31:31.947

@BetaDecay it'll break it heheh – cjfaure – 2015-09-13T19:10:30.660

1@AlexA. it also has these, if you look carefully: 8) (8 :] [: – cjfaure – 2015-09-13T19:11:15.333

16

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.

Martin Ender

Posted 2015-09-12T10:10:52.183

Reputation: 184 808

7Woah, give the rest of us a chance Martin :D – Beta Decay – 2015-09-12T10:31:39.303

10

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.

Martin Ender

Posted 2015-09-12T10:10:52.183

Reputation: 184 808

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 – 2015-09-12T10:47:33.470

@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 – 2015-09-12T10:50:22.157

8

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
X=s=>/[\])}>].|.[[({<c]/.test(s)?'sad':'happy'

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` ` 

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

edc65

Posted 2015-09-12T10:10:52.183

Reputation: 31 086

works great on chrome – Glycerine – 2015-09-12T13:39:10.573

3@Glycerine so now Chrome recognize => ? I missed that news – edc65 – 2015-09-12T13:45:52.677

4

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")

pawel.boczarski

Posted 2015-09-12T10:10:52.183

Reputation: 1 243

2You 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. – 2015-09-12T16:52:27.177

4

Python 3, 77 75 74 72 61 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.

xbarbie

Posted 2015-09-12T10:10:52.183

Reputation: 91

1Welcome to Programming Puzzles & Code Golf! – Dennis – 2015-09-14T22:30:57.270

Using a function is perfectly fine. In contrast, assuming the input is already stored in x is not allowed. – Dennis – 2018-03-24T15:34:42.213

3

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 "])>}"

Fatalize

Posted 2015-09-12T10:10:52.183

Reputation: 32 976

2

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"
print["Sad","Happy"][h>0]

Loovjo

Posted 2015-09-12T10:10:52.183

Reputation: 7 357

2

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('');.

slvrbld

Posted 2015-09-12T10:10:52.183

Reputation: 619

1

Python 3, 75 bytes

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 :)

etene

Posted 2015-09-12T10:10:52.183

Reputation: 448

1

Java 8, 52 bytes

e->e.matches(".+[\\[(c<{]|[)>\\]}].+")?"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

Kevin Cruijssen

Posted 2015-09-12T10:10:52.183

Reputation: 67 575

1

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"}

AdmBorkBork

Posted 2015-09-12T10:10:52.183

Reputation: 41 581