#πŸ”’ Writing a for loop using generator expressions and the zip function to display the first 8 tuples

116 messages Β· Page 1 of 1 (latest)

analog crown
#

Im trying to create a a for loop using generator expressions and the zip function to display the first 8 tuples (a, b), where a is obtained using generator rnd_gen(1, -1), b is obtained using generator rnd_gen(2, -1), and 0
≀ a ≀ b ≀ 100. The idea is to filter out tuples for which a > b. My code seem creates the tuples for both generator variables, however the filtered variable just prints "[ ]". Is there anyway I can adjust this?

nimble sequoiaBOT
#

@analog crown

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

analog crown
warm marten
#

Its easier if you include code snippets rather than images.

woven egret
#

!code

nimble sequoiaBOT
#
Formatting code on Discord

Here's how to format Python code on Discord:

```py
print('Hello world!')
```

These are backticks, not quotes. Check this out if you can't find the backtick key.

For long code samples, you can use our pastebin.

analog crown
#
# COP 4045
# Homework 5 
# Problem 2 

# The defined Python random generator to serve as a basis for Problem 2
def rnd_gen(x0, n): 
    counter = 0 
    while n < 0 or counter < n:
        x0 = (22695477 * x0 + 1) % (2**32)
        yield x0
        counter += 1 

# Part A
# Creating a generator that creates an infinite sequence of tuples (a, b) where a and b are
# two random integers
def gen_rndtup(m):
    rnd_generator = rnd_gen(1, -1)
    while True:
        a = next(rnd_generator) % m 
        b = next(rnd_generator) % m
        if a <= b:
            yield (a, b)

# Part B 
# Usage of the itertools module and the lambda command 
import itertools

filtered_tuples_b = itertools.islice(filter(lambda tup: sum(tup) >= 6, gen_rndtup(10)), 8)
print("Part B:")
print(list(filtered_tuples_b))

# Part C
print("\nPart C:")
gen_a = rnd_gen(1, -1)  # Generator for a
gen_b = rnd_gen(2, -1)  # Generator for b

filtered_tuples_c = [(a, b) for a, b in itertools.islice(zip(gen_a, gen_b), 8) if a <= b <= 100]
print("Filtered tuples:", filtered_tuples_c)


# Part D
print("\nPart D:")
filtered_numbers = itertools.islice(filter(lambda x: x % 13 == 0, map(lambda x: x % 101, rnd_gen(1,-1))), 10)
print(list(filtered_numbers))


# Part E
print("\nPart E:")
import functools # Importing the functools module

filtered_tuples_e = itertools.islice(filter(lambda tup: sum(tup) >= 5, gen_rndtup(10)), 10)
sum_of_tuples = functools.reduce(lambda x, y: (x[0] + y[0], x[1] + y[1]), filtered_tuples_e)
print(sum_of_tuples)
#

this pertains to part c

woven egret
#

an empty list isn't necessarily a wrong answer

#

if it's supposed to have stuff in it, make sure that you have read the condition properly

tulip halo
#

I think it's supposed to contain 8 tuples.

woven egret
#

hmm I see what you mean

#

you actually skip the ones for which the condition is false

#

which means you need to put the filtering inside of the islice?

#

that does make it take quite a while btw

analog crown
#

yeah there needs to be 8 tuples, but I can try your suggestion and see if it works

woven egret
#

(I stopped it now)

#

can you confirm the condition?

tulip halo
#

Take two random numbers 0..2**32, how likely is it that both are below 100 and that the first is smaller then the second? About 0.00000000000003% chance.

woven egret
#

well they aren't actually random, but I doubt that makes a massive difference

tulip halo
#

no idea.

woven egret
#

it might actually be impossible for that to happen with specific seeds together, idk

#

it took me like 1 minute to get just one number <= 100 with rnd_gen(1, -1) in a loop

#

ok nvm the long time was because I was building a set of the numbers seen

#

more like 15 to 20 seconds

tulip halo
#

The 50997500th number is 85.

woven egret
#
def rnd_gen(x0, n):
    counter = 0
    while n < 0 or counter < n:
        x0 = (22695477 * x0 + 1) % (2**32)
        yield x0
        counter += 1


s = set()
for i, x in enumerate(rnd_gen(1, -1)):
    if x <= 100:
        if x in s:
            break
        s.add(x)
        print(f"iteration {i}: {x}")
        print(f"{len(s) = }")
print("Repeat found")
#

this is what I'm cooking rn

#

I should've added a print for what the repeat number is...

#

I'm gonna rewrite the random generation specifically for the infinite case to save some time and make some changes to the loop code I wrote

analog crown
#

nothing seems to work I've tried adjusting it as much as I can be and it keeps printing []

woven egret
#

are you certain that the condition 0 <= a <= b <= 100 is correct by the instructions?

tulip halo
#

if it takes forever it shouldn't print [].

woven egret
#

wait sorry you said it is printing...

#

I realized before jenna said but typing = paing

tulip halo
#

I think the task is to write code, not to execute it.

woven egret
#

perhaps

woven egret
# analog crown

if you are actually able to run the code in a reasonable time to say "oh here's the output guys", you've done it wrong

analog crown
woven egret
#

skull

#

well, have fun leaving your python script running overnight (or longer, who knows)

analog crown
#

all other parts work completely perfect idk why part c is giving me a problem

woven egret
#

you need to islice after filtering, not before

woven egret
#

only 10 more numbers less than or equal to 100 left before I get a repeat (for rnd_gen(1, -1))

#

so looks like it visits every number (which I probably could've googled)

tulip halo
#

!e py from fractions import Fraction print(f"{Fraction(100, 2**32) ** 2 / 2:.15%}")

nimble sequoiaBOT
#

@tulip halo :white_check_mark: Your 3.12 eval job has completed with return code 0.

0.000000000000027%
woven egret
#

actually hol-up, I don't even need to run the second rnd_gen through

#

because all numbers are used, can just inspect starting at 2 and look at the deltas

#

~~sorry wait ~~

#

obviously there are seeds for which the condition can be true, and we can enumerate all of them using that data

#

I think I want to chance the data to show 0 as the 0th iteration tho

tulip halo
#

I think the function returns something along

#

not sure if that helps

woven egret
#

ok I checked, with inputs

gen_a = rnd_gen(1, -1)  # Generator for a
gen_b = rnd_gen(2, -1)  # Generator for b

you cannot satisfy the condition

#

simply because <= 100 never aligns

#

now I will check all combinations of seeds <= 100 because why not

tulip halo
#

so you can stop once the tuple (1,2) is encountered

woven egret
#

what

tulip halo
#

i mean like a itertools.takewhile(lambda t: t != (1, 2), zip(rnd_gen(1, -1), rnd_gen(2, -1))

#

so it stops searching once the initial seeds come up.

woven egret
tulip halo
#

ah

woven egret
#

ok fixed now

#
import json

with open("seq.json") as f:
    data = {int(k): v for k, v in json.load(f).items()}

reverse_data = {v: k for k, v in data.items()}


def from_n(n: int):
    offset = reverse_data[n]
    return dict(sorted(((k + 2**32 - offset) % 2**32, v) for k, v in data.items()))


def compare(x, y):
    return [a == b for a, b in zip(from_n(1), from_n(2))]


print(compare(1, 2))
woven egret
#

they only line up on the last iteration for that input

tulip halo
#

ah, i didn't think of that.

woven egret
#

so we can say that the output will be

[(1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2)]
#

nice

tulip halo
#

actually i'm not sure if they really get back to the initial seeds.

woven egret
#

I tested for input 1 and it goes through all possible values 0 <= x < 2**32

woven egret
#

but because 1 goes through all numbers, then every x0 goes through all numbers for OPs function

#

now to see if any can have possibly have multiple unique pairs, or only repeats the ending pair

woven egret
#

looks like the maximum that can overlap is one, which is the initial pair

#
import itertools
import json

with open("seq.json") as f:
    data = {int(k): v for k, v in json.load(f).items()}

reverse_data = {v: k for k, v in data.items()}


def from_n(n: int):
    offset = reverse_data[n]
    return dict(sorted(((k + 2**32 - offset) % 2**32, v) for k, v in data.items()))


def from_n_only_iteration(n: int):
    offset = reverse_data[n]
    return sorted((k + 2**32 - offset) % 2**32 for k in data)


def compare(x: int, y: int):
    return [a == b for a, b in zip(from_n_only_iteration(1), from_n_only_iteration(2))]


def delta(n: int):
    return [b - a for a, b in itertools.pairwise(from_n(n))]


one = []
many = {}
for a, b in itertools.combinations(range(101), 2):
    c = compare(a, b)
    s = sum(c)
    if s == 1:
        one.append((a, b))
    elif s > 1:
        many[(a, b)] = c

print(one)
print()
print()
print(many)
#

from_n_only_iteration makes a list of indices offset to start at the index of n
compare makes a list of equal indices after offsetting

#

and honestly I didn't even need to make the one list because we know that all inputs a, b will come back to themselves after 2**32 iterations

earnest glen
#

is there any way you might have misunderstood and you're actually supposed to reduce the numbers mod 101 so they are forced in the range [0,100]

woven egret
#

oh wait, I forgot about a == b

#

something like this

def answer_c(a: int, b: int) -> list[tuple[int, int]]:
    if a < b:
        return [(a, b)] * 8
    if a == b:
        return [
            (x, x)
            for x in itertools.islice((r for r in rnd_gen(a, -1) if 0 <= r <= 100), 8)
        ]
    return []
#

@tulip halo just gotta pray that a != b πŸ˜„

tulip halo
#

hm. yes in that case the return value is still not correct. it needs to be an infinite loop.

#

so maybe while True: pass instead of return [].

tulip halo
woven egret
#

an actual infinite loop I don't like

tulip halo
#

i find the loop+generator+zip requirement more concerning. that would be something likepy for a, b in islice(((a, b) for a, b in zip(rnd_gen(1, -1), rnd_gen(2, -1)) if 0 <= a <= b <= 100), 8): print(a, b)

vast harbor
woven egret
vast harbor
woven egret
#

I mean... still doesn't look like JS

analog crown
#

rnd_gen has already been defined for reference. I believe I posted that segment at the beginning of the discussion

tulip halo
woven egret
#

ES6 came out in 2015... although looks like comprehensions will again come to ES7, but better than they originally were

tulip halo
#

Ah.. Right, I totally forgot that Babel even exists. I'm glad I switched to python long ago. aniblobsweat

nimble sequoiaBOT
#
Python help channel closed

This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.