Generate a random array ignoring a selected value - python

In Python we can make a random array from 0 to 10 by doing:
randarray = random.sample(range(0, 10), 10)
My problem is that I want to create an array from 0 to 10, BUT in the first position I want to add a randomly generated number, and then append the rest of the numbers without repetition.
This means I first make:
first_value = random.randint(0,10)
and for example, if first_value is 4, I want to create a random array from 0 to 10 (without repetition) but ignoring number 4. For example, [0, 9, 5, 6, 1, 8, 7, 3, 2] . This is what I dont know how to do, so any help would be much appreciated.
Then I just want to append the first_value to randarray.
randarray.insert(0, first value)
So the desired output would be: [4, 0, 9, 5, 6, 1, 8, 7, 3, 2])

It sounds like you are really looking for a shuffled list:
>>> from random import shuffle
>>> xs = range(0, 10)
>>> shuffle(xs)
>>> xs
[2, 5, 4, 7, 1, 9, 3, 0, 6, 8]
For a more general way, use sample:
>>> from random import sample
>>> xs = sample(range(0, 10), 10)
If you actually do want to generate the head separately:
>>> from random import randint, sample
>>> x = randint(0, 10)
>>> p = range(0, 10)
>>> p.remove(x)
>>> xs = [x] + sample(p, 9)

Hope this helps -
first_value = random.randint(0, 10)
randarray = [i for i in random.sample(range(0, 10), 10) if i != first_value]
randarray.insert(0, first_value)

The way is:
you have a list
you have first number
remove number from list
shuffle list

Related

How to detect which random did I chose from only one list with random.choice()?

How can I detect which random number has been chosen from the list?
list = [3, 7, 5, 6, 3, 4, 1, 6]
random = random.choice(list)
print(random)
If random choice is 6, which 6 has been chosen from the list, how to know that?
I don't think you can.
import random
list = [3, 7, 5, 6, 3, 4, 1, 6]
total = len(list)
target = random.randint(0, total)
print(list[target])
print("this is number " + str(target) + " on the list")
You can do this instead.
Output:
6
this is number 3 on the list
#Bamar noted that you actually want target = random.randrange(0, total) for the reasons explained.
You can bypass the problem by indexing the original list and apply the random choice to it. In this particular case, with seeds' value equal to 26 and 27 to equal values are found but at different positions.
l = [3, 7, 5, 6, 3, 4, 1, 6]
import random
#random.seed(26)
random.seed(27)
index, random_value = random.choice(list(enumerate(l)))
print(f'index: {index}, value: {random_value}')
Output
index: 7, value: 6 # seed 27
index: 3, value: 6 # seed 26

Using a list to multiply a value?

n1 = 20*values[0]
n2 = 100*values[1]
print(n1,"\n",n2)
I've basically got a list above this, with a few values, only if I would have
currently if i have 3 in the first value and 7 in the second, 3 would show up 20 times, and 7 would show up 100 times,
however i would like it to be just multiplied.
Is there any way to do this without importing anything?
--edited again--
I Should have said this much sooner but i didn't realise inputted values would change anything, or factor into anything of this
top of the code i have:
for num in numbers:
values.append(num)
with values being an empty list, and "numbers" is the Input
I think this is what you want
>>> values = [3,7]
>>> n1 = 20 * [values[0]]
>>> n2 = 5 * [values[1]]
>>> print n1
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
>>> print n2
[7, 7, 7, 7, 7]
number * list_value = product
In [1752]: values = [3, 7]
In [1753]: 20 * values[0]
Out[1753]: 60
When you multiply by an int, the math functions take over. However, in order for repetition, just convert to a str then multiply:
n1 = 20*str(values[0])
n2 = 100*str(values[1])
print(n1,"\n",n2)
If you have a list of values and another list of numbers to multiply the corresponding values with:
values = [12, 14]
multiples = [20, 100]
Then, you can get what you want with:
result = [value * multiple for value, multiple in zip(values, multiples)]
See zip and list comprehensions.
If, on the other hand, you want to repeat the elements in values by the elements in multiples, you can do:
def repeat(values, repeats):
for value, rep in zip(values, repeats):
for _ in range(rep):
yield value
Now, you can use repeat() as a generator to do what you want:
>>> list(repeat([3, 7], [5, 10])
[3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7]

Python - Remove between indexes of two values if it occurs twice in a list

Title is definitely confusing, so here's an example: Say I have a list of values [1,2,3,2,1,4,5,6,7,8]. I want to remove between the two 1s in the list, and by pythonic ways it will also end up removing the first 1 and output [1,4,5,6,7,8]. Unfortunately, due to my lack of pythonic ability, I have only been able to produce something that removes the first set:
a = [1,2,3,2,1,4,5,6,7]
uniques = []
junks = []
for value in a:
junks.append(value)
if value not in uniques:
uniques.append(value)
for value in uniques:
junks.remove(value)
for value in junks:
a.remove(value)
a.remove(value)
a[0] = 1
print(a)
[1,4,5,6,7]
Works with the first double occurrence and will not work with the next occurrence in a larger list. I have an idea which is to remove between the index of the first occurrence and the second occurrence which will preserve the second and not have me do some dumb thing like a[0] = 1 but I'm really not sure how to implement it.
Would this do what you asked:
a = [1, 2, 3, 2, 1, 4, 5, 6, 7, 8]
def f(l):
x = l.copy()
for i in l:
if x.count(i) > 1:
first_index = x.index(i)
second_index = x.index(i, first_index + 1)
x = x[:first_index] + x[second_index:]
return x
So the output of f(a) would be [1, 4, 5, 6, 7, 8] and the output of f([1, 2, 3, 2, 1, 4, 5, 6, 7, 8, 7, 6, 5, 15, 16]) would be [1, 4, 5, 15, 16].
if you want to find unique elements you can use set and list
mylist = list(set(mylist))
a = [1, 2, 3, 2, 1, 4, 5, 6, 7, 8, 7, 6, 5, 15, 16]
dup = [x for x in a if a.count(x) > 1] # list of duplicates
while dup:
pos1 = a.index(dup[0])
pos2 = a.index(dup[0], pos1+1)
a = a[:pos1]+a[pos2:]
dup = [x for x in a if a.count(x) > 1]
print a #[1, 4, 5, 15, 16]
A more efficient solution would be
a = [1, 2, 3, 2, 1, 4, 5, 6, 7, 8, 7, 6, 5, 15, 16]
pos1 = 0
while pos1 < len(a):
if a[pos1] in a[pos1+1:]:
pos2 = a.index(a[pos1], pos1+1)
a = a[:pos1]+a[pos2:]
pos1 += 1
print a #[1, 4, 5, 15, 16]
(This probably isn't the most efficient way, but hopefully it helps)
Couldn't you just check if something appears twice, if it does you have firstIndex, secondIndex, then:
a=[1,2,3,4,5,1,7,8,9]
b=[]
#do a method to get the first and second index of the repeated number then
for index in range(0, len(a)):
print index
if index>firstIndex and index<secondIndex:
print "We removed: "+ str(a[index])
else:
b.append(a[index])
print b
The output is [1,1,7,8,9] which seems to be what you want.
To do the job you need:
the first and the last position of duplicated values
all indexes between, to remove them
Funny thing is, you can simply tell python to do this:
# we can use a 'smart' dictionary, that can construct default value:
from collections import defaultdict
# and 'chain' to flatten lists (ranges)
from itertools import chain
a = [1, 2, 3, 2, 1, 4, 5, 6, 7]
# build dictionary where each number is key, and value is list of positions:
index = defaultdict(list)
for i, item in enumerate(a):
index[item].append(i)
# let's take first only and last index for non-single values
edges = ((pos[0], pos[-1]) for pos in index.values() if len(pos) > 1)
# we can use range() to get us all index positions in-between
# ...use chain.from_iterable to flatten our list
# ...and make set of it for faster lookup:
to_remove = set(chain.from_iterable(range(start, end)
for start, end in edges))
result = [item for i, item in enumerate(a) if i not in to_remove]
# expected: [1, 4, 5, 6, 7]
print result
Of course you can make it shorter:
index = defaultdict(list)
for i, item in enumerate([1, 2, 3, 2, 1, 4, 5, 6, 7]):
index[item].append(i)
to_remove = set(chain.from_iterable(range(pos[0], pos[-1])
for pos in index.values() if len(pos) > 1))
print [item for i, item in enumerate(a) if i not in to_remove]
This solution has linear complexity and should be pretty fast. The cost is
additional memory for dictionary and set, so you should be careful for huge data sets. But if you have a lot of data, other solutions that use lst.index will choke anyway, because they are O(n^2) with a lot of dereferencing and function calls.

I need to generate x random numbers in an interval from 1 to x but each number have to occur only once

I need to generate a random number, actually i need 70128 random numbers form 1 to 70128. Here is what I'm using:
index = numpy.random.randint(1,70128,70128)
The other thing is, that I need each number between 1 and 70128 to be generated only once.
This means that I need a list of 70128 random generated numbers between 1 and 70128 but each number have to occur only once.
You you need x random numbers between 1 and x that are all unique then you just want a shuffled range:
x = 70128
numbers = range(1, x + 1)
random.shuffle(numbers)
If you are using Python 3, you want to add a list() call to the range() result.
Demo on Python 2.7 with x = 10 for practicality:
>>> import random
>>> x = 10
>>> numbers = range(1, x + 1)
>>> random.shuffle(numbers)
>>> numbers
[5, 2, 6, 4, 1, 9, 3, 7, 10, 8]
Use numpy's random.permutation function, which, if given a single scalar argument x, will return a random permutation of the numbers from 0 to x. For instance:
np.random.permutation(10)
Gives:
array([3, 2, 8, 7, 0, 9, 6, 4, 5, 1])
So, in particular, np.random.permutation(70128) + 1 does precisely what you'd like.

Creating lists of random length in python

I am writing a program in python. In it, I want to generate a list. This list will start at one and increment by one [1, 2, 3, 4, 5, etc.].
However, I want the length of the list to be random, between 3 numbers and 8 numbers long. For example, on one run the list might generate [1, 2, 3, 4], on another it might generate 1, 2, 3, 4, 5, 6], another run might generate [1, 2, 3], and so on.
I know how to make a list generate random numbers but not so that it increments numbers at a random length. Thank you for your time. I am using Python 2.7 by the way.
Just
l1 = [ i + 1 for i in range(randint(...) ]
import random
start = 1
end = random.randint(3, 8)
l = range(start, end + 1)
An itertools approach - which also means if you don't need to materialise the list, then you don't have to:
from itertools import count, islice
from random import randint
mylist = list(islice(count(1), randint(3, 8)))
Since count is a generator incrementing by 1 each time, we use islice to "limit" the total number of items we take from it, and then build a list.
you can do it using range() where the first argument is the start and the second argument is the random length
import random
range(1, random.randint(3, 8))
If you specify 4 at the bottom end and 9 as the top of randint you'll get up to 8 numbers like you ask for. You need to do this because you start the range at 1.
>>> import random
>>> range(1, random.randint(4,4))
[1, 2, 3]
>>> range(1, random.randint(9,9))
[1, 2, 3, 4, 5, 6, 7, 8]
>>> rand_list = range(1, random.randint(4,9))
>>> rand_list
[1, 2, 3, 4, 5, 6, 7]
Range() first argument is the starting point. The 2nd argument is the stop. Many of the other answers will sometimes return only two numbers, in the cases where stop == 3.
>>> range(1,3)
[1, 2]
>>> range(1,4)
[1, 2, 3]
>>> range(1,8)
[1, 2, 3, 4, 5, 6, 7]
>>> range(1,9)
[1, 2, 3, 4, 5, 6, 7, 8]
from random import randint
l = range(1,randint(3,8)+1 )
print l

Categories

Resources