29
\$\begingroup\$

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
\$\endgroup\$
1
  • 31
    \$\begingroup\$ I'm feeling -.- \$\endgroup\$
    – user41805
    Commented Nov 20, 2015 at 6:48

17 Answers 17

27
\$\begingroup\$

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

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.

\$\endgroup\$
6
  • \$\begingroup\$ 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 \$\endgroup\$
    – xnor
    Commented Nov 20, 2015 at 5:23
  • \$\begingroup\$ Actually, I think this doesn't work on =.-.o, since =.- vs -.o is the exception to the sort rule. \$\endgroup\$
    – xnor
    Commented Nov 20, 2015 at 5:37
  • \$\begingroup\$ 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. \$\endgroup\$
    – xsot
    Commented Nov 20, 2015 at 5:37
  • \$\begingroup\$ @xsot I believe ,key=sorted would be a solution, but this is 11 chars so yours is probably shorter. \$\endgroup\$
    – xnor
    Commented Nov 20, 2015 at 5:40
  • \$\begingroup\$ Yeah that's the fix I had in mind \$\endgroup\$
    – xsot
    Commented Nov 20, 2015 at 5:41
5
\$\begingroup\$

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.
\$\endgroup\$
4
\$\begingroup\$

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'
-.-
\$\endgroup\$
2
  • \$\begingroup\$ {(⊃⍒3+/'.??o='⍳⍵)⊃3,/⍵} \$\endgroup\$
    – user46915
    Commented Nov 22, 2015 at 22:53
  • \$\begingroup\$ And given the input constraints, that ?? is also unnecessary. \$\endgroup\$
    – user46915
    Commented Nov 22, 2015 at 23:05
4
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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")
# => "=.-"
\$\endgroup\$
1
\$\begingroup\$

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!

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
2
  • \$\begingroup\$ 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... \$\endgroup\$
    – TLW
    Commented Nov 21, 2015 at 23:54
  • 2
    \$\begingroup\$ 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) \$\endgroup\$
    – Sp3000
    Commented Nov 22, 2015 at 5:36
1
\$\begingroup\$

Brachylog, 10 bytes

s₃ᶠġ₂hᵐoᵒh

Try it online!

Translated from Dennis' Pyth answer.

\$\endgroup\$
0
\$\begingroup\$

Mathematica, 61 bytes

"."
Sort[Partition[#~StringSplit~%,2,1]][[1]]~StringRiffle~%&

Goes for the sleepiest one.

\$\endgroup\$
1
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Nov 30, 2015 at 12:27
0
\$\begingroup\$

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)

\$\endgroup\$
0
\$\begingroup\$

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.
\$\endgroup\$
0
\$\begingroup\$

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.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ 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`,` . \$\endgroup\$ Commented Nov 21, 2015 at 18:33
  • \$\begingroup\$ Using split could save 9 chars \$\endgroup\$
    – edc65
    Commented Nov 21, 2015 at 22:16
  • \$\begingroup\$ @ETHproductions Sorry I didn't notice that the original list of faces wasn't itself in order of sleepiness. \$\endgroup\$
    – Neil
    Commented Nov 22, 2015 at 20:17
0
\$\begingroup\$

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

\$\endgroup\$
0
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.