essentially same code,but different result - function

This is UCB CS61A's firt project hog 's problem5
this is wrong code(my code)
while(score0<goal and score1<goal):
if who==0 :
cur_strategy = strategy0
cur_score = score0
cur_op_score=score1
cur_op_strategy = strategy1
else:
cur_strategy = strategy1
cur_score = score1
cur_op_score=score0
cur_op_strategy = strategy0
cur_score=cur_score+take_turn(cur_strategy(cur_score,cur_op_score),cur_op_score,dice)
if(extra_turn(cur_score,cur_op_score)==False):
who=other(who)
this is the correct code(I have tested it)
while score0 < goal and score1 < goal:
if who == 0:
num_rolls = strategy0(score0, score1)
score0 += take_turn(num_rolls, score1, dice)
who = other(who) if extra_turn(score0, score1) == False else who
else:
num_rolls = strategy1(score1, score0)
score1 += take_turn(num_rolls, score0, dice)
who = other(who) if extra_turn(score1, score0) == False else who
But actually,I think these two codes are essentially same.
I don't know whether this is the problem (the quote from the project)
Only call a strategy function once per turn (or risk breaking the GUI).

I think that comes from the fact that in order to update the score0 an score1 variables, you define cur_score and update it instead. The problem is that cur_score is only a copy of the score you want to update, it is not the same object.

Related

Substituting multiple inputs for a function with one function?

I am trying to see if I can simplify input by using a function that produces more than one output for use with another function. Is there any way I can do this? Do I HAVE to make a function to return single variables for each input?
--here is a snippet of what im trying to do (for a game)
--Result is the same for game environment and lua demo.
en = {
box ={x=1,y=2,w=3}
}
sw = {
box = {x=1,y=2,w=3}
}
function en.getbox()
return en.box.x,en.box.y,en.box.w,en.box.w
end
function sw.getbox()
return sw.box.x,sw.box.y,sw.box.w,sw.box.w
end
function sw.getvis()
return true
end
function CheckCollision(x1,y1,w1,h1, x2,y2,w2,h2)
return x1 < x2+w2 and
x2 < x1+w1 and
y1 < y2+h2 and
y2 < y1+h1
end
if CheckCollision(en.getbox(),sw.getbox()) == true then
if sw.getvis() == true then
en.alive = false
end
end
print(tostring(en.alive))
I am expecting the enemy (en) to die (en.alive = false) but I am getting the error: input:25: attempt to perform arithmetic on a nil value (local 'w2')
You can find an explaination for the issue you are seeing here: Programming in Lua: 5.1 – Multiple Results
I suggest you read the whole page but here is a relevant section
A function call that is not the last element in the list always produces one result:
x,y = foo2(), 20 -- x='a', y=20
x,y = foo0(), 20, 30 -- x=nil, y=20, 30 is discarded
I suggest the following changes to get your code working. wrap your output from getbox into a table with clear keys that make it easy to understand.
function en.getbox()
return {
x = en.box.x,
y = en.box.y,
w = en.box.w,
h = en.box.w
}
end
function sw.getbox()
return {
x = sw.box.x,
y = sw.box.y,
w = sw.box.w,
h = sw.box.w
}
end
function CheckCollision(o1, o2)
return o1.x < o2.x + o2.w and
o2.x < o1.x + o1.w and
o1.y < o2.y + o2.h and
o2.y < o1.y + o1.h
end
Alternatively you can wrap the output of getbox "on the fly" like:
function CheckCollision(o1, o2)
return o1[1] < o2[1] + o2[3] and
o2[1] < o1[1] + o1[3] and
o1[2] < o2[2] + o2[4] and
o2[2] < o1[2] + o1[4]
end
if CheckCollision({en.getbox()}, {sw.getbox()}) == true then
if sw.getvis() == true then
en.alive = false
end
end
I do strongly encourage the first option over the last. The last option leads to code that is harder to follow and should be accompanied by clear comments explaining it.

Remove conditions from rails front-end html slim

I have following code in my rails front-end html.slim file. I want to remove these nested if-else conditions. Can I implement this by moving these if-else conditions to some helper class?
- if #current_task.task_type == 'econsent'
- if #patient_organization.organization.identity_verification
- if #patient_organization.manual_verified
- if session['kiosk_token']
= render "#{#current_task.task_type}_tasks"
- else
- if #reauthenticated
= render "#{#current_task.task_type}_tasks"
- else
= render 'relogin_required_screen'
- else
= render 'manual_verification_required_screen'
- else
- if #patient.self_verified
- if session['kiosk_token']
= render "#{#current_task.task_type}_tasks"
- else
- if #reauthenticated
= render "#{#current_task.task_type}_tasks"
- else
= render 'relogin_required_screen'
- else
- if #patient.self_verification_req_sent
= render 'verify_email_after_sent_screen'
- else
= render 'verify_email_screen'
- else
= render "#{#current_task.task_type}_tasks"
I think you need to refactor those conditions, not just move them to another place. For ex: there is 5 different conditions that ends with render "#{#current_task.task_type}_tasks" you need to find what those have in comum, you don't need so many conditionals. Take a look at the usage of if, elsif, else and unless.
I believe you could simply assign an #to_render variable in your controller action, something like:
class FooController < ApplicationController
def bar_action
...
#to_render = get_to_render
...
end
private
def get_to_render
if current_task_type == 'econsent'
if #patient_organization.organization.identity_verification
if #patient_organization.manual_verified
return :relogin_required_screen if (!#reauthenticated && !kiosk_token?)
else
return :manual_verification_required_screen
end
else
if #patient.self_verified
return :relogin_required_screen if (!#reauthenticated && !kiosk_token)
else
return #patient.self_verification_req_sent ? :verify_email_after_sent_screen : :verify_email_screen
end
end
end
return "#{current_task_type}_tasks".to_sym
end
def kiosk_token?
session['kiosk_token']
end
end
Then in your html.slim file, do:
= render #to_render
I can't remember, but you may need to do:
= render "#{#to_render}"
since #to_render will be a symbol. Doing the string interpolation will automatically convert the symbol to a string.

Complex joins with Peewee

It's rather embarrassing to ask this question, since it seems to be so trivial, yet I can't find a solution that works.
I have the following function:
def planner(departure_id, arrival_id):
departure = Stop.get(Stop.id == departure_id)
arrival = Stop.get(Stop.id == arrival_id)
buses = Bus.select().join(RideStopRelationship).join(Stop).where(Stop.id == departure)
for bus in buses:
print bus.line
for stop in bus.stops:
print stop.time, stop.stop.name
based on the following models:
class Stop(BaseModel):
name = CharField()
#lat = FloatField()
#lng = FloatField()
class Bus(BaseModel):
line = IntegerField()
number = IntegerField()
direction = IntegerField()
class RideStopRelationship(BaseModel):
bus = ForeignKeyField(Bus, related_name = "stops")
stop = ForeignKeyField(Stop, related_name = "buses")
time = TimeField()
The crucial line is Bus.select().join(RideStopRelationship).join(Stop).where(Stop.id == departure). I'm trying to get all buses that will stop at both departure and arrival. However, the above query returns all buses that stop at departure. How would I get buses that stop at both 'departure' and 'arrival'?
If I'm making this too complicated (either my models being too complicated, or my query), feel free to correct me.
EDIT:
There's one way that does work:
buses_departure = Bus.select().join(RideStopRelationship).join(Stop).where(Stop.id == departure)
buses_arrival = Bus.select().join(RideStopRelationship).join(Stop).where(Stop.id == arrival)
buses = Bus.select().where(Bus.id << buses_departure & Bus.id << buses_arrival)
but it's rather long for what should be a simply query...
You might try something like this:
departure = Stop.get(...)
arrival = Stop.get(...)
query = (Bus
.select(Bus)
.join(RideStopRelationship)
.where(RideStopRelationship.stop << [departure, arrival])
.group_by(Bus)
.having(fn.Count(Bus.id) == 2))
Unrelated, but one thing to note is that due to the way python evaluates operators, you need to put parentheses around your in queries:
buses = Bus.select().where(
(Bus.id << buses_departure) &
*Bus.id << buses_arrival))

Keeping the variable 's value in recursive function, python 3.3

I managed to do it, some other way.
but I have a question, I had this code before
def jumphunt(start, mylist, count = 0):
if count < len(mylist):
place = mylist[start]
print(place)
if place == 0:
return True
elif start >= len(mylist) or start < 0:
return False
move_left = (start - place)
move_right = (start + place)
return jumphunt(move_right, mylist, count+1) or jumphunt(move_left, mylist, count+1)
else:
return False
but for some reason it's not trying both ways
to get to the last item on the list.
for example: [1,2,2,3,4,5,3,2,1,7,0] and ,start=mylist[0]
it supposed to jump like this (from 1-2-4-1-left to 2-left to 5-right to 0)
but it keeps trying to go right and then index is out of range etc.
I thought that if u use return of or this or that, it will try both until it reaches True, why won't it work here?
Thanks!
Include the value you want to keep as a default parameter for the method, like this:
def my_func(int, list, i=0):
a = (i + int)
if int == 0:
return True
elif a > len(list):
i -= int
else:
i += int
int = list[i]
my_func(int, list, i)
Bear in mind that it may not even always be possible to arrive at the end of the list doing the jumping pattern you describe, and even if it is possible, this method may choose the wrong branch.
A better algorithm would look like this:
def branching_search(list, start):
marks = [0]*len(list)
pos = start
while list[pos]!=0:
marks[pos]++
if marks[pos] % 2 == 0 and pos + list[pos] < len(list):
pos += list[pos]
elif marks[pos] % 2 == 1 and pos - list[pos] >= 0:
pos -= list[pos]
else:
return False
if all(item == 0 or item > 1 for item in list)
return False
return True
This way, if it comes to an item that it has already visited, it will decide to go the opposite direction that it went last time. Also, if it comes to an item that it can't leave without going out-of-bounds, or if there is not way to get to the end, it will give up and return.
EDIT: I realized there are a number of flaws in this algorithm! Although it is better than the first approach, it is not guaranteed to work, although the reasons are somewhat complicated.
Just imagine this array (the unimportant elements are left blank):
1, 2, , 5, , , , , 5, 0
The first two elements would get only one mark (thus the loop checking condition would not work), but it would still get stuck looping between the two fives.
Here is a method that will always work:
def flood_search(list):
marks = [[]]*len(list)
marks[0] = [0]
still_moving = True
while still_moving:
still_moving = False
for pos in range(0,len(list)):
if marks[pos]:
if pos + list[pos] < len(list) and not marks[pos + list[pos]]:
marks[pos + list[pos]] = marks[pos] + [list[pos]];
pos += list[pos]
still_moving = True
if pos - list[pos] >= 0 and not marks[pos - list[pos]]:
marks[pos - list[pos]] = marks[pos] + [-list[pos]];
pos -= list[pos]
still_moving = True
return marks[-1]
This works by taking every possible branch at the same time.
You can also use the method to get the actual route taken to get to the end. It can still be used as a condition, since it returns an empty list if no path is found (a falsy value), or a list containing the path if a path is found (a truthy value).
However, you can always just use list[-1] to get the last item.

Tips for function inside while loop and i=i+1, Matlab

I have a problem with a function in matlab. This specific function is for filtering light signals. As you can see below I added the coding I’ve used in the function and in the while loop itself. The code is written for a NXT Lego robot.
Is there any tip how to get the count variable ( i = i + 1 ) to work in the function, so we can plot Light(i)? Because we’re getting a bunch of error messages when we try different codes to make it work.
function [light] = filter_func( i)
lightI(i) = GetLight(SENSOR_3);
if i==1
light(i)=lightI(i)
elseif i==2
light(i) = 0.55*lightI(i) + 0.45*lightI(i-1)
else
light(i) = 0.4*lightI(i) + 0.3*lightI(i-1) + 0.3*lightI(i-2);
end
end
i=1
while true
lightI(i) = GetLight(SENSOR_3); % Get’s a lightvalue between 0 and 1024.
if i>2
light =filter_func(i)
light=round(light);
else
light(i) = GetLight(SENSOR_3);;
end
i=1+i
plot(light(end-90:end), 'r-');
title('Lightvalue')
axis([0 100 0 1023]) ;
end
You probably mainly get errors because you are not allowed to mix script and functions like this in MATLAB (like you are in Python).
Your filter function is only used when i>2 so why are you doing the first 2 tests? It seems like you want lightI as a global variable, but that is not what you have done. The lightI inside the function is not the same as the one in the while loop.
Since your while loop runs forever, maybe you don't need to worry about updating the plot the first two times. In that case you can do this:
filter = [0.4 0.3 0.3]';
latest_filtered_light = nan(90,1);
lightI = [];
p = plot(latest_filtered_light, 'r-');
title('Lightvalue')
axis([0 100 0 1023]) ;
while True
lightI(end+1,1) = rand*1024; % Get’s a lightvalue between 0 and 1024.
if i>=3
new_val = lightI(end-2:end,1)'*filter;
latest_filtered_light = [latest_filtered_light(2:end);...
new_val];
set(p, 'ydata', latest_filtered_light)
drawnow
end
end
I think it is an important point to not call plot every time - at least if you are the least concerned about performance.