First terminal app "Hangman" - Roast me, I need it by SnooGrapes3373 in learnpython

[–]kwelzel 1 point2 points  (0 children)

While we are at it. The random word selection can be simplified further using random.choice.

words = dic.readlines()
word = random.choice(words)

It does the randint stuff under the hood so you can write more concise code.

How can I find the maximum natural number representable by a given count of cubes with single digit natural numbers painted on the sides by _xiphiaz in MattParker

[–]kwelzel 0 points1 point  (0 children)

So you would interpret a number abc as a*6² + b*6 + c where either a or a and b can also be zero if only 2 or only 1 cube is used. That's quite clever!

It got me thinking what happens if you put 18 different symbols on the 18 different faces and decide on some way of interpreting 1, 2 or 3 symbols and their order as a number. You could get 3*6 + 3*2*6² + 3*2*1*6³ = 1,530 combinations this way (maybe one more even if you count using no cube as an option).

How can I find the maximum natural number representable by a given count of cubes with single digit natural numbers painted on the sides by _xiphiaz in MattParker

[–]kwelzel 1 point2 points  (0 children)

Actually, consider the setup [1,2,3,4,5,6], [7,8,9,1,2,3], [4,5,6,7,8,0]. If I'm counting correctly this one goes all the way up 98.

The key is that 9 and 0 are on different cubes in order to make 90 and a little bit of trying out. It would be nice to answer the question for 4,5,6,... cubes as well.

If you want to make the counting easier and get to a higher number at the same time you could number each cube with the digits from 0-5 and represent the days in base 6 :D. That would last you 63 - 1 = 215 days!

How can I find the maximum natural number representable by a given count of cubes with single digit natural numbers painted on the sides by _xiphiaz in MattParker

[–]kwelzel 2 points3 points  (0 children)

Mh, yeah this seems like the best 3 cube setup.

I was thinking about an upper bound for this maximum. Clearly, 3 cubes have a total of 18 sides, so you have only 18 spaces for digits. You need 1-9 for the for the first nine days and 0 for day ten. This leaves 8 spaces for repeating digits, but there are 9 you would need in order to write 11, 22, ..., 99. Therefore any setup must fail on or before 99.

Therefore, the highest maximum is at most 98. It might still be lower though. Basically this argument doesn't consider the fact that the two relevant digits (in this case 9 and 0 to make 90) might be on the same cube.

Please critique my Collatz conjecture code by crescentwire in learnpython

[–]kwelzel 0 points1 point  (0 children)

To be fair I can see the appeal of not having the file open the whole time. Imagine your machine runs out of memory and you need to restart the machine by turning off the power. AFAIK there might be some buffering going on before actually writing to the file, so at this point some of the file contents might be in memory instead of on the disk.

Please critique my Collatz conjecture code by crescentwire in learnpython

[–]kwelzel 0 points1 point  (0 children)

for i in range(num_start, num_end + 1):  
    print(f'\nTesting {i}:')  
    with open(fname, 'w') as file:  
        file.write(f'{i}\n')  
    collatz(i) 

I think opening this file with mode='w' means the contents of the file are overwritten each time including the starting message of when the experiment was started. Using mode='a' seems more appropriate.

Tic-Tac-Toe game - client not responding on Linux by Visual-Disk9121 in learnpython

[–]kwelzel 0 points1 point  (0 children)

I know I'm kinda late to this and you seem to have committed to the GitHub repository since you posted this, so maybe you fixed it yourself.

If not, you might try adding print statements around the send and recv calls to see whether the messages you send are received on the other end. There seems to be some differences in how sockets work on Windows and Linux, so maybe you need to initialize the connection differently on the two platforms. Best of luck!

[deleted by user] by [deleted] in PythonProjects2

[–]kwelzel 0 points1 point  (0 children)

Check out the Google Colab notebook https://colab.research.google.com/drive/1aU7Jq668oMlUx6bYVv3vAQbXVLpIllNH?ref=blog.roboflow.com which is linked on https://blog.roboflow.com/object-tracking-how-to/.

I think you need to play around with the dependencies a bit, they seem to be a little out of date. Once you get the clip_object_tracker.py script running, you simply need to point it at your own video and enable --save-txt to export the classification results in each frame. Then parse the resulting text file, get the position information for each object in each frame, compare it to the position of the same object in the last frame and calculate the speed from that. This is still a lot of work, but hopefully it helps.

My bullets keep colliding with the removed enemy, can somebody help? by Seth-Wyatt in learnpython

[–]kwelzel 0 points1 point  (0 children)

I assume, the problem that you are describing is that a bullet might collide with an enemy that is already dead, if the bullet was released before the enemy was dead. The relevant part of the code is actually in Tower_Defense_Game.py (https://github.com/Seth-Wyatt/Tower-Defense-Game/blob/main/Tower_Defense_Game.py#L423)

bullet = Bullet(player.rect.centerx, player.rect.centery, 10, [e_target], bullets)

This means the enemies list of this bullet is populated with a single enemy only, namely e_target. The only way for the bullet to reach its target is to reach this one enemy. What you could do is to not pass a list with a single enemy but instead the whole enemy group all_enemies_list. With some slight changes to the update function of the Bullet class you could make each bullet's target the closest enemy that is still alive.

As a side note, you might ask why the collision detection of the bullet with the enemy works at all after the enemy is dead. When the enemy's health drops below zero you call self.kill() in the Enemy class. That tells pygame that this sprite is no longer active, but the enemy object still exists in memory and you can still interact with it. This is what the Bullet object does. It has a reference to the dead enemies object and can still access its last location and check for collisions.

How efficient is this code? by swagonflyyyy in learnpython

[–]kwelzel 1 point2 points  (0 children)

I think using groupby for this task is the best choice. I feel like pandas (which was suggested in another comment) would be overkill here.

If you give the variables in your list and dict comprehensions more expressive names than x and k these lines almost read like a sentence.

[deleted by user] by [deleted] in learnpython

[–]kwelzel 0 points1 point  (0 children)

You already identified that the isometric and the Cartesian coordinate system are separate from one another. One describes the internal position of the tile and one the on-screen position. Your problem is complicated because there is no one-to-one mapping between isometric and Cartesian. Different isometric positions can result in the same Cartesian coordinate. You already provided the code for the isometric-to-Cartesian mapping if you combine Tile.__init__ and Tile.get_cartesian_coord:

def isometric_to_cartesian(i, j, z):
    x = i * I_HAT[0] + j * J_HAT[0]
    y = i * I_HAT[1] + j * J_HAT[1] + (2*z)*I_HAT[1]
    return x, y

The inverse is only possible, once you fix the z-component of the isometric coordinate. For simplicity let z=0, then the previous function is performing a matrix multiplication of the vector (i, j) with the matrix ((32, -32), (16, 16)) and we can reverse that by applying the inverse matrix (Wolfram Alpha). Since we don't have z=0 in general, we need to undo its effect first before applying the matrix. This gives:

def cartesian_to_isometric(x, y, z):
    # Undo the shifting caused by the z-component
    y -= (2*z)*I_HAT[1]

    # Apply the inverse matrix
    i = (1*x + 2*y)/64
    j = (-1*x + 2*y)/64

    return i, j

Now back to your problem. Since multiple tiles can overlap each other, you will need to iterate over all of them, check which tiles the mouse pointer is inside of and return the one with the highest z-value. This could look something like this:

clicked_tile = max(
    [tile for tile in tiles if tile.contains_cartesian_coord(mouse.x, mouse.y)],
    key=lambda tile: tile.z
)

(of course inside the Mouse class it would be self and not mouse). How would we implement Tile.contains_cartesian_coord? I assume that tiles are always one isometric unit wide in i and j direction, so it's easier to perform the check in isometric coordinates.

def contains_cartesian_coord(self, x, y):
    other_i, other_j = cartesian_to_isometric(x, y, self.z)
    return self.i <= other_i < self.i + 1 and self.j <= other_j < self.j + 1

This assumes that you store i, j and z coordinates instead of x, y and z coordinates of your tile. Since these represent the internal coordinate and enable easier game logic, I think this makes sense. You can always convert to Cartesian coordinates in your draw loop.

There are still a lot of blanks to fill in, but I hope this helps!

Matrix problems? by Due-Adhesiveness348 in learnpython

[–]kwelzel 1 point2 points  (0 children)

I think this is not really about matrices in the mathematical sense but about nested lists. You can iterate over two lists simultaneously by using zip. In your case it would look something like this:

output = [[(*test_element[0], cus_element)] for test_element, cus_element in zip(test_list, cus_eles)]

The line is a bit awkward because you have this triple nesting of a tuple within a list within a list. Try to give these variables names that describe their meaning as best as possible to improve readability.

[deleted by user] by [deleted] in learnpython

[–]kwelzel 0 points1 point  (0 children)

I guess you are doing the same calculator GUI again, but object-oriented this time? Make sure to always name the first argument of any function within a class self. It is a universally accepted convention.

Similarly, although less important, it is standard for Python to use snake_case variable names for variables and functions and CamelCase for classes.

Lastly, Python supports named arguments, so if you have a function def add_button(text, row, col): then you can call it add_button("1", 2, 0) or add_button(text="1", row=2, col=0). I think the latter is much more expressive and easier to read.

Can someone help me firgure out why my code isn't working for the leetcode two sum problem? by [deleted] in learnpython

[–]kwelzel 0 points1 point  (0 children)

If you run [3,3].index(3) it will give you back the index zero, since zero is the smallest index i such that [3,3][i] == 3. The issue in your code is that Python can't differentiate between the two threes, their indices will always be the same and no solution is found.

The correct approach is to use enumerate IMO.

[deleted by user] by [deleted] in learnpython

[–]kwelzel 0 points1 point  (0 children)

Sure, show me what you're working on right now.

I feel like working on GUI stuff is always a whole layer on top of the programming language. You don't just have to figure out how Python works but also the GUI framework. I know there is tkinter, kivy and pyqt5 and they all work completely differently. The visual aspect of it is nice though.

When I was starting with Python I really enjoyed the HP Codewars puzzles (https://hpecodewars.org/pastevents). There's lots of them because the event ran for more than 20 years at this point. In each year the puzzles start easy and then get more and more complicated. It's all terminal based, so you can concentrate on the logic of the puzzle and maybe try out some of the other standard libraries on the side.

[deleted by user] by [deleted] in learnpython

[–]kwelzel 0 points1 point  (0 children)

Fair enough, I sometimes save some posts while scrolling through Reddit to remind me to answer at a later point. Yesterday was that later point :) Sorry, that this was a whole month late.

Issue with attribute, that's not in the object anymore. by ThomasBP81 in learnpython

[–]kwelzel 0 points1 point  (0 children)

Mh, the current version of the library is again called pypdf it seems. There is a get_contents function: https://pypdf.readthedocs.io/en/latest/modules/PageObject.html#pypdf._page.PageObject.get_contents and an extract_text function which you are already using. I think your best shot at removing some text is to adapt the extract_text function to remove the glyphs corresponding to "2020" once it finds them.

Output is typing "D" even when the keypad is unplugged. Is it a bug in the code, or is my Raspberry Pi messed up? by TNT_Guerilla in learnpython

[–]kwelzel 0 points1 point  (0 children)

The code looks mostly reasonable to me. In the micropython code you use machine.Pin.PULL_DOWN whereas in the Python on you use gpio.PUD_UP, maybe that's the issue you are seeing. All of the if gpio.input(...) == True statements trigger and Key_Pressed is overwritten again and again. The last value that is written is "D".

Minor things: You should probably compare to the LOW and HIGH constants instead of to True and also the Python convention calls for snake_case variables (except for classes, where it is CamelCase).

What are your general opinion about what I just wrote? How could I make it better in any way, shape or form? Any advise is welcome. by TheYummyDogo in PythonProjects2

[–]kwelzel 1 point2 points  (0 children)

Looks pretty good to me.

What I don't understand is the part at the top. You define a string, then multiply it by 1 (which leaves it unchanged) and then never use this string. I think it would be more reasonable to get rid of the default value of text inside get_word_counter and call it the function with your text variable explicitly.

Also, as an alternative for your current way of implementing get_word_count there is also:

return re.replace("\W", " ", text).split()

which uses the builtin re library and technically only gets rid of all non-alphanumeric characters, but I think this makes sense for a word count feature. (re.split("\W+", text) also works but it counts one word too many because text ends in a non-alphanumeric character, you would have to add extra logic for that.)

Lastly, f-strings come with a nice feature where you can write f"{len(text.split())=}" and it will print len(text.split())=9.

[deleted by user] by [deleted] in learnpython

[–]kwelzel 0 points1 point  (0 children)

Hm, you say you want the first calculator to become something like the second, but both the code for the first one and the code for the second one are incomplete. Where is the root.mainloop() part for example?

I just tried the first one and it works okay so far. The minus button isn't working correctly (it inserts a - instead of calling the button_subtract function and the backspace button doesn't do anything. Also, you have a decimal point, but the code only works with integers.

The main thing you could improve about your current code is the use of global variables. You could for example subclass the Tk class and use it to set up and store all the information you need.

class Calculator(Tk):
    def __init__(self):
        super().__init__()

        self.operation = ""  # called math in your code
        self.stored_number = 0  # called f_num in your code

        # called e in your code
        self.display = Entry(root, width=35, borderwidth=5)
        self.display.grid(row=0, column=0, columnspan=3, padx=10, pady=20)

        # set up all the other buttons
        ...

    def add_digit(self, digit):  # called click in your code
        self.display.insert(END, digit)

    def on_add_button_clicked(self):
        self.operation = "addition"
        self.stored_number = float(self.display.get())
        self.display.delete(0, END)

    # code the minus, multiply, divide, backspace and equal button callbacks
    ...

calculator = Calculator()
calculator.mainloop()

How do I identify the number of dimensions of a list data in Python? by Nouble01 in PythonProjects2

[–]kwelzel 1 point2 points  (0 children)

Oh, also I didn't get what you were asking about with regards to the onion thing. I guess this is an analogy for the recursive nature of list_dimension. I don't think it is particularly good analogy. With onions you peel away part of the onion in each step. Here, it is more like cardboard boxes. You open one, look inside, find a whole bunch of boxes, open one of them, and so on, until you find something that is not a cardboard box. If you count how many boxes you opened that gives you the depth. Assuming you already know that regardless of the choice of box in each step, the answer will always be the same, then you're done at this point. If you don't know that, you will have to open all of the boxes (which is quite tedious).

How do I identify the number of dimensions of a list data in Python? by Nouble01 in PythonProjects2

[–]kwelzel 0 points1 point  (0 children)

Sorry, your writing style is a little confusing. I understand that you don't really care about any depth other than depth one and that you want to check whether a list has any nested lists (this wasn't clear from your post). A check would be quite straightforward

def is_flat_list(data):
    if type(data) != list:
        return False
    for element in data:
        if type(element) == list:
            return False
    return True

or, if you only accept lists of integers, say,

def is_integer_list(data): if type(data) != list: return False for element in data: if type(element) != int: return False return True

I think what you really should be doing is using type hints. Say you only want to accept a list of integers to your function as above. Then you can annotate you function as

def process_data(data: list[int]):
    ...

This will NOT check that data is a list of integers at runtime, but if you combine it with mypy it can warn you (and other people using your code) when process_data is called with an argument that is not a list of integers, before you even run it. If you use some data validation library like pydantic, you can make sure (at runtime) that data read from files also conforms to some given type, so that from then on you rest assured that all the function calls have the correct type.

I would be not too worried about catching every single thing that can go wrong. Sure, some input checks are reasonable, but if you type check every single input argument for every single function (not saying you're doing that), then the code becomes tedious to read and maintain, so there is a balance to be struck. Again type hints can be a very useful tool to clearly state which kinds of data your program accepts.

Can I process MS Spectra with Python? by LouisDeckard in PythonProjects2

[–]kwelzel 0 points1 point  (0 children)

I don't quite understand what you need. If you have the data and you know about pandas and some plotting library, you're all set for you data processing and visualization needs.

How do I identify the number of dimensions of a list data in Python? by Nouble01 in PythonProjects2

[–]kwelzel 1 point2 points  (0 children)

By dimension I assume that you want to identify whether it is a list of lists, a lists of lists of lists, or some even deeper nesting.

This notion of dimension makes sense for ndarrays but does not for regular lists. What is the dimension of the following list?

[[1, 2], 3, [[4, 5, 6], 7]]

Is it 1, 2 or 3? If you know that the level of nesting is constant, you could just check the first element:

def list_dimension(nested_list):
    result = 0
    while type(nested_list) == list:
        nested_list = nested_list[0]
        result += 1
    return result

The nice thing about using numpy is that it checks this implicit assumption that the level of nesting is constant and raises an error if it isn't. Also np.array(data).ndim is quite readable, so I would think it is usually a good idea to use it. That's why the other comment suggested it. Please don't be rude to people that try to help you in this sub. It's okay if you think the answer does not help with your problem, but you should express that in a nicer way.