Who is the sleepiest of them all?

Write a program or function that takes in a string of the characters -=o. where the -=o's and .'s always alternate, character to character. The string will have an odd length greater than one and always start and end in one of -=o.

Basically, the input will look like a line of emoticon faces that share eyes in various states of sleepiness, e.g.

o.=.=.-.-.o.o


Your goal is to print or return the face that is either the sleepiest or the most awake (it's up to you which you choose). If there are multiple choices for who is sleepiest/most awake then any one of them may be output.

There are nine distinct faces and five levels of sleepiness:

-.- is 100% sleepy
-.= is 75% sleepy
-.o is 50% sleepy
=.- is 75% sleepy
=.= is 50% sleepy
=.o is 25% sleepy
o.- is 50% sleepy
o.= is 25% sleepy
o.o is 0% sleepy


In case it's not clear, the sleepiness percentage is computed by assigning 1 to - for fully asleep, 0.5 to = for half asleep, and 0 to o for awake. Then the sum of the two eye values divided by two is the percentage.

The shortest code in bytes wins.

Test Cases

Sleepiest

-.- GIVES -.-
=.- GIVES =.-
o.o GIVES o.o
o.-.= GIVES -.=
=.-.= GIVES =.- OR -.=
o.-.= GIVES -.=
-.-.= GIVES -.-
o.o.- GIVES o.-
=.=.=.o GIVES =.=
-.=.=.= GIVES -.=
=.o.-.= GIVES -.=
o.-.o.=.= GIVES o.- OR -.o OR =.=
-.o.-.=.= GIVES -.=
o.o.o.o.o GIVES o.o
-.-.-.-.- GIVES -.-
o.=.=.-.-.o.o GIVES -.-
-.=.-.o.o.=.o.-.o.=.-.o.=.o.- GIVES -.= OR =.-

Most Awake

-.- GIVES -.-
=.- GIVES =.-
o.o GIVES o.o
o.-.= GIVES o.-
=.-.= GIVES =.- OR -.=
o.-.= GIVES o.-
-.-.= GIVES -.=
o.o.- GIVES o.o
=.=.=.o GIVES =.o
-.=.=.= GIVES =.=
=.o.-.= GIVES =.o
o.-.o.=.= GIVES o.=
-.o.-.=.= GIVES -.o OR o.- OR =.=
o.o.o.o.o GIVES o.o
-.-.-.-.- GIVES -.-
o.=.=.-.-.o.o GIVES o.o
-.=.-.o.o.=.o.-.o.=.-.o.=.o.- GIVES o.o
• I'm feeling -.- Commented Nov 20, 2015 at 6:48

Pyth, 12 10 bytes

hoSN%2.:z3


This prints the sleepiest emoticon. Verify all test cases at once in the Pyth Compiler.

Credit goes to @Sp3000 for the idea to use sorting.

How it works

hoSN%2.:z3
(implicit) Save the in z.
.:z3    Compute all substrings of length 3.
%2        Keep every seconds substring. This discards non-emoticons.
o            Sort the emoticons by the following key:
SN            Sort the characters of the emoticon.
This works since '-' < '=' < 'o'.
h             Retrieve the first, minimal element.

• What is this sorcery?!
– AvZ
Commented Nov 20, 2015 at 5:51
• @Dennis I'm new to Pyth so this might be way wrong: Why not hS%2.:z3? Commented Nov 20, 2015 at 7:33
• @helix Because we want =.- to be sleepier than -.o, but they're sorted the other way. I had made the same mistake.
– xnor
Commented Nov 20, 2015 at 8:45

Python 2, 54 53 bytes

f=lambda s:s and max((s+' ')[:3],f(s[2:]),key=sorted)


This is a function that returns the face that is most awake.

Many thanks to xnor for providing many tactical tricks to shorten my original algorithm.

• Well, I feel silly not realizing the symbols are sorted by awakeness. I think you can recurse the max rather than iterating it through: f=lambda s:s[3:]and max(s[:3],f(s[2:]))or s
– xnor
Commented Nov 20, 2015 at 5:23
• Actually, I think this doesn't work on =.-.o, since =.- vs -.o is the exception to the sort rule.
– xnor
Commented Nov 20, 2015 at 5:37
• Actually, I just realised that I misread the op. I thought that the faces are sorted as they appear in the table. Because of this assumption my submission fails for "=.o.-". I think I have a fix though.
– xsot
Commented Nov 20, 2015 at 5:37
• @xsot I believe ,key=sorted would be a solution, but this is 11 chars so yours is probably shorter.
– xnor
Commented Nov 20, 2015 at 5:40
• Yeah that's the fix I had in mind
– xsot
Commented Nov 20, 2015 at 5:41

CJam, 12 bytes

q3ew2%{$}$0=


This prints the sleepiest emoticon. Try this fiddle or this test suite in the CJam interpreter.

Credit goes to @Sp3000 for the idea to use sorting.

How it works

q            e# Read all input from STDIN.
3ew         e# Push all overlapping slices of length 3.
2%       e# Keep every seconds slice. This discards non-emoticons.
{$}$   e# Sort the slices by their sorted characters.
e# This works since '-' < '=' < 'o'.
0= e# Retrieve the first, minimal slice.


Dyalog APL, 35 28 bytes

{⊃{⍵[⍒{+/'.??o='⍳⍵}¨⍵]}3,/⍵}


This is a monadic function that takes the string on the right and outputs the sleepiest face.

    {⊃{⍵[⍒{+/'.??o='⍳⍵}¨⍵]}3,/⍵}'o.=.=.-.-.o.o'
-.-

• {(⊃⍒3+/'.??o='⍳⍵)⊃3,/⍵} Commented Nov 22, 2015 at 22:53
• And given the input constraints, that ?? is also unnecessary. Commented Nov 22, 2015 at 23:05

Prolog, 205 189 bytes

Code

r([X|T],[N|B],M):-N=M,write(X);r(T,B,M).
p(X):-findall(S,sub_atom(X,_,3,_,S),L),findall(E,(nth1(I,L,E),I mod 2=\=0),R),maplist(atom_codes,R,Q),maplist(sum_list,Q,S),min_list(S,M),r(R,S,M).


Explanation

r([X|T],[N|B],M):-N=M,write(X);r(T,B,M).
p(X):-findall(S,sub_atom(X,_,3,_,S),L),              % L = all sublists of length 3
findall(E,(nth1(I,L,E),I mod 2=\=0),R),        % R = every other element of L
maplist(atom_codes,R,Q),                       % Q = list of decimal ascii codes
created from R

maplist(sum_list,Q,S),                         % S = list of sums of R's lists
min_list(S,M),                                 % M = minimum sum
r(R,S,M).                                      % Prints first element in R with sum M


Example

>p('-.=.-.o.o.=.o.-.o.=.-.o.=.o.-').
-.=


Edit: Saved 16 bytes by unifying r-clauses with OR.

Clojure, 82 bytes

(fn[x](println(apply str(apply min-key #(reduce +(map int %))(partition 3 2 x)))))


Bonus: the following smaller function prints the same face, but with more style!

(fn[x](println(apply min-key #(reduce +(map int %))(partition 3 2 x))))


Test here.

Ruby, 59 bytes

Function returns sleepiest face, using the sorting trick.

f=->(s){s.split(?.).each_cons(2).min_by{|e|e.sort}.join(?.)}


Called like this:

f.call("o.=.=.-.-.o.o")
# => "-.-"


Works on awkward eye order due to internal sort of eyes:

f.call("=.-.o")
# => "=.-"


Minkolang 0.12, 119 bytes

At first, I tried doing this short and really golfy. I gave up and went for something a bit more "fun", but still relatively golfy.

>2@fv$oI2:[9[i$z3[iciz1+q=]++3=tt"^"3zpt]$x$x]IX3140w
o.o1F
o.=1$=.o1+ =.=12 o.-1: -.o11 =.-1+ -.=13 -.-1[ /c0i< \qO].  Try it here! Explanation But really, click on the link above and click Slow! Anyway... >2@fv  This skips over the fv, which will be important later. $o                                                  Read in whole input as characters
I2:                                               Half the stack length
[                                              Open for loop (for each face)
9[                                            Open another for loop - 9 repeats
i$z Stores loop counter in register 3[ Open another for loop - 3 repeats ic Copy char 1/2/3 iz1+q Retrieve char from lookup table = 1 if equal, 0 otherwise ] Close for loop ++ Add twice 3= 1 if equal to 3, 0 otherwise tt t Ternary - executes first part when 0, second part otherwise "^"3zp Put a ^ next to the face that matched ] Close lookup for loop$x$x Dump first two characters ] Close for loop IX Dump the whole stack 31 Push a 3, then a 1 40w Wormhole to (4,0) in the code  What all that did was put a ^ next to the faces that matched. So now the codebox might look like this: >2@fv$oI2:[9[i$z3[iciz1+q=]++3=tt"^"3zpt]$x$x]IX3140w o.o1F o.=1$
=.o1+
=.=^2   <-- caret
o.-^:   <-- caret
-.o11
=.-1+
-.=^3   <-- caret
-.-1[
/c0i<
\qO].


Without the comments, of course. Now, the 40w wormhole sent the instruction pointer to v, which immediately redirects it onto F. Now, F is a "gosub" command. It's like a goto, but you can return to where you called it. At the time F is encountered, the stack is [3,1], so it jumps to the 1 (maybe) on the second row. As the program counter was heading downwards, it continues, pushing 1s onto the stack along the way. That is...until it hits a ^, at which point it's redirected back up, where it pushes each 1 again. The instruction pointer then hits f, which restores its position and direction (when F was encountered earlier). For convenience, I will take the following code and change its layout. (The </\ serve to redirect the instruction pointer as needed.)

$+ Sum up the whole stack 2: Divide by 2 (because each 1 was pushed twice) 1+ Add 1 (shift down one row) 3[ Open for loop - 3 repeats i Push loop counter 0c Copy top of stack q Retrieve face character O Output as character ]. Close for loop and stop when it's done.  I'm actually kinda proud of how I used multiple features unique to Minkolang that I haven't often used before. Mainly the ternary and the gosub. Anyway, there you have it! C, 70 bytes char*f(char*s){char*p=s[3]?f(s+2):s;return*s+s[2]>*p+p[2]?s[3]=0,s:p;}  The function returns the most awake face. It modifies the input string in place, so as to return a null-terminated string. Python 2/3, 54 56 bytes lambda x:".".join(max(zip(x[::2],x[2::2]),key=sorted))  Just wanted to take an alternative tack to xsot's recursive answer. This takes the best (or worst?) tuple of adjacent pairs of eyes and joins them together. Replace max with min to return the most sleepy (as is this returns the most awake) Seems to work, using the following test: for line in """-.- GIVES -.- =.- GIVES =.- o.o GIVES o.o o.-.= GIVES o.- =.-.= GIVES =.- OR -.= o.-.= GIVES o.- -.-.= GIVES -.= o.o.- GIVES o.o =.=.=.o GIVES =.o -.=.=.= GIVES =.= =.o.-.= GIVES =.o o.-.o.=.= GIVES o.= -.o.-.=.= GIVES -.o OR o.- OR =.= o.o.o.o.o GIVES o.o -.-.-.-.- GIVES -.- o.=.=.-.-.o.o GIVES o.o -.=.-.o.o.=.o.-.o.=.-.o.=.o.- GIVES o.o""".splitlines(): inp, _, opts = line.partition(" GIVES ") optst = opts.split(" OR ") act = f(inp) print(inp, "expected", opts, "got", act, "equal?", act in optst)  Which gives the following result: -.- expected -.- got -.- equal? True =.- expected =.- got =.- equal? True o.o expected o.o got o.o equal? True o.-.= expected o.- got o.- equal? True =.-.= expected =.- OR -.= got =.- equal? True o.-.= expected o.- got o.- equal? True -.-.= expected -.= got -.= equal? True o.o.- expected o.o got o.o equal? True =.=.=.o expected =.o got =.o equal? True -.=.=.= expected =.= got =.= equal? True =.o.-.= expected =.o got =.o equal? True o.-.o.=.= expected o.= got o.= equal? True -.o.-.=.= expected -.o OR o.- OR =.= got =.= equal? True o.o.o.o.o expected o.o got o.o equal? True -.-.-.-.- expected -.- got -.- equal? True o.=.=.-.-.o.o expected o.o got o.o equal? True -.=.-.o.o.=.o.-.o.=.-.o.=.o.- expected o.o got o.o equal? True  • Two quick questions: 1) is labeling as Python 2 / 3 when something works with both recommended? 2) Is the f= part required as part of the code size for this challenge? If I don't do that it'll create the lambda and then just immediately throw it away again... – TLW Commented Nov 21, 2015 at 23:54 • 1) "Python 2/3" or just "Python" is fine I think 2) If you don't need the f= then the current consensus seems to be that anonymous functions are okay by default, so you can drop the f= in this case (xsot's needs it since it's recursive) Commented Nov 22, 2015 at 5:36 Brachylog, 10 bytes s₃ᶠġ₂hᵐoᵒh  Try it online! Translated from Dennis' Pyth answer. Mathematica, 61 bytes "." Sort[Partition[#~StringSplit~%,2,1]][[1]]~StringRiffle~%&  Goes for the sleepiest one. • This function only works once, unless you repeat the entire code each time you want to call it. The point of function submissions is for them to be reusable. Calling your function breaks the value of the global % which it relies on. Commented Nov 30, 2015 at 12:27 F# 60 fun s->Seq.max[for n in 0..2..String.length s-2->s.[n..n+2]]  Returns the most awake face (change max by min for the sleepest) Perl 5, 127 bytes %h=qw[- 2 = 1];sub r{$b=0;$b+=$h{$_}for split'',pop;$b}($_)=<>;@a='o.o';while(/.../g){push@a,$& if(r$&)>r$a[-1];--pos}say$a[-1]  (I'm sure it's doable more briefly.) How it works: 1. Grab each three-character string from the string, with overlap by one (that's what the --pos does). 2. Append that three-character string to an array if its value exceeds that of the last element of the array; here, "value" is just the sum of its characters' values in sleepiness. 3. Print the last element of the array. ES6, 81 72 bytes a=>"-.-,-.=,=.-,-.o,=.=,o.-,=.o,o.=,o.o".split,.find(b=>a.includes(b))  Probably requires Chrome 45 or Firefox 41. Thanks to @ETHproductions for saving 9 bytes. • Nice, but "=.-" should be switched with "-.o"; same with "=.o" and "o.-". Also, you may be able to save some bytes by putting everything in one string, separated by commas, and using .split, . Commented Nov 21, 2015 at 18:33 • Using split could save 9 chars Commented Nov 21, 2015 at 22:16 • @ETHproductions Sorry I didn't notice that the original list of faces wasn't itself in order of sleepiness. – Neil Commented Nov 22, 2015 at 20:17 ><>, 55 bytes try it here! <v~i:i&0"."0 >i:@+:&:@)?v&~i0(?v ^?)0i:r~r&~<;ooo$r<


Outputs most awake face.

Since the ASCII values for -, =, and o increase respectively, I could use that to my advantage. Basically it adds the values of the current and previous eye part, check if it's a higher value than before, if it is it saves the new value and updates what face that represents, then loops until the end of the input. Then outputs the face that remains. (I'm very pleased at how nicely all the code fits in place)

Perl 5-MList::Util=max -p, 68 bytes

s|..(?=(.))|$t=max$t,ord($&)%15%4+ord($1)%15%4 .$&.$1|eg;$_=$t;s/.//


Try it online!

Grabs each set of three characters, ignores the . in the middle, maps the addition of the other two to an integer in the range 0-4, concatenates that to the front of the emoticon face, then sorts by that. Grabs the last entry (most awake), removes the number from the front, and outputs it.