# Problem:

Your task is to write a program that takes as input a height (in meters) and weight (in kilograms), and outputs the corresponding BMI category.

BMI is a measure of the ratio of your weight to your height. It's dated and inaccurate for many people, but that doesn't matter here!

BMI can be calculated using the following equation:

BMI = (mass in kilograms) / (height in meters)^2


The categories will be defined as follows:

• BMI < 18.5: "Underweight"

• 18.5 <= BMI < 25: "Normal"

• 25 <= BMI: "Overweight"

For the sake of the challenge, I'm ignoring all the "extreme" categories. Also, since some numbers like "25" sit between 2 categories, I adjusted the bounds slightly so there's a definite answer.

You can write either a function, or a full program.

# Input:

Input can be in any reasonable form. Two numbers (or strings), either as 2 separate arguments, or as a single string. An array/list of 2 numbers, a dictionary with "weight" and "height" keys... Decimal values should be supported. You can assume the input will always be valid (no negative values, and height will never be 0).

# Output:

Output will be a string containing the case-insensitive category names. The strings must match the category names exactly as above, ignoring case. It can be output to the stdout, returned (in the case of a function), or written to file.

# Test Cases (weight, height => result):

80, 1 =>   "Overweight"
80, 2 =>   "Normal"
80, 3 =>   "Underweight"

50, 1 =>   "Overweight"
50, 1.5 => "Normal"
50, 2 =>   "Underweight"

Edge Cases:

41, 1.5 => "Underweight" (18.2 BMI)
42, 1.5 => "Normal" (18.667 BMI)

56, 1.5 => "Normal" (24.889 BMI)
57, 1.5 => "Overweight" (25.3 BMI)

73, 2 =>   "Underweight" (18.25 BMI)
74, 2 =>   "Normal" (18.5 BMI)

99, 2 =>  "Normal" (24.75 BMI)
100, 2 => "Overweight" (25 BMI)


Here's some pseudocode that shows an example implementation:

function bmi_category(weight, height):
var bmi = (weight / (height**2))

if (bmi < 18.5):
return "Underweight"

if (18.5 <= bmi < 25):
return "Normal"

if (25 <= bmi):
return "Overweight"


This is code-golf, so the fewest number of bytes wins.

(Yes, this task is exceedingly trivial in most languages. Most of the challenges lately seem to be harder than normal, so I thought I'd post a more accessible one).

NOTE! An hour after I posted this challenge, I had to modify the ranges slightly since the ranges as stated had "holes" as pointed out in the comments. Please see the new ranges.

# Python, 69 bytes

lambda w,h:["UOnvd"[w/h/h>20::2]+"erweight","Normal"][18.5<=w/h/h<25]


Try it online!

Compare to 72 bytes:

lambda w,h:"Underweight"*(w/h/h<18.5)or"Normal"*(w/h/h<25)or"Overweight"


# TI-Basic, 58 54 bytes

Input
X/Y²→C
"NORMAL
If 2C≤37
"UNDERWEIGHT
If C≥26
"OVERWEIGHT


Also, for fun, here's a more compact version that is more bytes:

Prompt A,B
sub("UNDERWEIGHTNORMAL      OVERWEIGHT ",sum(A/B²≥{18.5,25})11+1,11


All I can say is, thank you for making this case-insensitive ;)

P.S. Input takes graph input to X and Y similar to Prompt X,Y

• Also, I've looked at this multiple times, and I don't think there's any way to save bytes even though the last two share the string ERWEIGHT Feb 6, 2017 at 22:06
• Out of curiosity, how would it have changed your answer if I enforced case-sensitivity? Feb 8, 2017 at 5:54
• @Carcigenicate In TI-Basic, the lowercase letters are two bytes each. Thus, it would have increased the byte count by a lot. Feb 8, 2017 at 13:33
• Ah, I see. That's odd. Feb 8, 2017 at 14:48
• @Carcigenicate It's important to remember that this version of TI-Basic was introduced in 1990 as a calculator language... no one knew I'd be golfing it 27 years later Mar 29, 2017 at 19:03

# Jelly, 24 bytes

÷÷⁹Ḥ“%2‘>Sị“$⁽¿“;ṅẒ“&ċ)»  Try it online! ### How? Calculates the BMI, doubles it, compares that with the greater than operator with each of the numbers 37 and 50 (18.5 and 25 doubled), sums the resulting ones and zeros (yielding 1, 2, or 0 for Normal, Underweight, and Overweight respectively) and indexes into the list of strings ["Normal","Underweight","Overweight"]. ÷÷⁹Ḥ“%2‘>Sị“$⁽¿“;ṅẒ“&ċ)» - Main link: weight, height
÷                        - weight ÷ height
⁹                      - right argument, height
÷                       - ÷ by height again to get the BMI
Ḥ                     - double the BMI
“%2‘                 - list of code page indexes [37,50]
>                - greater than? (vectorises) - i.e [18.5>bmi, 25>bmi]
S               - sum -- both:=2 (Underweight), just 50:=1 (Normal) or neither:=0 (Overweight)
ị              - index into (1-based)
“$⁽¿“;ṅẒ“&ċ)» - compressed list of strings ["Normal","Underweight","Overweight"] - implicit print  • Wow. Talk about obfuscation. If this is golf, I think you got a hole in one! Or 24... Feb 7, 2017 at 17:36 • @cullub it is 24 characters and 24 bytes - Jelly uses it's own code-page linked to by the word "bytes" in the heading, mothereff.in is counting Unicode I believe. Feb 7, 2017 at 18:14 • @TheBitByte, yes, take a look at the TIO link counter "24 chars, 24 bytes (SBCS)" or count it by hand using the code-page linked to by bytes in the heading. Feb 7, 2017 at 18:20 • ... as hex: 1C 1C 89 AF FE 25 32 FC 3E 53 D8 FE 24 8D 0B FE 3B F0 BD FE 26 E8 29 FB Feb 7, 2017 at 18:28 # Mathematica, 67 bytes "Normal"["Underweight","Overweight"][[Sign@⌊(2#/#2^2-37)/13⌋]]&  Uses the fact that a[b,c][[Sign@d]] returns a if d equals 0, returns b if d is positive, and returns c if d is negative. ⌊...⌋ is Mathematica's Floor function using the three-byte characters U+230A and U+230B. Couldn't figure out how to do better than using weight twice. • Surprised Mathematica doesn't have a built-in for this Feb 7, 2017 at 11:26 • you have to go to the fan fiction for that ;) Feb 7, 2017 at 17:04 # Ruby, 917774 67 bytes First naive try: ->(w,h){case w/h/h when 0..18.5 'underweight' when 18.5..25 'normal' else 'overweight' end}  Second try with ”inspiration“ from previous answers: ->w,h{["#{(w/=h*h)<18.5?'und':'ov'}erweight",'normal'][(18.5..25)===(w)?1:0]}  Third try: ->w,h{["#{(w/=h*h)<18.5?'und':'ov'}erweight",'normal'][w>=18.5&&w<25?1:0]}  Fourth try: ->w,h{18.5<=(w/=h*h)&&w<25?'normal':"#{w<18.5?'und':'ov'}erweight"}  Try it online! • reitermarkus from homebrew-cask?! Woah, didn't expect to see you here! :o Mar 29, 2017 at 8:13 • @numbermaniac, haha, yes, it's me! 😂 Mar 29, 2017 at 13:33 # JavaScript (ES6), 70 67 64 63 bytes Saved 4B thanks to Arnauld a=>b=>(a/=b*b)<25&a>=18.5?"Normal":(a<19?"Und":"Ov")+"erweight"  ## Usage f=a=>b=>(a/=b*b)<25&a>=18.5?"Normal":(a<19?"Und":"Ov")+"erweight" f(80)(1)  ### Output "Overweight"  ## Explanation This answer is quite trivial, though there is one clever trick: Underweight and Overweight both end in erweight, so we only have to change those characters. I assumed that Normal means a BMI between 25 (exclusive) and 18.5 (inclusive). Underweight means a BMI less than 18.5, and Overweight means a BMI greater than or equal to 25. • Now the answer doesn't contain any ES7 features ;-) Feb 8, 2017 at 15:02 # C, 81 bytes f(float m,float h){m/=h*h;puts(m<26?m<18.6?"Underweight":"Normal":"Overweight");}  # 05AB1E, 28 bytes n/©37;‹®25‹O’‚Š‰ß îÂ ‚â‰ß’#è  Uses the CP-1252 encoding. Try it online! ## QBIC, 61 58 bytes ::m=a/b^2~m<18.5|?@Und+@erweight\~m>=25|?@Ov+B\?@Normal  @Luke used the Force and chopped off two bytes. Thanks! The rules change saved another byte. Explanation: :: gets weight and height as a and b m=a/b^2 Calculates BMI ~m<18.5| If BMI < 18.5 then ?@Und Print the string literal 'Und' (which is now A$)
+@erweight and the string literal 'erweight'  (which is now B$) \~m>=25| else if the BMI is greater than or equal to 25 ?@Ov+B Print 'Ov' and B$ ('erweight')
\?@Normal   Else, if we're here, BMI is normal.


# Python 2, 72 bytes

lambda a,b:"UNOnovdreemrrawwlee ii gg hh tt"[(18.6<a/b/b)+(a/b/b>25)::3]


Try it online!

• How do you get the colours for Python? I never figured it out.
– user63571
Feb 6, 2017 at 22:51
• @JackBates It's just <!-- language-all: lang-python --> which TIO automatically inserted for me. Feb 6, 2017 at 22:52

# Python 3, 97 95 bytes

a,b=map(int,input().split())
a/=b*b*5
print(["UOnvd"[a>93::2]+"erweight","Normal"][93<=a<=125])


Full program.

Multiply by five to save a byte. Thanks Jonathan Allan.

Line by line:

1. Map the two space separated user input numbers to ints. Unpack to a and b.

2. Calculate

3. If the bmi is between 18.6 and 25, inclusive, the expression on the right will evaluate to True. Booleans can be 0 or 1 when used as list indexes, so we get either "Normal" or the constructed string in the zero index. "erweight" is a shared suffix for the remaining two options, so it doesn't need to be repeated. Then we use the [start:stop:step] pattern of Python list/string slicing. c>18.6 will evaluate to either 0 or 1 (False or True) and becomes our start. Stop isn't indicated so we go to the end of the literal. Step is 2 so we take every second index. If start start evaluates to 1, we get "Ov", otherwise we get "Und". Either way, we append "erweight" to what we got and we have our final output.

• Write it as a function for 79: def f(h,w):c=h/w/w;print(["UOnvd"[c>18.6::2]+"erweight","Normal"][18.6<=c<=25]) Feb 6, 2017 at 22:24
• If you multiply up by five first you can save a byte by comparing to 93 and 125. If you use a lambda you have to calculate c in both places but don't need to name the function or use print(), so can do lambda h,w:["UOnvd"[h/w/w*5>93::2]+"erweight","Normal"][93<=h/w/w*5<=125] for 73. Feb 6, 2017 at 22:33
• ...actually because you will be calculating c twice the multiply by 5 costs more than it saves in the lambda, so just lambda h,w:["UOnvd"[h/w/w>18.6::2]+"erweight","Normal"][18.6<=h/w/w<=25] for 72 Feb 6, 2017 at 22:34
• Jonathan Allan Somebody already did it as just a function. Feb 6, 2017 at 22:36
• That's OK, your way will out-golf them :D Feb 6, 2017 at 22:37

# PowerShell, 81 bytes

param($m,$h)('Underweight','Normal','Overweight')[(18.5,25-lt($m/($h*$h))).Count]  Try it online! ## Explanation The main bit that needs explaining is 18.5,25 -lt$b (where I'm substituting $b for the BMI which is calculated in place in the code). Most operators in PowerShell, when given an array on the left side, return an array of items that satisfy the test, instead of returning a boolean value. So this will return an empty array if $b is smaller than 18.5, an array containing only 18.5 if it's in the middle, and an array containing both 18.5 and 25 if it's larger than 25.

I use the count of the elements as an index into an array of the strings, so count 0 gets element 0 which is 'Underweight', etc.

## R, 898480 74 bytes

f=pryr::f(c('Overweight','Normal','Underweight')[sum(w/h^2<c(18.5,25),1)])


With a nod to StewieGriffin's Octave answer, creates an array of strings, then sums the result of BMI < c(18.5,25) and references the array at that position + 1.

First argument needs to be height, then weight; if that's not allowed, then

f=pryr::f(w,h,c('Overweight','Normal','Underweight')[sum(w/h^2<c(18.5,25),1)])


works for 4 more bytes.

## Clojure, 63 bytes

#(condp <(/ %(* %2 %2))25"Overweight"18.5"Normal""Underweight")

• Damn. As always, this is a shorter version of what I was thinking of. Feb 7, 2017 at 0:19

# dc, 58 bytes

Fk[Ov]?2^/d[[Normal]pq][[Und]26]sasb18.5>a25>bn[erweight]p


Takes input as 2 space separated numbers in the format <mass> <height> . Outputs a string on a separate line.

Try it online!

### Explanation

For the purposes of this explanation, the input is 80 1.

Fk                                                         # Set decimal precision to 16.
[Ov]                                                     # Push the string "Ov" onto the main stack.
# Main Stack: [[Ov]]
?2^/d                                                # Take and evaluate input, squaring the 2nd one, and the dividing by the first one by the 2nd. Then duplicate the result.
# Main Stack: [[Ov],80.000000000000000,80.000000000000000]
[[Normal]pq][[Und]26]sasb                       # Push and store the executable macros "[Normal]pq" and "[Und]26" on registers "a" and "b", respectively.
# Main Stack: [[Ov],80.000000000000000,80.000000000000000], reg. a: [[[Normal]pq]], reg. b: [[[Und]26]]
18.5>a25>b             # Push, "18.5" onto stack, and then pop top 2 values. If "18.5 > (top of stack)", then execute the macro on top of reg. "a", which in turn pushes the string "Und" onto the main stack followed by the number 26.
# The "26" will automatically prompt the next comparison to not execute the macro on top of reg. "b", regardless of the value on top of the main stack.
# Otherwise, if "18.5 <= (top of stack) < 25", then execute "b"s macro, which in turn pushes the string "Normal" onto the main stack, outputs it, then quits the program.
# In this case, Main stack: [[Ov]], reg. a: [[[Normal]pq]], reg. b: [[[Und]26]]
n[erweight]p # If "Normal" has not been output, only then will the program get to this point. Here, it will output whatever string, either "Und" or "Ov", on top of the main stack, followed by "erweight" and a new line.


# Octave, 64 bytes

@(w,h){'Underweight','Normal','Overweight'}{3-sum(2*w/h^2<'%2')}


Try it online

This is an anonymous function that takes two input arguments, h (height) and w (weight).

The function creates a cell array containing there strings 'Underweight','Normal','Overweight', and outputs string number 3-sum(2*w/h^2<'%2').

Yes, that one looks a bit strange. We want the first string if w/h^2<=18.5, the second string if (w/h^2 > 18.5) & (w/h^2 < 25) and the third string if none of the above conditions are true. Instead of creating a bunch of comparisons, we could simply compare the string to: w/h^2 < [18.5, 25], which would return one of the following arrays [1 1], [0 1], [0,0] for Underweight, Normal and Overweight respectively.

[18.5,25] takes 9 bytes, which is a lot. What we do instead, is multiply the BMI by 2, and compare the result with [37, 50], or '%2' in ASCII. This saves three bytes.

# Perl 6, 59 bytes

{<Overweight Normal Underweight>[sum 18.5,25 X>$^a/$^b**2]}


### How it works

{                                                         }  # A lambda.
$^a/$^b**2    # Compute BMI from arguments.
18.5,25 X>              # Compare against endpoints.
sum                         # Add the two booleans together.
<Overweight Normal Underweight>[                        ]   # Index into hard-coded list.


Too bad the string erweight has to be repeated, but all variations I tried in order to avoid that ended up increasing the overall byte count:

• With string substitution, 62 bytes:

{<Ov_ Normal Und_>[sum 18.5,25 X>$^a/$^b**2].&{S/_/erweight/}}
• With string interpolation, 67 bytes:

{$_='erweight';("Ov$_","Normal","Und$_")[sum 18.5,25 X>$^a/$^b**2]} • Rough translation of xnor's Python solution, 65 bytes: {$_=$^a/$^b**2;25>$_>=18.5??"Normal"!!<Und Ov>[$_>19]~"erweight"}

# OCaml, 93 bytes

let b w h=if w/.h/.h<18.5 then"underweight"else if w/.h/.h>=25.0 then"overweight"else"normal"

• No, this is a function. Mar 29, 2017 at 13:39

# Python, 75 74 bytes

lambda h,w:18.5<=w/h/h<=25and"normal"or["ov","und"][25>w/h/h]+"erwe‌​ight"


Try it online!

Fairly basic solution that takes advantage of other people's techniques for solving it.

Thanks @ovs for saving a byte.

## Alternatives

### 1. 73 bytes

lambda h,w:"normal"if 18.5<=w/h/h<=25 else"uonvd"[25<w/h/h::2]+"erweight"


I rejected this as it was too similar to another answer I saw.

### 2. 71 bytes

lambda h,w:"normal"if 18.5<w/h/h<25 else"uonvd"[25<w/h/h::2]+"erweight"


I rejected this because, despite working on all the tests in the question, there are some numbers it can fail on as it's missing the = in the <=.

• You don't need the space between 25 and else - but anyway, using short circuiting and/or (as @ovs commented) is shorter. Feb 7, 2017 at 19:21
• @FlipTack: regarding the space between 25 and else, you definitely do need it with some (most?) interpreters (including CPython, IIRC). If you write it as 25else, the 25e is interpreted as the start of a scientific-notation numeric literal, and the interpreter then baulks when there are no following digits.
– Mac
Feb 8, 2017 at 3:44

# C#, 6362 61 bytes

Saved 1 more byte thanks to TheLethalCoder.

Saved 1 byte thanks to anonymous user.

w=>h=>w/h/h<18.5?"Underweight":w/h/h<25?"Normal":"Overweight";


A pretty straightforward anonymous function. The whole trick is using the ternary operator to return directly (thus omitting the return keyword, a pair of curly braces and a variable declaration and assignment).

Full program with test cases:

using System;

class BodyMassIndex
{
static void Main()
{
Func<double, Func<double, string>> f =
w=>h=>w/h/h<18.5?"Underweight":w/h/h<25?"Normal":"Overweight";

// test cases:
Console.WriteLine(f(80)(1));  // "Overweight"
Console.WriteLine(f(80)(2));  // "Normal"
Console.WriteLine(f(80)(3));  // "Underweight"
Console.WriteLine(f(50)(1));  // "Overweight"
Console.WriteLine(f(50)(1.5));  // "Normal"
Console.WriteLine(f(50)(2));  // "Underweight"
}
}


# Common Lisp, 89878584 83 bytes

A function:

(lambda(w h)(if(< #1=(/ w(* h h))18.5)'underweight(if(< #1#25)'normal'overweight)))


### Example of usage:

((lambda(w h)(if(< #1=(/ w(* h h))18.5)'underweight(if(< #1#25)'normal'overweight)))150 2)


Try it online! (I added printing function to see output in TIO)

Ideas for improvement are welcomed.

# MATL, 544544 42 bytes

U/E'%2'<sqt?q?'ov'}'und']'erweight'h}x17Y0


Try it at matl.io

Starts off by calculating the BMI and doubling it U\E, then creates the vector [37 50] with the string literal '%2'. Compares the BMI to this vector and uses if statements to get the answer, taking advantage of normal as a predefined literal 17Y0.

• You can replace [BC]UQ with '%2' and save 2 bytes. Jul 17, 2018 at 18:17

# Thunno 2, 25 bytes

²/¿}ȯE¿©S‘Ọḃẋɠ Ḳẇ ṁẓẋɠ‘Oi


Try it online!

#### Explanation

²/...©S...i  # Implicit input
²/           # Divide the weight by the height squared
...        # Compressed numeric list [18.5, 25]
©       # Vectorised lesser than or equal to
S      # Sum the list to get an integer from 0 to 2
# (0=overweight, 1=normal, 2=underweight)
...i  # Index into compressed list of strings
# ["Overweight", "Normal", "Underweight"]
# Implicit output


# K (ngn/k), 57 bytes

{((,"Normal"),("Ov";"Und"),\:"erweight")3!("%2"%2)'x%y*y}


Try it online!

• you can replace ,"Normal" and ("Ov";"Und") with symbols and do a ,/$ at the end – ngn Aug 27, 2023 at 14:49 • like this: {,/$(Normal,OvUnd,'erweight)3!("%2"%2)'x%y*y}
– ngn
Aug 27, 2023 at 14:51
• ("%2"%2)' -> 18.5 25'
– ngn
Aug 27, 2023 at 14:57
• same length but more straighforward: {$Underweight^Normal[email protected] 25'x%y*y} – ngn Aug 27, 2023 at 15:07 • I mostly just liked how (“%2”%2) looked. :) I do prefer the symbols though. – doug Aug 27, 2023 at 20:25 # Java 8, 61 bytes w->h->w/h/h<18.5?"Underweight":w/h/h<25?"Normal":"Overweight"  Assign to a DoubleFunction<DoubleFunction<String>> and call thusly: bmi.apply(50).apply(1.5)  • You can spare one byte by reusing w: w->h->(w/=h*h)<18.5?"Underweight":w<25?"Normal":"Overweight". Feb 7, 2017 at 20:33 • @OlivierGrégoire Nope :( Error: local variables referenced from a lambda expression must be final or effectively final Can't assign to w. Feb 7, 2017 at 21:04 • Oh... I checked with inlined stuff like int w = ... , h = ... ; System.out.println((w/=h*h)<18.5?"Underweight":w<25?"Normal":"Overweight"), sorry :) Feb 7, 2017 at 23:09 • @OlivierGrégoire No problem. I wish Java allowed it. Feb 7, 2017 at 23:15 # dc, 64 bytes [erweight][[Und]PszPq]su[[Normal]Pq]sn9k?d*/d18.5>ud25>n[Ov]PszP  Try it online! • Dang it! Just beat me by a few seconds. I was about to post mine, until I saw this. Anyways, here is another 64 byte answer: 3k[Overweight]??2^/dsp[[Normal]][[Underweight]]sasb25>blp18.5>ap. Feb 7, 2017 at 1:16 • @R.Kap You can actually get yours to be one byte shorter than mine by omitting one of the question marks. Feb 7, 2017 at 1:22 • Oh yeah, I forgot that I could do that. You can post that as your own if you want. Feb 7, 2017 at 1:25 • No, that's fine -- go ahead and post it yourself, it's your solution. (You can credit me for one byte if you want.) Feb 7, 2017 at 1:26 • By the way, I was able to get it down to 58 bytes. :) Feb 7, 2017 at 2:30 ## Javascript (ES6), 63 bytes (m,h)=>(w="erweight",b=m/h/h)<18.5?"Und"+w:b<25?"Normal":"Ov"+w  Example f=(m,h)=>(w="erweight",b=m/h/h)<18.5?"Und"+w:b<25?"Normal":"Ov"+w console.log(f(80, 1)); console.log(f(80, 2)); console.log(f(80, 3)); # PHP, 69 68/85 bytes If you want it to be more as a program, $a=$args;$b=$a[0]/($a[1]*$a[1]);echo$b>=18.5&&$b<25?normal:($b<18.5?und:ov).erweight; // 85

$b=$k/($h*$h);echo$b>=18.5&&$b<25?normal:($b<18.5?und:ov).erweight; // 68$b=$k/pow($h,2);echo$b>=18.5&&$b<25?normal:($b<18.5?und:ov).erweight; // 69  You can test with $k=80; $h=1;. I had three choices, via $args, like this or as defined values (K&H). I choose the middle as most fair.

# Swift, 97 bytes

{(w:Float,h)->String in return 18.5<=w/h/h&&w/h/h<25 ?"normal":"\(w/h/h>25 ?"ov":"und")erweight"}


# Japt, 46 bytes

/=V²U<25©U¨18½?NŽµl:ºU<19?U˜:"Ov")+€³ight


Try it online!

### Explanation

/=V²U<25©U¨18½?NŽµl:ºU<19?U˜:"Ov")+€³ight


Decompresses to :

U=U/V**2,U<25&&U>18.5?"Normal":(U<19?"Und":"Ov")+"erweight"


Japt has an implicit input U. The second input is V.

Japt uses the shoco library for string compression. Backticks are used to decompress strings.

Unicode shortcuts used:

² : **2
`