I'm working on assignment 2 of CS193P - Stanford's IOS programming course. One thing I was wondering about is how the calculatorBrain is supposed to be able to accept and run a stored program, a program being an array or stack of operands and operations.
So let's say we want to perform the following calculation: 2, 3, 4, +, *
If you typed this into the calulator, the following would happen:
2 3 4 get pushed onto the stack one at a time, and runProgram called for each one, which simply pops the number off the stack and returns it's value which gets pushed onto the stack.
You press +, and runProgram pops this and sees it has to add the top 2 items which it does and pushes the result onto the stack which now contains 2, 7. You press * and the stack now contains 14.
But I can't see how you can pass an array containing (2, 3, 4, +, *) to the brain (the instructor says later you can just pass a program to the runProgram class method and get the result, without having to instantiate a brain object), as runProgram would first try to execute the top operand i.e. * and to do this it would take the next two objects off the stack and try to multiply them and to push the result back onto the stack. These 2 objects are "+" and "4" which won't work.
Now the instructor has been doing this a lot longer than I have, as I assume that I'm missing somethings, but I'm not sure what.
Any ideas?
If you look at this as passing "2,3,4,+,*" to the "brain", you need to be thinking in the context of the stack processor.
The arguments are evaluated in the order in which they are encountered in the array. But, don't confuse the array for the stack, they are different objects. The stack is internal to the calculator routine and the array of input is external to the routine. Since I'm not taking that particular class at whatever school you're in, I can't speak to the particulars of the language in use, but basically, think of the array "2,3,4,+,*" as input to the keyboard of the calculator. However, the calculator is a very simple machine and only processes one key press at a time.
Thus, when you process the array, you're basically passing each element of the array to the calculator for processing and the calculator is then deciding whether to push to the stack or execute the operator. These elements are passed in order, so the calculator receives: 2 followed by 3, followed by 4, followed by '+', followed by '*'.
It looks like you're trying to think of the problem in terms of the array being passed in to the calculator as the stack, and that's not what you want to do here.
I hope this is clear.
OK - the answer is that the way runProgram gets the next item off the stack is by recursively calling a popOperandOffStack (pOOS) method.
So when it gets passed a program consisting of 2 3 4 + *, it starts by popping * off the stack. It then has to pop the next two operands off the stack. So it calls pOOS, which firstly returns a '+', so it then calls pOOS again (twice) which gets '4' & '3' respectively, which are added to get 7 which is pushed back onto the stack (which now contains 2 7) and also returned as the result of calling pOOS. So when it called pOOS for the first operand of the '*' operation it didn't get '+', it actually got '7'. The second call to pOOS (for the second operand of the *) gets '2' which it then happily multiplies to get 14.
I did try looking up recursion in my IT dictionary, but it just said 'See recursion'.
#steve Ives, I think you nailed the answer with this last comment. Having gone through this assignment a few weeks back (also on my own), I found this site to be helpful understanding the reverse polish calculator, it basically emulates one. But as you are thinking recursion, your brain can go into overload mode. Hope this helps validating some of your scenario testing...Good luck.
HP12C Emulator
Related
I've followed "Procedural Generation in Godot: Dungeon Generation" by KidsCanCode #https://www.youtube.com/watch?v=o3fwlk1NI-w and find myself unable to debug the current problem.
This specific commit has the code, but I'll try to explain in more detail bellow.
My main scene has a Camera2D node, a generic Node2D calles Rooms and a TileMap, everything is empty.
When the script starts, it runs a
func make_room(_pos, _size):
position = _pos
size = _size
var s = RectangleShape2D.new()
s.custom_solver_bias = 0.5
s.extents = size
$CollisionShape2D.shape = s
A few times and it fills $Rooms using .add_child(r) where r is a instance of the node that has the make_room() function. It will then iterate over $Rooms.get_children() a few times to create a AStar node to link all the rooms:
The magic comes when make_map() is called after afterwards, it fills the map with non-walkable blocks and then it carves the empty spaces, which works fine too:
There is a find_start_room() that is called to find the initial room, it also sets a global variable to the Main script start_room, which is used to write 'Start' on the map using draw_string(font, start_room.position - Vector2(125,0),"start",Color(3,4,8))
When I hit 'esc' it runs this simple code to instance the player:
player = Player.instance()
add_child(player)
player.position = start_room.position + Vector2(start_room.size.x/2, start_room.size.y/2)
play_mode = true
The problem comes when spawning the player. I tried doing some 'blind' fixing, such as adding or subtracting a Vector2(start_room.size.x/2, start_room.size.y/2) to player.position to see if I could make it fall within the room, to no avail.
Turning to the debugger didn't help, as the positions expressed by the variable inspectors don't seem to mean anything.
I tried implementing a simple 'mouse click print location':
print("Mouse Click/Unclick at: ", event.position)
print("Node thing",get_node("/root/Main/TileMap").world_to_map(event.position))
And also a 'start_room' print location:
print(get_node("/root/Main/TileMap").world_to_map(start_room.position))
And a when player moves print location, written directly into the Character script:
print(get_node("/root/Main/TileMap").world_to_map(self.position))
Getting results like the ones bellow:
Mouse Click/Unclick at: (518, 293)
Node thing(16, 9)
(-142, 0)
(-147, -3)
So, the player doesn't spawn on the same position as the start_room and the mouse position information is not the same as anything else.
Why is the player now spawning correctly? How can I debug this situation?
EDIT1: User Theraot mentioned about how the RigidBody2D is doing some weird collisions, and from what I understood, changing their collision behavior should fix the whole thing.
There's a section on the code that -after generating the random rooms- it removes some of the rooms like this:
for room in $Rooms.get_children():
if randf() < cull:
room.queue_free()
else:
room.mode = RigidBody2D.MODE_STATIC
room_positions.append(Vector3(room.position.x, room.position.y, 0))
From what I understand, if the room is randomly selected it will be deleted using queue_free() OR it will be appended to a room_positions for further processing. This means if I shift all the rooms to a different collision layer, the player/character instance would be alone with the TileMap on the same collision layer.
So I just added a simple room.collision_layer = 3 changing this section of the code to
for room in $Rooms.get_children():
if randf() < cull:
room.queue_free()
else:
room.mode = RigidBody2D.MODE_STATIC
room.collision_layer = 3
room_positions.append(Vector3(room.position.x, room.position.y, 0))
It doesn't seem to have changed anything, the player still spawns outside the room.
Do you see the rooms spread outwards?
You didn't write code to move the rooms. Sure, the code gives them a random position. But even if you set their position to Vector2.ZERO they move outwards, avoiding overlaps.
Why? Because these rooms are RigidBody2D, and they do push other physics objects. Such as other rooms or the player character.
That's the problem: These rooms are RigidBody2D, and you put your KinematicBody2D player character on top of one of them. The RigidBody2D pushes it out.
The tutorial you followed is exploiting this behavior of RigidBody2Ds to spread the rooms. However you don't need these RigidBody2D after you are done populating your TileMap.
Instead, you can store the start position in a variable for later placing the player character (you don't need offsets - by the way - the position of the room is the center of the room), and then remove the RigidBody2Ds. If you want to keep the code that writes the text, you would also have to modify it, so it does not fail when the room no longer exists.
Alternatively, you can edit their collision layer and mask so they don't collide with the player character (or anything for that matter, but why would you want these RigidBody2Ds that collide with nothing?).
Addendum post edit: Collision layers and mask don't work as you expect.
First of all, the collision layer and mask are flags. The values of the layers are powers of two (1, 2, 4, 8...). So, when you set it to 3, it is the layer 1 plus the layer 2. So it still collides with a collision mask of 1.
And second, even if you changed the collision layer of the rooms to 2 (so it does not match the collision mask of 1 that the player character has). The player character still has a layer 1 which match the collision mask of the rooms.
See also the proposal Make physics layers and masks logic simple and consistent.
Thus, you would need to change the layer and mask. Both. in such way that they don't collide. For example, you can set layer and mask to 0 (which disable all collisions). The algorithm that populates the TileMap does not use the layer and mask.
I am building a work-logging app which starts by showing a list of projects that I can select, and then when one is selected you get a collection of other buttons, to log data related to that selected project.
I decided to have a selected_project : Maybe Int in my model (projects are keyed off an integer id), which gets filled with Just 2 if you select project 2, for example.
The buttons that appear when a project is selected send messages like AddMinutes 10 (i.e. log 10 minutes of work to the selected project).
Obviously the update function will receive one of these types of messages only if a project has been selected but I still have to keep checking that selected_project is a Just p.
Is there any way to avoid this?
One idea I had was to have the buttons send a message which contains the project id, such as AddMinutes 2 10 (i.e. log 10 minutes of work to project 2). To some extent this works, but I now get a duplication -- the Just 2 in the model.selected_project and the AddMinutes 2 ... message that the button emits.
Update
As Simon notes, the repeated check that model.selected_project is a Just p has its upside: the model stays relatively more decoupled from the UI. For example, there might be other UI ways to update the projects and you might not need to have first selected a project.
To avoid having to check the Maybe each time you need a function which puts you into a context wherein the value "wrapped" by the Maybe is available. That function is Maybe.map.
In your case, to handle the AddMinutes Int message you can simply call: Maybe.map (functionWhichAddsMinutes minutes) model.selected_project.
Clearly, there's a little bit more to it since you have to produce a model, but the point is you can use Maybe.map to perform an operation if the value is available in the Maybe. And to handle the Maybe.Nothing case, you can use Maybe.withDefault.
At the end of the day is this any better than using a case expression? Maybe, maybe not (pun intended).
Personally, I have used the technique of providing the ID along with the message and I was satisfied with the result.
I am very new to labview and recently I had been trying to make this sequence loop.
E.g.
myRio's starting position is ((x <0.05) && (y <=0.05) &&( z>0.9))
next while detecting myRio's position changes to ((x<0.2) && (y <= -0.9) &&( z<=0.3)) and then back again to the starting position, it will turn validate this as one correct cycle and change the counter from 0 to 1. and loop this whole sequence again.
Would really appreciate if you could highlight how can I do these kind of sequence looping. Thank you very much.
It sounds as if what you are trying to do is to count transitions between states. A great design pattern for anything involving transitions between states - which covers a large part of what people generally use LabVIEW for - is a state machine.
The link gives an explanation but essentially what you need is:
a While loop with a shift register
a case structure inside the loop whose case selector is wired to the left shift register terminal
some logic inside each case that decides what value to output to the right shift register terminal, i.e. what state to go to next.
In your case you could implement this with just two states:
State 1: Check position and see if we have reached the target position.
If so go to State 2
If not go to State 1 again
State 2: Check position and see if we have got back to the start position.
If so, increment the count and go to State 1
If not, go to State 2 again
However it would be slightly more elegant to use three states:
State 2: Check position and see if we have got back to the start position.
If so, go to State 3
If not, go to State 2 again
State 3: Increment the count and go to State 1.
You can use a second shift register for the counter: initialise it to 0, wire the left terminal across to the right one in States 1 and 2 (leaving the count unchanged) and increment it in State 3.
You can use an integer value or a string for the case selector, but the best practice is to use an enum which you save as a typedef. This allows you to reorder, rename, add or remove states later on without breaking existing code.
I know the question seems a bit broad. I tried searching for answers, couldn't find much.If anyone could describe or point me to the right source.
Assuming a bytecode-based interpreter, the usual way to do this would be as follows:
You have a variable, the program counter, which tells you the index of the instruction to execute. Usually you increase that counter by 1, but when executing a branch, you instead set it to the target location of the jump.
For function calls you do the same thing, but you also push the old value of the counter plus one onto the call stack. Then when you execute the return instruction, you pop the value of the stack and set the counter to that.
Definition:
As defined here, CGGetDisplaysWithPoint takes 4 parameters:
A CGPoint object
An int32 representing the maximum number of displays returned
A mutable array passed by reference, which will be filled with the displayIDs found.
An int32 representing the matching display count
Syntax:
CGError CGGetDisplaysWithPoint(CGPoint point, uint32_t maxDisplays, CGDirectDisplayID *displays, uint32_t *matchingDisplayCount);
This is fine and I can get this function working however I am quite confused as to how I should deal with the maxDisplays parameter?
As I understand it, if I set maxDisplays to 5 then if someone has 6 displays, there is a 1/6 chance that a randomly selected pixel will find no displays?
So do we just set maxDisplays to something unrealistic, like 99, and release the array afterwards? What's the point in this argument?
The point of the argument is to prevent the function from writing past the end of your array. You have to tell it the capacity of the array. Note that the displays parameter is neither a Cocoa nor Core Foundation mutable array object. It's a C-style array. It's "mutable" in the sense that it's not "const", but it's not an object that manages its own storage. You are responsible for managing that storage and must communicate its capacity to any function that is intended to store data in it (or otherwise guarantee that such function won't overrun it).
So, your question should really be how to decide on the capacity of the array. There are two basic approaches:
1) Call the function passing NULL for the displays parameter and any arbitrary value (best to use 0) for maxDisplays. As documented, when displays is NULL, maxDisplays is ignored and the function outputs via matchingDisplayCount the number of displays whose bounds contain the given point. Then, allocate an array with (at least) that many elements to use to receive the display IDs and call the function again, passing that array for displays and its capacity for maxDisplays.
2) Use an array with capacity of 32. It's not explicitly documented but it's implicit in the API that that's the maximum number of supported displays. A display ID can be converted to an OpenGL display mask using CGDisplayIDToOpenGLDisplayMask(). The type CGOpenGLDisplayMask is used to hold OpenGL display masks. It is defined as uint32_t, a 32-bit value. Therefore, there can be at most 32 active displays.
This technique is used in some Apple docs, like here, here, here, and here. That last one even makes a direct connection between the number of bits in CGOpenGLDisplayMask and the maximum number of displays.