Syntax Error Invalid Syntax. No idea why though - syntax

height = float(input("enter your height in m: "))
weight = float(input("enter your weight in kg: "))
bmi = weight / height ** 2
bmi2 = int(bmi)
if bmi2 < 18.5:
print(f"Your BMI is {bmi2}, you are underweight")
elif bmi2 > 18.5 < 25:
print(f"Your BMI is {bmi2}, you are normal weight")
elif bmi2 > 25 < 30:
print(f"Your BMI is {bmi2}, you are slightly overweight")
elif bmi2 > 30 < 35:
print(f"Your BMI is {bmi2}, you are obese")
else:
print(f"Your BMI is {bmi2}, you are cliniclly obese")
it says Syntax Error invalid syntax on "elif bmi2 > 18.5 < 25:" this part but I have no idea why

The issue is indentation. There are also a few other things that I'll explain later.
This is how your script should look in order for it to work:
#!/usr/bin/env python3
height = float(input("enter your height in m: "))
weight = float(input("enter your weight in kg: "))
bmi = weight / height**2
bmi2 = int(bmi)
if bmi2 < 18.5:
print(f"Your BMI is",bmi2," you are underweight")
elif 18.5 < bmi2 <= 24.99:
print(f"Your BMI is",bmi2," you are normal weight")
elif 24.99 < bmi2 <= 29.99:
print(f"Your BMI is ",bmi2," you are slightly overweight")
elif 30 <= bmi2 <= 34.99:
print(f"Your BMI is ",bmi2," you are obese")
else:
print(f"Your BMI is ",bmi2," you are clinically obese")
All of the if and else conditions should be aligned to the beginning of the line. One would only indent inside if there were a nested statement such as
if apple > 5;
if orange > 3;
And so on and so forth. Your script doesn't have that so there doesn't need to be any indentation on the statements.
The syntax for greater than or less than should be in this format:
elif value < variable < value2:
That sets the condition as being greater than value one but less than value two. With the way that you have it, it is, in fact, setting the condition in the first one for example, as bmi being greater than 18.5 and 18.5 being less than 25. This will cause every bmi2 that's over 18.5 to be result in normal weight because no matter what bmi2 is in that case, the second condition of 18.5 being less than 25 will always be true no matter what one enters.
For accuracy, I also changed less than 25 in the second statement to less than or equal to 24.99, greater than 25 to greater than 24.99 and less than 30 to less than or equal to 29.99 in the third statement, and finally, greater than 30 to greater than or equal to 30 and less than 35 to less than or equal to 34.99 in the third statement as that lines up with the ranges from the actual BMI calculator and prvents other wonkiness from overlapping values.
Now that the important things have been covered, I also made some cosmetic changes including adding a blank line between the variable declarations and using commas and quotes to separate the variable bmi2 from the text. This makes it a bit easier to tell which one is who and what's going on.

Related

Performance issues with evaluation of custom tree data structure in Julia

I am implementing a Binary Tree in Julia. The binary tree has nodes and leafs. The nodes point to left and right children, which are also nodes/leafs objects. The following code exemplifies the data structure:
using TimerOutputs
mutable struct NodeLeaf
isleaf::Bool
value::Union{Nothing,Float64}
split::Union{Nothing,Float64}
column::Union{Nothing,Int64}
left::Union{Nothing,NodeLeaf}
right::Union{Nothing,NodeLeaf}
end
function evaluate(node::NodeLeaf, x)::Float64
while !node.isleaf
if x[node.column] < node.split
node = node.left
else
node = node.right
end
end
return node.value
end
function build_random_tree(max_depth)
if max_depth == 0
return NodeLeaf(true, randn(), randn(), rand(1:10), nothing, nothing)
else
return NodeLeaf(false, randn(), randn(), rand(1:10), build_random_tree(max_depth - 1), build_random_tree(max_depth - 1))
end
end
function main()
my_random_tree = build_random_tree(4)
#timeit to "evaluation" for i in 1:1000000
evaluate(my_random_tree, randn(10))
end
end
const to = TimerOutput()
main()
show(to)
I notice that a lot of allocations occur in the evaluate function, but I don't see the reason why this is the case:
julia mytree.jl
───────────────────────────────────────────────────────────────────────
Time Allocations
─────────────────────── ────────────────────────
Tot / % measured: 476ms / 21.6% 219MiB / 62.7%
Section ncalls time %tot avg alloc %tot avg
───────────────────────────────────────────────────────────────────────
evaluation 1 103ms 100.0% 103ms 137MiB 100.0% 137MiB
───────────────────────────────────────────────────────────────────────
As I increase the evaluation loop, the allocation continues to increase without bound. Can anybody explain why allocation grows so much and please suggest how to avoid this issue? Thanks.
EDIT
I simplified too much the code for the example. The actual code is accessing DataFrames, so the main looks like this:
using DataFrames
function main()
my_random_tree = build_random_tree(7)
df = DataFrame(A=1:1000000)
for i in 1:9
df[!, string(i)] = collect(1:1000000)
end
#timeit to "evaluation" for i in 1:size(df, 1)
evaluate(my_random_tree, #view df[i, :])
end
end
I expect this to yield 0 allocations, but that isn't true:
julia mytree.jl
───────────────────────────────────────────────────────────────────────
Time Allocations
─────────────────────── ────────────────────────
Tot / % measured: 551ms / 20.5% 305MiB / 45.0%
Section ncalls time %tot avg alloc %tot avg
───────────────────────────────────────────────────────────────────────
evaluation 1 113ms 100.0% 113ms 137MiB 100.0% 137MiB
───────────────────────────────────────────────────────────────────────%
On the other hand, if I use a plain array I don't get allocations:
function main()
my_random_tree = build_random_tree(7)
df = randn(1000000, 10)
#timeit to "evaluation" for i in 1:size(df, 1)
evaluate(my_random_tree, #view df[i, :])
end
end
julia mytree.jl
───────────────────────────────────────────────────────────────────────
Time Allocations
─────────────────────── ────────────────────────
Tot / % measured: 465ms / 5.7% 171MiB / 0.0%
Section ncalls time %tot avg alloc %tot avg
───────────────────────────────────────────────────────────────────────
evaluation 1 26.4ms 100.0% 26.4ms 0.00B - % 0.00B
───────────────────────────────────────────────────────────────────────%
The thing that allocates is randn not evaluation. Switch to randn!:
julia> using Random
julia> function main()
my_random_tree = build_random_tree(4)
x = randn(10)
#allocated for i in 1:1000000
evaluate(my_random_tree, randn!(x))
end
end
main (generic function with 1 method)
julia> main()
0
EDIT
Solution with DataFrames.jl:
function bar(mrt, nti)
#timeit to "evaluation" for nt in nti
evaluate(mrt, nt)
end
end
function main()
my_random_tree = build_random_tree(7)
df = DataFrame(A=1:1000000)
for i in 1:9
df[!, string(i)] = collect(1:1000000)
end
bar(my_random_tree, Tables.namedtupleiterator(df))
end

Is there a way to cast a a set of unequal line segments to enum without conditional constructions?

So, basically, I have implemented a naive rarity system, where I have randomly generated byte values(0-255). From them I determine an enum variable as such:
case < 100:
return 0;
case > 100 and < 180:
return 1;
case >180 and <235:
return 2;
case > 235:
return 3;
So now I'm at the point, where I would like to improve some of my code and this method keeps bothering me. As you can see, values, corresponding to different enum numbers, are unequal. And I started wondering, is there a way to represent this kind of a cast with a formula? I fidgeted a bit with it, but I'm really no mathematician) So I'd appreciate some help
If you want those exact rarity thresholds, then I would write something like rarity1.
If you're a little flexible, you could do rarity2 or rarity3. For rarity2, in essence, we interpret b as a fixed point fraction x ∈ [0, 1) and return ⌊4x²⌋. The boundaries are x = 1/2, x = 1/√2, x = √3/2, i.e., b = 128, b = 182, b = 222.
The rarity3 alternative is not monotone. It takes the min of the upper and lower 2-bit quantities. The outcome probabilities are 7/16, 5/16, 3/16, 1/16, corresponding to decision boundaries 112, 192, 240.
def rarity1(b):
if b < 100:
return 0
elif b < 180:
return 1
elif b < 235:
return 2
else:
return 3
def rarity2(b):
return (b * b) >> 14
def rarity3(b):
return min(b >> 6, b & 3)

Ruby simple math outputs 0.0 every time

recently I have started writing the same thing (bmi calculator) in many languages. And I got stuck in ruby. Everything is done, but simple math problem always outputs 0.0. I tried researching the problem, but I couldn't find anything similar in ruby.
Here is my code:
print 'Weight: [lbs/kg] '
w = gets.to_f
print 'Height: [in/m] '
h = gets.to_f
print 'Choose your measurement system: [I/M] '
mSys = gets.to_s
if mSys == 'i' || mSys == 'I'
bmi = 703 * (w / (h**2)) # Problem is here
elsif mSys == 'm' || mSys == 'M'
bmi = w / ((h)**2) # And here.
end
bmi = bmi.to_f
puts bmi
if bmi < 18.5
puts 'Consider eating few burgers.'
elsif bmi > 18.5 && bmi < 25
puts 'You have nothing to worry about.'
elsif bmi > 25
puts 'Great Council of BMI says You are overwieght!'
end
The bmi is never calculated.
You lack an else clause on your bmi calculation. If we add one in and examine mSys...
if mSys == 'i' || mSys == 'I'
bmi = 703 * (w / (h**2))
elsif mSys == 'm' || mSys == 'M'
bmi = w / ((h)**2)
else
p "#{mSys}"
end
We get "i\n". You need to strip the newline.
mSys = gets.chomp
Note there's no need for a to_s, gets already returns a String.
The more Rubyish way to write your logic would be to use case, snake case, clear variable names, and constants.
BMI_CONVERSION_FACTOR = 703
bmi = case measurement_system.downcase
when 'i'
BMI_CONVERSION_FACTOR * (w / (h**2))
when 'm'
w / (h**2)
else
raise "Unknown measurement system: #{measurement_system}"
end

Print a floating point number as a decimal number with printf()

I found a very good answer to this question on this thread
I want to understand a little bit more about why printf() can't print a floating point number as a decimal (with %d).
The program is a simple one converting Fahrenheit to Celsius degree.
I understand that %.f or %.0f is doing what i want.
But when i try to do the same thing with %d, the output is unpredictable.
I searched for more detailed pieces of information cplusplus, but i don't see where it overflows or why i get this result. For example, if you use an uninitialized variable, you will get some random (or not so random) value that is in that place of memory where your variable's name is "pointing" towards. Here, what is the reason ?
float fahr, celsius;
int lower, upper, step;
lower = 0; upper = 300; step = 20;
fahr = lower;
while(fahr <= upper){
celsius = (5 / 9.) * (fahr - 32);
printf("%d\t%d\n",fahr,celsius);
fahr+=step;
}
i was expecting :
0 20 40 60 .... 300 (first column)
-17, -6, -4, ... (second column)
instead i got
0 0 0 0 0 0 0 ,,, 0 (first column)
0, 1077149696, 1078198272, ... (second column)

How to generate a random number in Crystal?

In Crystal, how can I generate a random number?
Using Python, I can simply do the following to generate a random integer between 0 and 10:
from random import randint
nb = randint(0, 10)
Solution 1 - Use the Random module
Random Integer
Random.new.rand(10) # >= 0 and < 10
Random.new.rand(10..20) # >= 10 and < 20
Random Float
Random.new.rand(1.5) # >= 0 and < 1.5
Random.new.rand(6.2..18.289) # >= 6.2 and < 18.289
Solution 2 - Use the top-level method rand
As pointed out by #Jonne in the comments, you can directly use the top-level method rand that calls the Random module:
Random Integer
rand(10) # >= 0 and < 10
rand(10..20) # >= 10 and < 20
Random Float
rand(1.5) # >= 0 and < 1.5
rand(6.2..18.289) # >= 6.2 and < 18.289
Even shorter is rand:
# ints
rand(10)
rand(10..20)
# floats
rand(1.5)
rand(6.2..18.289)

Resources