11
\$\begingroup\$

Maybe some of you already know this game: you have a collection of jelly beans of different colors. For every color, the bean can have different tastes, some are good and some are bad, and you cannot tell them apart. You have to pick a bean of a given color, and pray you have select a good one.

So, write the shortest program that receives a color of your choice (from a given list), and randomly returns the taste selected. The taste has to be picked from a built-in list. The possible list of inputs and outputs are:

Input      Output choices [only one from the list]
--------------------------------------------------
green      lawn clippings, lime, mucus, pear
yellow     rotten eggs, buttered popcorn
blue       toothpaste, blue berry
orange     vomit, peach
brown      canned dog food, chocolate
white      stinky socks, tutti-frutti, baby diapers, coconut

Rules:

  • You can assume that the input is going to be always a color from the input choices.
  • Case and trailing spaces and/or newlines do not matter.
  • Output must be uniformly random: succesive program executions must yield different results, and the chances of getting a given taste must be the same for all tastes in a list.

This is , so may the shortest program win!

\$\endgroup\$
  • \$\begingroup\$ In one part of your question, you state that the taste will be selected from a given list, implying that we will receive it as input. However, in your examples, it seems the opposite is so. \$\endgroup\$ – Okx Jun 9 '17 at 11:53
  • \$\begingroup\$ @Okx sorry, is it better now? I'm still getting used to posting here... \$\endgroup\$ – Charlie Jun 9 '17 at 11:56
  • 1
    \$\begingroup\$ Maybe state that the output must be uniformly random so that all possible outputs have the same odds of appearing or else I can just add 2 options from each list. \$\endgroup\$ – LiefdeWen Jun 9 '17 at 11:57
  • \$\begingroup\$ @StefanDelport thank you, fixed! \$\endgroup\$ – Charlie Jun 9 '17 at 11:58
  • 1
    \$\begingroup\$ It's a bit late now, but it should probably have been blueberry not blue berry. \$\endgroup\$ – Jonathan Allan Jun 9 '17 at 20:39

13 Answers 13

7
\$\begingroup\$

C#, 418 313 305 271 bytes

s=>{var a="lawn clippings,lime,mucus,pear|rotten eggs,buttered popcorn|toothpaste,blue berry|vomit,peach|canned dog food,chocolate|stinky socks,tutti-frutti,baby diapers,coconut".Split('|')["eluaoi".IndexOf(s[2])].Split(',');return a[new System.Random().Next(a.Length)];}

Too long even for C# but I can't see how to get it any shorter.

Full/Formatted version:

using System;

class P
{
    static void Main()
    {
        Func<string, string> f = s =>
        {
            var a = "lawn clippings,lime,mucus,pear|rotten eggs,buttered popcorn|toothpaste,blue berry|vomit,peach|canned dog food,chocolate|stinky socks,tutti-frutti,baby diapers,coconut"
                    .Split('|')["eluaoi".IndexOf(s[2])].Split(',');

            return a[new System.Random().Next(a.Length)];
        };

        Console.WriteLine(f("green"));
        Console.WriteLine(f("yellow"));
        Console.WriteLine(f("blue"));
        Console.WriteLine(f("orange"));
        Console.WriteLine(f("brown"));
        Console.WriteLine(f("white"));

        Console.ReadLine();
    }
}
\$\endgroup\$
  • \$\begingroup\$ That's a hell of a golf! +1 \$\endgroup\$ – Shaggy Jun 9 '17 at 13:17
  • \$\begingroup\$ @Shaggy Thanks :) I started off doing it a really naive way and slowly realised the shorter way of doing things. I had it stuck in my head I'd need a dictionary and then saw your answer using the string and splitting and realised the path to the light! \$\endgroup\$ – TheLethalCoder Jun 9 '17 at 13:19
5
\$\begingroup\$

05AB1E, 126 bytes

¨¤.•4Õ!Õ•.•QCQΓ^ïTÁÕ#HвΘÊÓΘñ…~çÌùY$J*shÉÉk‹Ú&žвZÍζö<^'¢βŽÚq¡eζd`Ãó¨₅γ!i"v_Ym¤ÓδVË5¥vżQЉøΣγ9∞\L‰,ǝ¦8VÜUт:x+sм•'x'-:'q¡'j¡€.R‡

Explanation:

¨¤                              Get the second to last character of the string
  .•4Õ!Õ•                       Compressed string: "eougwt"
         .• .. •                Compressed base-27 string
                'x'-:           Replace "x" with "-" (for tutti-frutti)
                     'q¡        Split on 'q'
                        'j¡     Split each on 'j'
                           €    For each...
                             .R  Select a random element
                               ‡ Transliterate

If anyone's wondering, here's the uncompressed string:

lawn clippingsjlimejmucusjpearqrotten eggsjbuttered popcornqtoothpastejblue berryqvomitjpeachqcanned dog foodjchocolateqstinky socksjtuttixfruttijbaby diapersjcoconut

I can probably compress it more using some clever tricks and the dictionary, though.

Try it online!

\$\endgroup\$
  • \$\begingroup\$ You can compress "eougwt" to .•4Õ!Õ• for -1. \$\endgroup\$ – Erik the Outgolfer Jun 9 '17 at 13:14
  • \$\begingroup\$ @EriktheOutgolfer When I tried that, I was comparing the length of eougwt and .•4Õ!Õ•, instead of "eougwt" and .•4Õ!Õ•. Oops. \$\endgroup\$ – Okx Jun 9 '17 at 13:18
5
\$\begingroup\$

JavaScript (ES6), 235 bytes

I need to figure out how to compress strings in JS!

c=>(a="lawn clippings,lime,mucus,pear|rotten eggs,buttered popcorn|toothpaste,blue berry|vomit,peach|canned dog food,chocolate|stinky socks,tutti-frutti,baby diapers,coconut".split`|`["eluaoi".search(c[2])].split`,`)[new Date%a.length]

If that's not "random enough" for your tastes then add 7 bytes replacing new Date with Math.random().

c=>(a="lawn clippings,lime,mucus,pear|rotten eggs,buttered popcorn|toothpaste,blue berry|vomit,peach|canned dog food,chocolate|stinky socks,tutti-frutti,baby diapers,coconut".split`|`["eluaoi".search(c[2])].split`,`)[Math.random()*a.length|0]

Try it

f=
c=>(a="lawn clippings,lime,mucus,pear|rotten eggs,buttered popcorn|toothpaste,blue berry|vomit,peach|canned dog food,chocolate|stinky socks,tutti-frutti,baby diapers,coconut".split`|`["eluaoi".search(c[2])].split`,`)[Math.random()*a.length|0]

r=(d=document).createElement("input");r.name="i";r.type="radio";l=d.createElement("label");j="Kiwi,sour_lemon,berryBlue,OrangeSherbet,rootBeer,Coconut".split`,`;for(s in e="green,yellow,blue,orange,brown,white".split`,`){r=r.cloneNode();l=l.cloneNode();l.setAttribute("for",r.id=r.value=e[s]);l.style.backgroundImage=`url(https://cdn-tp1.mozu.com/9046-11441/cms//files/${j[s]}.jpg)`;g.prepend(r,l);}onchange=_=>o.innerText=(v=(i=d.querySelector(":checked")).value)+": "+f(v,i.checked=0)
body{align-items:center;background:#eee;display:flex;flex-wrap:wrap;height:100vh;justify-content:center;margin:0;text-align:center;}#g{background:#fff;box-shadow:5px 5px 5px #ccc;padding:10px;}input{display:none;}label{background-repeat:no-repeat;background-size:contain;cursor:pointer;display:inline-block;height:64px;margin:10px;width:75px;}#o{font-family:monospace;font-size:18px;margin:10px auto;text-align:center;width:100%;}
<div id=g><pre id=o>click a jelly bean</pre></div>

\$\endgroup\$
  • 3
    \$\begingroup\$ Nice idea with eluaoi, I thought of it by myself and thought, "Oooh look how clever I'm being" then saw you beat me to it! \$\endgroup\$ – TheLethalCoder Jun 9 '17 at 12:34
  • \$\begingroup\$ new Date%a.length isn't "uniformly random". \$\endgroup\$ – Olivier Grégoire Jun 9 '17 at 12:43
  • \$\begingroup\$ Thanks, @TheLethalCoder - I was that lazy, I nearly didn't bother checking for uniqueness past the 2nd characters! \$\endgroup\$ – Shaggy Jun 9 '17 at 13:21
  • 3
    \$\begingroup\$ Heh, I think about 4 or 5 of us came up with eluaoi around the same time :P \$\endgroup\$ – ETHproductions Jun 9 '17 at 13:21
  • \$\begingroup\$ @OlivierGrégoire, this solution predates that requirement but I've added another option that uses Math.random instead. \$\endgroup\$ – Shaggy Jun 9 '17 at 13:22
4
\$\begingroup\$

Jelly, 101 100 bytes

3ị“©ȷ#Ȧ-»iị“'æLṬẏeṃɼẹ-N0ṁH)A“¬ɗ-ṃȥḞ“I$aṇṾjð4“£Ʋṛ÷pḶƥƑL]p“÷Hnøgİỵ£@ḥEḶƑƤi÷Ḃ\oŻẆ#ụqU½b“ḥĠḄĿĖṇ⁻Œḳ-¬"»ỴX

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Japt, 148 146 bytes

`È}hpŠ1½ue ¼rry
lawn c¦ppÄ1Ò˜1muc«1pe‡
vÇ1pea®
ÐXky socks1ÉÍi-frÔk1baby ¹ap€s1¬¬n©
¯nšd ºg food1®o¬ÓŠ
݁ eggs1瘪 pop¬rn`·g`uÁ4`âUg2¹q1 ö

Try it online!

Saved 6 bytes thanks to Shaggy and ETHproductions

\$\endgroup\$
  • \$\begingroup\$ Split on R instead of 0 to save a byte. Also, you might be able to compress eluaoi by playing around with the order. \$\endgroup\$ – Shaggy Jun 9 '17 at 12:19
  • \$\begingroup\$ @Shaggy How would that save a byte? I would need to call qR which is the same length? \$\endgroup\$ – Tom Jun 9 '17 at 12:22
  • \$\begingroup\$ Check the Unicode​ shortcuts in the docs ;) \$\endgroup\$ – Shaggy Jun 9 '17 at 12:25
  • \$\begingroup\$ Sorry, forgot to say you can remove the space before ® too. \$\endgroup\$ – Shaggy Jun 9 '17 at 12:30
  • \$\begingroup\$ Nice, almost exactly what I had. You only need 5 of the 6 chars in the string because the missing one will have an index of -1, and therefore gets the last item in the array. If you use eaiou as the string you can compress it down to three bytes (there may be other three-byte combinations). \$\endgroup\$ – ETHproductions Jun 9 '17 at 12:58
3
\$\begingroup\$

Python 2, 301 258 bytes

lambda x:choice({'e':'lawn clippings,lime,mucus,pear','l':'rotten eggs,buttered popcorn','u':'toothpaste,blue berry','a':'vomit,peach','o':'canned dog food,chocolate','i':'stinky socks,tutti-frutti,baby diapers,coconut'}[x[2]].split(','))
from random import*

Try it online!

Saved very many bytes by shortening the keys to use the 2nd index of the input, as suggested by @TheLethalCoder, and by splitting on commas instead of using a direct list.

\$\endgroup\$
  • 1
    \$\begingroup\$ Use eluaoi as the dictionary keys and access it with index 2 of the string should save you bytes. \$\endgroup\$ – TheLethalCoder Jun 9 '17 at 12:32
  • \$\begingroup\$ Big (y) to LethalCoder's idea \$\endgroup\$ – officialaimm Jun 12 '17 at 8:12
3
\$\begingroup\$

Jelly,  95  94 bytes

OḄị“÷Hnøgİỵ£@ḥEḶƑƤi÷Ḃ\oŻẆ#ụqU½b““¬ɗ-ṃȥḞ“'æLṬẏeṃɼẹ-N0ṁH)A“ḥĠḄĿĖṇ⁻Œḳ-¬"““I$aṇṾjð4“£Ʋṛ÷pḶƥƑL]p»ỴX

A monadic link accepting a list of (lowercase) characters and returning a list of characters.

Try it online! or eat a packet of 48.

How?

Eighty-nine of the ninety-four bytes are a compressed list of eight strings. Two of these are empty strings and the other six are each newline separated flavours for one of the colours:

“...““...“...“...““...“...»
“...““...“...“...““...“...»
“                         » - a compression of dictionary words & or strings
    ““   “   “   ““   “     - list separations
    ^            ^          - the two empty lists of characters
 ...^ ... ... ...^ ... ...  - bytes used to encode the data
 wht  org grn ylw^ blu brn  - with the colours indicated. For example:
  1 2  3   4   5 6  7   0   -   “ḥĠḄĿĖṇ⁻Œḳ-¬"» is a compression of:
                            -     word     + word   + string + word       + word
                             -     "rotten" + " egg" + "s\n"  + "buttered" + " popcorn"
                             - and is at the fifth index, relating to "yellow"

The rest of the program parses the input to decide which list to use, splits the chosen list by newlines and picks a random element:

OḄị“...»ỴX - Main link:s e.g.: "blue"           "yellow"                  "brown"              "white"               "orange"                 "green"
O          - cast to ordinals  [98,108,117,101] [121,101,108,108,111,119] [98,114,111,119,110] [119,104,105,116,101] [111,114,97,110,103,101] [103,114,101,101,110]
 Ḅ         - from binary       3276             7125                      1151                 6899                  3272                     3489
  ị        - index into - 1 based and modular with 8 items so...
           -          indexes: 3276%8=4         7125%8=5                  1151%8=7             6899%8=3              3272%8=0                 3489%8=1
        Ỵ  - split at newlines (gets the list of flavours for the chosen colour)
         X - random choice (gets one of those flavours at random)
\$\endgroup\$
2
\$\begingroup\$

Java, 288 bytes

s->{String[]a="lawn clippings,lime,mucus,pear#rotten eggs,buttered popcorn#toothpaste,blue berry#vomit,peach#canned dog food,chocolate#stinky socks,tutti-frutti,baby diapers,coconut".split("#")["eluaoi".indexOf(s.charAt(2))].split(",");return a[new java.util.Random().nextInt(a.length)];}

Test it yourself!

Could be golfed by using a char[].

However the random part can't be "uniformly distributed" without the explicit use of Random.nextInt(int). Even (int)(Math.random()*a.length) isn't uniformly distributed.

\$\endgroup\$
  • \$\begingroup\$ Hmm, I din't get the explanation about why you have to use new java.util.Random().nextInt(a.length) instead of (int)(Math.random()*a.length).. \$\endgroup\$ – Kevin Cruijssen Jun 13 '17 at 12:33
  • 1
    \$\begingroup\$ Math.random() provides a number that has some specificities (a power of 0 and a sign of 0 and 52 random bits). So you actually use an entropy of 52 without any further check. If length is 3, for instance, 2^52 is not divisible by 3. So it is not randomly distributed. This is why Random.nextInt(int) (actual java file, not javadoc, at line 394) has a loop mechanism to make sure the number is amongst fair numbers. Unless I'm said "it's good enough", only Random.nextInt(n) is fair. \$\endgroup\$ – Olivier Grégoire Jun 13 '17 at 13:06
  • \$\begingroup\$ @KevinCruijssen My mistake: it's 53 random bits, not 52. \$\endgroup\$ – Olivier Grégoire Jun 13 '17 at 13:16
  • 1
    \$\begingroup\$ Ah ok, thanks for the explanation. So Math.random() can't be used when 2^53 cannot be evenly divided by the number you multiply it with? So if you want a random number from 0-3, (int)(Math.random()*4) is acceptable to evenly divide it (four time 2251799813685248), but when you use *3 instead it isn't (which is three times 3002399751580330.666...), because casting it to int floors it, making some parts 1 smaller than others. And since length is variable in your case, it's not uniformly distributed either (with the possibility of being length 3). \$\endgroup\$ – Kevin Cruijssen Jun 13 '17 at 13:27
  • 1
    \$\begingroup\$ Yep, you understood it all! If someone says "random", use Math.random(), if someone says something along "uniformly" or "fairly" random, use java.util.Random. That's also why I complained about Shaggy's answer. \$\endgroup\$ – Olivier Grégoire Jun 13 '17 at 13:35
1
\$\begingroup\$

><>, 311 bytes

</"y"/\_  _
v\i-?\x"sgge nettor"
v/"l"/\"nrocpop derettub"
v\i-?\x"etsaphtoot"
v/"o"/\"yrreb eulb"
v\i-?\x"etalocohc"
v/"n"/\"doof god dennac"
v\i-?\x"timov"
v/"n"/\"hcaep"
v\i-?\>x\/~~"srepaid ybab"
v"lime" x"sgnippilc nwal"
v"pear"x  _"sucum"
v    \~__>x\
v"coconut" x"skcos yknits"
>l?!;/\  \x_"itturf-ittut"

Try it online, or watch it at the fish playground

Featuring SK cosy knits and Doof God Dennac!

Explanation: The fish's first task is to figure out what the input word is by zig-zagging down the left hand side. The fish can only read one letter at a time, and it takes fewer bytes to do this destructively. First, the fish reads the first letter and asks if it's "y" — if it is, the word is "yellow", otherwise it moves on. It then reads the second letter — if it's "l", the word is "blue", otherwise it moves on; and so on. If it reads five letters and they don't match "y" (Yellow), "l" (bLue), "o" (brOwn), "n" (oraNge) or "n" (greeN) respectively, then the colour must have been "white".

Next comes the random bit. For the colours with two possible outputs, this is pretty straightforward — for yellow, for example, the fish enters the following code at the x:

/\
\x"sgge nettor"
 \"nrocpop derettub"

The x sets the direction randomly: if it's up or left, the fish swirls around the mirrors back to the x, but if it's right or down, it reads "rotten eggs" or "buttered popcorn" (in reverse).

The four-way splits (for white and green) are messier, but they follow the same general principal — the first is:

     >x\
"lime" x"sgnippilc nwal"
"pear"x   "sucum"
      __

Note that if the fish swims up from the first x, it passes through eight "s, which toggle string mode on and off four times, then it hits a mirror and swims back down.

To get to the last four-way split, the fish has to swim through the e and r of "lime" and "pear", which add e = 14 to the stack (and reverse it), so we first have to delete that with ~. One of the four branches also involves swimming through a junk string, "> ", which we delete with ~~.

    \   /~~"srepaid ybab"
    e   "
    r    _
    \~  >x\
"coconut" x"skcos yknits"
        \x_"itturf-ittut"
         _

Finally, after adding one of the bean flavours to the stack, the fish reaches the stream of vs in the leftmost column, which sends it to

v    \
v    o
>l?!;/

which prints characters (using one of the os in "coconut") until there are none left.

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

T-SQL, 432 423 375 367 336 295 bytes

Finally, a set-based operation!!

SELECT TOP 1 SUBSTRING(value,2,99)
FROM t,STRING_SPLIT('elawn clippings-elime-emucus-epear-lrotten eggs-lbuttered popcorn-utoothpaste-ublue berry-avomit-apeach-ocanned dog food-ochocolate-istinky socks-itutti-frutti-ibaby diapers-icoconut','-')
WHERE SUBSTRING(c,3,1)=LEFT(value,1)
ORDER BY NEWID()

(Line breaks are for display and are not counted in total.)

Input is via column c in named table t, per our guidelines.

I'm simply joining our input table to a table full of the valid color/flavor combinations, then selecting a random row. ORDER BY NEWID() is a common way to randomize sort order in SQL. Depending on how strict you are, you might not consider it perfectly uniformly random, but it should be sufficiently random for jelly bean selection.

EDIT 1: Saved 9 bytes by using only the 3rd character of the color, inspired by other answers.

EDIT 2: Saved 48 bytes by putting the color flag and flavor in a single column. Lots of characters saved in the INSERT.

EDIT 3: Saved 8 bytes by replacing INSERT INTO b(o) with INSERT b

EDIT 4: Saved 31 more bytes by joining straight to the virtual table of VALUES and therefore eliminating the CREATE TABLE and INSERT.

EDIT 5: Save 41 bytes by upgrading to SQL 2016-only STRING_SPLIT function, which allows me to eliminate the variable and dynamic SQL execution.

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

PHP, 242 bytes

<?=($a=explode(_,[e=>'lawn clippings_lime_mucus_pear',l=>'rotten eggs_buttered popcorn',u=>'toothpaste_blue berry',a=>vomit_peach,o=>'canned dog food_chocolate',i=>'stinky socks_tutti-frutti_baby diapers_coconut'][$argn[2]]))[array_rand($a)];

Try it online!

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

Mathematica, 247 bytes

R=RandomChoice
green=R@{lawn clippings,lime,mucus,pear}
yellow=R@{rotten eggs,buttered popcorn}
blue=R@{toothpaste,"blue berry"}
orange=R@{vomit,peach}
brown=R@{canned dog food,chocolate}
white=R@{stinky socks,tutti-frutti,baby diapers,coconut}
#&

Input form

[green]

\$\endgroup\$
  • \$\begingroup\$ Can you index into the string and use the eluaoi trick? I don't know mathematica so just an idea. \$\endgroup\$ – TheLethalCoder Jun 9 '17 at 14:40
0
\$\begingroup\$

Clojure, 231 bytes

#(rand-nth({\e["lawn clippings""lime""mucus""pear"]\l["rotten eggs""buttered popcorn"]\u["toothpaste""blue berry"]\a["vomit""peach"]\o["canned dog food""chocolate"]\i["stinky socks""tutti-frutti""baby diapers""coconut"]}(get % 2)))

Same idea as the others, I can just save some space compared to other languages. Compressing strings seems like a lost cause.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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