python function will not return value that is based on condition - function

I am new to this, and I am looking for help. I currently am stuck in a program I'm trying to complete. Here it is:
def printStock(stockList, stockPrice, p):
for i in range(len(stockPrice)):
if stockPrice[i] > p:
p = stockList[i]
print("The stocks with a higher value are:", p)
def searchStock(stockList, stockPrice, s):
for i in range(len(stockList)):
if s == stockList[i]:
s = stockPrice[i]
elif s != stockList[i]:
s = -1
return s
def mainFun():
stockList= []
stockPrice = []
l = 1
while l > 0:
stocks = str(input("Enter the name of the stock:"))
stockList += [stocks]
if stocks == "done"or stocks == 'done':
l = l * -1
stockList.remove("done")
else:
price = int(input("Enter the price of the stock:"))
stockPrice += [price]
l = l + 1
print(stockList)
print(stockPrice)
s = input("Enter the name of the stock you're looking for:")
searchStock(stockList, stockPrice, s)
p = s
printStock(stockList, stockPrice, p)
Every time I run the program to the end, it never returns the variable s for some reason. If i replace return with print, it always prints -1 instead of the stockPrice if its on the list. I also get an error saying "unorderable types int() > str()" regarding line 3. Basically the function printStock takes the three parameters and once the function is done it should print the names of the stocks higher than the value 'p'. The value of 'p' is the same as the value I get after calling searchStock function, but I cant seem to get it to work. Can someone please help me?

s is being returned from the function, but the return value is not being assigned to any variable on the outer scope.
Just replace
searchStock(stockList, stockPrice, s)
with
s=searchStock(stockList, stockPrice, s)
And everything should work as expected

Related

How to write Python functions and nested functions?

link to assignment**
This is what I have so far but I cant figure out the rest. I am having a hard time solving the rest of the problem. Like calling sum variables from other functions. If anyone could lend a hand I would appreciate it, thank you.
#hello function
def hello():
print("***************************************")
print("*** WELCOME TO THE MAGIC PROGRAM *****")
print("***************************************")
#get_highest function
def get_highest():
first_num = int(input("\nEnter first number: "))
second_num = int(input("Enter second number: "))
largest_num = 0
if first_num > 0 and second_num > 0 and first_num >= second_num:
print("\nThe largest number is: ", first_num)
first_num = largest_num
elif second_num > 0 and first_num > 0 and second_num >= first_num:
print("\nThe largest number is:", second_num)
second_num = largest_num
else:
print("\nERROR: Both numbers must be greater than 0!")
print("Try again.")
get_highest()
return largest_num
#odd_or_even function
def odd_or_even(largest_num):
largest_num = get_highest()
if (largest_num % 2 == 0):
print(largest_num, " is an EVEN NUMBER!!")
else:
print(largest_num, " is an ODD NUMBER!!")
#print_magic function
def print_magic(largest_num):
largest_num = get_highest()
total = 0
for x in range(1, largest_num):
total = total + x
hello()
get_highest()
odd_or_even()

Putting last element of list in the first index "n" times SML

I'm trying to put the last element of a list in the front of the list while keeping the rest of the elements in the same order N times. I can do it once with this function, but I want to add another parameter to the function so that the function in called N times.
Code:
fun multcshift(L, n) =
if null L then nil
else multcshift(hd(rev L)::(rev(tl(rev L))));
Thanks
To make the parameter n work, you need recursion. You need a base case at which point the function should no longer call itself, and a recursive case where it does. For this function, a good base case would be n = 0, meaning "shift the last letter in front 0 times", i.e., return L without modification.
fun multcshift(L, n) =
if n = 0
then L
else multcshift( hd(rev L)::rev(tl(rev L)) , n - 1 )
The running time of this function is terrible: For every n, reverse the list three times!
You could save at least one of those list reversals by not calling rev L twice. E.g.
fun multcshift (L, 0) = L
| multcshift (L, n) =
let val revL = rev L
in multcshift ( hd revL :: rev (tl revL) , n - 1 ) end
Those hd revL and rev (tl revL) seem like useful library functions. The process of applying a function to its own output n times seems like a good library function, too.
(* Return all the elements of a non-empty list except the last one. *)
fun init [] = raise Empty
| init ([_]) = []
| init (x::xs) = x::init xs
(* Return the last element of a non-empty list. *)
val last = List.last
(* Shift the last element of a non-empty list to the front of the list *)
fun cshift L = last L :: init L
(* Compose f with itself n times *)
fun iterate f 0 = (fn x => x)
| iterate f 1 = f
| iterate f n = f o iterate f (n-1)
fun multcshift (L, n) = iterate cshift n L
But the running time is just as terrible: For every n, call last and init once each. They're both O(|L|) just as rev.
You could overcome that complexity by carrying out multiple shifts at once. If you know you'll shift one element n times, you might as well shift n elements. Shifting n elements is equivalent to removing |L| - n elements from the front of the list and appending them at the back.
But what if you're asked to shift n elements where n > |L|? Then len - n is negative and both List.drop and List.take will fail. You could fix that by concluding that any full shift of |L| elements has no effect on the result and suffice with n (mod |L|). And what if n < 0?
fun multcshift ([], _) = raise Empty
| multcshift (L, 0) = L
| multcshift (L, n) =
let val len = List.length L
in List.drop (L, len - n mod len) #
List.take (L, len - n mod len) end
There are quite a few corner cases worth testing:
val test_zero = (multcshift ([1,2,3], 0) = [1,2,3])
val test_empty = (multcshift ([], 5); false) handle Empty => true | _ => false
val test_zero_empty = (multcshift ([], 0); false) handle Empty => true | _ => false
val test_negative = (multcshift ([1,2,3,4], ~1) = [2,3,4,1])
val test_nonempty = (multcshift ([1,2,3,4], 3) = [2,3,4,1])
val test_identity = (multcshift ([1,2,3,4], 4) = [1,2,3,4])
val test_large_n = (multcshift [1,2,3,4], 5) = [4,1,2,3])
val test_larger_n = (multcshift [1,2,3,4], 10) = [3,4,1,2])

Why isn't my return statement working?

I have a function that converts a decimal value to binary. I understand I have the logic correct as I can get it to work outside of a function.
def decimaltobinary(value):
invertedbinary = []
value = int(value)
while value >= 1:
value = (value / 2)
invertedbinary.append(value)
value = int(value)
for n, i in enumerate(invertedbinary):
if (round(i) == i):
invertedbinary[n] = 0
else:
invertedbinary[n] = 1
invertedbinary.reverse()
value = ''.join(str(e) for e in invertedbinary)
return value
decimaltobinary(firstvalue)
print (firstvalue)
decimaltobinary(secondvalue)
print (secondvalue)
Let's say firstvalue = 5 and secondvalue = 10. The values returned each time the function is executed should be 101 and 1010 respectively. However, the values I get printed are the starting values of five and ten. Why is this happening?
The code works as expected, but you didn't assign the returned value:
>>> firstvalue = decimaltobinary(5)
>>> firstvalue
'101'
Note that there are easier ways to accomplish your goal:
>>> str(bin(5))[2:]
'101'
>>> "{0:b}".format(10)
'1010'

How to get working variables out of a function in F#

I have a function in F# , like:
let MyFunction x =
let workingVariable1 = x + 1
let workingVariable2 = workingVariable1 + 1
let y = workingVariable2 + 1
y
Basically, MyFunction takes an input x and returns y. However, in the process of calculation, there are a few working variables (intermediate variables), and due to the nature of my work (civil engineering), I need to report all intermediate results. How should I store all working variables of the function ?
I'm not exactly sure what kind of "report" your are expecting. Is this a log of intermediate values ? How long time this log should be kept ? etc. etc This is my attempt from what I understand. It is not ideal solution because it allows to report values of intermediate steps but without knowing exactly which expression has generated the intermediate value (I think that you would like to know that a value n was an output of workingVariable1 = x + 1 expression).
So my solution is based on Computation Expressions. Computation expression are a kind of F# "monads".
First you need to define a computation expression :
type LoggingBuilder() =
let log p = printfn "intermediate result %A" p
member this.Bind(x, f) =
log x
f x
member this.Return(x) =
x
Next we create an instance of computation expression builder :
let logIntermediate = new LoggingBuilder()
Now you can rewrite your original function like this:
let loggedWorkflow x =
logIntermediate
{
let! workingVariable1 = x + 1
let! workingVariable2 = workingVariable1 + 1
let! y = workingVariable2 + 1
return y,workingVariable1,workingVariable2
}
If you run loggedWorkflow function passing in 10 you get this result :
> loggedWorkflow 10;;
intermediate result 11
intermediate result 12
intermediate result 13
val it : int * int * int = (13, 11, 12)
As I said your intermediate values are logged, however you're not sure which line of code is responsible for.
We could however enchance a little bit to get the FullName of the type with a corresponding line of code. We have to change a little our computation expression builder :
member this.Bind(x, f) =
log x (f.GetType().FullName)
f x
and a log function to :
let log p f = printfn "intermediate result %A %A" p f
If you run again loggedWorkflow function passing in 10 you get this result (this is from my script run in FSI) :
intermediate result 11 "FSI_0003+loggedWorkflow#34"
intermediate result 12 "FSI_0003+loggedWorkflow#35-1"
intermediate result 13 "FSI_0003+loggedWorkflow#36-2"
This is a hack but we get some extra information about where the expressions like workingVariable1 = x + 1 were definied (in my case it is "FSI_") and on which line of code (#34, #35-1). If your code changes and this is very likely to happen, your intermediate result if logged for a long time will be false. Note that I have not tested it outside of FSI and don't know if lines of code are included in every case.
I'm not sure if we can get an expression name (like workingVariable1 = x + 1) to log from computation expression. I think it's not possible.
Note: Instead of log function you coud define some other function that persist this intermediate steps in a durable storage or whatever.
UPDATE
I've tried to came up with a different solution and it is not very easy. However I might have hit a compromise. Let me explain. You can't get a name of value is bound to inside a computation expression. So we are not able to log for example for expression workingVariable1 = x + 1 that "'workingVariable1' result is 2". Let say we pass into our computation expression an extra name of intermediate result like that :
let loggedWorkflow x =
logIntermediate
{
let! workingVariable1 = "wk1" ## x + 1
let! workingVariable2 = "wk2" ## workingVariable1 + 1
let! y = "y" ## workingVariable2 + 1
return y,workingVariable1,workingVariable2
}
As you can see before ## sign we give the name of the intermediate result so let! workingVariable1 = "wk1" ## x + 1 line will be logged as "wk1".
We need then an extra type which would store a name and a value of the expression :
type NamedExpression<'T> = {Value:'T ; Name: string}
Then we have to redefine an infix operator ## we use une computation expression :
let (##) name v = {Value = v; Name = name}
This operator just takes left and right part of the expression and wraps it within NamedExpression<'T> type.
We're not done yet. We have to modify the Bind part of our computation expression builder :
member this.Bind(x, f) =
let {Name = n; Value = v} = x
log v n
f v
First we deconstruct the NamedExpression<'T> value into name and wraped value. We log it and apply the function f to the unwrapped value v. Log function looks like that :
let log p n = printfn "'%s' has intermediate result of : %A" n p
Now when you run the workflow loggedWorkflow 10;; you get the following result :
'wk1' has intermediate result of : 11
'wk2' has intermediate result of : 12
'y' has intermediate result of : 13
Maybe there are better way to do that, something with compiler services or so, but this is the best attempt I could do so far.
If I understand you correctly, then there are several options:
let MyFunction1 x =
let workingVariable1 = x + 1
let workingVariable2 = workingVariable1 + 1
let y = workingVariable2 + 1
y,workingVariable1,workingVariable2
MyFunction1 2 |> printfn "%A"
type OneType()=
member val Y = 0 with get,set
member val WV1 = 0 with get,set
member val WV2 = 0 with get,set
override this.ToString() =
sprintf "Y: %d; WV1: %d; WV2: %d\n" this.Y this.WV1 this.WV2
let MyFunction2 x =
let workingVariable1 = x + 1
let workingVariable2 = workingVariable1 + 1
let y = workingVariable2 + 1
new OneType(Y=y,WV1=workingVariable1,WV2=workingVariable2)
MyFunction2 2 |> printfn "%A"
Out:
(5, 3, 4)
Y: 5; WV1: 3; WV2: 4
http://ideone.com/eYNwYm
In the first function uses the tuple:
https://msdn.microsoft.com/en-us/library/dd233200.aspx
The second native data type.
https://msdn.microsoft.com/en-us/library/dd233205.aspx
It's not very "functional" way, but you can use mutable variable to store intermediate results:
let mutable workingVariable1 = 0
let mutable workingVariable2 = 0
let MyFunction x =
workingVariable1 <- x + 1
workingVariable2 <- workingVariable1 + 1
let y = workingVariable2 + 1
y

F# value is not a function error

Continuing my F# learning today by attempting to recreate a simple bisection method using recursion, here I am using the MathNet library to inherit from the Beta distribution.
I receive errors on the function 'search' (binary search method) saying the value is not a function and cannot be applied.
//Beta class inheriting from MathNet Beta distribution
//Extends the class by implementing an InverseCDF function
type newBeta(alpha:double, beta:double) =
inherit MathNet.Numerics.Distributions.Beta(alpha, beta)
member this.InverseCDF(p: float) =
let rec search (min: float, max: float, acc: uint32) =
let x = (min + max) / 2.0
let error = 0.001
let maxiters : uint32 = 1000u
let cdf = this.CumulativeDistribution(x)
match cdf, (Math.Abs(cdf - p) < error || acc > maxiters) with //while statement
| _ , true -> cdf //auto match cdf and if while statement evaluates true then break and return cdf result
| p , _ -> cdf //if exactly matches p then break and return cdf result
| p , false when p > cdf -> search (min) (x) (acc + 1) //if p > cdf then set max = x and increment then call func with new params
| p , false when p < cdf -> search (x) (max) (acc + 1) //if p < cdf then set min = x and increment then call func with new params
search (0.0) (1.0) (0) //Call the bisection method with initial parameters
Can anyone help? Also obviously any input on how to make this more 'functional' would be cool. Havn't been able to run this yet to test due to the error though. My first 2 match patterns look suspect given I'm trying to return the current value of cdf.
As #John said, your fundamental error is that you declared the function in the tuple form but used it in the curried form.
I notice that you pattern-matched cdf with p. The new value p will shadow parameter p of this.InverseCDF; therefore, that parameter isn't available for comparison anymore. You actually compared cdf with cdf itself and two when guards are always false, which you do not want at all.
A few corrections:
Remove cdf from pattern matching since you only want to compare its value with p, not match with specific literals.
Move two when guards up. The last pattern shouldn't be a when guard; the compiler will complain about incomplete pattern matching in that case.
Use suffix u for any arithmetic operation on acc (which is of type unint32).
The new search function:
let rec search (min: float) (max: float) (acc: uint32) =
let x = (min + max) / 2.0
let error = 0.001
let maxiters : uint32 = 1000u
let cdf = this.CumulativeDistribution(x)
match abs(cdf - p) < error || acc > maxiters with // while statement
| false when p > cdf -> search min x (acc + 1u) // if p > cdf then set max = x and increment then call func with new params
| false when p < cdf -> search x max (acc + 1u) // if p < cdf then set min = x and increment then call func with new params
| _ -> cdf // if exactly matches p or returns true then break and return cdf result
search 0.0 1.0 0u // call the bisection method with initial parameters
Your definition is in tuple style, not curried style - just change it to
let rec search (min: float) (max: float) (acc: uint32) =
This is because when you call the function you have used the curried style f a b but your definition has the tupled style f (a,b)
Also, your match cases aren't quite correct - the last two cases will never be matched because the second case will grab them - you probably want
match cdf, (Math.Abs(cdf - p) < error || acc > maxiters) with //while statement
| _ , true -> cdf //auto match cdf and if while statement evaluates true then break and return cdf result
| p when p=cdf, _ -> cdf //if exactly matches p then break and return cdf result
| p , false when p > cdf -> search (min) (x) (acc + 1) //if p > cdf then set max = x and increment then call func with new params
| p , false when p < cdf -> search (x) (max) (acc + 1) //if p < cdf then set min = x and increment then call func with new params