Counting up and down sequentially using loop - python

I am writing a test that needs to plug in values from a list to a peripheral going forwards then backwards sequentially without breaking the loop. here is the structure I need to modify:
exampleList = [5 10 60 9 3]
for i, listValue in enumerate(exampleList):
self.log += 'Status: iteration {0}, sending {1}\n'.format(i, listValue)
self.device.writeToPeripheral(listValue)
...
I am trying to essentially write [5 10 60 9 3 3 9 60 10 5] (single or extra middle value doesn't matter) to an external device. Changing the list contents will mess up critical objects elsewhere in the environment for different tests. Is there a creative way in python to structure the loop to iterate going up the list, then back down immediately after? I could simply put this in a function and reverse the list after the first call, but I would like to avoid this approach if possible.

One way is to use itertools.chain() like:
Code:
import itertools as it
exampleList = [5, 10, 60, 9, 3]
forward_back = it.chain(exampleList, reversed(exampleList))
for i, list_value in enumerate(forward_back):
print i, list_value
Results:
0 5
1 10
2 60
3 9
4 3
5 3
6 9
7 60
8 10
9 5

Another option is to append the reversed list when iterating:
for i, list_value in enumerate(exampleList + exampleList[::-1]):

Related

how to reverse the order of the output

What are the possible ways of reversing order of any output?
For example, if I have a code like this:
for i in range(10):
print(i)
This is fairly a simple example of course. I can just say
for i in range(9, -1, -1):
print(i)
But what happens when you have very complicated functions, lists, maps, arrays, etc. So my question is: Is there a generic way (or ways) to reverse the order of any output?
I've been thinking about pushing every element (element can be anything) onto a stack, then pop() elements and printing the popped element. But maybe there are better solutions
You can use the reversed builtin:
for i in reversed(range(10)):
print(i)
output:
9
8
7
6
5
4
3
2
1
0
for i in range(10)[::-1]:
print(i)
OUTPUT
9
8
7
6
5
4
3
2
1
0

Why does shuffling array 'A' also shuffle array 'B', but updating int 'a' doesn't update int 'b'? [duplicate]

This question already has answers here:
How do I pass a variable by reference?
(39 answers)
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 1 year ago.
I'm trying to make a shuffled copy of an array called tst. I've defined a copy of tst called batch, and then shuffled batch so that tst remains intact & unshuffled. However, in doing so, I'm finding that shuffling batch also (for some reason) shuffles tst in the process.
To fully understand my dilemma, consider the following code snippet:
# First code snippet
tst = np.array([0,1,2,3,4,5,6,7,8,9])
batch = tst
print(tst)
print(batch)
seed = 42
np.random.seed(seed)
np.random.shuffle(batch)
print(tst)
print(batch)
When I run my code, the outputs that correspond to this code snippet look like this:
[0 1 2 3 4 5 6 7 8 9]
[0 1 2 3 4 5 6 7 8 9]
[8 1 5 0 7 2 9 4 3 6]
[8 1 5 0 7 2 9 4 3 6]
...whereas I'd think it would look like this:
[0 1 2 3 4 5 6 7 8 9]
[0 1 2 3 4 5 6 7 8 9]
[0 1 2 3 4 5 6 7 8 9]
[8 1 5 0 7 2 9 4 3 6]
Loosely speaking, my first thought was that tst and batch are "looking" at the same location in memory (I'm not experienced in programming, so I apologize if my terminology is wrong), and so updating the particular value in that location might update any other variables "looking" at the same place. However, if this was the case, then I would assume that running the following code:
# Second code snippet
a = 5
b = a
print(a)
print(b)
a = 3
print(a)
print(b)
...would output:
5
5
3
3
However, this is not the case...Instead, it outputs:
5
5
3
5
Truth be told, the output behavior of the second code snippet is what I initially thought would happen with the first code snippet, as this seems to make much more sense to me. Performing an operation on one variable shouldn't affect any other "equal" variables, unless explicitly specified by some supplemental code or something.
Alas, I'm hoping to understand why the outputs of the first code snippet behave differently than the outputs of the second code snippet, and what needs to change so that I can shuffle batch without also shuffling tst at the same time. I've been looking around online for an answer, but I feel like everything I find is either too advanced for my current skillset, and/or simply doesn't pertain to this exact issue. Any help would be appreciated. Thanks in advance!
You have to use ndarray.copy, or other similar method, if you really want to create array copy. a = b just creates another variable that points to the same array. Variables are just references to "real piece of data" in python and many other languages. Sometimes a = b is a save way to create a backup for 'immutable data' such as scalars or tuples, but with mutable data types, which can be changed 'in place', that is mutated, this usually fails. Take extra care with arrays, lists, objects, dictionaries and any other "mutable" data types.
https://numpy.org/doc/stable/reference/generated/numpy.ndarray.copy.html#numpy.ndarray.copy

How can I combine binary a set of data

I have a set of values vertically
2,4
4,7
5,8
9
I want to have binary combination of each two values in vertical for example 2 and 4, 2 and 5 etc . the same for the second
2 4
2 5
4 5
4 7
4 8
.
.
.
Ok it seems very complicated so I try to make it easier
I convert my data into horizon
I have
2,4,5
4,7,8,9
I want to have the binary combination of the first row
2 4
2 5
4 5
and the the binary combination of the second row
4 7
4 8
4 9
7 8
7 9
8 9
If you have values stores in two collectables, use list comprehension
from itertools import izip_longest
a = [(1,'a'),(2,'b'),(3,None)]
b,c = izip_longest(*a)
d = [(i, j) for i in b if i for j in c if j]
I think I understand. Try this code:
test.py
#!/bin/python
# put items side by side
# take first item and put the next item besides it
# if there are any more items after the next, put that item besides the first item
# if there are no more items after the next, switch to the next item in the list
# repeat
def two_items_side_by_side(mylist):
list_len = len(mylist)
for i in range(list_len):
for j in range(i+1, list_len):
print '{} {}'.format(mylist[i], mylist[j])
# -------------------------------------------------------------------
# these are two lists
list1 = [2, 4, 5]
list2 = [4, 7, 8, 9]
two_items_side_by_side(list1)
two_items_side_by_side(list2)
When you run this, your results will look like so:
Result
python test.py
2 4
2 5
4 5
4 7
4 8
4 9
7 8
7 9
8 9
If your test case is a string with each line containing comma separated text like this, you can use test2.py as an example
2,4
4,7
5,8
,9
test2.py
#!/bin/python
# put items side by side
# take first item and put the next item besides it
# if there are any more items after the next, put that item besides the first item
# if there are no more items after the next, switch to the next item in the list
# repeat
def two_items_side_by_side(mylist):
list_len = len(mylist)
for i in range(list_len):
for j in range(i+1, list_len):
print '{} {}'.format(mylist[i], mylist[j])
# -------------------------------------------------------------------
# process the data and store them into a list
# then do the same work as we did in the first example
def convert_data_into_lists():
lines = data.split('\n')
for line in lines:
# ignore empty lines
if len(line.strip()) < 1:
continue
# split by comma and ignore if we don't get 2 or more values
items = line.split(',')
if len(items) < 2:
continue
# put first item in list1 and second item in list2
if len(items[0].strip()) > 0: list1.append(items[0].strip())
if len(items[1].strip()) > 0: list2.append(items[1].strip())
# -------------------------------------------------------------------
# this is my string
data = """
2,4
4,7
5,8
,9
"""
list1 = []
list2 = []
convert_data_into_lists()
two_items_side_by_side(list1)
two_items_side_by_side(list2)
Result
python test2.py
2 4
2 5
4 5
4 7
4 8
4 9
7 8
7 9
8 9
There are more elegant ways to write this code. I have written it in a manner that will help you understand the code and try it out yourself.
Requirement change
Based on the change in requirement, data is in a text file. We will take three test cases (see in results). To accommodate the requirements, I am going to use the same code I used in test2.py. Instead of creating individual lists for each column we have in our text file, I will create one list that will dynamically contain as many lists as you have columns in your text file.
Code
#!/bin/python
# put items side by side
# take first item and put the next item besides it
# if there are any more items after the next, put that item besides the first item
# if there are no more items after the next, switch to the next item in the list
# repeat
def two_items_side_by_side(mylist):
list_len = len(mylist)
for i in range(list_len):
for j in range(i+1, list_len):
print '{} {}'.format(mylist[i], mylist[j])
# -------------------------------------------------------------------
# process the data and store them into a list
# then do the same work as we did in the first example
def convert_data_into_lists():
with open(data) as f:
lines = f.readlines()
for line in lines:
# ignore empty lines
if len(line.strip()) < 1:
continue
# split by comma and ignore if we don't get 2 or more values
items = line.split(',')
counter = 0
for item in items:
if len(mylist) < counter + 1:
mylist.append([])
if len(item.strip()) > 0:
mylist[counter].append(item.strip())
counter += 1
# -------------------------------------------------------------------
# this is my string
data = 'test.txt'
mylist = []
convert_data_into_lists()
for individual_list in mylist:
two_items_side_by_side(individual_list)
Result
Case 1
Data:
2,4
4,7
5,8
,9
Results:
2 4
2 5
4 5
4 7
4 8
4 9
7 8
7 9
8 9
Case 2
Data:
2,4
4,7
5,8
6,9
Results:
2 4
2 5
2 6
4 5
4 6
5 6
4 7
4 8
4 9
7 8
7 9
8 9
Case 3
Data:
2,4,10
4,7,11
5,8,
,9,13
Results:
2 4
2 5
2 6
4 5
4 6
5 6
4 7
4 8
4 9
7 8
7 9
8 9
10 11
10 13
11 13
EDIT
By modifying the code above to only use a single parameter, we can read the contents of a csv file and (using some form of delimiter) provide combinations across the entire data set. Just call total_zipper() and replace 'filename.txt' with your file name.
def total_zipper():
def zipper(a):
lst = []
for i in range(1,len(a)+1):
lst+=zip(a,a[i:])
return sorted(lst)
f = open('filename.txt','r')
return [zipper(line) for line in f]
This treats all lines as iterables (Strings). For readline() to work, I believe you need a return statement at the end of each line in the txt. See the input/output page for Python for more.
Here's the shortest version I could come up with. You can use the built-in zip() function. This, when combined with list slicing, results in a pythonic way to pair the values in the required order.
def zipper(a,b):
lst = []
for i in range(1,len(b)+1):
lst+=zip(a,b[i:])
return sorted(lst)
Now simply call zipper on the various rows of data.
>>> a = [2,4,5]
>>> b = [4,7,8,9]
>>> print(zipper(a,a))
[(2, 4), (2, 5), (4, 5)]
>>> print(zipper(b,b))
[(4, 7), (4, 8), (4, 9), (7, 8), (7, 9), (8, 9)]
As a side note, I tried to use list comprehension to make the code shorter. For example, the following code does the same thing as zipper(a):
def zipper(a):
return list(zip(a,a[i:]) for i in range(1,len(a)+1))
However, with zip() returning generator objects in Python 3, the results aren't as "clean" as the output from the version above. I'd have to use next() on each generator object in the list outputted by zipper in order to get the same output, but this is a tedious process. Anyone have suggestions for making the list comprehension work?

Keeping Python from spacing after breaking a line when printing a List

(yes, I've searched all around for a solution, and, if did I see it, I wasn't able to relate to my issue. I'm new to Python, sorry!)
I've got a work to do, and it says to me:
"User will input X and Y. Show a sequence from 1 to Y, with only X elements each line."
e.g
2 4 as entrance
1 2
3 4
e.g 2 6
1 2
3 4
5 6
Okay... So, I thought on doing this:
line, final = input().split()
line = int(line)
final = int(final)
List = []
i = 0
total = (final // line)
spot = 0
correction = 0
k = 1
if i != final:
List = list(range(1, final + 1, 1))
i += 1
while k != total:
spot = line * k + correction
correction += 1
k += 1
list.insert(List, spot, '\n')
print(*List)
Ok. So I managed to build my List from 1 to the "final" var.
Also managed to find on which spots (therefore, var "spot") my new line would be created. (Had to use a correction var and some math to reach it, but it's 10/10)
So far, so good.
The only problem is this work is supposed to be delivered on URI Online Judge, and it DEMANDS that my result shows like this:
2 10 as entrance
1 2
3 4
5 6
7 8
9 10
And, using the code I just posted, I get this as a result:
1 2
3 4
5 6
7 8
9 10
Thus, it says my code is wrong. I've tried everything to remove those spaces (I think). Using sys won't work since it only prints one argument. Tried using join (but I could have done it wrong, as I'm new anyway)
Well, I've tried pretty much anything. Hope anyone can help me.
Thanks in advance :)
You have built a list that includes each necessary character, including the linefeed. Therefore, you have a list like this:
[1, 2, '\n', 3, 4, '\n'...]
When you unpack arguments to print(), it puts a separator between each argument, defaulting to a space. So, it prints 1, then a space, then 2, then a space, then a linefeed, then a space... And that is why you have a space at the beginning of each line.
Instead of inserting linefeeds into a list, chunk that list with iter and next:
>>> def chunks(x, y):
... i = iter(range(1, y+1))
... for row in range(y//x):
... print(*(next(i) for _ in range(x)))
... t = tuple(i)
... if t:
... print(*t)
...
>>> chunks(2, 6)
1 2
3 4
5 6
>>> chunks(2, 7)
1 2
3 4
5 6
7
The problem with the approach you're using is a result of a space being printed after each "\n" character in the series. While the idea was quite clever, unfortunately, I think this means you will have to take a different approach from inserting the newline character into the list.
Try this approach: (EDITED)
x, y = input().split()
x, y = int(x), int(y)
for i in range(1, y+1):
if i % x == 0 or i == y:
print(i)
else:
print(i, end=" ")
Output for 3 11
1 2 3
4 5 6
7 8 9
10 11
Output for 2 10
1 2
3 4
5 6
7 8
9 10
Use itertools to take from an iterable in chunks:
>>> import itertools
>>> def print_stuff(x,y):
... it = iter(range(1, y + 1))
... chunk = list(itertools.islice(it,X))
... while chunk:
... print(*chunk)
... chunk = list(itertools.islice(it,X))
...
>>> print_stuff(2,4)
1 2
3 4
>>>
And here:
>>> print_stuff(2,10)
1 2
3 4
5 6
7 8
9 10
>>>
I split user input into two string then convert them into int and comapre if y greater than x by 2 because this is minimum for drawing your sequence
Then i make a list from 1 to y
And iterate over it 2 element for each iteration printing them
x,y=input().split()
if int(y)>int(x)+2:
s=range(1,int(y)+1)
for i in range(0,len(s),2):
print(' '.join(str(d) for d in s[i:i+2]))
result:
1 2
3 4
5 6
7 8
9 10

Aligning text in a table using string formatting with a loop inside a loop

I'm supposed to align some numbers in a table while using a loop inside a loop. It should look like this when it's done:
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
What I've stared with is:
for i in range(1,10,1):
for c in range(1,6,1):
print(i, end='\n')
Though after running this it just prints them bellow each other. And replacing "\n" with "\t" doesn't help either. I've tried .format but with no success. Sorry if this seems very simple and that it should be stated somewhere but I can't find someone with the same problem or some chapter referring to this specific problem.
I did manage to do this table by using while like this:
i = 1
while i < 6:
print("1 2 3 4 5 6 7 8 9\n" , end='' '')
i += 1
This is of course not the best way to do it, I just don't have the knowledge to do it in a smarter way.
First, you have inverted loop ranges it should be:
for i in range(1, 6, 1):
for c in range(1, 10, 1):
Second, in the inner loop you have to print c, not i.
The full code would be like this:
for i in range(1, 6, 1):
for c in range(1, 10, 1):
print(c, end=" ")
print('')
If you want to code only one for loop you can:
for i in range(1, 6, 1):
print( " ".join(map(str, range(1, 10, 1))) )
Firstly, your loops are in the wrong order. As you write your code, you will get 10 rows with 6 numbers.
Next, you can't print in the inner loop, because you will get just 60 rows. So you can store rows in some temp value inside first loop, and on each cycle of outer loop print it. Also, for more pretty code, you can use list comprehensions.
for i in range(1, 10):
print ' '.join([str(number) for number in range(1, 6)])
Also, to perfect this, you can write it in 1 string of code, but this is more understandable.

Categories