# Why? To please the rich programmer!

Have you ever wanted to ask the compiler "Why?" Most of us have been frustrated when the code isn't working as it should. Mathworks has therefore implemented a nice little function, why, that answers the question. To give a few examples from MATLAB:

why
The programmer suggested it.

why
To fool the tall good and smart system manager.

why(2)
You insisted on it.

why(46)
Bill insisted on it.


Your task is to implement the why function in your language. The function should work with and without an input argument (alternatively use input 0 or -1). The function must be named why (or, writing why(n) in STDIN should result in the appropriate string being printed).

If no argument is given, or the argument is zero or negative, the output string should be a random, valid phrase. So, there should be a function why, why(), why(0) or why(-1) that returns a random sentence.

If an input argument, n is given (function argument, not STDIN), the output should be the n'th string (defined below). So, why(1) should always output (print/display) the same result.

The sentences are built up as follows (Type 1, Type 2 and Special). All sentences end with !.

"Person" "ending" !
A list of special cases


The list of persons:

Stewie
Peter
Homer
The programmer
The system manager
You


The list of endings:

suggested it
insisted on it
did it


The list of verbs are:

To fool
To satisfy


the smart
the bald
the tall
the rich
the stupid


The list of special cases:

How should I know?


The way to select a numbered one is:

Type of sentences:

Odd number => Type 1
Even number => Type 2
n % 7 = 0 => Type 3 (% is the modulus operator)


Names: The nth name is defined using modulus (%).

n = 1:   1 % 7  => Stewie
n = 2:   2 % 7  => Peter
...
n = 6:   6 % 7  => You
n = 7:   7 % 7  => How should I know?
n = 11:  11 % 7 => The programmer
n = 14:  14 % 7 => Stop asking!
n = 21:  21 % 7 => Don't ask!


Endings: The nth ending is also defined using the modulus. Assume the endings (1, 2 and 3) are listed like (1 2 2 3). As the numbers are always odd, use ((n+1)/2 % 4)

n = 1:    ((1+1)/2 % 4)  => suggested it
n = 3:    ((3+1)/2 % 4)  => insisted on it
n = 13:   ((13+1)/2 % 4) => did it


Adjectives: The nth adjective is defined using the modulus. As the numbers are always even, use: (n % 10)/2

n = 2:   (2 % 10)/2 => Smart
n = 6:   (6 % 10)/2 => The tall
...


Verbs: The nth verb is also defined using the modulus. Assume the verbs (1, 2 and 3) are listed like (1 2 2 3) As the numbers are always even for verbs, use (n % 8) / 2

n = 2:   (2 % 8)/2 => To fool
n = 4:   (4 % 8)/2 => To satisfy
n = 6:   (6 % 8)/2 => To satisfy
n = 8:   (8 % 8)/2 => To please


Now, the way to create a random one should be fairly simple, simply select a random n.

Some examples:

why
You suggested it!

why
To fool the tall Homer!

why

why(1)
Stewie suggested it!

why(14)

why(8)


Standard code golf rules apply. A winner will be selected one week from the day the challenge was posted.

• writing why in the stdin should return the string I might be able to work with that. Does it have to be lowercase why or would WHY be acceptable? Oct 7, 2015 at 16:00
• Lower and upper case are both fine. Oct 7, 2015 at 16:28
• Also the Endings should not need /2 to work. That gives fractional values. 13 should also be insisted (14/2=7 %4 = 3 = 2nd of insisted). Oct 7, 2015 at 16:44
• Does it matter if you end up with cases like the rich The programmer due to the specified the? Oct 7, 2015 at 17:03
• @StewieGriffin The words The and To in your lists should probably be lowercase to match your examples... Oct 7, 2015 at 17:06

# JavaScript (ES6) 345

Not sure about the numbers, but here is my attempt.

Test running the snippet below in an EcmaScript compliant browser.

why=n=>(n<1?n=Math.random()*840|0:0,s="suggested,insisted on,did,fool,satisfy,please,stupid,smart,bald,tall,rich,Don't ask!,How should I know?,Stop asking!,Stewie,Peter,Homer,programmer,system manager,You".split,,n%7?(p=s[n%7+13],n&1?(p>'a'?'The ':'')+p+ ${s['2011'[-~n/2%4]]} it!:To${s['5344'[n%8/2]]} the ${s[n/2%5+6]}${p}!):s[11+n%3])

for(o='',i=0;++i<1e3;)o+=i+':'+why(i)+'\n';O.innerHTML=o

function test() { R.innerHTML=why(+I.value) }

// Less golfed

WHY=n=>(
n=n<1?Math.random()*999|0:n,
s=["suggested", "insisted on", "did", "fool", "satisfy", "please",
"stupid", "smart", "bald", "tall", "rich",
"Stewie", "Peter", "Homer", "programmer", "system manager", "You"],
n%7
? ( p=s[n%7+13],
n&1
? (p>'a'?'The ':'')+p+ ${s['2011'[-~n/2%4]]} it! : To${s['5344'[n%8/2]]} the ${s[n/2%5+6]}${p}!)
: s[11+n%3]
)  
#O { height:300px; width:50%; overflow:auto }
#I { width:2em }
Why(<input id=I>)<button onclick=test()>-></button><span id=R></span>
<pre id=O>

• Nice answer! Can't speak authoritatively on the number validity, but you can save 1 byte (!) using 0 as your string delimiter instead of ,! Oct 8, 2015 at 7:26
• @DomHastings I think that trick is no more needed with template strings. split(0) is the same length of split',' (pretend these are backticks) Oct 8, 2015 at 7:34
• Ahhh, sorry, I was thinking you could lose the brackets, this isn't coffeescript! :) Oct 8, 2015 at 7:35

# C#, 502 bytes

This project needs to have the AssemblyName set to why which will produce an executable with the correct name.

Fully golfed:

using System;class W{static void Main(string[]i)int n=i.Length>0?int.Parse(i):new Random().Next();string[]s={"Don't ask!","How should I know?","Stop asking!"},v={"To please ","To fool ","To satisfy ",null},a={"the stupid","the smart","the bald","the tall","the rich"},p={"","Stewie","Peter","Homer","The programmer","The system manager","You"},e={"suggested it!","insisted on it!",null,"did it!"};Console.Write(n%7<1?s[n%3]:n%2<1?(v[n%8/2]??v)+a[n%10/2]+" {0}!":"{0} "+(e[n/2%4]??e),p[n%7]);}}


Indentation and new lines for clarity:

using System;
class W{
static void Main(string[]i)
int n=i.Length>0
?int.Parse(i)
:new Random().Next();
string[]
v={"To please ","To fool ","To satisfy ",null},
a={"the stupid","the smart","the bald","the tall","the rich"},
p={"","Stewie","Peter","Homer","The programmer","The system manager","You"},
e={"suggested it!","insisted on it!",null,"did it!"};
Console.Write(
n%7<1
?s[n%3]
:n%2<1
?(v[n%8/2]??v)+a[n%10/2]+" {0}!"
:"{0} "+(e[n/2%4]??e),
p[n%7]
);
}
}


Example input/output:

>Why
To fool the bald Homer!
>Why 1
Stewie suggested it!


# Powershell 437461 453 Bytes

Edit: Missed the duplicated verbs

Splitting between the corpus and the calculations for byte-count

• 267 Bytes = Pre-coded text (excluding to,the,it and ! since they have fixed places).
• 186 Bytes = calculation

Sets default argument to 0 if not specified. If argument is <1 then it gets a random number <99 fn:1 and reruns. Technically this means -50 will work as well, being treated as a random case.

function why{param($b=0)$p=@('Stewie','Peter','Homer','The programmer','The system manager','You');$e=@('did','suggested','insisted on','insisted on');$v=@('please','fool','satisfy','satisfy');$a=@('stupid','smart','bald','tall','rich');$s=@("Don't ask!",'How should I know?','Stop asking!');if($b-le0){why(Get-Random 99)}elseif(!($b%7)){$s[$b/7%3]}else{$n=$p[$b%7-1];if($b%2){"$n$($e[($b+1)/2%4]) it!"}else{"To $($v[$b%8/2]) the$($a[$b%10/2]) $n!"}}}  Explanation: # Any -1 in calculations is to account for arrays starting at index 0 # Final key placed in position 0 for indexing (4%4 = 0) # Powershell 1 = True, 0 = False if($b-le0){why(Get-Random 99)}          # If not positive, choose random number
elseif(!($b%7)) #$b%7 means special so use that
{$s[$b/7%3]}                          # Divide by 7 and find modulo, use that phrase.
else{$n=$p[$b%7-1] # Get the correct person (Used in both types). 6 max if($b%2){"$n$($e[($b+1)/2%4]) it!"}    # Create type 1 sentence
else{"To $($v[$b%8/2]) the$($a[$b%10/2]) $n!"} # Type 2  fn:1 99 Chosen to save a byte. If there are more than 99 possible sentences above (did not calculate) increase to 999 or 9999 as applicable (+1/2 bytes) # MUMPS, 379 bytes f(s,i) s:'i i=$L(s,"^") q $P(s,"^",i) why(n) s:'n n=$R(840) s p="Stewie^Peter^Homer^The programmer^The system manager^You",e="suggested^insisted on^did",v="fool^satisfy^please",a="smart^bald^tall^rich^stupid",s="How should I know?^Stop asking!^Don't ask!" q:n#7=0 $$f(s,n#3) q:n#2$$f(p,n#7)_" "_$$f(e,n+1/2#4)_" it!" q "To "_$$f(v,n#8/2)_" the "_$$f(a,n#10/2)_" "_$$f(p,n#7)_"!"


When no input is given, a random number in 0..839 is generated.

Usage:

>w $$why(15) Stewie did it! >w$$why()


MUMPS's left-to-right evaluation strategy saves a good few bytes on parentheses here.

Side note: see those strings that look like "foo^bar^baz^qux"? Those are so-called "delimited strings", and are the standard way of storing lists that fit within the maximum string size limit, since MUMPS does not actually have lists/arrays (or, indeed, any data structures besides trees). For lists too large to fit in a single string, we instead use trees of depth 1 and put the values on the leaves of the tree. Fun!

• +1: MUMPS, of all languages, really needs a why function. ;) Oct 14, 2015 at 0:47

# Emacs Lisp 473 Bytes

(defun why(n)(if(and n(> n 0))(let*((p'(t"Stewie""Peter""Homer""The programmer""The system manager""You"))(e'("did""suggested""insisted on""insisted on"))(v'("please""fool""satisfy""satisfy"))(a'("stupid""smart""bald""tall""rich"))(s'("Don't ask!""How should I know?""Stop asking!"))(q(nth(% n 7)p)))(cond((=(% n 7)0)(nth(%(/ n 7)3)s))((=(% n 2)1)(format"%s %s it!"q(nth(%(/(1+ n)2)4)e)))(t(format"To %s the %s %s!"(nth(/(% n 8)2)v)(nth(/(% n 10)2)a)q))))(why(random 99))))


Largest 'waste' is probably the format,%s... sections. If variables could be inlined into the strings without the specification it would save 10 bytes on %s and another 12 on format

# Ruby 396378 372 bytes

I'm sure this is not golfed to the max.

p=%w[a Stewie Peter Homer The\ programmer The\ system\ manager You]
why=->n{n<1 ? why[rand(99)+1]:n%7<1 ? $><<%w[a How\ should\ I\ know? Stop\ asking! Don't\ ask!][n/7]:n%2<1 ?$><<'To '+%w[fool satisfy satisfy please][n%8/2-1]+' the '+%w[smart bald tall rich stupid][n%10/2-1]+' '+p[n%7]+?!:\$><<p[n%7]+' '+%w[a suggested insisted\ on insisted\ on did][(n+1)/2%4]+' it!'}


Edit: I've just realized that I don't know operator precedence. Oh well..

• rand(21) seems way too small Oct 7, 2015 at 20:02
• What about 99? :P Oct 7, 2015 at 20:04
• There are 108 compound sentences + 3 special cases. The sequence of sentences is periodic but the period ... I don't know Oct 7, 2015 at 20:09
• The period is probably 840 ... good choice of numbers Oct 7, 2015 at 20:15

## CJam, 281 bytes

99mrqi_])0>=i:A7md{;A2%{S["suggested""insisted on""did"]A2/=+" it"+}{"To "["fool""satisfy"_"please"]A(2/:B=" the "["smart""bald""tall""rich""stupid"]B=SM}?[M"Stewie""Peter""Homer""The programmer""The system manager""You"]A=\'!}{["How should I know?""Stop asking!""Don't ask!"]\(=}?


Haven't used CJam before, so I'll take any tips. I'm sure there's a lot of tricks I don't know!

(I couldn't figure out how to name this as a function called "why" - it appears that functions don't exist in CJam - so I'm not sure if a CJam answer is okay or not...)

• Functions do exist, but there are only 26 valid function names (A to Z). Oct 8, 2015 at 5:48

# Lua 5.3.0, 452460 446 bytes

This is my first attempt at a code golf, so please correct me if I did something wrong!

a={"Stewie","Peter","Homer","The Programmer","The system manager","You"}b={"fool ","satisfy ",n,"please "}b=bwhy=function(n)pcall(math.randomseed,n and n>0 and n)n=math.random(1e9)q=n>>4r=n>>8return 1>n&7 and({"How should I Know?","Stop asking!","Don't ask!"})[q%3+1]or 0<n%2 and a[q%6+1]..({" suggested"," insisted on"," did"})[r%3+1].." it"or"To "..b[q%4+1].."the "..({"smart ","bald ","tall ","rich ","stupid "})[r%5+1]..a[(r>>4)%6+1]end


Ungolfed:

a={
"Stewie",
"Peter",
"Homer",
"The Programmer",
"The system manager",
"You"
}
b={
"fool ",
"satisfy ",
n,
}
b=b
why=function(n)
pcall(math.randomseed,n and n>0 and n)
n=math.random(1e9)
q=n>>4
r=n>>8
return
1>n&7 and
or 0<n%2 and
a[q%6+1]..({" suggested"," insisted on"," did"})[r%3+1].." it"
or
"To "..b[q%4+1].."the "..({"smart ","bald ","tall ","rich ","stupid "})[r%5+1]..a[(r>>4)%6+1]
end


# Python (2), 692 bytes

I’m still learning, so please be gentle! :)

from sys import argv,maxint
import random
def why(*O):
if len(argv)>1:A=O
else:A=random.randint(-maxint-1,maxint)
if A%7==0:print S[A%3]
else:
M=P[A%6]
if A%11==0:
M=P
if A%2==0:
if M==P:M="you"
U=I[(A%8)/2];Z=Q[(A%10)/2];print"To %s the %s %s!"%(U,Z,M)
if A%2==1:
if M==P:M="The %s"%P
if M==P:M="The %s"%P
C=E[((A+1)/2)%4];print"%s %s it!"%(M,C)
if len(argv)>1:why(int(argv))
else:why()


Works with or without an int as a command line argument.

I tried to emphasise code correctness as much as possible, as with generating random numbers from -sys.maxint - 1 to sys.maxint and displaying sentences in the right case.

The code relies very heavily of if-statements that I’m sure could be replaced with something more place efficient.

Feedback is very welcome!

### Ungolfed (1341 bytes)

from sys import argv, maxint
import random

def Why(*Optional):
Persons = ["You", "Stewie", "Peter", "Homer", "programmer", "system manager"]
Endings = ["did it", "suggested it", "insisted on it", "insisted on it"]
Verbs = ["please", "fool", "satisfy", "satisfy"]
Adjectives = ["stupid", "smart", "bald", "tall", "rich"]

if len(argv) > 1:
Argument = Optional
else:
Argument = random.randint(-maxint - 1, maxint)

if Argument % 7 is 0:
print SpecialCases[Argument % 3]
else:
Person = Persons[(Argument) % 6]
if Argument % 11 is 0:
Person = "programmer"
if Argument % 2 is 0:
if Person is "You":
Person = "you"
Verb = Verbs[(Argument % 8) / 2]
print "To %s the %s %s!" % (Verb, Adjective, Person)
if Argument % 2 is 1:
if Person is "programmer":
Person = "The programmer"
if Person is "system manager":
Person = "The system manager"
Ending = Endings[((Argument + 1) / 2) % 4]
print "%s %s!" % (Person, Ending)

if len(argv) > 1:
Why(int(argv))
else:
Why()

• I suggest you read [codegolf.stackexchange.com/questions/54/…—in particular, you can save many bytes by using the first tip on that page. You can also index from the back of the verb list so you only need one "satisfy": use argument%8/2-1 and remove the second one. You can also replace ==0 with <1. Oct 8, 2015 at 1:10