I have never programmed before and I am trying to do an assignment.
I have to construct a change machine, that will give change to 1 euro, given an input, e.g input = 70, change = 30. The machine wants to give as few coins as possible among the coins with values 50, 20, 10, 5, 2 and 1 cent. So if the input is 65, the machine will give: 20 10 5.
The computation is run in a while-Loop, that runs until the remaining change needed is 0. In each loop body, I have to determine the largest coin still fitting in the remaining change needed. All the coins should be added to a list. Finally, the contents of that list should be displayed to the user.
So, I created the button to start the computation and the code should look like and I called my input money.
to compute-change
Create empty list
while [ remaining change > 0] [
Determine largest coin c, such that remaining change - c >= 0
Update the list with the chosen coin
Update the remaining change to be determined
]
end
So, I know how to create an empty list, i.e. [], and I know what the change is gonna be: 100-money; I also think I understood what the while means, however, even by following the skeleton of the report I don't know how to go on.
Can you help me?
Edit: How can I do this in NetLogo?
I downloaded and installed Netlogo and had a look at how the language works. I created a solution that you can use as base for your development (don't worry, I will explain it):
globals [
remaining_change
biggest_coin
possible_coins
returned_coins
]
to compute_change
set remaining_change 57
set returned_coins []
set possible_coins [1 2 5 10 20 50]
while [ remaining_change > 0 ] [
foreach possible_coins
[
if( remaining_change - ? >= 0 )
[
set biggest_coin ?
]
]
;Print next result
print "Return a coin of value: "
print biggest_coin
print "Remaining change: "
print remaining_change
;Append coins to list
set remaining_change remaining_change - biggest_coin
set returned_coins lput biggest_coin returned_coins
]
print returned_coins
end
How does it work?
Let us begin with the first block:
globals [
remaining_change
biggest_coin
possible_coins
returned_coins
]
At this point, I create a few variables I use for data storage:
remaining_change is the amount of change that needs to be returned.
biggest_coin is the value of the coin that will be returned next (the biggest possible value)
possible_coins is a list of all coins-sizes available
returned_coins is a list of all returned coins.
So, with these variables we can now start initializing them:
set remaining_change 57 we use an amount of 57 cents to return as example
set returned_coins [] initialize returned_coins with an empty list (nothing is yet returned)
set possible_coins [1 2 5 10 20 50] this is a list of our types of coins. The ascending order is important as we will see later.
Lets do stuff!
We start of with a while loop around the computation, that will keep returning coins, untilthere is no more change left to return.
while [ remaining_change > 0 ] [
]
After that, we need to determine which coin would be next to return to the user. We doo that by examining every possible coin with a foreach loop.
Basically, what we do next translates to:
"Let us look at this coin. Is it less or equal than what we need to
return? Yes? Then this is currently the biggest coin to give back. But
what about the next biggest coin?
Speaking in code, that looks like this:
foreach possible_coins
[
if( remaining_change - ? >= 0 )
[
set biggest_coin ?
]
]
do not let yourself get confused by the ?. It is just Netlogos way of saying "This is the currently examined item in your foreach loop" - so it is your current coin-value.
Let us tell the user what is going on!
This is not necessary for your computation, but nice for understanding whats going on. Its simply some output of what we calculated for the user to see.
;Print next result
print "Return a coin of value: "
print biggest_coin
print "Remaining change: "
print remaining_change
Finally, return the coin!
It is now time to return the next coin:
set remaining_change remaining_change - biggest_coin first, decrease our left amount of change by the value of our biggest coin.
set returned_coins lput biggest_coin returned_coins after that, append our value to the resulting list.
And there you go!
You have successfully computed a list of coins, that you can simply print returned_coins.
I am by no means an expert on NetLogo, but I tried this code and it works just fine. There are other ways of doing this, some probably simpler, but this code will provide you with a good starting point.
Base answer:
You basically need to understand the following concepts:
conditionals
Example in pseudo code:
if( remainingChange >= 50 )
{
output.append(new FiftyCentCoin());
remainingChange -= 50;
}
else
{
...
}
What happens here?
The if statement (or a slight variation, depending on your language) - also known as conditional - evaluates a boolean expression. Based on the result (true or false) it can execute a block of statements, basically using this algorithm:
if (*this is true*)
*do this*
else
*do that*
The example compares the amount of change to be returned with the value 50 (your biggest coin). If you need to return this amount of money or more, 50 cents will be subtracted from the leftover Change and a new FiftyCentCoin is appended to your output.
looping
Example in pseudo code:
while ( remainingChange > 0 )
{
returnACoin();
}
What happens here?
The while statement is a variation of a conditional, that will evaluate an expression, and repeat a block of code, as long as the expression holds true - using this algorithm:
while(*this is true*)
*do this*
The given example performs the action returnACoin again and again, until the amount of remainingChange is 0.
Using these basic blocks you can create your algorithm:
Be aware, that I have given you just a short introduction, and you should still read through multiple tutorials to get to know your language and its syntax.
In the following you can find some pseudo code (as you did not tell what language you are using) that you can use as rough guideline for your development:
price = 1.33 //1.33€ as example
sumPaid = 2 //amount of money the user paid
changeToReturn = sumPaid - price
changeCoins = []
while( changeToReturn > 0 )
{
if( changeToReturn >= 50 )
{
changeCoins[] = 50
changeToReturn -= 50
}
else if( changeToReturn >= 20 )
{
changeCoins[] = 20
changeToReturn -= 20
}
...
}
Related
Goal: perform rolling window calculations on panel data in Stata with variables PanelVar, TimeVar, and Var1, where the window can change within a loop over different window sizes.
Problem: no access to SSC for the packages that would take care of this (like rangestat)
I know that
by PanelVar: gen Var1_1 = Var1[_n]
produces a copy of Var1 in Var1_1. So I thought it would make sense to try
by PanelVar: gen Var1SumLag = sum(Var1[(_n-3)/_n])
to produce a rolling window calculation for _n-3 to _n for the whole variable. But it fails to produce the results I want, it just produces zeros.
You could use sum(Var1) - sum(Var1[_n-3]), but I also want to be able to make the rolling window left justified (summing future observations) as well as right justified (summing past observations).
Essentially I would like to replicate Python's ".rolling().agg()" functionality.
In Stata _n is the index of the current observation. The expression (_n - 3) / _n yields -2 when _n is 1 and increases slowly with _n but is always less than 1. As a subscript applied to extract values from observations of a variable it always yields missing values given an extra rule that Stata rounds down expressions so supplied. Hence it reduces to -2, -1 or 0: in each case it yields missing values when given as a subscript. Experiment will show you that given any numeric variable say numvar references to numvar[-2] or numvar[-1] or numvar[0] all yield missing values. Otherwise put, you seem to be hoping that the / yields a set of subscripts that return a sequence you can sum over, but that is a long way from what Stata will do in that context: the / is just interpreted as division. (The running sum of missings is always returned as 0, which is an expression of missings being ignored in that calculation: just as 2 + 3 + . + 4 is returned as 9 so also . + . + . + . is returned as 0.)
A fairly general way to do what you want is to use time series operators, and this is strongly preferable to subscripts as (1) doing the right thing with gaps (2) automatically working for panels too. Thus after a tsset or xtset
L0.numvar + L1.numvar + L2.numvar + L3.numvar
yields the sum of the current value and the three previous and
L0.numvar + F1.numvar + F2.numvar + F3.numvar
yields the sum of the current value and the three next. If any of these terms is missing, the sum will be too; a work-around for that is to return say
cond(missing(L3.numvar), 0, L3.numvar)
More general code will require some kind of loop.
Given a desire to loop over lags (negative) and leads (positive) some code might look like this, given a range of subscripts as local macros i <= j
* example i and j
local i = -3
local j = 0
gen double wanted = 0
forval k = `i'/`j' {
if `k' < 0 {
local k1 = -(`k')
replace wanted = wanted + L`k1'.numvar
}
else replace wanted = wanted + F`k'.numvar
}
Alternatively, use Mata.
EDIT There's a simpler method, to use tssmooth ma to get moving averages and then multiply up by the number of terms.
tssmooth ma wanted1=numvar, w(3 1)
tssmooth ma wanted2=numvar, w(0 1 3)
replace wanted1 = 4 * wanted1
replace wanted2 = 4 * wanted2
Note that in contrast to the method above tssmooth ma uses whatever is available at the beginning and end of each panel. So, the first moving average, the average of the first value and the three previous, is returned as just the first value at the beginning of each panel (when the three previous values are unknown).
What I am trying to do is a little addon which would let me know how much time I have spent casting during combat in %,
function()
local spell, _, _, _, _, endTime = UnitCastingInfo("player")
-- getting information from the game itself whether im "Casting"
local inCombat = UnitAffectingCombat("player")
-- getting information form the game if combat is true (1) or not (nil)
local casting = {}
local sum = 0
if inCombat == 1 then
if spell then
table.insert(casting, 1)
else
table.insert(casting, 0)
end
else
for k in pairs (casting) do
casting [k] = nil
end
end
for i=1, #casting, 1 do
sum = sum + casting[i]
end
return( sum / #casting ) end
-- creating a list which adds 1 every frame I am casting and I am in combat,
-- or adds 0 every frame I'm not casting and I'm not in combat.
-- Then I sum all the numbers and divide it by the number of inputs to figure
-- out how much % I have spent "casting".
-- In case the combat condition is false, delete the list
For some reason these numbers don't add up at all, I only see "1" when both conditions are satisfied, or 0 if the combat condition is satisfied.
There might be some better approach I'm sure, but I am kind of new to lua and programming in general.
You say you're new to Lua, so I will attempt to explain in detail what is wrong and how it can be improved, so brace yourself for a long read.
I assume that your function will be called every frame/step/tick/whateveryouwanttocallit of your game. Since you set sum = 0 and casting = {} at the beginning of the function, this will be done every time the function is called. That's why you always get 0 or 1 in the end.
Upvalues to the rescue!
Lua has this nice thing called lexical scoping. I won't go into much detail, but the basic idea is: If a variable is accessible (in scope) when a function is defined, that function remembers that variable, no matter where it is called. For example:
local foo
do
local var = 10
foo = function() return var end
end
print(bar) -- nil
print(foo()) -- 10
You can also assign a new value to the variable and the next time you call the function, it will still have that new value. For example, here's a simple counter function:
local counter
do
count = 0
counter = function() count = count + 1; return count; end
end
print(counter()) -- 1
print(counter()) -- 2
-- etc.
Applying that to your situation, what are the values that need to persist from one call to the next?
Number of ticks spent in combat
Number of ticks spent casting
Define those two values outside of your function, and increment / read / reset them as needed; it will persist between repeated calls to your function.
Things to keep in mind:
You need to reset those counters when the player is no longer casting and/or in combat, or they will just continue where they left off.
casting doesn't need to be a table. Tables are slow compared to integers, even if you reuse them. If you need to count stuff, a number is more than enough. Just make casting = 0 when not in combat and increase it by 1 when in combat.
Thank you for feedback everyone, in the end after your suggestions and some research my code looks like this and works great:
function()
local spell, _, _, _, startTime, endTime, _, _, _ = UnitCastingInfo("player")
local inCombat = UnitAffectingCombat("player")
local inLockdown = InCombatLockdown()
local _, duration, _, _ = GetSpellCooldown("Fireball")
casting = casting or {}
local sum = 0
if inCombat == 1 or inLockdown == 1 then
if spell or duration ~= 0 then
casting[#casting+1] = 1
elseif spell == nil or duration == 0 then
casting[#casting+1] = 0
end
else
local next = next
local k = next(casting)
while k ~= nil do
casting[k] = nil
k = next(casting, k)
end
end
for i=1, #casting, 1 do
sum = sum + casting[i]
end
return(("%.1f"):format( (sum / #casting)*100 ).. "%%") end
what i noticed is there was a problem with reseting the table in the original code:
for k in pairs (casting) do
casting [k] = nil
it seemed like either some zeros stayed there, or the table size didnt "shrink" i dont know.
Maybe intereger would be faster then a table, but honestly i dont see any performance issues even when the table gets ridicolously big (5 min, 60 fps, thats 18k inputs) also for the sake of learning a new language its better to do it harder way in my opinion
Regards
How can I check if the value in cell #0 is equal to the value in cell #1? I am trying to write code equivalent to:
if(a == b)
{
//do stuff
}
else
{
//do something else
}
I have read Brainfuck compare 2 numbers as greater than or less than, and the second answer gave me a general idea of what I'd need to do, but I cannot figure it out. (That solution gives if a < b, else.)
I am thinking I need to do something along the lines of decrementing both values, and if they reach 0 at the same time, then they are true. But I keep getting stuck at the same exit point every time I think about it.
How can I check if two cells are equal in brainfuck?
I think I have it, I'm not a brainfuck expert but this question looked interesting. There might be a simpler way to do it, but I went with your method of decrementing values one by one.
In this case, if the two values in cell 0 and 1 are equal jump a ton forward, if they are not equal jump a little forward (second brackets is the not equal case, third brackets is the equal case)
Note that I'm using brainfucks while statements as a ghetto if (cell != 0)
+++++++++++++++++
>
+++++++++++++++++
>+<
[ - < - >] <[>>>>>] >> [>>>>>>>>>>>>>>>>>>>>>]
Try it online: http://fatiherikli.github.io/brainfuck-visualizer/#KysrKysrKysrKysrKysrKysKPgorKysrKysrKysrKysrKysrKwo+KzwKWyAtIDwgLSA+XSA8Wz4+Pj4+XSA+PiBbPj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+XQoKCg==
An example implementation, print T (true) if the two values are equal, F (false) if they are not equal
http://fatiherikli.github.io/brainfuck-visualizer/#KysrCj4KKysrKwo+KzwKWyAtIDwgLSA+XSA8Wz4+PgorKysrKysrKysrKysrKysrKysrKworKysrKysrKysrKysrKysrKysrKworKysrKysrKysrKysrKysrKysrKworKysrKysrKysrCi4KPgoKXSA+PiBbCisrKysrKysrKysrKysrKysrKysrCisrKysrKysrKysrKysrKysrKysrCisrKysrKysrKysrKysrKysrKysrCisrKysrKysrKysrKysrKysrKysrCisrKwouCj4KXQ==
+>>(a+++++)>(b+++++)>>+<<<
[[->]<<]
<
[>>>>>-<<<<<
a>b
]
>>
[->>-<
a<b
]
>>
[-
a=b
]
Pointer ends on the same pointer in the same state but the code within the appropriate brackets has been executed.
I came up with this for my bf compiler thing
basically it subtracts and then checks if the result is 0.
Can be easily changed to execute stuff in if/else-ish way
Layout:
[A] B
>[-<->]+<[>-<[-]]>
Output
0 [result]
Result is 1 if equal
I've been messing around with this code for much longer than necessary. I'm changing to change the value of a dictionary entry depending on a person's choice.
while points <= 10:
print "You have " + str(points) + " points left.\n"
stats = {
"Strength": 0,
"Dexterity": 0,
"Constitution": 0,
"Intelligence": 0,
"Wisdom": 0,
"Charisma": 0
}
for i in sorted(stats):
print i + ": \t" + str(stats[i])
statInc = raw_input("\nWhere do you want to put your points? ").capitalize()
if statInc in stats:
points -= 1
stats[statInc] += 1
I started off with the stats[statInc] as a if/elif that specifies the strings by name. I can't get the values to change, but the point number will decrease accordingly. I know this because I originally had points set to 10.
I've never had this problem before with my other codes that revolved around dictionaries and their values. But I've tried tackling this from every angle and I feel like an idiot.
Nothing is changing because you are setting stats to {"Strength": 0,"Dexterity": 0,"Constitution": 0,"Intelligence": 0,"Wisdom": 0,"Charisma": 0} within your while loop. Every time it loops around, it will recreate stats, making it appear like it never changed.
The way to fix this would be to put the stats = {"Strength": 0,"Dexterity": 0,"Constitution": 0,"Intelligence": 0,"Wisdom": 0,"Charisma": 0} line before you enter your while loop.
You're re-instantiating your dictionary every time the loop evaluates. Move your initial stats declaration out of your loop (before it) so those values aren't reset continuously.
Note that you'll also want to test for while points > 0 instead of points <= 10 since you're starting at 10 and decrementing rather than starting at 0 and incrementing. You could also just test your max points value against sum(stats.values()) to be sure you're getting the current sum rather than using a counter variable, though in this case it doesn't really matter.
Ok guys, as requested, I will add more info so that you understand why a simple vector operation is not possible. It's not easy to explain in few words but let's see. I have a huge amount of points over a 2D space.
I divide my space in a grid with a given resolution,say, 100m. The main loop that I am not sure if it's mandatory or not (any alternative is welcomed) is to go through EACH cell/pixel that contains at least 2 points (right now I am using the method quadratcount within the package spatstat).
Inside this loop, thus for each one of this non empty cells, I have to find and keep only a maximum of 10 Male-Female pairs that are within 3 meters from each other. The 3-meter buffer can be done using the "disc" function within spatstat. To select points falling inside a buffer you can use the method pnt.in.poly within the SDMTools package. All that because pixels have a maximum capacity that cannot be exceeded. Since in each cell there can be hundreds or thousands of points I am trying to find a smart way to use another loop/similar method to:
1)go trough each point at a time 2)create a buffer a select points with different sex 3)Save the closest Male-Female (0-1) pair in another dataframe (called new_colonies) 4)Remove those points from the dataframe so that it shrinks and I don't have to consider them anymore 5) as soon as that new dataframe reaches 10 rows stop everything and go to the next cell (thus skipping all remaining points. Here is the code that I developed to be run within each cell (right now it takes too long):
head(df,20):
X Y Sex ID
2 583058.2 2882774 1 1
3 582915.6 2883378 0 2
4 582592.8 2883297 1 3
5 582793.0 2883410 1 4
6 582925.7 2883397 1 5
7 582934.2 2883277 0 6
8 582874.7 2883336 0 7
9 583135.9 2882773 1 8
10 582955.5 2883306 1 9
11 583090.2 2883331 0 10
12 582855.3 2883358 1 11
13 582908.9 2883035 1 12
14 582608.8 2883715 0 13
15 582946.7 2883488 1 14
16 582749.8 2883062 0 15
17 582906.4 2883317 0 16
18 582598.9 2883390 0 17
19 582890.2 2883413 0 18
20 582752.8 2883361 0 19
21 582953.1 2883230 1 20
Inside each cell I must run something according to what I explained above..
for(i in 1:dim(df)[1]){
new_colonies <- data.frame(ID1=0,ID2=0,X=0,Y=0)
discbuff <- disc(radius, centre=c(df$X[i], df$Y[i]))
#define the points and polygon
pnts = cbind(df$X[-i],df$Y[-i])
polypnts = cbind(x = discbuff$bdry[[1]]$x, y = discbuff$bdry[[1]]$y)
out = pnt.in.poly(pnts,polypnts)
out$ID <- df$ID[-i]
if (any(out$pip == 1)) {
pnt.inBuffID <- out$ID[which(out$pip == 1)]
cond <- df$Sex[i] != df$Sex[pnt.inBuffID]
if (any(cond)){
eucdist <- sqrt((df$X[i] - df$X[pnt.inBuffID][cond])^2 + (df$Y[i] - df$Y[pnt.inBuffID][cond])^2)
IDvect <- pnt.inBuffID[cond]
new_colonies_temp <- data.frame(ID1=df$ID[i], ID2=IDvect[which(eucdist==min(eucdist))],
X=(df$X[i] + df$X[pnt.inBuffID][cond][which(eucdist==min(eucdist))]) / 2,
Y=(df$Y[i] + df$Y[pnt.inBuffID][cond][which(eucdist==min(eucdist))]) / 2)
new_colonies <- rbind(new_colonies,new_colonies_temp)
if (dim(new_colonies)[1] == maxdensity) break
}
}
}
new_colonies <- new_colonies[-1,]
Any help appreciated!
Thanks
Francesco
In your case I wouldn't worry about deleting the points as you go, skipping is the critical thing. I also wouldn't make up a new data.frame piece by piece like you seem to be doing. Both of those things slow you down a lot. Having a selection vector is much more efficient (perhaps part of the data.frame, that you set to FALSE beforehand).
df$sel <- FALSE
Now, when you go through you set df$sel to TRUE for each item you want to keep. Just skip to the next cell when you find your 10. Deleting values as you go will be time consuming and memory intensive, as will slowly growing a new data.frame. When you're all done going through them then you can just select your data based on the selection column.
df <- df[ df$sel, ]
(or maybe make a copy of the data.frame at that point)
You also might want to use the dist function to calculate a matrix of distances.
from ?dist
"This function computes and returns the distance matrix computed by using the specified distance measure to compute the distances between the rows of a data matrix."
I'm assuming you are doing something sufficiently complicated that the for-loop is actually required...
So here's one rather simple approach: first just gather the rows to delete (or keep), and then delete the rows afterwards. Typically this will be much faster too since you don't modify the data.frame on each loop iteration.
df <- generateTheDataFrame()
keepRows <- rep(TRUE, nrow(df))
for(i in seq_len(nrow(df))) {
rows <- findRowsToDelete(df, df[i,])
keepRows[rows] <- FALSE
}
# Delete afterwards
df <- df[keepRows, ]
...and if you really need to work on the shrunk data in each iteration, just change the for-loop part to:
for(i in seq_len(nrow(df))) {
if (keepRows[i]) {
rows <- findRowsToDelete(df[keepRows, ], df[i,])
keepRows[rows] <- FALSE
}
}
I'm not exactly clear on why you're looping. If you could describe what kind of conditions you're checking there might be a nice vectorized way of doing it.
However as a very simple fix have you considered looping through the dataframe backwards?