Що таке мій індекс маси тіла?


21

Проблема:

Ваше завдання - написати програму, яка приймає як введення висоту (в метрах) і вагу (в кілограмах), і виводить відповідну категорію ІМТ.

ІМТ - це показник відношення ваги до вашого зросту. Він датований і неточний для багатьох людей , але це не має значення!

ІМТ можна обчислити, використовуючи наступне рівняння:

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

Категорії визначатимуться наступним чином:

  • ІМТ <18,5: "Недостатня вага"

  • 18,5 <= ІМТ <25: "Нормальний"

  • 25 <= ІМТ: "Зайва вага"

Заради виклику я ігнорую всі "крайні" категорії. Крім того, оскільки деякі цифри, наприклад, "25", перебувають між двома категоріями, я трохи відкоригував межі, так що є однозначна відповідь.

Ви можете написати або функцію, або повну програму.

Вхід:

Введення даних може бути в будь-якій розумній формі. Два числа (або рядки), або як 2 окремі аргументи, або як один рядок. Масив / список з 2 чисел, словник з клавішами "вага" та "висота" ... Десяткові значення повинні підтримуватися. Ви можете припустити, що введення завжди буде дійсним (від’ємних значень немає, а висота ніколи не буде 0).

Вихід:

Виведенням буде рядок, що містить імена категорії, що не залежать від регістру . Рядки повинні відповідати назвам категорій точно, як вище, ігноруючи регістр. Він може бути виведений у stdout, повернутий (у випадку функції) або записаний у файл.

Випробування (вага, зріст => результат):

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)

Ось кілька псевдокодів, які показують приклад реалізації:

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"

Це код-гольф, тому виграє найменша кількість байтів.

(Так, це завдання надзвичайно банальне для більшості мов. Більшість проблем останнім часом здаються складнішими, ніж звичайні, тому я подумав, що опублікую більш доступне).


ПРИМІТКА! Через годину після того, як я опублікував цей виклик, мені довелося трохи змінити діапазони, оскільки вказані діапазони мали «дірки», як зазначено в коментарях. Перегляньте нові діапазони.

Відповіді:


9

Желе , 24 байти

÷÷⁹Ḥ“%2‘>Sị“$⁽¿“;ṅẒ“&ċ)»

Спробуйте в Інтернеті!

Як?

Обчислює ІМТ, подвоює його, порівнює, що більше, ніж оператор, з кожним із чисел 37 і 50 (18,5 і 25 удвічі), підсумовує отримані та нулі (виходить 1, 2 або 0 для нормальної, низької ваги і надмірної ваги відповідно) та вказує на список рядків ["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

1
Ого. Поговоріть про обфускування. Якщо це гольф, я думаю, у вас є дірка в одному! Або 24 ...
Cullub

2
@cullub це 24 символи і 24 байти - Jelly використовує власну кодову сторінку, пов'язану словом "байти" у заголовку, mothereff.in вважає Unicode, я вважаю.
Джонатан Аллан

1
@TheBitByte, так, подивіться на лічильник посилань TIO "24 символи, 24 байти (SBCS)" або порахуйте його вручну, використовуючи кодову сторінку, пов’язану з байтами в заголовку.
Джонатан Аллан

... як 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
Джонатан Аллан


10

TI-Basic, 58 54 байти

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

Крім того, для розваги, ось більш компактна версія, що має більше байтів:

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

Все, що я можу сказати, дякую за те, що ви зробили цю справу нечутливою;)

PS Inputприймає графічне введення Xта Yподібне доPrompt X,Y


Крім того, я переглядав це кілька разів, і не думаю, що немає жодного способу збереження байтів, хоча останні два ділять рядокERWEIGHT
Timtech

З цікавості, як це змінило б вашу відповідь, якби я застосував чутливість до справ?
Carcigenicate

1
@Carcigenicate У TI-Basic малі літери - це два байти. Таким чином, це значно збільшило б байт.
Timtech

1
А, бачу. Це дивно.
Carcigenicate

1
@Carcigenicate Важливо пам’ятати, що ця версія TI-Basic була представлена ​​в 1990 році як мова калькулятора ... ніхто не знав, що я буду займатися гольфом через 27 років
Timtech

6

Математика, 67 байт

"Normal"["Underweight","Overweight"][[Sign@⌊(2#/#2^2-37)/13⌋]]&

Використовує той факт, що a[b,c][[Sign@d]]віддача, aякщо dдорівнює 0, повертає, bякщо dє позитивною, і повертає, cякщо dнегативна. ⌊...⌋є Floorфункцією Mathematica, використовуючи трибайтові символи U + 230A та U + 230B. Не вдалося зрозуміти, як зробити це краще, ніж використовувати weightдвічі.


3
Здивований Mathematica не має для цього вбудованого
Даніель

1
вам доведеться перейти до фан-фантастики для цього;)
Грег Мартін

5

Рубі, 91 77 74 67 байт

Перша наївна спроба:

->(w,h){case w/h/h
when 0..18.5
'underweight'
when 18.5..25
'normal'
else
'overweight'
end}

Друга спроба "натхнення" з попередніх відповідей:

->w,h{["#{(w/=h*h)<18.5?'und':'ov'}erweight",'normal'][(18.5..25)===(w)?1:0]}

Третя спроба:

->w,h{["#{(w/=h*h)<18.5?'und':'ov'}erweight",'normal'][w>=18.5&&w<25?1:0]}

Четверта спроба:

->w,h{18.5<=(w/=h*h)&&w<25?'normal':"#{w<18.5?'und':'ov'}erweight"}

Спробуйте в Інтернеті!


reitermarkus від домашньої кашки ?! Вау, не сподівався побачити вас тут! : o
numbermaniac

1
@numbermaniac, ха-ха, так, це я! 😂
reitermarkus

5

JavaScript (ES6), 70 67 64 63 байт

Збережено 4B завдяки Arnauld

a=>b=>(a/=b*b)<25&a>=18.5?"Normal":(a<19?"Und":"Ov")+"erweight"

Використання

f=a=>b=>(a/=b*b)<25&a>=18.5?"Normal":(a<19?"Und":"Ov")+"erweight"
f(80)(1)

Вихідні дані

"Overweight"

Пояснення

Ця відповідь є досить тривіальною, хоча є одна хитра хитрість: Underweightі Overweightобидва закінчуються erweight, тому нам залишається лише змінити цих символів.

Я припускав, що Normalце ІМТ між 25 (виключно) і 18,5 (включно). Underweightозначає ІМТ менше 18,5 і Overweightозначає ІМТ, що перевищує або дорівнює 25.


1
Тепер відповідь не містить жодних функцій ES7 ;-)
ETHproductions

4

C, 81 байт

f(float m,float h){m/=h*h;puts(m<26?m<18.6?"Underweight":"Normal":"Overweight");}


4

QBIC , 61 58 байт

::m=a/b^2~m<18.5|?@Und`+@erweight`\~m>=25|?@Ov`+B\?@Normal

@Luke використав Force і відрубав два байти. Спасибі!

Зміна правил зберегла ще один байт.

Пояснення:

::          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.


3

Python 3, 97 95 байт

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

Повна програма.

Помножте на п’ять, щоб зберегти байт. Дякую Джонатану Аллану.

Рядок за рядком:

  1. Зіставте два введені користувачем цифри для введення цифр. Розпакуйте на a і b.

  2. Обчисліть

  3. Якщо значення bmi становить від 18,6 до 25, включно, вираз праворуч буде оцінено як True. Булеви можуть бути 0 або 1 при використанні в якості індексів списку, тому ми отримуємо або "Звичайний", або побудований рядок в нульовому індексі. "erweight" - це спільний суфікс для двох інших варіантів, тому його не потрібно повторювати. Тоді ми використовуємо шаблон [start: stop: step] із списку Python / нарізки рядків. c> 18.6 оцінюється до 0 або 1 (Неправдиво чи Істинно) і стає нашим початком. Стоп не вказується, тому ми переходимо до кінця буква. Крок 2, тому ми беремо кожен другий індекс. Якщо start start оцінюється до 1, ми отримуємо "Ov", інакше отримуємо "Und". Так чи інакше, ми додаємо "легку вагу" до того, що ми отримали, і ми маємо остаточний результат.


1
Запишіть це як функцію для 79:def f(h,w):c=h/w/w;print(["UOnvd"[c>18.6::2]+"erweight","Normal"][18.6<=c<=25])
Джонатан Аллан

Якщо ви помножите на п'ять спочатку, ви можете зберегти байт, порівнявши з 93і 125. Якщо ви використовуєте лямбда, вам доведеться розраховувати cв обох місцях, але не потрібно називати функцію або використовувати print(), це можна зробити lambda h,w:["UOnvd"[h/w/w*5>93::2]+"erweight","Normal"][93<=h/w/w*5<=125]за 73.
Джонатан Аллан

... насправді тому, що ви будете обчислювати cвдвічі помноження на 5 коштує дорожче, ніж економить в лямбда, тож лише lambda h,w:["UOnvd"[h/w/w>18.6::2]+"erweight","Normal"][18.6<=h/w/w<=25]на 72
Джонатан Аллан

Джонатан Аллан Хтось уже зробив це як просто функцію.
mypetlion

Все гаразд, ваш шлях випередить їх: D
Джонатан Аллан

3

R, 89 84 80 74 байт

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

Киваючи на відповідь Октави StewieGriffin, створює масив рядків, потім підсумовує результат BMI < c(18.5,25)та посилає масив у цій позиції + 1.

Спочатку аргументом потрібно бути висота, потім вага; якщо це не дозволено, то

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

працює на ще 4 байти.


2

Clojure, 63 байти

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

Блін. Як завжди, це коротша версія того, про що я думав.
Carcigenicate

2

постійного струму , 58 байт

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

Приймає введення як 2 проміжки, розділені пробілом у форматі <mass> <height>. Виводить рядок в окремий рядок.

Спробуйте в Інтернеті!

Пояснення

Для цілей цього пояснення вхід є 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.

2

Октава, 64 байти

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

Спробуйте в Інтернеті

Це анонімна функція, яка бере два вхідні аргументи, h(висота) та w(вага).

Функція створює масив комірок, що містить там рядки 'Underweight','Normal','Overweight', і виводить номер рядка 3-sum(2*w/h^2<'%2').

Так, це виглядає дещо дивно. Ми хочемо, щоб перша рядок if w/h^2<=18.5, друга рядок if (w/h^2 > 18.5) & (w/h^2 < 25)і третя рядок, якщо жодне з перерахованих вище умов не відповідає дійсності. Замість того, щоб створювати купу порівнянь, ми могли б просто порівняти рядок з:, w/h^2 < [18.5, 25]що поверне один із наведених нижче масивів [1 1], [0 1], [0,0]для недостатньої ваги, нормальної та зайвої ваги відповідно.

[18.5,25]займає 9 байт, що дуже багато. Що ми робимо замість цього, множимо ІМТ на 2 і порівнюємо результат з [37, 50]або '%2'в ASCII. Це економить три байти.


2

Perl 6 , 59 байт

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

Як це працює

{                                                         }  # 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.

Шкода, що рядок erweightповинен повторюватися, але всі варіанти я намагався, щоб уникнути збільшення загального числа байтів:

  • З підстановкою рядків 62 байти:

    {<Ov_ Normal Und_>[sum 18.5,25 X>$^a/$^b**2].&{S/_/erweight/}}
  • Із інтерполяцією рядків 67 байт:

    {$_='erweight';("Ov$_","Normal","Und$_")[sum 18.5,25 X>$^a/$^b**2]}
  • Грубий переклад рішення Python xnor , 65 байт:

    {$_=$^a/$^b**2;25>$_>=18.5??"Normal"!!<Und Ov>[$_>19]~"erweight"}

2

PowerShell , 81 байт

param($m,$h)('Underweight','Normal','Overweight')[(18.5,25-lt($m/($h*$h))).Count]

Спробуйте в Інтернеті!

Пояснення

Основний біт, який потребує пояснення, - це те, 18.5,25 -lt $bде я замінюю $bІМТ, який розраховується на місці в коді). Більшість операторів PowerShell, коли їм дано масив зліва, повертає масив елементів, що задовольняє тесту, замість повернення булевого значення. Таким чином, це поверне порожній масив, якщо $bвін менше 18,5, масив, що містить лише 18,5, якщо він знаходиться в середині, і масив, що містить і 18,5, і 25, якщо він більший за 25.

Я використовую кількість елементів як індекс в масив рядків, тому count 0отримує елемент, 0який є 'Underweight'і т.д.



2

Пітон, 75 74 байт

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

Спробуйте в Інтернеті!

Досить базове рішення, яке використовує переваги чужих методик її вирішення.

Дякуємо @ovs за збереження байта.

Альтернативи

1. 73 байти

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

Я відкинув це, оскільки це було занадто схоже на іншу відповідь, яку я бачив.

2. 71 байт

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

Я відкинув це, тому що, незважаючи на роботу над усіма тестами в питанні, є деякі цифри, на яких він може вийти з ладу, оскільки він пропущений =в <=.


Вам не потрібно місця між 25і else- але все одно, використання короткого замикання and/or(як коментував @ovs) коротше.
FlipTack

@FlipTack: про простір між, 25і elseвам, безумовно, це потрібно з деякими (більшості?) Інтерпретаторами (включаючи CPython, IIRC). Якщо ви пишете це як 25else, то 25eінтерпретується як початок науково-нотаційного числового літералу, а інтерпретатор тоді розгортається, коли немає наступних цифр.
Мак

2

C #, 63 62 61 байт

Збережено ще 1 байт завдяки TheLethalCoder .

Збережено 1 байт завдяки анонімному користувачеві.

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

Досить проста анонімна функція. Вся хитрість полягає у використанні потрійного оператора для повернення безпосередньо (таким чином пропускаючи returnключове слово, пару фігурних дужок та змінну заяву та призначення).

Повна програма з тестовими кейсами:

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"
    }
}

2

Лисп звичайний, 89 87 85 84 83 байт

Функція:

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

Приклад використання:

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

Спробуйте в Інтернеті! (Я додав функцію друку, щоб побачити вихід у TIO)

Ідеї ​​для вдосконалення вітаються.


2

MATL, 54 45 44 42 байт

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

Спробуйте це на сайті matl.suever.net

Починається з обчислення ІМТ і подвоєння його U\E, а потім створює вектор [37 50]з рядковим буквалом '% 2'. Порівняє ІМТ з цим вектором і використовує, якщо заяви отримують відповідь, використовуючи переваги normalяк заздалегідь заданий буквальний 17Y0.


Ви можете замінити [BC]UQз '%2'і зберегти 2 байти.
sundar

1

Java 8, 61 байт

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

Призначте a DoubleFunction<DoubleFunction<String>>і зателефонуйте таким чином:

bmi.apply(50).apply(1.5)

Ви можете заощадити один байт за рахунок багаторазового використання w: w->h->(w/=h*h)<18.5?"Underweight":w<25?"Normal":"Overweight".
Олів'є Грегоар

@ OlivierGrégoire Nope :( Error: local variables referenced from a lambda expression must be final or effectively finalНеможливо призначити в ч.
Девід Конрад

1
Ой, я перевірив нарізні речі, як int w = ... , h = ... ; System.out.println((w/=h*h)<18.5?"Underweight":w<25?"Normal":"Overweight"), вибачте :)
Олів'є Грегоар

@ OlivierGrégoire Немає проблем. Я б хотів, щоб Java дозволила це.
Девід Конрад

1

постійного струму , 64 байти

[erweight][[Und]PszPq]su[[Normal]Pq]sn9k?d*/d18.5>ud25>n[Ov]PszP

Спробуйте в Інтернеті!


Пограв! Просто побили мене на кілька секунд. Я збирався розмістити свою, поки не побачив цього. У будь-якому випадку, ось ще 64 байт відповіді: 3k[Overweight]??2^/dsp[[Normal]][[Underweight]]sasb25>blp18.5>ap.
Р. Кап

@ R.Kap Насправді ви можете зробити ваш на один байт коротшим, ніж мій, опустивши один із знаків питання.
Мітчелл Спектор

О так, я забув, що можу це зробити. Ви можете розмістити це як своє, якщо хочете.
Р. Кап

Ні, це добре - продовжуйте і розміщуйте самі, це ваше рішення. (Ви можете позичити мені один байт, якщо хочете.)
Мітчелл Спектор

До речі, мені вдалося звести її до 58 байт. :)
Р. Кап

1

Javascript (ES6), 63 байти

(m,h)=>(w="erweight",b=m/h/h)<18.5?"Und"+w:b<25?"Normal":"Ov"+w

Приклад

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


1

Свіфт, 97 байт

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

1

Japt , 46 байт

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

Спробуйте в Інтернеті!

Натхненний @ Луки відповідь .

Пояснення

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

Декомпресується до:

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

Japt має неявний вхід U. Другий вхід - V.

Japt використовує бібліотеку шоко для стискання рядків. Зворотній зв'язок використовується для декомпресії рядків.

Використані ярлики Unicode:

² : **2
© : &&
¨ : >=
½ : .5
º : ((


1

Скала, 124 байти

val x="erweight"
def b(i:Float,a:Float):Any=i/a/a match{case z if(z<18.5)=>"Und"+x
case z if(z<25)=>"Normal"
case z=>"Ov"+x}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.