iPart( and int( returning 0 for 1? - ti-basic

Ok, here's my problem. I wrote an advanced Pythagorean Theorem program, but it apparently is having exceptions. Here's an instance of my problem. When I input A? √(3) and B? 2, I get 0 back. Here's the code:
:Prompt A,C
:(C^2-A^2)->B
:If B<0
:Then
:Disp "THAT IS N
OT A VALID TRIA
ANGLE
:Else
:If iPart(√(B))≠
√(B)
:Then
:Disp "B = √(",B
:Else
:Disp "B = ",√(B)
:End
:End
Therefore, if B = 1, then hypothetically it should output B = 1 but instead it outputs:
A=? √(3)
C=? 2
B = √(
1
Done
What am I doing wrong and how can I fix it?

When I quickly evaluate your program, it seems to work correctly when you get B≠1. For example if I want to calculate the famous 3,4,5 - triangle it shows:
A=?4
C=?5
B=
3
Done
Apparently the iPart( doesn't work correctly with √(1). You could include an extra statement to the If iPart( ... statement to rule this out. Like this.
:...
:If iPart(√(B))≠√(B) and B≠1
:...
Besides that I think the program looks cleaner and nicer if you use the Input, ClrHome and Output( commands.
:ClrHome
:Input "A: ",A
:Input "C: ",C
:(C^2-A^2)->B
:If B<0
:Then
:Output(4,1,"THA
T IS NOT A")
:Output(5,1,"VAL
ID TRIANGLE")
:Else
:If iPart(√(B))≠
√(B) and B≠1
:Then
:Output(3,1,"B:
√( )")
:Output(3,5,B)
:Else
:Output(3,1,"B:")
:Output(3,5,√(B))
:End
:End
:Pause
:ClrHome
Now the results screen looks something like this:
A: √(3)
C: 2
B: 1
I think this is cleaner, with the 3 aligned istead of in the bottom right corner. When you press ENTER everything will remove itself from the screen (due to the Pause command).

Related

Trouble on "If" statement on TI-84 Plus C Silver Edition

I've got a small code in TI BASIC on my TI-84 Plus C Silver Edition calculator that will determine correct dosage of drugs based on the patient's weight. For example, if aspirin is given at 5 mg per kg of patient weight (it isn't), then the code should tell me to give a 100kg patient 500mg of aspirin.
However, the code is solving for every possible drug. Here it is:
PROGRAM:DRUG1
:Input "PATIENT WEIGHT: ",W
:Input "AGENT NAME: ",A
:If A=IPPI
:Disp "DOSAGE",W*2
:If A=NEVO
:Disp "DOSAGE", W*0.5
So in this case, the two drugs are IPPI and NEVO. If I give a patient weight of 100kg, and choose IPPI, then I would expect to see
DOSAGE 200
However, what I do see is
DOSAGE 200
DOSAGE 50
so apparently both "if" statements are running, even though I've given a only one value (IPPI). [The same error occurs when I set A as NEVO].
I've tried enclosing both If statements within Then...End as well, so the code would look like:
PROGRAM:DRUG1
:Input "PATIENT WEIGHT: ",W
:Input "AGENT NAME: ",A
:If A=IPPI
:Then
:Disp "DOSAGE",W*2
:End
:If A=NEVO
:Then
:Disp "DOSAGE", W*0.5
:End
but that changes nothing.
I'm pretty new to BASIC, so I'm sure there's a simple error that I can't see, but I'm stumped at the moment.
You need to change the second Input command so the information is stored to a string instead of the numeric variable A. TI-84 series calculators have ten string variables in the [VARS][7] menu for this purpose.
Note also that you must compare the string against the string "IPPI" rather than the sequence of letters (numeric variables) IPPI. So your code could be:
:Input "PATIENT WEIGHT: ",W
:Input "AGENT NAME: ",Str1
:If Str1="IPPI"
:Disp "DOSAGE: ",W*2
:If Str1="NEVO"
:Disp "DOSAGE: ",W*0.5
or more concisely:
:Input "PATIENT WEIGHT: ",W
:Input "AGENT NAME: ",Str1
:Disp "DOSAGE:"
:If Str1="IPPI"
:Disp 2W
:If Str1="NEVO"
:Disp .5W
You're trying to use variable names as strings.
:If A=IPPI
This isn't comparing a string to "IPPI", it's comparing a numeric variable A to the numeric value I*P*P*I, which I'm guessing results in 0 in your case.
Similarly, when you take input, if you enter IPPI, it's going to multiply those variables and assign A to be that product.
You'll need to use a string variable and quotes.
The main problem with your program is that you aware assigning a string to a variable that only supports numbers. That leaves the new value of the variable the Boolean value of the string, True, which in the case of TI-BASIC is the value, 1. To fix this you need to assign it to a variable which supports characters in a string, in this case you can use STR1.

Syntax error on simple If Else

I get an error at the 'Else' on a TI-84 Plus.
I can't figure out why this doesn't work.
I'm writing a GCD program just as an exercise in programming a TI calculator.
It's recursive (or as recursive as TI-BASIC gets).
If B=0
Disp A
Else
C->B
B->remainder(A,B)
A->B
prgmGCD2
TI-Basic is often rather picky about the syntax of if statements.
There are three general formats for an If statement.
Single Statement If
:If <boolean>
:<expression>
Note that <expression> consists of exactly one line of code.
Multi Statement If
:If <boolean>
:Then
:<expresion>
:<expresion>
:End
As opposed to the first option, this option can contain any number of lines of code after the If.
If Else
:If <boolean>
:Then
:<expresion>
:<expresion>
:Else
:<expresion>
:<expresion>
:End
As with the previous option, any number of statements can be put after the If and after the Else.
You are obviously trying to use an if else statement. The correct syntax for this is:
:If B
:Then
:C->B
:B->remainder(A,B)
:A->B
:prgmGCD2
:Else
:Disp A
:End

Factoring program (TI-84 plus)

My Program, just learning how to code calculators today, is not giving me any response but
"DONE"
PROGRAM:FACTORS
:ClrHome
:Input "A=", A
:Input "B=", B
:Input "C=", C
:For(D,1,100,1)
:For(E,1,100,1)
:If (D*E)=C and (D+E)=B
:Stop
:End:End:End
:Disp D
:Disp E
Two problems:
1: All of the ":end"s are on the same line. Do a different one for each
2: This is probably the biggest problem: The "stop" command. "Stop" is used to end the program altogether, and go back to regular function. I'm assuming what you want to do is make it stop looping once D*E=C and once D+E=B. In that case, you can do one of two things: write the breakout code into a repeat loop; for instance
:ClrHome
:Input "A=", A
:Input "B=", B
:Input "C=", C
:For(D,1,100,1)
:For(E,1,100,1)
:Repeat (D*E)=C and (D+E)=B
:End
:End
:End
:Disp D
:Disp E
Or, you can use a Goto command
:If (D*E)=C and (D+E)=B
:Goto Lbl A
And further down in your code, you would put the "Lbl A" above where you wanted it to display your variables
The problem you have is that stop ends the program entirely instead of just breaking the loops. To fix this, instead or using For loops, you could use Repeat loops:
:1→D
:Repeat (D*E=C and D+E=B) or D=100
::1→E
::Repeat (D*E=C and D+E=B) or E=100
:::E+1→E
::End
::1+D→D
:End
You can ignore the extra colons, they are just there for clarity, but if you leave them the code will still work because they function identically to newlines.
The Repeat loops will break by themselves when the condition D*E=C and D+E=B is met, but you have to handle the initialization and incrementing of the variables E and D yourself.
Also note that your factoring algorithm can fail if A does not equal one. Consider dividing both B and C by A, and then outputting A as a constant factor.
Another error with your code is that you have too many End statements, but fixing this would not fix the program, and it would still exit at the Stop. An If without a Then does not need an End, but only one line will be run if the condition is true. For example:
:If <condition>
:<one statement>
or
:If <condition>
:Then
:<statement 1>
:<statement 2>
:<statement ...>
:<statement n>
:End

How to write an "if in" statement in Ruby

I'm looking for and if-in statement like Python has for Ruby.
Essentially, if x in an_array do
This is the code I was working on, where the variable "line" is an array.
def distance(destination, location, line)
if destination and location in line
puts "You have #{(n.index(destination) - n.index(location)).abs} stops to go"
end
end
if line.include?(destination) && line.include?(location)
if [destination,location].all?{ |o| line.include?(o) }
if ([destination,location] & line).length == 2
The first is the most clear, but least DRY.
The last is the least clear, but fastest when you have multiple items to check. (It is O(m+n) vs O(m*n).)
I'd personally use the middle one, unless speed was of paramount importance.
How about using include?
def distance(destination, location, line)
if line.any? { |x| [destination, location].include?(x) }
puts "You have #{(n.index(destination) - n.index(location)).abs} stops to go"
end
end
You can use Enumerable#include? -which looks a bit ugly- or create your own abstraction so you can write write how you think about the operation:
class Object
def in?(enumerable)
enumerable.include?(self)
end
end
2.in?([1, 2, 3]) #=> true
Ruby supports set operations. If you want concise/terse, you can do:
%w[a b c d e f] & ['f']
=> ['f']
Turning that into a boolean is easy:
!(%w[a b c d e f] & ['f']).empty?
=> true
If it is that you want to ensure that both destination and location are in line, I'd go with one intersect in preference to two ".include?" checks:
def distance(destination, location, line)
return if ([destination, location] - line).any? # when you subtract all of the stops from the two you want, if there are any left it would indicate that your two weren't in the original set
puts "You have #{(line.index(destination) - line.index(location)).abs} stops to go"
end

Ruby remove the implicit break in Case statement? (How to make case like Switch)

x='bob'
case x
when "bob"
puts 'it stops here'
when 'bob'
puts 'but i want it to stop here'
end
Is there anyway to make case statements behave like the vanilla switch? So that it'll cycle through all the "when's" before breaking out? I'm surprised that ruby has it behave almost identically like a elsif.
Michael,
While your example is a bit misleading ('bob' matches both 'bob' and "bob" so the first case would always match), you just can use simple if's like in if_test method below :
def case_test(x)
puts case
when x > 3
"ct: #{x} is over 3"
when x > 4
"ct: #{x} is over 4"
end
end
case_test(4)
case_test(5)
def if_test(x)
puts "it: #{x} is over 3" if x > 3
puts "it: #{x} is over 4" if x > 4
end
if_test(4)
if_test(5)
This yields :
ct: 4 is over 3
ct: 5 is over 3
it: 4 is over 3
it: 5 is over 3
it: 5 is over 4
Note that you can also use multiple statements with when, which might help you or not depending on your real use case :
def many(x)
case x
when 'alice','bob'
puts "I know #{x}"
else·
puts "I don't know #{x}"
end
end
many('alice')
many('bob')
many('eve')
Yields :
I know alice
I know bob
I don't know eve
No. Case statements evaluate the first when block whose target's === method evaluates to true when passed the comparison, and stop there.

Resources