How to restrict the longest sequence of the same letter using python - python

How can I determine the longest sequence of the same letter using python?
For example I use the following code to print a shuffled list with 3 conditions A,B and C
from random import shuffle
condition = ["A"]*20
condition_B = ["B"]*20
condition_C = ["C"]*20
condition.extend(condition_B)
condition.extend(condition_C)
shuffle(condition)
print(condition)
Now i want to make sure that the same condition does not happen more than three times in a row.
E.g., allowed: [A, B, C, A, B, B, C, C, C, A, B….]
Not allowed: [A, A, B, B, B, B, C, A, B...] (because of four B’s in a row)
How can I solve this problem?
Thank you in advance.

Maybe you should build the list sequentially, rather than shuffling:
result = []
for i in range(60): # for each item in original list
start = true # we haven't found a suitable one yet
if start or i>2: # don't do checking unless 3 items in list
while start or (
c==shuf[-1] and # is the chosen value
c==shuf[-2] and # the same as any of
c==shuf[-3] ): # the last 3 items?
idx = random.randint(0,len(condition)) # chose a new one
c = condition[idx]
start = false
result.append(c) # add to result
del condition[i] # remove from list
Warning! not tested - just conceptual...

# Validate with this function it return false if more than three consecutive characters are same else True.
def isValidShuffle( test_condition):
for i in range(len(test_condition)-4):
if len(set(test_condition[ i:i+4])) == 1:
# set size will be 1 all four consecutive chars are same
return False
return True
Simplest way to create shuffled sequence of A,B,C for which isValidShuffle will return True.
from random import shuffle
# condition list contains 20 A's 20 B's 20 C's
seq = ['A','B','C']
condition = []
for seq_i in range(20):
shuffle(seq)
condition += seq
print(condition) # at most two consecutive characters will be same
print(isValidShuffle(condition))
-----------------------------------------------------------------------------
Output
['A', 'B', 'C', 'B', 'C', 'A', 'C', 'B', 'A', 'C', 'B', 'A', 'C', 'A', 'B', 'C', 'B', 'A', 'B', 'A', 'C', 'B', 'C', 'A', 'B', 'C', 'A', 'C', 'A', 'B', 'B', 'C', 'A', 'B', 'A', 'C', 'A', 'B', 'C', 'C', 'A', 'B', 'A', 'B', 'C', 'B', 'A', 'C', 'C', 'A', 'B', 'B', 'C', 'A', 'B', 'A', 'C', 'A', 'B', 'C']
...............................................................................................................................................................
This is not imposing your restriction while creating shuffled sequence but keeps on trying until it find the sequence which meets your consecutive char restriction.
validshuffle = False
condition = ['A']*20 + ['B']*20 + ['C']*20
while not validshuffle:
shuffle(condition)
if isValidShuffle(condition):
validshuffle = True
print(condition)
-------------------------------------------------------------------------------
Output
try
try
['A', 'C', 'A', 'B', 'B', 'C', 'B', 'C', 'A', 'C', 'A', 'C', 'B', 'B', 'B', 'C', 'A', 'A', 'B', 'C', 'A', 'A', 'B', 'B', 'C', 'B', 'B', 'C', 'B', 'C', 'C', 'B', 'A', 'B', 'B', 'A', 'C', 'A', 'A', 'C', 'A', 'C', 'B', 'C', 'A', 'A', 'C', 'A', 'C', 'A', 'C', 'B', 'B', 'B', 'A', 'B', 'C', 'A', 'C', 'A']

If you just want to know, how long is the longest subsequence, you could do this.
This is iterating over it the sequence and recording the length of the subsequences of the same character, saving it, getting the max for each subsequence, and then, getting the max of characters.
This is not exactly the problem you mention, but It could be useful.
from random import shuffle
sequence = ['A']*20 + ['B']*20 + ['C']*20
sequences = {'A': [], 'B':[], 'C':[]}
shuffle(sequence)
current = sequence[0]
acc = 0
for elem in sequence:
if elem == current:
acc += 1
else:
sequences[current].append(acc)
current = elem
acc = 1
else:
sequences[current].append(acc)
for key, seqs in sequences.items():
sequences[key] = max(seqs)
print(max(sequences.items(), key=lambda i: i[1]))

Related

How to get the same value for duplicates values in a list

I have 2 list (keywords, a):
keywords = ['a','b','c','d','j','i','k']
a = ['a','b','c','d','e','f','a','b','c','d','e','f']
What I need to achieve is that the values that are not in the keywords list in list a are replaced with var_x, but identical values must have the same value
Example:
a = ['a','b','c','d','e','f','a','b','c','d','e','f'] ---> ['a','b','c','d','var_1','var_2','a','b','c','d','var_1','var_2']
The problem I am having is that equal values have different values of var_x.
keywords = ['a','b','c','d','j','i','k']
a = ['a','b','c','d','e','f','a','b','c','d','e','f']
def replace_sub_b(sub_b):
bl = sub_b.split()
print(bl)
index = 0
rl = []
for c in bl:
if c in keywords:
rl.append(c)
else:
index += 1
rl.append(f'var_{index}')
return ' '.join(rl)
new_b = [replace_sub_b(sub_b) for sub_b in a]
new_b
['a', 'b', 'c', 'd', 'var_1', 'var_1', 'a', 'b', 'c', 'd', 'var_1', 'var_1']
and it should be: ['a', 'b', 'c', 'd', 'var_1', 'var_2', 'a', 'b', 'c', 'd', 'var_2', 'var_1']
Could you give me some clue or tip?
You can use a mapping dict to keep track of the name that each non-keyword maps to:
mapping = {}
for i, v in enumerate(a):
if v not in keywords:
if v not in mapping:
mapping[v] = f'var_{len(mapping) + 1}'
a[i] = mapping[v]
so that with your sample input, a becomes:
['a', 'b', 'c', 'd', 'var_1', 'var_2', 'a', 'b', 'c', 'd', 'var_1', 'var_2']

How to reverse a part of a list?

I have the next list:
abclist = ['a', 'b', 'c', 'd', 'e']
With the above list I how to create the next one?
Reversed_part = ['c', 'b', 'a', 'd', 'e']
Only the first 3 items are reversed and the last two stay in the same order.
This is one way.
lst = ['a', 'b', 'c', 'd', 'e']
def partial_reverse(lst, start, end):
"""Indexing (start/end) inputs begins at 0 and are inclusive."""
return lst[:start] + lst[start:end+1][::-1] + lst[end+1:]
partial_reverse(lst, 0, 2) # ['c', 'b', 'a', 'd', 'e']
abclist = ['a', 'b', 'c', 'd', 'e']
quantityToReverse = 3
remainder = len(abclist) - quantityToReverse
reverseArray = list(reversed(abclist[:quantityToReverse]))+abclist[-remainder:]
print(reverseArray)
You can do it using a combination of reversed method & string slicing
Ex:
abclist = ['a', 'b', 'c', 'd', 'e']
print(list(reversed(abclist[:3]))+abclist[-2:])
Output:
['c', 'b', 'a', 'd', 'e']

Create combinations from a list and 3 ranges using itertools

I have the following:
a_list = [A,B,C]
r1 = range(1,5)
r2 = range(1,5)
r3 = range(1,5)
I would like to be able to find the various combinations of the elements in this list against the ranges. For example:
combi1 = [A, B, C, C, C]
combi2 = [A, A, B, C, C]
combi3 = [A, A, A, B, C]
combi4 = [A, B, B, C, C]
Etc.
I am able to do so if there were only 2 range, but I'm not sure how to fit 3 range in.
inc = range(1, 5)
desc = range(5, 1, -1)
combis = [list(itertools.chain(*(itertools.repeat(elem, n) for elem, n in zip(list, [i,j])))) for i,j in zip(inc,desc)]
SOLUTION:
def all_exist(avalue, bvalue):
return all(any(x in y for y in bvalue) for x in avalue)
combins = itertools.combinations_with_replacement(a_list, 5)
combins_list = [list(i) for i in combins]
for c in combins_list:
if all_exist(a_list, c) == True:
print c
output:
['A', 'A', 'A', 'B', 'C']
['A', 'A', 'B', 'B', 'C']
['A', 'A', 'B', 'C', 'C']
['A', 'B', 'B', 'B', 'C']
['A', 'B', 'B', 'C', 'C']
['A', 'B', 'C', 'C', 'C']
#doyz. I think this is may be what you are looking for :
From a list abc = ['A','B','C'], you want to obtain its various combinations with replacement. Python has built-in itertools to do this.
import itertools
abc = ['A', 'B', 'C'];
combins = itertools.combinations_with_replacement(abc, 5);
combins_list = [list(i) for i in combins];
print(combins_list[0:10]);
This is the first 10 combinations with replacement :
[['A', 'A', 'A', 'A', 'A'], ['A', 'A', 'A', 'A', 'B'], ['A', 'A', 'A', 'A', 'C'], \
['A', 'A', 'A', 'B', 'B'], ['A', 'A', 'A', 'B', 'C'], ['A', 'A', 'A', 'C', 'C'], \
['A', 'A', 'B', 'B', 'B'], ['A', 'A', 'B', 'B', 'C'], ['A', 'A', 'B', 'C', 'C'], ['A', 'A', 'C', 'C', 'C']]
If you want to include all elements in abc, here is one way, that also includes the permutations :
import itertools
abc = ['A', 'B', 'C'];
combins = itertools.combinations_with_replacement(abc, 5);
combins_list = list(combins);
combins_all =[];
for i in combins_list:
if len(set(i))==len(abc):
combins_all.append(i);
print(combins_all);
include_permutations=[];
for i in combins_all:
permut = list(itertools.permutations(i));
include_permutations.append(permut);
print(include_permutations);
Is this okay?
*Note : itertools.combinations_woth_replacement and itertools.permutations do not result in a list, or tuple, but a different object itself, so you can't treat it as those.

using lambda or list comprehesion to create list with loop

for the following code, how I can write into one line using lambda function or using python list comprehension?
def f():
lst=[]
for i in range(1, 101):
if i < 50:
lst.append('A')
else:
lst.append('B')
return lst
You can use a ternary conditional in a list comprehension:
lst = ['A' if i < 50 else 'B' for i in range(1, 101)]
Note that your function outputs 49 'A's and 51 'B's. I'm not sure if that's intentional.
The easiest way to get 50/50 would be :
['A'] * 50 + ['B'] * 50
If you want to define a lambda:
>>> a_or_b = lambda x: 'AB'[x>50]
>>> [a_or_b(x) for x in range(1,101)]
['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B']
As a one-liner :
['AB'[x>50] for x in range(1,101)]
or
['AB'[x>=50] for x in range(100)]
Those comprehensions use the fact that False is 0 and True is 1, and that 'AB'[0] is 'A' and 'AB'[1]is'B'`.
The code, mirroring yours, would be like this:
def f():
return ['A' if i < 50 else 'B' for i in range(1,101)]

Comparing 2 lists and appending the differences into a 3rd

I have an issue and I can't for the life of me get anything to return past ()
exam_solution = ['B', 'D', 'A', 'A', 'C', 'A', 'B', 'A', 'C', 'D', 'B', 'C',\
'D', 'A', 'D', 'C', 'C', 'B', 'D', 'A']
student_answers = ['B', 'D', 'B', 'A', 'C', 'A', 'A', 'A', 'C', 'D', 'B', 'C',\
'D', 'B', 'D', 'C', 'C', 'B', 'D', 'A']
I need to compare the 2 lists and append the differences into questions_missed = []
I haven't found anything remotely close to working. Any help would be appreciated
edit: In python been stroking out over it all day.
use python list comprehensions to check list diff:
print [(index, i, j) for index, (i, j) in enumerate(zip(exam_solution, student_answers)) if i != j]
[(2, 'A', 'B'), (6, 'B', 'A'), (13, 'A', 'B')]
You can modify this solution to fit your needs:
exam_solution = ['B', 'D', 'A', 'A', 'C', 'A', 'B', 'A', 'C', 'D', 'B', 'C', 'D', 'A', 'D', 'C', 'C', 'B', 'D', 'A']
student_answers = ['B', 'D', 'B', 'A', 'C', 'A', 'A', 'A', 'C', 'D', 'B', 'C', 'D', 'B', 'D', 'C', 'C', 'B', 'D', 'A']
results = []
correct = 0
incorrect = 0
index = 0
while index < len(student_answers):
if student_answers[index] == exam_solution[index]:
results.append(True)
correct += 1
else:
results.append(False)
incorrect += 1
index += 1
print("You answered " + correct + " questions correctly and " + incorrect + " questions incorrectly.")
Using list comprehensions:
[x for i, x in enumerate(exam_solution) if exam_solution[i] != student_answers[i] ]
['A', 'B', 'A']
Assuming you want an output in common English like this -
Question 3 A != B
Question 7 B != A
Question 14 A != B
You could try -
from array import *
exam_solution = ['B', 'D', 'A', 'A', 'C', 'A', 'B', 'A', 'C', 'D', 'B', 'C',\
'D', 'A', 'D', 'C', 'C', 'B', 'D', 'A']
student_answers = ['B', 'D', 'B', 'A', 'C', 'A', 'A', 'A', 'C', 'D', 'B', 'C',\
'D', 'B', 'D', 'C', 'C', 'B', 'D', 'A']
questions_missed = []
count = 0
for answer in exam_solution:
if (answer != student_answers[count]):
questions_missed.append(count)
count = count + 1
for question in questions_missed:
print str.format("Question {0} {1} != {2}", question+1,
exam_solution[question], student_answers[question]);
Using the KISS design principle, that's how I'd do it:
exam_solution = ['B', 'D', 'A', 'A', 'C', 'A', 'B', 'A', 'C', 'D', 'B', 'C',\
'D', 'A', 'D', 'C', 'C', 'B', 'D', 'A']
student_answers = ['B', 'D', 'B', 'A', 'C', 'A', 'A', 'A', 'C', 'D', 'B', 'C',\
'D', 'B', 'D', 'C', 'C', 'B', 'D', 'A']
questions_missed = []
for index in range(len(exam_solution)):
# this assumes exam_solution and student_answers have the same size!
if exam_solution[index] != student_answers[index]:
questions_missed.append(index)
print (questions_missed)
And the output is:
[2, 6, 13]
L = [(a, b) for a, b in zip(exam_solution, student_answers) if a != b]
print(L)
Mybe you can use zip function.
The output is:
[('A', 'B'), ('B', 'A'), ('A', 'B')]
Solution (use set):
>>> def result(solution, answers):
... return set(str(n)+s for n, s in enumerate(solution)) - \
... set(str(n)+r for n, r in enumerate(answers))
...
>>> result(exam_solution, student_answers)
... set(['6B', '13A', '2A'])
>>>
The result are wrong responses (you can convert to list list(result(student_answers)).

Categories

Resources