sequence of repeated values in a list - python

I have problems with a program, I hope someone can help me to fix this. Basically I have a random generated list with 20 values, and I want to place between brackets the values that are repeated (for example if the list is [1,2,2,4,5] it should display 1 ( 2 2 ) 4 5 )
Now here's my code that works only if there is no repeated value in the end, because the list index goes out of range. How can I fix this?
from random import randint
lanci = []
for i in range(20):
x = randint(1,6)
lanci.append(x)
print(lanci)
i=0
while i < len(lanci)-1):
if lanci[i] == lanci[i+1]:
print("(",end=" ")
print(lanci[i],end=" ")
while lanci[i]==lanci[i+1]:
i = i + 1
print(lanci[i],end=" ")
print(")",end=" ")
else:
print(lanci[i],end=" ")
i = i + 1

Alternatively to your more manual approach, you could use itertools.groupby to group equal values in the list and then enclose those in parens:
>>> import random, itertools
>>> lst = [random.randint(1, 5) for _ in range(20)]
>>> tmp = [list(map(str, g)) for k, g in itertools.groupby(lst)]
>>> ' '.join(g[0] if len(g) == 1 else "(" + " ".join(g) + ")" for g in tmp)
'5 4 1 2 1 4 (5 5) 4 5 1 5 4 3 (5 5) 3 (5 5 5)'

Not the pretiest but will do it:
from random import randint
from itertools import groupby
lanci = [randint(1,6) for _ in range(20)]
result = [tuple(v) for _, v in groupby(lanci)]
print(*[i[0] if len(i) == 1 else '('+' '.join(map(str, i))+')' for i in result], sep=' ')
#(2 2) 3 5 3 1 5 4 6 2 1 4 6 4 (5 5) 3 6 3 4

Just check for "last element" before your inner while loop.
from random import randint
lanci = []
for i in range(20):
x = randint(1,6)
lanci.append(x)
print(lanci)
i=0
while i < len(lanci)-1):
if lanci[i] == lanci[i+1]:
print("(",end=" ")
print(lanci[i],end=" ")
while (i+1 < len(lanci)) and (lanci[i]==lanci[i+1]):
i = i + 1
print(lanci[i],end=" ")
print(")",end=" ")
else:
print(lanci[i],end=" ")
i = i + 1

convert the list of number to a string then you can use this function.
split it if you need the list back again.
def add_brackets(string):
_character, _index = None, 0
_return_string = ''
for i, c in enumerate(string+ ' '):
if _character is None or _character != c :
if len(string[_index:i])>1:
_return_string+='(' + string[_index: i] + ')'
else:
_return_string+=string[_index: i]
_character, _index = c, i
return _return_string

This is another option using just basic list:
def group_consecutives(lst):
res, sub, memo = [None], [], None
lst.append(memo)
for x in lst:
if memo == x:
sub.append(memo)
if res[-1] != sub: res.append(sub)
else:
sub.append(memo)
if memo and not len(sub) > 1: res.append(memo)
memo, sub = x, []
return res[1:]
print(group_consecutives(lanci))

Related

iterate through a list and restart index_1 at 0 if list index is out of range

I am trying to make a program where I have a list my_list_1 = [1,2,3,...] and a second list `my_list_2 = [1,2,3,...] and len(my_list_1) < len(my_list_2). I want to iterate through the lists like this:
my_list_1 = [1,2,3]
my_list_2 = [5,6,7,8,9]
result = []
for i in range(len(my_list_2)):
result.append(my_list_1[i] + my_list_2[i])
# i == 0: 1 + 5 = 6
# i == 1: 2 + 6 = 8
# i == 2: 3 + 7 = 10
# i == 3: 1 + 8 = 9
# i == 4: 2 + 9 = 11
""" what I want to happen is when i > len(my_list_1), instead of giving a index out of range
error, I want the loop to start at the beginning if the smaller list"""
I tried something like this:
for i in range(len(my_list_2)):
if i % (len(my_list_1) - 1) == 0 or i == 0:
x = 0
else:
x+=1
result.append(my_list_1[x] + my_list_2[i])
or
for i in range(len(my_list_2)):
if x == (len(my_list_1) - 1) or i == 0:
x = 0
else:
x += 1
result.append(my_list_1[x] + my_list_2[i])
this works but I am looking for something a bit more elegant and possibibly even making a copy of my_list_1 and extend it to the length of my_list_2 so that it would look like this:
>>> my_list_1 = [1,2,3]
>>> my_list_2 = [5,6,7,8,9]
>>> extend_list(my_list_1, len(my_list_2))
[1,2,3,1,2]
You can also use itertools.cycle to create a cyclical list iterator, and use zip for the iterator and the other list.
from itertools import cycle
my_list_1 = [1,2,3]
my_list_2 = [5,6,7,8,9]
# I use list comprehension here
result = [ a + b for a, b in zip(cycle(my_list_1), my_list_2) ]
print(result)
# [6, 8, 10, 9, 11]
You just need modulo for the first index:
for i in range(len(my_list_2)):
x = i % len(my_list_1)
result.append(my_list_1[x] + my_list_2[i])

Group string by 3 character to a List

for example, I have string "25037654", and I want to Group the string by 3.
but, since the string is 8 character, and 8 % 3 is not 0. it have remainder. and I want the final List is ["25", "037", "654"], the first Index will only accept the remainder, for example 1 or 2 character
I think this code may satisfy your requirement.
First get the idx of every slice, then cut this string to each substring.
str_num = "25037654"
idx = [len(str_num)%3+3*i for i in range(len(str_num)//3+1)]
print(idx) # [2, 5, 8]
if(idx[0]!=0):
idx = [0]+idx
res = [str_num[idx[i]:idx[i+1]] for i in range(len(idx)-1)]
print(res) # ['25', '037', '654']
One easy way, in this case, is to use f-string:
s = "25037654"
output = f"{int(s):,}".split(',')
print(output) # ['25', '037', '654']
The above won't work if the input is not numeric. Then try:
leading = len(s) % 3
output = ([s[:leading]] if leading else []) + [s[i:i+3] for i in range(leading, len(s), 3)]
Thanks everyone who respond and answer My Question.
after a few moments I post my question. I found the answer LoL
it's the Long Way, my version. thanks Guyss
s = "25037654"
if len(s) % 3 == 2:
fn = s[0:2]
xx = s[2:len(s)]
group = list(map(''.join, zip(*[iter(xx)]*3)))
final = fn + " " + " ".join(group)
elif len(s) % 3 == 1:
fn = s[0:1]
xx = s[1:len(s)]
group = list(map(''.join, zip(*[iter(xx)]*3)))
final = fn + " " + " ".join(group)
elif len(s) % 3 == 0:
group = list(map(''.join, zip(*[iter(s)]*3)))
final = " ".join(group)
print(final) # 25 037 654
t = "25037654555"
i, j = divmod(len(t), 3) # i - int part, j - remainder
print([t[:j]] + [t[j+(i-1)*3:j+i*3] for i in range(1,i+1) ])
Result:
['25', '037', '654', '555']
You can try my version:
s = "25037654"
rem = len(s)%3
lst = []
i = 0
while i < len(s)-2:
if i == 0:
lst.append(s[:rem])
i+=rem
else:
lst.append(s[i:i+3])
i+=3

Looping Based on 2 Value Python

i have 2 variable
ex :
compt = 9
first = 3
second = 2
then i want to looping based on compnt length and then change status on or off based on variable first and second
Output that i want :
On
On
On
Off
Off
On
On
On
Off
my current code is:
x,y=0,0
for i in range(0,compt):
if x != first:
print("On")
x+=1
elif x == first and y != second:
print("Off")
but the output from code above is
On
On
On
Off
Off
On
On
On
On
can someone help me to solve my problem , thank you
compt = 9
first = 3
second = 2
for i in range(compt):
max_val = first + second
if i % max_val < first:
print("on")
else:
print("off")
Output:
on
on
on
off
off
on
on
on
off
from itertools import cycle, islice
total = 9
first = 3
second = 2
sequence = ["On" for _ in range(first)] + ["Off" for _ in range(second)]
print(sequence)
result = islice(cycle(sequence), 0, total)
for state in result:
print(state)
output :
['On', 'On', 'On', 'Off', 'Off']
On
On
On
Off
Off
On
On
On
Off
Another variation with itertools:
from itertools import cycle, repeat, chain
compt = 9
first = 3
second = 2
on = repeat("On", first) # ["On", "On", ..]
off = repeat("Off", second) # ["Off", "Off", ..]
for status in cycle(chain(on, off)): # combine on and off and repeat
print(status)
# break when compt is exhausted
compt -= 1
if compt <= 0:
break
You can use %. We have a total first + second possibility. If our i is less than first it means that we are looking for on and if it's more than first we want to print off:
compt = 9
first = 3
second = 2
for i in range(compt):
if i % (first + second) < first:
print("ON")
else:
print("OFF")
try it...
compt = 9
first = 3
second = 2
i=0
while i < compt:
for k in range(0,first):
i += 1
print('on')
if i >= compt:
break
for j in range(0,second):
i += 1
print('off')
if i >= compt:
break

Python: Splitting numbers and factor them to 2

This code is to identify if the number factored to 2 for the 4th time, would get 1 or not.
a = int(input())
terms = 4
result = list(map(lambda x: a ** x, range(terms)))
for i in range(terms):
print(a, "^2 = ", result[i])
if result == 1:
print('True')
else:
print('False')
If I input 14, this is the result:
14 ^2 = 1
14 ^2 = 14
14 ^2 = 196
14 ^2 = 2744
False
But I want it to be like this.
1^2 + 4^2 = 17
1^2 + 7^2 = 50
5^2 + 0^2 = 25
2^2 + 5^2 = 29
False
Try this:
a = str(int(input()))
def split_and_print(a):
x = [int(y) for y in list(str(a))]
return sum([y**2 for y in x])
def split_sum_print(a):
a_split = list(str(a))
print(' + '.join([x+'^2' for x in a])+ ' = '+str(split_and_print(a)))
return str(split_and_print(a))
n = 4
for i in range(n):
a = split_sum_print(a)
if a == '1':
print(True)
else:
print(False)
Output:
14
1^2 + 4^2 = 17
1^2 + 7^2 = 50
5^2 + 0^2 = 25
2^2 + 5^2 = 29
False
I made two functions, one responsible for calculation, the other for printing. Then combined them and used a for loop. Change n for different number of iterations.
First of all, a = str(int(input())) seems quite unnecessary, as input() returns string by itself.
Second, you then cast it to string ... in str(a): once again (again unnecessary).
And third of all, you are iterating over some string (a in this case), which would product a stream of single characters, but your code is written as if you expected tuples instead...?
For example
for char in "abc":
print(char)
... would print
a
b
c
What you essentially have
for a, b in "abc":
print(a, b)
... what should happen here?
What do you expect to happen with your code, exactly? 🤔

Random Simulation of 20 Die Throws

Trying to simulate 20 dice throws randomly, the code needs to enclose with parenthesis a value that is the same, the parenthesis appear, but I am missing something on my formula, any advise can greatly help, eg:
1 ( 4 1 ) 2 3 6 1 4 3 2 6 6 6 5 6 2 1 3 5 3 # incorrect
1 4 1 2 3 6 1 4 3 2 ( 6 6 6 ) 5 6 2 1 3 5 3 # this is a correct example
def main():
exampleList = [ ]
for i in range(20):
exampleList.append(randint(1, 6))
print(exampleList)
print(list(range(0,20)))
max_count = 0
run_count = 0
matched = False #inRun = False
# find max run
for rollValue in exampleList:
#print(rollValue)
if run_count == 19:
print()
else:
print("-------")
print("Roll Value %s" % exampleList[run_count])
print("Position %s" % run_count)
print("Next Roll value %s" % exampleList[run_count + 1])
if exampleList[run_count] == exampleList[run_count + 1]:
matched = True
print("------->>>matched")
else:
matched = False#inRun = False
run_count += 1
if rollValue < 19:
if exampleList[rollValue] == exampleList[rollValue + 1]:
run_count += 1
if matched == False:
matched == True
run_count = rollValue
else:
matched = False
if run_count > max_count:
run_count = 1
# print sequence
for rollValue in range(20):
if rollValue == run_count:
print("(", exampleList[rollValue], end = " ")
elif rollValue == run_count + max_count + 1:
print(exampleList[rollValue], ")", end = " ")
else:
print(exampleList[rollValue], end = " ")
main()
Here is a solution using regex. This creates a string out of the dice rolls, then finds repeating digits and uses re.sub to add parenthesis.
import re
import random
rolls = ''.join(map(str, [random.choice(range(1, 7)) for _ in range(20)]))
rolls = ' '.join(re.sub(r'(\d)(\1+)', r'(\1\2)', rolls))
print(rolls)
A couple sample runs:
4 1 4 3 4 6 5 2 3 ( 5 5 ) 1 6 4 3 5 2 5 ( 4 4 )
2 ( 1 1 ) 4 1 ( 5 5 ) ( 3 3 ) 6 2 ( 1 1 ) 5 1 4 3 4 ( 5 5 )
Regex explanation:
( // start of matching group 1
\d // matches a single digit
) // end of matching group 1
( // start of matching group 2
\1+ // matches group 1, 1 or more times
) // end of matching group 2
This adds the parenthesis as part of the list:
#!/usr/bin/python
import sys
from random import randint
# add parenthesis as part of the list
def main():
exampleList = [ ]
previous = -1
opened = False
for i in range(20):
roll = randint(1, 6)
if roll == previous:
if not opened:
exampleList.insert(-1, '(')
opened = True
else:
if opened:
exampleList.append(')')
opened = False
exampleList.append(roll)
previous = roll
if opened:
exampleList.append(')')
for item in exampleList:
sys.stdout.write('{0} '.format(item))
sys.stdout.write('\n')
if __name__ == '__main__':
main()
Examples:
( 2 2 ) 4 5 1 2 1 ( 6 6 ) 1 6 1 4 1 ( 6 6 ) 1 6 2 4
2 ( 6 6 ) ( 1 1 ) 3 2 1 ( 4 4 ) 1 2 5 4 1 5 3 ( 5 5 5 )
There are a number of issues with your code, so it was just quicker to rewrite the whole thing.
def main():
example_list = []
for _ in range(20):
example_list.append(random.randint(1, 6))
inside = False
for index in range(len(example_list)):
try:
if inside:
if example_list[index] != example_list[index + 1]:
print("%d )" % example_list[index], end=" ")
inside = False
else:
print(example_list[index], end=" ")
else:
if example_list[index] == example_list[index + 1]:
print("( %d" % example_list[index], end=" ")
inside = True
else:
print(example_list[index], end=" ")
except IndexError:
print("%d" % example_list[index], end=" ")
if inside:
print(")")
else:
print()
As you can see I keep track of whether I'm inside a parenthesis by using a variable. I look to the next number to guess if I should add a closing parenthesis.
The last case is handled by a try-except.
You could also handle each number by looking forward and backward but that'd require you to add some extra condition for the try-except part so this was just
There are various ways to do this, but this is the most similar to what you were doing already. Basically just iterate over the index of your list of rolls. Each number we examine it to see if it is the same as the one before, if yes, then we increment the count and move on. If not then we add however many of that number were in the count to the output. If there was one, we write it out by itself, if more, in parenthesis.
exampleList = [randint(1, 6) for i in range(20)]
# the current number that could be a potential sequence
current = exampleList[0]
# count for the number of occurences in a sequence (often 1)
count = 1
# The string to outpu
output = ''
# Iterate over the rolls, ignoring the first one
for i in range(1, len(exampleList)):
if exampleList[i] == current:
count += 1
else:
if count > 1:
output += ('(' + count * str(current) + ')')
else:
output += str(current)
current = exampleList[i]
count = 1
# Handle final addition
if count > 1:
output += ('(' + count * str(current) + ')')
else:
output += str(current)
print(output)
Output:
64(66)15253(66)2143454(22)
The logical error is that you're confusing "the index where the run starts" with "the length of the (last) run".
You need a variable like max_run_start_index.
Look at the code:
if rollValue == run_count:
print("(", exampleList[rollValue], end = " ")
Read it back to yourself 'if the index of the next output is equal to the length of the last run, output open bracket before it'.
So if the length of the last run is 3 the longest run starts at index 3?
Surely not...
I'm not a Python coder, so you'll need to fix it yourself...

Categories

Resources