Related
I have this python script that helps me with generating random combinations based upon odds, it could be used for harness racing when we have to pick the winning horse in 7 consecutive races.
Now I would like to refine this script a bit more to my wishes if possible. As already said the script now spits out random numbers based upon odds. Now I would like that to be done in a bit more distinguished manner. I don't want combinations with too many numbers corresponding with low odds. In other words, I want the script to select randomly 4 of the 7 races and come back with a random number with higher odds (+20%) for each of the 4 races. For the 3 remaining races it must give me numbers each with less than a 10% probability.
This all goes way beyond my own python knowledge so I was hoping to receive some help here.
Thx in advance for all useful input.
import bpy
import random
scene = bpy.context.scene
def get_random_value(race):
"""
Function which returns a String containing random values based on the given probability distribution
"""
# Generates an Array [1,2,3,...,amount_of_race_participants]
numberList = [x+1 for x in range(len(race))]
temp = ' '
for x in random.choices(numberList, weights=race, k=1):
temp = temp + str(x) + ","
temp1 = temp[0:-1] + ''
return temp1
def generate_text(iteration, race):
"""
Creates a Text Object with random content and a location based on the input value
Also gives race odds to the get_random_value function, which is used for the probability distribution
"""
# Create Curve with text content
font_curve = bpy.data.curves.new(type="FONT",name="Font Curve")
font_curve.body = get_random_value(race)
# Put Curve into Object and link it to the scene
font_obj = bpy.data.objects.new(name="Font Object", object_data=font_curve)
scene.collection.objects.link(font_obj)
# Set location of Object
font_obj.location = (0,-iteration,0)
return font_obj
def generate_n_texts():
"""
Creates a variable amount of Texts objects and returns them
"""
races = [
[5, 58, 4, 4, 8, 3, 3, 2, 5, 1, 6, 1 ],
[3, 4, 6, 5, 19, 4, 4, 2, 2, 21, 11, 19 ],
[12, 3, 6, 14, 6, 8, 4, 3, 18, 2, 1, 23 ],
[15, 4, 23, 4, 29, 4, 3, 5, 8, 5 ],
[9, 2, 12, 3, 4, 43, 5, 4, 3, 7, 1, 7 ],
[3, 3, 2, 4, 3, 61, 3, 2, 7, 11, 1 ],
[10, 3, 13, 31, 6, 14, 6, 9, 4, 2, 2 ]
]
font_objs = []
# enumerate goes through the array race and gives us an element and its index
for iteration, race in enumerate(races):
font_objs.append((generate_text(iteration, race), race))
# Font Objects includes tuples of font objects and their respective probability distribution
# like this [(obj, race), (obj, race), ...]
return font_objs
# Generate font_objs list before definint recalculate_text() so the function can use the list
font_objs = generate_n_texts()
def recalculate_text(scene):
"""
Sets the bodies of the font_objs list to a random number
"""
#Remove seed to get a different number for every frame, even when revisiting a frame
random.seed(scene.frame_current)
for obj, race in font_objs:
obj.data.body = get_random_value(race)
def register():
bpy.app.handlers.frame_change_post.append(recalculate_text)
def unregister():
bpy.app.handlers.frame_change_post.remove(recalculate_text)
register()
I have a list of integers that represent how many times an item has been used and I need to find the next number in the sequence that has been used the least amount of times (it might not even be in the list)
The amount of items is dynamic, the example uses 9 but that could be. Also, the amount of times it can appear is dynamic too.
We have X items, all of which are allowed to be used y times
Example.
We have 9 items, both of which are allowed to be used 2 times but should be used in order.
[1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2]
the above should return 3 as the next available item
[1, 2, 3, 4, 5]
the above should return 6 as the next available item
[1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9]
the above should return nothing, as there's no more available
I've already got me a function that's checking if the number appears at the max amount of uses
def is_item_available(item_number: int, uses: int, used_items: List):
"""Check if the item is available.
Args:
item_number (int): item number to be checked
uses (int): number of uses allowed
used_items (list): list of items currently used in a session
Returns:
bool: returns True if used item count is less than the uses number
"""
return used_items.count(item_number) < uses
I think this function works, if the numbers are guaranteed to be from 1-9:
def next_item(used_items):
if (used_items[-1] == 9 and len(used_items) == 18):
return "nothing"
elif (used_items[-1] == 9):
return 1
else:
return used_items[-1] + 1
Most optimal solution would be to use a min-heap to store the online data and fetch the top of the heap:
import collections, heapq
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2]
## Counter will maintain the count of each element in the list
counter = collections.Counter(lst)
## We now create a min-heap with (counter.count, list.val) as elements
heap = [(value, key) for key,value in dict(counter).items()]
## Now fetch the top element from the min-heap. By definition, this would correspond to the minimum list.val with minimum count
smallest_element = heapq.nsmallest(1, heap)
## If the list.val is already been used twice, return "None" else return the list.val
if smallest_element[0] > 1:
return None
return smallest_element[1]
This is question for my interview.
Write a recursive function that does the following:
Input: An array A of length N. N is an even number and N >= 2.
Output: A reordered array B. The first half of B contains A’s elements with even indices. The second half of B contains A’s elements with odd indices. Convention: the first index of an array is 0 (and thus it is an even number).
Input 1: [4, 8, 12, 16]
For this array, the indices and the values are as follows:
Index: 0, 1, 2, 3
Value: 4, 8, 12, 16
Thus, the output is as follows:
Expected output 1: [4, 12, 8, 16]
ADDITIONAL TEST CASE
Input 2: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Expected output 2: [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
TASK
Write a recursive function in a programming language of your choice (as if you are writing real code to be used on a production server) for the above problem
In addition to the main function, you are free to write helper functions (if needed)
The code should have as few lines as possible (but it should still be clear and readable)
Note: Your recursive function must show the 'spirit' of a recursive function (not just the recursive form of a for loop)
Here is my code:
def slove(array, deep=0):
'''para:
array: list input.
return: list.
!!!Do not set value for deep!!!'''
if len(array) > 2:
if deep > 0:
for i in xrange(0, len(array), 2):
array[i], array[i + 1] = array[i + 1], array[i]
left = array[0]
right = array[-1]
array = array[1:-1]
array = slove(array, deep + 1)
array.insert(0, left)
array.append(right)
return array
else:
array[0], array[-1] = array[-1], array[0]
return array
if __name__ == '__main__':
array = map(int, raw_input('Enter array with sep is space key: ').split(' '))
# array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print slove(array)
He said that it is wrong because I use loop in program. He is correct? So how to solve it?
Why not just use slicing?
lst = [11,12,13,14,15,16]
lst[0::2] + lst[1::2]
Returns:
[11, 13, 15, 12, 14, 16]
This pseudocode function might help:
Let A[n] and B[n] be the 2 arrays where n is the size.
Then we will call the following method rearrange(0,0):
rearrange(int i, int j) {
b[j] = a[i];
b[j+n/2] = a[i+1];
if (j < n/2-1)
rearrange(i+2,j+1);
}
In this method, i jumps 2 times each therefore the odd items get stored in the first half of the output array. For the second half, j+n/2 saves the even items.
This is one (awkward) way to do it:
def even_odd_split(seq):
"""
>>> even_odd_split([4, 8, 12, 16])
[4, 12, 8, 16]
>>> even_odd_split([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
[1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
"""
assert(len(seq) % 2 == 0)
assert(len(seq) > 1)
def _split(seq):
if len(seq) == 0: return [], []
a, b = _split(seq[2:])
return [seq[0]] + a, [seq[1]] + b
a, b = _split(seq)
return a + b
if __name__ == '__main__':
import doctest
doctest.testmod()
I would solve it like this:
def f(l):
if len(l) == 1:
# only one element left
return l
if len(l) % 2 == 0:
# length is even
return l[:1] + f(l[1:])
else:
# length is odd
return f(l[1:]) + l[:1]
Every invocation of the function removes one element from the list and either puts it at the beginning or at the end of the resulting list.
It does not produce the given “expected” outputs, because the elements of the list appear in another order than they appear in the input list, but it matches the specification… and also, I think it’s pretty simple.
In Python, I have several lists that look like variations of:
[X,1,2,3,4,5,6,7,8,9,X,11,12,13,14,15,16,17,18,19,20]
[X,1,2,3,4,5,6,7,8,9,10,X,12,13,14,15,16,17,18,19,20]
[0,X,2,3,4,5,6,7,8,9,10,11,X,13,14,15,16,17,18,19,20]
The X can fall anywhere. There are criteria where I put an X, but it's not important for this example. The numbers are always contiguous around/through the X.
I need to renumber these lists to meet a certain criteria - once there is an X, the numbers need to reset to zero. Each X == a reset. Each X needs to become a zero, and counting resumes from there to the next X. Results I'd want:
[0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,10]
[0,1,2,3,4,5,6,7,8,9,10,0,1,2,3,4,5,6,7,8,9]
Seems like a list comprehension of some type or a generator could help me here, but I can't get it right.
I'm new and learning - your patience and kindness are appreciated. :-)
EDIT: I'm getting pummeled with downvotes, like I've reposted on reddit or something. I want to be a good citizen - what is getting me down arrows? I didn't show code? Unclear question? Help me be better. Thanks!
Assuming the existing values don't matter this would work
def fixList(inputList, splitChar='X'):
outputList = inputList[:]
x = None
for i in xrange(len(outputList)):
if outputList[i] == splitChar:
outputList[i] = x = 0
elif x is None:
continue
else:
outputList[i] = x
x += 1
return outputList
eg
>>> a = ['X',1,2,3,4,5,6,7,8,9,'X',11,12,13,14,15,16,17,18,19,20]
>>> fixList(a)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> b = ['y',1,2,3,4,5,6,7,8,9,10,'y',12,13,14,15,16,17,18,19,20]
>>> fixList(b, splitChar='y')
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
EDIT: fixed to account for the instances where list does not start with either X or 0,1,2,...
Using the string 'X' as X and the_list as list:
[0 if i == 'X' else i for i in the_list]
This will return the filtered list.
My program does not return the correct question in the end but it shows correct ones in the intermediate results. I needs help, thanks.
Output sample:
sort begin: A,start,end [3, 5, 2, 1, 7, 6, 8, 4] 0 7
sort begin: A,start,end [2, 1, 3, 5, 7, 6, 8, 4] 0 1
sort begin: A,start,end [1, 2, 3, 5, 7, 6, 8, 4] 3 7
sort begin: A,start,end [1, 2, 3, 4, 5, 6, 8, 7] 3 3
sort begin: A,start,end [1, 2, 3, 4, 5, 6, 8, 7] 5 7
sort begin: A,start,end [1, 2, 3, 4, 5, 6, 8, 7] 5 4
sort begin: A,start,end [1, 2, 3, 4, 5, 6, 8, 7] 6 7
####################################################
final result [1, 2, 3, 5, 4, 6, 8, 7]
My code:
def qSort(A,start,end):
print "sort begin: A,start,end",A,start,end
if start >= end:
return A
elif end == start + 1:
if A[start] > A[end]:
A[start],A[end] = A[end],A[start]
return A
else:
i = start + 1
j = i
p = A[start]
while j < end:
j = j + 1
if p > A[j]:
A[i],A[j] = A[j],A[i]
i = i + 1
A = A[0:start] + A[start+1:i]+ [p] + A[i:end+1]
qSort(A,start,i-2)
qSort(A,i,end)
return A
print "###################"
myarray = [3,5,2,1,7,6,8,4]
result = qSort(myarray,0,7)
print "final result",result
Sorry for my lack luster comments. I reviewed your code and realized it was correct! You have one minor coding mistake which I will point out and then explain. In your else block you currently have:
else:
# Bunch of correct stuff
# ...
# Stuff that is ALMOST correct
qSort(A,start,i-2)
qSort(A,i,end)
return A
you need to change this to:
else:
# Bunch of correct stuff
# ...
# Stuff that is definitely correct
A = qSort(A,start,i-2)
A = qSort(A,i,end)
return A
Without going too deeply into this, your function does not discriminate between list references and newly created lists. If you put print A in you elif block right before return A you will notice that on the final iteration, your sort, as is, does everything correctly, and produces the correct list!
Unfortunately, the call that produced this change was one of the lines I've mentioned above which calls the sort but doesn't store the resulting list returned by the recursive function call!
My simple change just takes the modified list returned from secondary function calls to qSort and reassigns the variable A.
Weirdly, this behavior actually worked ok for you sometimes for reasons I cannot fully explain (like the first time you enter your `elif' block which does the right thing and modifies the list correctly). I am sure someone smarter than I surely can explain the odd behavior.
Alternatively, you could come up with a simple way to count recursion depth (number of times your function calls itself) and print that out while debugging with some breakpoints in your favorite IDE.
Heres how you could do that with global variables:
recursion_depth = -1
def qSort(A,start,end):
global recursion_depth
recursion_depth += 1
print "sort begin: A,start,end,level",A,start,end,recursion_depth
# bunch of code edited out for brevity
# ...
result = qSort(myarray,0,7)
print "final result",result