Say I have a list of numbers:
foo = [random.randint(0, 9) for n in range(10)]
and I have a function
def bar(lst):
total = 0
for i in lst:
total += i
if total % 4 == 0:
print "passed multiple of 4"
bar(foo)
How do I get the print statement to execute if total skips over a multiple of 4?
EDIT: say foo = [4,5], then total takes the values 0, 4, and 9. I want the print statement to execute twice, once for 4, which it does, and once for 8, which total "skips over" when it jumps from 4 to 9.
I want the print statement to execute twice, once for 4, which it does, and once for 8, which total "skips over" when it jumps from 4 to 9.
So basically, you do not want to check the modulus, but just whether the total passed a multiple of four.
Something like this:
def bar(lst):
total = 0
# keep track of the numbers we need to “pass” to print the notice; the first one is 4
passed = 4
for i in lst:
total += i
# when the total passed the number
while total >= passed:
# print the notice
print('passed multiple of 4, total is {0}'.format(total))
# and skip to the next number
passed += 4
>>> bar([4, 5])
passed multiple of 4, total is 4
passed multiple of 4, total is 9
>>> bar([1, 3, 4])
passed multiple of 4, total is 4
passed multiple of 4, total is 8
>>> bar([1, 12])
passed multiple of 4, total is 13
passed multiple of 4, total is 13
passed multiple of 4, total is 13
Related
I am still pretty new at programming and I would appreciate any help on how to approach the following problem:
Given a matrix (3x5)
a = [1 2 3 4 5;
6 7 8 9 10;
11 12 13 14 15;]
I want to iterate through every row
For each row, I want each element to be checked
With each element, I want to store a separate array that holds the element and the next 2 elements.
Ex:
Row 1 = [1 2 3 4 5]
For element 1
return newArray = [1 2 3]
For element 2
return newArray = [2 3 4]
Getting stuck on part 3. How to make the for loop check only up to the next 2 elements and then continue to the next element in the row.
I took a shot at solving what you asked for, but I agree with the others that you need to think more about what you are trying to do and what you want your output to look like. Your request does not sound like something a beginner programmer would realistically use. I am not sure what shape you want to store your "separate array"s in. I have options below for keeping them in a vector or in the original shape of a.
function nexttwo(row, i)
newarray::Vector{Any} = [row[i]]
for j=1:2
i+=1
if length(row) >= i
push!(newarray, row[i])
else
push!(newarray, nothing)
end
end
return newarray
end
function collectnexttwo(a)
result_collection = []
for i in axes(a,1)
for j in axes(a,2)
row = a[i,:]
newarray = nexttwo(row, j)
push!(result_collection, newarray)
end
end
return result_collection
end
function restoreshape(v, a)
permutedims(reshape(v, reverse(size(a))))
end
julia> a = [1 2 3 4 5; 6 7 8 9 10; 11 12 13 14 15;]
3×5 Matrix{Int64}:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
julia> result = restoreshape(collectnexttwo(a), a)
3×5 Matrix{Any}:
Any[1, 2, 3] Any[2, 3, 4] Any[3, 4, 5] Any[4, 5, nothing] Any[5, nothing, nothing]
Any[6, 7, 8] Any[7, 8, 9] Any[8, 9, 10] Any[9, 10, nothing] Any[10, nothing, nothing]
Any[11, 12, 13] Any[12, 13, 14] Any[13, 14, 15] Any[14, 15, nothing] Any[15, nothing, nothing]
I think that you have some problems with the statement of what you want to achieve. That can often make a programming assignment much harder.
Restating what you have already:
I want to iterate through every row
This is pretty easy
for row = 1:size(a)[1]
...
end
For each row, I want each element to be checked
This is where things begin to get squishy? What do you mean by "checked". Let's assume you have some function called checkElement.
With each element, I want to store a separate array that holds the element and the next 2 elements.
How long do you want that separate array to live? Do you just want to hold 3 elements? Or three elements for every cell of the original (i.e. have a 3x5x3 result for a 3x5 input like you show)
Also, what do you want to do about elements 4 and 5 in each row? What values do you want to use for their "next" elements? You could use missing as a value or NaN. Or you could make the result just not contain the problematic inputs.
If you answer these questions, you are likely to find it much easier to write the code you need.
I'm hoping there is SPSS syntax that I can use to randomly select a number from among a couple of variables. For example: the data lists the ages of respondent's children in four variables - Age1 Age2 Age3 Age4
Resp 1: 3 6 8
Resp 2: 2 10
Resp 3: 4
I want to create a variable that stores a randomly selected age for each respondent - something like:
Resp 1: 6
Resp 2: 2
Resp 3: 4
The code I'm using at the moment:
COUNT kids=age1 to age4 (1 thru 16).
COMPUTE rand=RND(RV.UNIFORM(1, kids),1).
DO REPEAT
x1=age1 to age4
/x2=1 to 4.
IF (rand=x2) random_age=x1.
END REPEAT.
Here is my suggested code for the task.
First creating some sample data to demonstrate on:
data list list/id age1 to age4 (5f2).
begin data
1, 4, 5, 6, 7
2, 4, 5, 6,
3, 6, 7,,
4, 8,,,
5, 5, 6, 7,
6, 10,,,
end data.
Now to randomly select one of the ages:
compute numages=4-nmiss(age1 to age4).
compute SelectThis = rnd(uniform(numages)+.5).
do repeat ag=age1 to age4 /ind=1 to 4.
if SelectThis=ind SelectedRandAge=ag.
end repeat.
exe.
Well, here's my attempt for the time being:
data list list /age1 to age4.
begin data.
10 9 5 8
3
13 15
1 4 5
4 7 8 2
end data.
count valid=age1 to age4 (lo thru hi).
compute s=trunc(1+uniform(valid)).
vector age=age1 to age4.
compute myvar=age(s).
list age1 to age4 myvar.
The problem is the following:
1) Total load is given as input
2) Number of steps over which the load is divided is also given as input
3) Each step can have different discrete number of elements, which is multiple of 3 for example (i.e. 3, 6, 9, 12, 15 elements ...).
4) Elements are given as input.
5) Acceptable solutions are within a certain range "EPSILON" from the total load (equal to total load or greater but within certain margin, for example up to +2)
Example:
Total load: 50
Number of steps: 4
Allowed elements that can be used are: 0.5, 1, 1.5, 2.5, 3, 4
Acceptable margin: +2 (i.e. total load between 50 and 52).
Example of solutions are:
For simplicity here, each step has uniform elements, although we can have different elements in the same step (but should be grouped into 3, i.e. we can have 3 elements of 1, and 3 other elements of 2, in the same step, so total of 9).
Solution 1: total of 51
Step 1: 3 Elements of 4 (So total of 12), (this step can be for example 3 elements of 3, and 3 elements of 1, i.e. 3 x 3 + 3 x 1).
Step 2: 3 Elements of 4 (total of 12),
Step 3: 9 Elements of 1.5 (total of 13.5),
Step 4: 9 Elements of 1.5 (total of 13.5),
Solution 2: total of 51
Step 1: 3 Elements of 4 (total of 12)
Step 2: 3 Elements of 4 (total of 12)
Step 3: 6 Elements of 2 (total of 12)
Step 4: 15 Elements of 1 (total of 15)
The code that I used takes the above input, and writes another code depending on the number of steps.
The second code basically loops over the number of steps (loops inside each other's) and checks for all the possible elements combinations.
Example of loops for 2 steps solution:
Code:
For NumberofElementsA = 3 To 18 Step 3
'''''18 here is the maximum number of elements per step, since I cannot let it go to infinity, so I need to define a maximum for elemnt
For NumberofElementsB = 3 To 18 Step 3
For AllowedElementsA = 1 To 6
For AllowedElementsB = AllowedElementsA To 6
''''Allowed elements in this example were 6: [0.5, 1, 1.5, 2.5, 3, 4]
LoadDifference = -TotalLoad + NumberofElementsA * ElementsArray(AllowedElementsA) + NumberofElementsB * ElementsArray(AllowedElementsB)
''''basically it just multiplies the number of elements (here 3, 6, 9, ... to 18) to the value of the element (0.5, 1, 1.5, 2.5, 3, 4) in each loop and subtracts the total load.
If LoadDifference <= 2 And LoadDifference >= 0
'''Solution OK
End If
Next AllowedElementsB
Next AllowedElementsA
Next NumberofElementsB
Next NumberofElementsA
So basically the code loops over all the possible number of elements and possible elements values, and checks each result.
Is there an algorithm that solves in a more efficient way the above problem ? Other than looping over all possible outcomes.
Since you're restricted to groups of 3, this transforms immediately to a problem with all weights tripled:
1.5, 3, 4.5, 7.5, 9, 12
Your range is a target value +2, or within 1 either way from the midpoint of that range (51 +- 1).
Since you've listed no requirement on balancing step loads, this is now an instance of the target sum problem -- with a little processing before and after the central solution.
Simple question but, I see exclusive and inclusive when referring to number ranges.
For example, this is a line from an algorithms book:
The following function prints the powers of 2 from 1 through n (inclusive).
What is meant by this? What makes a number range inclusive or exclusive?
In Computer Science, inclusive/exclusive doesn't apply to algorithms, but to a number range (more specifically, to the endpoint of the range):
1 through 10 (inclusive)
1 2 3 4 5 6 7 8 9 10
1 through 10 (exclusive)
1 2 3 4 5 6 7 8 9
In mathematics, the 2 ranges above would be:
[1, 10]
[1, 10)
You can remember it easily:
Inclusive - Including the last number
Exclusive - Excluding the last number
The following function prints the powers of 2 from 1 through n (inclusive).
This means that the function will compute 2^i where i = 1, 2, ..., n, in other words, i can have values from 1 up to and including the value n. i.e n is Included in Inclusive
If, on the other hand, your book had said:
The following function prints the powers of 2 from 1 through n (exclusive).
This would mean that i = 1, 2, ..., n-1, i.e. i can take values up to n-1, but not including, n, which means i = n-1 is the highest value it could have.i.e n is excluded in exclusive.
In simple terms, inclusive means within and the number n, while exclusive means within and without the number n.
Note: that each argument should be marked its "clusivity"/ "participation"
# 1 (inclusive) through 5 (inclusive)
1 <= x <= 5 == [1, 2, 3, 4, 5]
# 1 (inclusive) through 5 (exclusive)
1 <= x < 5 == [1, 2, 3, 4]
# 1 (exclusive) through 5 (inclusive)
1 < x <= 5 == [2, 3, 4, 5]
# 1 (exclusive) through 5 (exclusive)
1 < x < 5 == [2, 3, 4]
The value of n inclusive 2 and 5 [2,5]
including both the numbes in case exclusive only the first is included
programming terms n>=2 && n<=5
The value of of n exlcusive of 2 and 5 [2,5)
n>=2 && n<5
I am trying to remove all 7s from an array:
a = [1,2,3,4,5,7,7,7,7,7,7,7,7,7,9,10,11,12,13]
I did:
a.each_with_index do |item, index|
if item == 7
a.delete_at(index)
end
end
a # => [1, 2, 3, 4, 5, 7, 7, 7, 7, 9, 10, 11, 12, 13]
How did this happen?
The fact that only about half (5/9) of your items have disappeared is a dead giveaway that the problem is deleting while iterating over the collection.
The iteration will be processing indexes 1, 2, 3, 4 and so on. If you delete index 2 while processing it, that will shift all later indexes down by one.
So, when you then move on to index 3 in the next iteration, you will skip the original index 3 because that will have been shifted down to index 2.
In other words, let's start with a simpler example with two consecutive items to remove:
index | 0 | 1 | 2 | 3 |
value | 1 | 7 | 7 | 9 |
You check the first index and the value is 1 so you do nothing. You then check the second index and the value is 7 so you delete it, giving:
index | 0 | 1 | 2 |
value | 1 | 7 | 9 |
You then check the third index and the value is 9 so you do nothing. You've also reached the end so it stops.
So you can see there that you actually skipped the second item you wanted to delete, because you shifted things around while iterating. This isn't a Ruby-specific problem, a great many languages have this same issue.
In general, each complete pair of adjacent items will only have the first of the pair deleted while an item on its own (not followed by another of the same value) will be deleted normally. That's why only 5/9 of your 7s are deleted, one for each of the four pairs and the final standalone one.
The correct way (in Ruby) to delete all items of a single given value is to use the array delete method:
a.delete(7)
You can also use conditional delete for more complex conditions such as deleting everything greater than 7:
a.delete_if {|val| val > 7}
And, if you really want to do it yourself (as an educational exercise), you just have to realise that the problem is because you process the array in a forward manner - when you do that, changes beyond where you're deleting may cause issues.
If you were to find some way to process the array in a backwards manner, this issue would not occur. Luckily, Ruby has such a beast:
a.to_enum.with_index.reverse_each do |item, index|
That line will process the array in such a way that deletions will not affect future operations. Just be aware that deleting while iterating can still be a problem if the data structure you're processing is not a simple indexed array.
I still warrant that delete and delete_if are the correct way to go since they're baked into Ruby already, and therefore incredibly unlikely to have bugs.
This happens because in each iteration you are updating/deleting the same array which you are looping through.
For this purpose, you should use this delete method:
a = [1,2,3,4,5,7,7,7,7,7,7,7,7,7,9,10,11,12,13]
a.delete(7)
# [1, 2, 3, 4, 5, 9, 10, 11, 12, 13]
You can see the problem by running this program:
a = [1,2,3,4,5,6]
a.each_with_index do |item, index|
puts "#{index} : #{item}"
if item == 4
a.delete_at(index)
end
end
Output:
0 : 1
1 : 2
2 : 3
3 : 4 # made delete here
4 : 6 # See the problem !
Hope it helps :)
In general, deleting from the Array you're iterating over, in any language, is going to get weird. To see why, look at the code for Array#each_index.
VALUE rb_ary_each_index(VALUE ary)
{
long i;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
for (i=0; i<RARRAY_LEN(ary); i++) {
rb_yield(LONG2NUM(i));
}
return ary;
}
Note that it's really a for loop from 0 to the length of the array. The loop will just count from 0 to the original length of the array.
When you delete an item from the array, everything after it shifts over 1. If i = 5 and you call a.delete_at(i) that means a[6] is now a[5]. a[7] is now a[6]. And so on. Next iteration will have i = 6 which means you effectively skipped an element.
To illustrate, and assuming you want to delete 2.
i = 0
a = [1,2,2,2,3,4,5]
^
-------------------
i = 1
a = [1,2,2,2,3,4,5]
^
a.delete_at(i)
a = [1,2,2,3,4,5]
-------------------
i = 2
a = [1,2,2,3,4,5]
^
a.delete_at(i)
a = [1,2,3,4,5]
-------------------
i = 3
a = [1,2,3,4,5]
^
-------------------
i = 4
a = [1,2,3,4,5]
^
-------------------
i = 5
a = [1,2,3,4,5]
-------------------
i = 6
a = [1,2,3,4,5]
Note that the last two iterations have walked off the array, because the array is now two elements smaller than it was before.