# Have you been nice this year?

## Introduction

Santa has too many names to process, and needs your help! He needs you to write a program or a function, which outputs nice, naughty, very naughty or very very naughty. To determine how nice or naughty someone is, Santa had developed an algorithm:

Nice (, ):

First of all, we obtain a number from the name by adding all the letters up (spaces ignored). For example:

Doorknob =

D = 4
o = 15
o = 15
r = 18
k = 11
n = 14
o = 15
b = 2

4 + 15 + 15 + 18 + 11 + 14 + 15 + 2 = 94


If the number of divisors is equal to the length of the name, the person is considered nice. This means that your program should output [name] has been nice. Here, the divisors of 94 are:

Divisors of 94: 1, 2, 47, 94


There are 4 divisors, but the name has length 8 (spaces included). Conclusion, Doorknob has not been nice. So we continue our journey:

Naughty (, ):

Santa has developed a new sequence, the christmas number. First, we will look at the following christmas trees:

n = 1        n = 2          n = 3          n = 4

*
***
*****
*******
*********
_   *             ***
|   ***           *****
|  *****         *******
*         | *******       *********
*           ***        |   ***            ***
***         *****   n*n |  *****          *****
*           ***        | *******        *******
*****       |   ***         *********
*         |  *****           ***
|_*******         *****
*           *******
|_____|       *********
2n+1            *

5            18             47             98


The amount of asterisks determines the christmas number. The sequence goes as following: 5, 18, 47, 98, 177, ....

From here, we can conclude that 94 is not a christmas number. That means that Doorknob has not just been naughty.

Very naughty ():

For this, we need to find out if Doorknob is a raising ladder string. This is determined by the letters in the name with A = 1, B = 2, C = 3, etc.:

First we will look at the first letter, the D. This has value 4. This is our starting point. The next letter is o. This has the value 15, which is higher than our previous value, so we're going a step higher on the ladder. The next value is also an o. This is the same, so we're doing nothing. If the next value is higher than the current value, we will go a step higher. If the next value is lower than the current value, we will go a ster lower. If it's the same, we'll stay on the same step. This visualised for Doorknob, Martin Buttner and Alex A:

            O
/ \
R   N   B
/ \ /
O-O   K                 T   N   U                 L   X
/                       / \ / \ / \               / \ / \
D                   M   R   I   B   T-T           A   E   A
\ /               \
A                 N   R
\ /
E


You can see that Doorknob ended higher than the starting position. So Doorknob has been very naughty. Martin Buttner and Alex A didn't get higher than the starting point. So they are both very very naughty.

## Test cases

Input: Doorknob
Output: Doorknob has been very naughty

Input: Martin Buttner
Output: Martin Buttner has been very very naughty

Input: Jakube
Output: Jakube has been nice

Input: B
Output: B has been very very naughty


## Rules

• You need to provide a program or a function which takes input (which consists of at least one letter).
• The input will consist of uppercase letters, lowercase letters and spaces. Spaces are ignored during the process, except for the length of the input.
• This is , so the submission with the least amount of bytes wins!
• Btw, the proper way to write Büttner without an umlaut is Buettner, not Buttner. Commented Dec 20, 2015 at 15:50
• The Christmas numbers are generated by n^3 + 2n^2 + 2, btw.
– lynn
Commented Dec 20, 2015 at 16:10
• Alrighty. Then the maximum "score" for a name is ZZZ...Z = 26 * 99 = 2574, meaning you only need to check Christmas numbers up to and including n=13. (Useful info for other golfers.)
– lynn
Commented Dec 20, 2015 at 16:23
• Santa has been very very naughty. Wait, what? Commented Dec 20, 2015 at 18:35
• @Doorknob冰 - You didn't get his full name: Santa Claus has been very naughty. Should also try Saint Nick, Saint Nicholas, St. Nick, St. Nicholas, Kris Kringle, Father Christmas, Pere Noel, and all his other aliases - maybe one of them will work? Though why a "nice" guy should need so many aliases is already pretty suspect... Commented Dec 20, 2015 at 22:48

## CJam, 109108 107 bytes

l" has been "1$[_,\S-:eu'@f-:A:+__,:)f%0e=@=\_{)__2+**))}%&A2ew::-:g1b0<]{}#4,="very "*_5>\"naughty""nice"?  Try it online. ### Explanation A full explanation will have to wait until later, but here is the code broken down into the different sections: l" has been "1$[                    e# Some preparation...
_,\S-:eu'@f-:A:+                  e# Determine letter sum.
__,:)f%0e=@=                      e# Check divisor count.
\_{)__2+**))}%&                   e# Check for Christmas number.
]{}#4,="very "*_5>\"naughty""nice"? e# Determine nice/naughtiness.

• @RikerW I stole that from Doorknob's comment. Commented Dec 20, 2015 at 19:50
• I +1'nd his comment too. Commented Dec 20, 2015 at 19:51
• "Santa has been very very naughty" Commented Dec 21, 2015 at 2:24

# Pyth 86 bytes

Apparently I've been nice this year...

jd[z"has been"?qlzl{yPJsKxL+NG@Grz0"nice"+*"very "&!}Jm+*+2d*dd2SJhgs._M-VKtK0"naughty


Try it online: Demonstration or Test Suite

### Explanation:

jd[z"has been"...      list with input string, "has been" and ...; join with spaces
qlzl{yPJsKxL+NG@Grz0   compares the length of input with the number of divisors
(computes all prime factors and counts the elements in the powerset)
?..."nice"             if True, use "nice" as last list element
else:
}Jm+*+2d*dd2SJ            check for christmas number
(checks, if its of the form n^3+2*n^2+2)
gs._M-VKtK0               check if raising ladder string ends lower or equal
(assigns each neighbor pair a number -1,0,1 and computes the sum)
&!...h...                 returns 0, 1 or 2
*"very "                  repeat "very " this times
+..."naughty              add "naughty" and use this as the third list element


# MATL, 117 bytes

My longest MATL program so far :-) :-(

Uses current release of the language, which is earlier than this challenge.

jttk96-t0>)tstt:\~s4$bn=?xx'nice'}[1,2,0,2]99:ZQ=a?'naughty'}dt0>sw0<s-O>~'very naughty'w?'very 'wh]]]' has been 'whh  ### Examples >> matl > jttk96-t0>)tstt:\~s4$bn=?xx'nice'}[1,2,0,2]99:ZQ=a?'naughty'}dt0>sw0<s-O>~'very naughty'w?'very 'wh]]]' has been 'whh
>
> Doorknob
Doorknob has been very naughty

>> matl
> jttk96-t0>)tstt:\~s4$bn=?xx'nice'}[1,2,0,2]99:ZQ=a?'naughty'}dt0>sw0<s-O>~'very naughty'w?'very 'wh]]]' has been 'whh > > Jakube Jakube has been nice  ### Explanation jt % input string. Duplicate tk96-t0>) % duplicate. Convert to lower, then to numbers, remove spaces ts % duplicate. Sum tt: % duplicate. Vector from 1 to obtained sum \~s % modulus operation. Count zeros to determine number of divisors 4$bn=                     % does it equal original name length?
?                         % if so
xx'nice'              % remove values not needed, and push string
}                         % else
[1,2,0,2]99:ZQ        % all Christmas numbers
=a                    % does sum equal any Christmas number?
?                     % if so
'naughty'         % push string
}                     % else
dt0>s             % total number of increases
w0<s              % total number of decreases
-O>~              % subtract both. Is total <=0?
'very naughty'w   % push string, which will be needed in either case. Swap
?                 % if total was <=0
'very 'wh     % prepend string
]                 % end if
]                     % end if
]                         % end if
' has been 'whh           % build complete string from pushed parts


# Lua, 371 284 bytes

I'm sure there's room for improvement, I'd like to cut out some if's.

Edit: 4 months later, I learned a lot about lua and wanted to get back to this submission, I did well: cutted out 87 bytes!

a=... .." has been "s=(...):lower()b="very "x=0y=s:byte(1)-96z=0r="naughty"for i=2,#s
do c=s:byte(i)y=c+y-96z=z+c<s:byte(i-1)and-1or 1 end
for i=1,y do x=y%i<1 and x+1or x end
for i=1,13 do d=y==i^3+2*i^2+2 and 0or d end
print(a..(x==#s and"nice"or(d and""or b..(z>0 and""or b))..r))


### Ungolfed

a=... .." has been "           -- Start of the sentence
s=(...):lower()                -- convert the input to lower case
b="very "
x=0                            -- y's divisor count
y=s:byte(1)-96                 -- will contain the sum of the char's position in the alphabet
z=0                            -- will contain the raising ladder state
r="naughty"

for i=2,#s                     -- iterate over each character in s
do
c=s:byte(i)                  -- shorthand for the byte value of the current char
y=c+y-96                     -- increment the sum of letter's positions
z=z+c<s:byte(i-1)            -- if the previous char is greater than the current
and-1                  -- the ladder goes down
or 1                     -- else, it goes up
end

for i=1,y                      -- iterate on the range 1..y
do
x=y%i<1                      -- if i is a divisor of y
and x+1                  -- increment x
or x
end

for i=1,13                     -- iterate on the range 1..13
do                             -- no need to go further for the christmas numbers
d=y==i^3+2*i^2+2             -- if y is a christmas number
and 0                    -- set d
or d                       -- else let d as it is
end
print(a..                      -- output "Name has been"
(x==#s                   -- if y's divisor==length of input
and"nice"              -- append "nice"
or(d                     -- else, if d is not set
and""
or b..                 -- append "very"
(z>0                 -- and if the raising ladder doesn't raise
and""
or b))..             -- append a second "very"
r))                    -- append "naughty"


### Old 371 bytes solution

function f(s)a,b,c,d,e,r,g,s=s.." has been ","very ",0,0,0,"naughty",math.pow,s:lower()for i=1,#s
do if 32<s:byte(i)then e,d=i>1 and(s:byte(i)<s:byte(i-1)and e-1 or e+1)or e,d-96+s:byte(i)end end
for i=1,d do c=d%i>0 and c or c+1 end if c==#s then return a.."nice"end
for i=1,13 do if g(i,3)+2*g(i,2)+2==d then return a..r end end
return e>0 and a..b..r or a..b..b..r end


Ungolfed version :)

function f(s)
a,b,c,d,e,r,g,s=s.." has been ","very ",0,0,0,"naughty",math.pow,s:lower()
for i=1,#s
do
if 32<s:byte(i)
then
--sum of the char's order in the alphabet
d=d-96+s:byte(i)
e=i>1 and(s:byte(i)<s:byte(i-1)and e-1 or e+1)or e
end
end
for i=1,d
do
-- number of d's divisors
c=d%i>0 and c or c+1
end
if c==#s then return a.."nice" end
for i=1,13
do
--Christmas number are equals n^3+2n^2+2 as @Mauris said
if g(i,3)+2*g(i,2)+2==d then return a..r end
end
--is he very naughty or very very naughty?
return e>0 and a..b..r or a..b..b..r
end


## Seriously, 138 bytes

" has been ",;' @-û╗+╝╜O8ª@-MΣ;2┐wiXuMπ╜l="nice"╛+.éó╬é03┐2└3╤1x;;⌐**⌐MíuY3└+3┐╜Ok0)p)p;(@)-s@)+(╬l>Y(Xu3└*"naughty"@"very "*+╛+


Hex Dump:

2220686173206265656e20222c3b2720402d96bb2bbcbd604f38a6402d604de43b32bf7760695875604de3bd6c3d60226e69636522be2b2e82a260ce823033bf32c033d13178603b33405e29a6e7326be4604da1755933c02b33bfbd4f6b3029702960703b2840292d7340292b2860ce6c3e5928587533c02a226e6175676874792240227665727920222a2bbe2b


Try It Online

It is hard to effectively golf this on account of how difficult complicated flow control is in Seriously. The ability to nest functions without the use of registers would help. (I imagine this could already be shortened somewhat through judicious use of stored functions, but it would result in such spaghetti code I don't have the heart to attempt it.)

Explanation:

" has been "                                  push this string
;' @-û╗                                       copy, remove space, uppercase, put in reg0
+╝                                            put '<input> has been ' in reg1
╜                                             bring back the processed input
O8ª@-MΣ                                     convert letters to numbers and sum
;2┐                                           store a copy of the sum in reg2
wiXuMπ                                      compute the number of divisors
╜l                                            get processed input length
=                                             check if they're equal
"nice"╛+.éó╬                                if so, run this function that retrieves the
list we made earlier, appends "nice",
prints it, empties the stack
and immediately exits
é                                             empty the stack (it contains a 1)
03┐                                           put a 0 in reg3
2└                                            call back the letter sum from reg2
3╤1x                                          push [1,...1000]
;;⌐**⌐M                                     plug each number into x^3+2x^2+2
í                                             check if the letter sum is there
uY                                            make a 1 if it is not, 0 if it is
3└+3┐                                         add this number to reg3
╜Ok                                           convert the processed input into char codes
0)                                            put a zero behind it
p)                                            pop the first char code to bottom of stack
p;(@)-s@)+(╬                                Until the list of char codes is empty,
subtract each one from the previous one,
accumulating the signums
l                                             turn the leftover empty list into a 0
>Y                                            put a 1 if the accumulated signs are
>=0 (not rising), else 0 (rising)
(X                                            clean up the last char code
u                                             increment to make 0 into 1 and 1 into 2
3└*                                           bring back the value from reg3
which is 0 if *only* naughty, else 1
and multiply it with preceding test result;
this turns a very into a very very if this
test failed, but leaves plain and single
very naughty alone
"naughty"@                                    put "naughty" below the 'very' count

"very "*                                      put "", "very ", or "very very "
+                                             append the "naughty"
╛+                                            bring back the string in reg1 and append
the constructed suffix


## Python 2, 249 bytes

i=input()
g=[ord(c)-96for c in i.lower()if' '!=c]
s=sum(g)
S=0
a=g.pop()
while g:b=a;a=g.pop();S+=(a<b)-(b<a)
r=range(1,14+s)
print i+' has been '+[['very '*(1+(S<1)),''][s in[x**3+2*x**2+2for x in r]]+'naughty','nice'][sum(s%x<1for x in r)==len(i)]