#algos-and-data-structs
1 messages ยท Page 34 of 1
Builtin objects are usually faster than custom, yes
Given your cuda reference: i think youโre mixing up list comprehensions with stuff like numpy arrays. Youโll likely end up using dataframes and numpy, not Python lists.
Paying someone to help me fix a problem
is a binary tree with only the root present (i.e. root with root.left and root.right = None) a full binary tree?
sure, the only node has 0 children, so "all nodes have either 0 or 2 children" is fullfilled.
alrighty, thanks!
(checking for a perfect binary tree). is this solution the same time complexity as this solution: https://www.programiz.com/dsa/perfect-binary-tree
my solution:
def is_perfect_binary_tree(self) -> bool:
#traverse the tree in level order, putting nodes into a dict with the keys as levels like so:
#{0: [4], 1: [2, 6], 2: [1, 3, 5, 7]}
level_order_nodes = self.collect_level_info(self.root)
count = 2
#go through each level, check how many nodes are in each level (call it width)
#if the current level * 2 isn't = the next levels width, return false
for k in level_order_nodes.keys():
if len(level_order_nodes[k])*2 != count:
return False
count *= 2
return True
i think that both time complexities should be O(h) + O(n) (where h is the height of the tree), which comes out to be O(n) ofc. i just want to check
def perfect_depth(node) -> Optional[int]:
"""
Returns the depth of the perfect binary tree, or None
"""
if node is None:
return 0
d_l = perfect_depth(node.left)
d_r = perfect_depth(node.right)
if d_l == d_r is not None:
return d_l + 1
return None
I think this would work
is_perfect should be perfect_depth
indeed
guys how do i do this in python 3
there is a string s print True if s has any alphabetical characters Otherwise, print False.
Get a list representing the alphabet. Then iterate trough it and check if the letter is in the given stringโฆ If every letter is in the string, return True
Use this: "abcdefghijklmnopqrstuvwxyz"
src/darwinio/distribution.py line 413
def get_points_between_2_points(```
Is there a better way to do this?
print(any(map(str.isalpha, s)))
Consider a pair or points, for example
(ax, ay), (bx, by) = (4, 7), (10, -2)
Calculate coordinate-wise difference between points
(dx, dy) = (bx - ax, by - ay)
Notice that only the difference matters for the amount of points in the answer, not the positions of points.
How are points distributed on the segment? Well, evenly. I hope this part is fairly obvious, but if it is not, grab a piece of paper and draw a few pictures, you will understand why pretty quickly. This means that every point can be obtained as a + k * d, where K is an integer, which "walks" from 0 to N (where N is some number of points), and d is the different between two consecutive points. Consider an example, in our case the answer is [(4, 7), (6, 4), (8, 1), (10, -2)]. Take the difference between the zero-th and first point (or any other consecutive pair, those are evenly distributed, remember?). That's the vector 2, -3. You can then add it again and get another point, which is also on the segment. And then again, and again, and again, until you end up on the end of the segment. Let's say that the the difference is 1/Nth of the length of the entire segment, and K walks from 0 to N inclusive (N=3 in the example), giving you new points every time.
The goal now is to find maximum N such that for every 0 <= k <= N, k * dx/N and k * dy/N are integers. Of course, k must equal to 1 at some point, so it is only required that dx/N and dy/N are integers. So N must be the maximum integer such that both dx and dy are divisible by N. This is called the Greatest Common Divisor, or GCD, and it can be computed very quickly using the Euclidian algorithm, conveniently built-in into math module.
!e
Now, let's put it all together.
(ax, ay), (bx, by) = (4, 7), (10, -2)
(dx, dy) = (bx - ax, by - ay)
import math
N = math.gcd(dx, dy)
answer = [(ax + (dx // N) * k, ay + (dy // N) * k) for k in range(N + 1)]
print(answer)
yeah, that's it. But as you can see, there is a pretty complicated math involved in this little piece of code. Ask me anything if you are still confused, and don't forget to rewrite the list comprehension with numpy.
@outer rain :white_check_mark: Your 3.11 eval job has completed with return code 0.
[(4, 7), (6, 4), (8, 1), (10, -2)]
@inland flax ^^^^
Thanks but I am going to bed and I cant brain math now
Good night
np!
can anyone give me a hand with understanding complete binary trees? i don't understand the "leaning to the left" aspect of them
I think whoever wrote this had made a mistake
not the "last leaf element", but the "last non-leaf element"
anyway
every white tree is a "complete binary tree", every red tree is a "binary tree", but not complete
I think that basically all this saying is that if you consider the tree layer by layer, from root then every layer, except possibly the last one, must be full, and the last one can be partially full, but if it is, it must use left-most nodes on that layer
I might be wrong though
that sounds about right, i'm going to look into it more though
actually this makes a bit more sense now, because nodes should be "filled from the left"
here's (what I think is) a much better description:
Every level except the last one is full.
The last level's nodes are as far left as possible.
hey, anyone need help?
guys anyone know a proper algorithm to get a number which needs the less number of exponents to produce a number when divided by a base number gives the remainder of 1?
I assume you want, for a given number n, find a such that a^p = 1 (mod n), and minimize p (assuming p > 0).
1 needs the power of 1, obviously, n-1 needs the power of two (because (n-1)^2 = n^2 -2n + 1, the rem is 1), and you can prove that for prime n's every other number (modulo n) requires power greater than 3, and for non-primes it's complicated.
yes
exactly
So I guess the answer n - 1 just always suffice with p=2 (I assume you are not interested in trivial case of 1)
right
yeah , the case of p=1 isnt really a need rn, might improvise that later
I am back!
I am not able to understand much of it ๐
can u gimme a psuedocode for it ? if u dont mind xD
I'm confused. I said that the answer is your number minus 1, what pseudocode do you expect?
tf, ok my bad wrong channel reply
ffs
Lol, that happens ๐
Can you tell me where i can learn more about your algorithm?
I am still confused
you can ask me questions
saying you are still confused does not give me any info about what exactly you now undertand
if you want to learn more, you can google something like "integer points on a segment problem", it's a pretty common one
I didnt dx/N
Anything after vector
Why we found hcf etc
Integer points split line into equal pieces, right?
Equal pieces?
see how in the example, the segment is evenly divided by the points in the answer
[(4, 7), (6, 4), (8, 1), (10, -2)]
Oh yeah
the difference between each pair of consecutive points is the same
(2, -3)
so, if we have the amount of points in the answer, we can divide the difference between the last point and the first one by some integer N and get that difference
N + 1 is amount of points in the answer btw
is that clear?
Hmm
Wait
So you find the number of points between them?
But how?
Using the difference?
We have not found it yet, but if we did, we could have used it that way. Actually, our goal from now is to find N.
The difference between the pair of consecutive points is (dx/N, dy/N), where (dx, dy) is the difference between the end points
what we want, is to find the maximal N such that both dx and dy are divisible by N
if we consider smaller divisor, we might not find every point, and if we consider larger non-divisor, we will get a non-integer difference
That's just hcf
Anyone know what does it mean?> (blind 75 and neetcode 150) mean? If someone can tell me what this means, it would be greatly appreciated. I noticed this word used by several people who claimed to have done this to get job in FAANG
blind is a website, someone made a list of top 75 leetcode question there: https://www.teamblind.com/post/New-Year-Gift---Curated-List-of-Top-75-LeetCode-Questions-to-Save-Your-Time-OaM1orEU
neetcode is a youtuber iirc, he must have made his own LC curation
wow great! thanks a lot
can i ask for a hint on how to implement this infinite series for approximating pi to n terms in the series: (pic attached)
for each term i can write a list comprehension for the denominator and for the plus/minus sign i can test if the term is even or odd
yeah, that'd work
or you could even do it the direct way: term = (-1)**(i-1) * 4 / ((2*i)*(2*i+1)*(2*i+2))
Neet =Not in Education, Employment, or Training?
not sure. quite possibly!
no_of_points: int = np.gcd(y2 - y1, x2 - x1)
m = (y2 - y1) / (x2 - x1)
dm = int(m / no_of_points)
x_coords: np.ndarray = np.arange(x1, x2, dm)
y_coords: np.ndarray = np.arange(y1, y2, dm)
Am I doing it right?
Nevermind
I don't get what you need m for. And the step size for each coordinate can be different, it's not dm for sure. And other useful correctness metric: consider units. Coordinates are measured in units of distance, m is measured in distance/distance=nothing, and then you add nothing to distance in arange. Something is definitely off here. So no, you are not doing it right ๐
I read your explainatioj again
Dy: int = y2 - y1
Dx: int = x2 - x1
no_of_points: int = np.gcd(Dy, Dx)
m = Dy / Dx
dm = int(m / no_of_points)
dy: int = Dy // no_of_points
dx: int = Dx // no_of_points
x_coords: np.ndarray = np.arange(x1, x2, dx)
y_coords: np.ndarray = np.arange(y1, y2, dy)
Did I get it right this time?
Woah thanks for the units tip
I feel extremely stupid now
yep, this looks right
m and dm are unused now
Yeah removed them
I think i am going to get crazy performance gains
oh, just noticed
np.arange is exclusive of last value
so the last point won't be included in the result
ooh, this is also a good question
maybe just use linspace instead
does it work for integers?
oh, it does if you set dtype=int explicitly
So I think it's just
Dy: int = y2 - y1
Dx: int = x2 - x1
# I added 1 here because it's what it does now
# vvvv
no_of_points: int = np.gcd(Dy, Dx) + 1
x_coords: np.ndarray = np.linspace(x1, x2, no_of_points, dtype=int)
y_coords: np.ndarray = np.linspace(y1, y2, no_of_points, dtype=int)
oh god
= instead of : lol
started writing typst there for a moment
Lol
Hey, I have an numpy array of 4 ints and these are supposed to represent the genes of an organism. I want to color the organisms according to their genes. For this I used the nilsimsa algorithm and used the hex as the color. But i wonder if there is a better way to acheive this.
src/darwinio/genome.py line 82
def array2hex(array: np.ndarray) -> str:```
heya quick question letโs say i have a FOR loop (for x in x) and another FOR loop (for y in y). if these FOR loops are not nested but occur within the same algorithm, is the time complexity O(2n) or O(mn)?
function hello():
x = [] of length ??
y = [] of length ??
for x in x:
#do something
for y in y:
#do something
Hi guys, i have this question:
The basic idea is a gomoku AI. Board is a 15x15 numpy array, and I am looking for the patterns in the board defined in Three_patterns(for now only horizontal check is alright). Here is my current implementation:
def find_threes(board: Board): # sourcery skip: use-itertools-product
board_height, board_width = board.shape
Three_patterns: dict[str, list[int]] = {
"open_three": [0, 0, 1, 1, 1, 0, 0],
"three_left": [0, 1, 1, 1, 0, 0],
"three_right": [0, 0, 1, 1, 1, 0],
"broken_three_right": [0, 1, 1, 0, 1, 0],
"broken_three_left": [0, 1, 0, 1, 1, 0],
}
for name, pattern in Three_patterns.items():
pattern_size: int = len(pattern)
for row in range(board_width):
for col in range(board_height):
if np.array_equal(board[row, col : col + pattern_size], pattern):
print(f"Pattern found at {row=}, {col=}, {name=}")
However this implementation is flawed, because if I have a row with [0, 0, 1, 1, 1, 0, 0]...(other elements are unimportant) this will be detected as an open_three, three_left and three_right but i would only want it to get detected as an open three. How could i catche the already found threes?
i know i could improve on the search but for now performance is unimportant
You could copy board before starting the search, and whenever you find a pattern, zero out that slice so that it doesn't participate in further matches (or set it to 2, depending on whether you want ones to count as zeros for adjacent patterns).
huh, that actually works flawlessly not sure why i did not think of that
another followup questions, what would be the right structure for my code, i will obviously need to do the same checks for patterns of fours and one for five. the main logic will always be:
def find_pattern(board: Board): # sourcery skip: use-itertools-product
board_copy = board.copy() # i think i always need to define these 3 lines
board_height, board_width = board_copy.shape
board_values = board_copy.get_board() # get values on the board
Three_patterns: dict[str, list[int]] = { # patterns specific for function, e.g: you can see the 5 patterns for three,
"open_three": [0, 0, 1, 1, 1, 0, 0], # for four there are 6
"three_left": [0, 1, 1, 1, 0, 0],
"three_right": [0, 0, 1, 1, 1, 0],
"broken_three_right": [0, 1, 1, 0, 1, 0],
"broken_three_left": [0, 1, 0, 1, 1, 0],
}
for name, pattern in Three_patterns.items(): # iterate over the board and look for patterns, horizontally,
# diagonally and vertically
pattern_size: int = len(pattern)
for row in range(board_width):
for col in range(board_height):
if np.array_equal(board_values[row, col : col + pattern_size], pattern):
# set the pattern to 4, so it does not appear in the next iteration
# ? is this the right way?
board_values[row, col : col + pattern_size] = 4
print(f"Pattern found at {row=}, {col=}, {name=}")
I feel like my functions will have a lot of redundant code, but i also feel that shoving all the patterns into one big function is not the best idea
could anyone help me understand why this function works?
def isComplete(root, index, number_nodes):
# An empty is complete
if root is None:
return True
# If index assigned to current nodes is more than
# number of nodes in tree, then tree is not complete
if index >= number_nodes :
return False
# Recur for left and right subtrees
return (isComplete(root.left , 2*index+1 , number_nodes)
and isComplete(root.right, 2*index+2, number_nodes)
)
the function checks if a binary tree matches the criteria of a complete binary tree (nodes are filled from the left, any internal nodes have 2 children)
i whiteboarded a few examples and it makes sense that it works, but I don't understand why it works. my biggest confusion is the index, where on the left side we pass in 2*index+1, and on the right we pass in 2*index+2. why do we do that?
It requires a prerequisite in mathematics in computer science. Can i skip it and still learn DSA in this perticular course??
anyone ? who have done this course?
Looking at the syllabus, it's asking for: "Basic knowledge of discrete mathematics: set theory, relations and logic, combinatorics, proofs, recursion, number theory, graph theory, and probability."
I haven't done the course, but those seem like reasonable pre-reqs for a DSA course.
how to get that basic knowledge without doing an entire course?
Some DSA courses will assume no prior knowledge of recursion... so if the MIT sequence assumes a certain pre-req, I'd say it's probably not wise to skip the pre-req.
Maybe just find a different / more introductory DSA course. Or, just take it and if your'e stuck, go study what you don't know.
Got it. In that case can you suggest one?
Maybe ask in #python-discussion for what DSA course people have taken. I don't have any first hand experience with any of the online stuff.
(although I've watched many OCW courses and love them)
Oke. thanks ๐
Hi. I've implemented a FIFO and a LIFO queue with lists (using .pop(0) / .pop(-1)), now I need a priority queue (like queue.PriorityQueue) where I can take a look at the lowest-priority entry's priority. With queue.PriorityQueue I'd have to .get that item, then .put it again, which seems like wasted computing time, and I don't care about the queue's thread safety anyway for this use case. Is there a simpler way, e.g. another way to abuse lists for this?
have you considered using heapq
!d heapq
Source code: Lib/heapq.py
This module provides an implementation of the heap queue algorithm, also known as the priority queue algorithm.
Heaps are binary trees for which every parent node has a value less than or equal to any of its children. This implementation uses arrays for which heap[k] <= heap[2*k+1] and heap[k] <= heap[2*k+2] for all k, counting elements from zero. For the sake of comparison, non-existing elements are considered to be infinite. The interesting property of a heap is that its smallest element is always the root, heap[0].
(also using lists for fifo is not very efficient because pop(0) takes O(n) time, use collections.deque for that)
How would you approach this?
Is there a resource where I can train in optimizing not time, but memory? Leetcode and other resources focus more on time complexity
i have a list of lists, for example length of each inner list is like : 4, 3, 3, 1, 1, 2, 5, 5
whats the best way to make sure neither inner list have a lenght of 1 so its combines with others like: 4,3,4,3,5,5
https://paste.pythondiscord.com/2EEQ
my alpha beta pruning cuts 4 more states than it should anyone have any idea why that could be the case?
solving problems with Python
wrong channel (and probably server)
there is a nim discord server
def isDifferenceLowerThanTwo(i1: int, i2: int):
return abs(i1-i2)<2
So I have this function where it compares two ints. And I'm given a list of ints. Is there a way to filter the list so that comparing each int with each other, only the ones which have at least one True result from isDifferenceLowerThanTwo are left, ordered ascendingly?
So:
input = [1,9,2,6,8,16]
output = [1,2,8,9]
# Ordered list
# 6 and 16 removed since there isn't a single other int inside the list that fulfills the isDifferenceLowerThanTwo condition
Is this a leetcode or something?
Like, a naive O(N^2) implementation is for each i in input, for each j in input, checking isDifferenenceLowerThanTwo, etc. And then adding to a set or list (if not already in) and sorting.
Similar, the issue is very simplified but the main point is this. The isDifferenceLowerThanTwo function is one I've made, is not part of the problem, and the list is of dictionaries, but the point is the same which is to filter some out comparing with the other elements within the list and then order it
There's not a more optimal way of doing this, then, right?
Oh, there's certainly better ways. Could sort the input, and take advantage of adjacency, for instance.
adjacency?
Isn't that done with graphs and matrices?
If input was sorted, would you need to compare input[i] against every other input?
Nope, you're right, only the ones adjacent until isDifferenceLowerThanTwo doesn't fulfill
So as a quick basic idea it would be something like this, right?
arr.sort()
filteredArr = []
for i in range(0, len(arr)):
j = i+1
while isDifferenceLowerThanTwo(arr[i],arr[j]):
filteredArr += arr[j]
j += 1
return filteredArr[]
Wait there's cleanup to do, it would have repeated values inside filteredArray
Yes, and you'd miss some values (1,2,9 wouldn't add the 2, I think)
And, why a while loop? If it's sorted, why do you need to check anythign past the next value?
Also, you can use enumerate instead of range() there.
Well my mistake in explaining the issue, I made it simpler so in the example I gave you it doesn't make sense, but in reality the comparison is between dicts and the field is a datetime and they have to be within 1 minute from each other
so there could be a couple
Yah, but still, you just need to compare value[i] to value[i+1], right?
If it's sorted by date.
Sure, but
value[i] = 10:00:00 # yes
value[i+1] = 10:00:01 # Yes
value[i+2] = 10:00:15 # Yes
value[i+3] = 10:05:00 # No
Last one is after 1 minute, the rest are within 1 minute
I'm really unclear on what you're trying to do then.
But, if you just want to know if, given a value[i], whether there's a value[j] within some X of value[i]... then you had the right idea: but you only need to compare value[i] to value[i+1] (and value[i-1], but yuou can do that in a single comparison) if value is sorted.
I see what you're saying, you're right
Hey guys, i have this piece of code. What i want to do is when i find the patterns in the board i want to get their gain squares to create a class object.
What is the best way to do this dynmically if i want to use it for all patterns?
def find_threes(board: Board): # sourcery skip: use-itertools-product
board_copy = board.copy()
board_height, board_width = board_copy.shape
board_values = board_copy.get_board()
Three_patterns: dict[str, list[int]] = {
"open_three": [0, 0, 1, 1, 1, 0, 0],
"three_left": [0, 1, 1, 1, 0, 0],
"three_right": [0, 0, 1, 1, 1, 0],
"broken_three_right": [0, 1, 1, 0, 1, 0],
"broken_three_left": [0, 1, 0, 1, 1, 0],
}
for name, pattern in Three_patterns.items():
pattern_size: int = len(pattern)
for row in range(board_width):
for col in range(board_height):
if np.array_equal(board_values[row, col : col + pattern_size], pattern):
"""
Here i wanna identify the gain squares e.g.: for open three they are open_three[1] and open_three[5].
Then i want to create objects from them:
for open_three[1]:
Threat1 = Threat(gain_square=board_values[row + 1, col:col+pattern_size],
for open_three[5]:
Threat2 = Threat(gain_square=board_values[row + 4, col:col+pattern_size],
"""
# set the pattern to 4, so it does not appear in the next iteration
# ? is this the right way?
board_values[row, col : col + pattern_size] = 4
print(f"Pattern found at {row=}, {col=}, {name=}")```
guys any recommendations to learn data structures and algorithms it can be udemy course or yt tutorials
is this any good?
Good course. But it gets a little bit confusing later on.
Did it way back and realised it doesn't explain Big O as well as any other paid course
Best course I found was this one
Hey, I have a problem:
Given a M x N grid filled with some values I need to find a path from a target node which maximizes the sum of all values along its path.
I can move in any direction. Path has a max length of x
The naive solution is basically: walk the path recursively. From target node, sum max path from each adjacent node.
Thank u Very much appreciate brother
bump ^
The intuition is: that at each depth, either there are no children (both left and right are false) or there's a children at each position of the tree. If the tree is length 3, then there must be a node at position 0, 1, and 2 (0, 20+1, 20+2) and so on. If the tree is complete, a tree with length 5 will have nodes at positions: (0, 20+1, 20+2, 21+1, 21+2). Here's a visualization (sorry for long URL, it encodes your code): https://www.recursionvisualizer.com/?function_definition=from dataclasses import dataclass %40dataclass class Node()%3A i%3A int left%3A "Node" right%3A "Node" tree1 %3D Node(i%3D0%2C left%3DNode(1%2C left%3DNone%2C right%3DNone)%2C right%3DNone) tree2 %3D Node(i%3D0%2C right%3DNode(1%2C left%3DNone%2C right%3DNone)%2C left%3DNone) def isComplete(root%2C index%2C number_nodes)%3A %23 An empty is complete if root is None%3A return True %23 If index assigned to current nodes is more than %23 number of nodes in tree%2C then tree is not complete if index >%3D number_nodes %3A print(f"Index exceeded numnodes {index}") return False %23 Recur for left and right subtrees return (isComplete(root.left %2C 2*index%2B1%2C number_nodes) and isComplete(root.right%2C 2*index%2B2%2C number_nodes) ) &function_call=isComplete(tree1%2C 0%2C 2)
So, to simplify: if the left side is None, then the Right side must be None.
ah ok, that makes more sense. awesome website by the way, that looks a lot easier to use than a whiteboard
I'm having a little hard time verbalizing the point/intuition here too, it's a subtle point: that if the node is None and we've exceeded the number of nodes, then we return false.
yea, that makes sense, thank you!
Assuming that I have two objects performing approximately the same motion. Each object has the same size and shape and the duration of the motion of each object is the same. I have access to a 3 dimensional array that consists of:
- Dimension 1: The n frames of the motion
- Dimension 2: The n points that the objects consist of
- Dimension 3: The X, Y coordinates of each point
Now each point of an object may or may not move the same way as the same point of other would. What I want to do is to find a way to calculate the overall percentage of divergence of the second motion compared to the first motion and which point diverges more. Is there any algorithm I can look at?
I'm studying an Algorithms class in which we're doing mergesort, and I want to know about the analyzing the time complexity (Big-O) of it. Well, i actually want to know if what I've done is correct. Here's my notes:
the only thing i don't quite get why the n log n is next to the c (i.e. the merge function) instead of the T(1), because isn't the splitting the function the 'longer' function?
This looks correct to me
Well, one way to think about it is to try to explicitly split this into parts:
T(n) = s(n) + m(n)
m(n) = c n
s(n) = 2 T(n/2)
# but expand s(n) and:
s(n) = 2s(n/2) + c n
notice how cn appears in the supposed splitting part, too.
so, in a sense, each split includes a merge, and so that merge function is what tends to grow more
Yeah, sure. I'd say merging is the actual work and splitting just ends up traversing the entire list once (if the merging wasn't there, the solution would clearly be T(n) ~ n)
Do someone knows Backtesting py ?
I really need help with that
https://pastebin.com/a0ht1nnh
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
calling it a split is a bit weird, it's the cost of splitting into 2 and sorting the two halves
well don't u sort the halves only before you merge it?
class Solution:
def maxValue(self, events: List[List[int]], k: int) -> int:
e = sorted(events, key=lambda x: x[0])
d = {}
def g(i, j, t, c):
if i > j:
return c
m = (j+i)//2
if e[m][0] == t:
return m
if e[m][0] < t:
return g(m+1, j, t, c)
if e[m][0] > t:
return g(i, m-1, t, min(m, c))
@cache
def f(i, k):
if k == 0 or i == len(e):
return 0
a = g(i+1, len(e)-1, e[i][1]+1, len(e))
if a == len(e):
x = e[i][2]
else:
x = e[i][2] + f(a, k-1)
y = f(i+1, k)
return max(x, y)
return f(0, k)
Wrong Answer
66 / 67 testcases passed
https://leetcode.com/problems/maximum-number-of-events-that-can-be-attended-ii/
what am i doing wrong?
(returns 300 for the last test case when it should return 304)
from functools import cache
from typing import List
class Solution:
def maxValue(self, events: List[List[int]], k: int) -> int:
events.sort(key=lambda x: x[0])
n = len(events)
@cache
def dp(i, k):
if k == 0 or i == n:
return 0
next_event = self.findNextEvent(i, events)
if next_event == n:
include_value = events[i][2]
else:
include_value = events[i][2] + dp(next_event, k - 1)
exclude_value = dp(i + 1, k)
return max(include_value, exclude_value)
return dp(0, k)
def findNextEvent(self, i, events):
start_day = events[i][1]
left, right = i + 1, len(events) - 1
next_event = len(events)
while left <= right:
mid = (left + right) // 2
if events[mid][0] > start_day:
next_event = mid
right = mid - 1
else:
left = mid + 1
return next_event
nice, it works ๐
not sure why that's relevant?
can u help me to explain this https://leetcode.com/problems/minimum-number-of-days-to-make-m-bouquets/description/ question
class Solution:
def minDays(self, bloomDay: List[int], m: int, k: int) -> int:
def feasible(days):
boquets, flowers = 0,0
for bloom in bloomDay:
if bloom>days:
flowers = 0
else:
boquets += (flowers+1)//k
# print(boquets)
flowers = (flowers+1)%k
# print(flowers)
return boquets>=m
if len(bloomDay)<m*k:
return -1
left,right= 1, max(bloomDay)
while left<right:
mid = left + (right-left)//2
if feasible(mid):
right = mid
else:
left = mid+1
return left```
Can anyone explain me feasible part
i didn't understand the question how we make boquets
so the fix turns out to have been
def g(i, j, t, c):
if i > j:
return c
m = (j+i)//2
# if e[m][0] == t:
# return m
if e[m][0] < t:
return g(m+1, j, t, c)
if e[m][0] >= t:
return g(i, m-1, t, min(m, c))
Those variable names tho
The idea of this algorithm is that, for each feasible(days) : you walk through the "bloomDays" left to right and accumulate flowers until you fill a bouquet. If a flower isn't bloomed if bloom>days, then you restart flowers=0 . The else block (inside feasible) says: If I've accumulated enough flowers, add 1 to my boquet boquets += (flowers+1)//k. And, if the flower is in bloom, then add to my bundle flowers = (flowers+1).... but, as a shortcut, use %k so that if my bundle is full, then flowers = 0. The "else" block could've been written as an if statement: pseudocode like: flowers += 1 and if flowers ==k, then add 1 to boquet and set flowers = 0
So, as an analogy: You're walking through a row of flowers with a basket that holds "k" flowers. You keep filling the basket until you reach "k" flkowers in the basket. If your basket is full, you make a bouquet: and of course, that means your basket is empty. When/if you reach a flower that isn't in bloom, you put all the flowers in your basket back, and continue.
Thanks I understand
it's just check one by one flower which statisfy bloom<days if not they makes flowers zero so we need to start count flowers from zero and after loop they return boolean for shifting left and right values
The left and right part is just using a binary search to subdivide the problem so you don't check every day rather than iterating over every day. This shrinks complexity from O(n^2) to O(nlogn), I think.
If I want to append to add an element at the start of the list, which is the most efficient method? Is it the dequeue.appendleft()?
Just list.insert(0, obj)?
I was gonna do this, but found https://stackoverflow.com/questions/8537916/how-do-i-prepend-to-a-short-python-list
Oh, most efficient. Yah, i guess deque.appendleft is supposed to be faster.
Okay thanks
it's a tradeoff. if you only need to read/pop/push elements on the sides, a deque is made for it - but getting an element from the middle of a deque is slow, unlike a list.
Alright, thanks
Thanks Again!
# Test List
l = [i for i in range(1000000)]
o = 'abc'
%timeit l.insert(0, o)
# 698 ยตs ยฑ 9.02 ยตs per loop (mean ยฑ std. dev. of 7 runs, 1,000 loops each)
# Test Deque
from collections import deque
l = deque(i for i in range(1000000))
o = 'abc'
%timeit l.appendleft(o)
# 107 ns ยฑ 1.18 ns per loop (mean ยฑ std. dev. of 7 runs, 10,000,000 loops each)
Bigger diff than I expected.
Damn quite a bit, is it that much better with the normal append too? I gotta try that
# Test List
mylist = [i for i in range(1000000)]
%timeit mylist.append('abc')
# 95.5 ns ยฑ 7.99 ns per loop (mean ยฑ std. dev. of 7 runs, 10,000,000 loops each)
# Test Deque
from collections import deque
myd = deque(i for i in range(1000000))
%timeit myd.append('abc')
# 74.6 ns ยฑ 4.75 ns per loop (mean ยฑ std. dev. of 7 runs, 10,000,000 loops each)
append should be about the same
insert at 0, though, is done in O(1) for a deque but O(n) for a list, so up to infinity times faster ๐
(on the other hand, indexing is the opposite.)
Oh alright, thank you!
Sure it does:
l = list(range(10**6))
d = collections.deque(l)
%timeit l[5*10**5] # 49.3 ns ยฑ 3.4 ns per loop (mean ยฑ std. dev. of 7 runs, 10,000,000 loops each)
%timeit d[5*10**5] # 89.2 ยตs ยฑ 943 ns per loop (mean ยฑ std. dev. of 7 runs, 10,000 loops each)
quick time complexity question, when writing big o notation, are you allowed to have coefficients? for exmaples O(4n) or would i have to write O(n)
we ignore the coefficient, because big O is about asymptotic behavior, where the coefficient is dominated by N as N approaches infinity... but in real world, of course, the coefficient matters.
okay thank you
If you're going through the data multiple times, you can call it "two-pass", "three-pass", etc., and "one-pass" if you only go through it once.
If you look at the definition of the O-notation (there's a bunch, but the one I like is "f(n) is O(g(n)) if the limit of f(n)/g(n) as n->โ exists (like, isn't infinite)"), you'll see that according to it, O(4n) and O(n) are exactly the same thing (because if f(n)/n has a limit, so does f(n)/(4n), and vice versa). So it's customary to only write it as the latter.
Hi
yeah, when I think of the definitions in my head it's not the formal "for n large enough there exist a constant c such that..."
it's "how does this quotient behave as n tends to infinity"
i.e. take f(n) and g(n), how does f(n)/g(n) behave?
if it tends to zero or a constant f(n) is in O(g(n))
if it tends to infinity or a constant f(n) is in ฮฉ(g(n))
if it tends to constant f(n) is in ฮ(g(n))
having these several notations might seem intimidating at first, but they are literally just what โค โฅ and = corresponds to in asymptotics
def findKthNumber(m: int, n: int, k: int) -> int:
def feasible(num) -> bool:
count = 0
for val in range(1, m + 1): # count row by row
add = min(num // val, n)
if add == 0: # early exit
break
count += add
return count >= k
left, right = 1,n*m
while left<right:
mid = left + (right-left)//2
if feasible(mid):
right = mid
else:
left = mid+1
return left ```
Can anyone explain me add part of code
add = min(num // val, n)
if add == 0: # early exit
break
count += add```
This one
Imagine num is 10 and val is 3: you know there are three multiples of 3 less than 10: 3,6,9. And, if you want to know how many values in a multiplication table are less than 10, then youโd check 1, 2, 3, 4, and add them up (from 1 to m+1). So, that min function says: for a given num, how many multiples of val are less than it (up to a max of n), and this is wrapped in a loop that adds up for each value from 1 to m+1
i understand the problem but how left comes at there right position
Youโre asking about why the left/right part is there? Thatโs a binary search that narrows down the lower and upper estimate, until they converge. You donโt need that: you could just iterate over all the n*m values to search for the kth, but the binary search reduces the search space to logn. Its easiest to just step through the function to understand whatโs happening, try pasting the code here and step through the results: https://pythontutor.com/visualize.html
I think i understand if add becomes zero that means no values is smaller than nums/mid.
Thanks for ur help
i am not able to solve binary search problem how can i solve difficult problem/topics graph and dp
These are pretty advanced problems: are you just googling the optimal solutions to these leetcode questions?
I am learning binary search from this i think this a good template
If you really want to understand it, start with a simple case, add some debug print statements, and walk through what happens at each iteration. This stuff is really hard to understand intuitively without visualizing it, at least for me
Secondly, you should first understand the algorithm without binary search: look at the On^2 linear search. Then see how/why a binary search improves things.
0n^2 soln gives mle
firstly i tried brute force than binary search
Are you only running the code inside leetcode? Copy it out and run it locally.
Itโs good practice to learn how to debug (either with a debugger or print statements), rather than trying to logically decipher the code.
Advice Noted!
I started learning Python a month ago, and now that I feel im in a intermediate level, is now the right time to use the start dsa? Or do I need to become more proficient in Python?
Can we solve this question with this template? I already solve with binary search but i am trying to solve that problem from binary search.
This stuff is language agnostic, you can just go ahead and start learning it.
i am stuck on a porblem in which i have to enumerate all combinations
lets say I have 3 platforms and the following 4 nodes
each node can talk to itself
nodes on the same platform are interconnected
how can i enumerate all possible links on each platform
platform: node
1: 1
2:2,3
3:1
possible links on platform 1 is 1,1 1,2 1,3 and 1,4
possible links on platform 2 is 2,1 2,4 2,3 3,1 and 3.,4
possible links on platform 3 is 4,4 4,3 4,2 , 4,,1
For enumerating all possible links on each platform is it possible to do it with itertools
do u have any guidance
Hey guys I need some help here.
Long story short I took DSaA course in the first semester of the last year of university and the course was in java, and now I'm learning python and I wanna learn the data structures in it and solve problems on leetcode, any general tips and advices will be appreciated โค๏ธ
Is shelve optmial for collecting results from loops? Lets say I will have million results, can I append 5 reults every iteration or should I just go with csv ?
Hey guys, How do I realistically complete data structures and algorithms within 6 months
define "complete"
learn every algorithm 
Can anyone help me
seems like an interesting problem. Can you rephrase you solved it with binary search and now want it solved again with... um, binary search?
just learning till hashing/hashmaps and special cases of trees like trie etc, seems good enough in 6 months
yeah it's easy problem i solved using binary search but i want to solve that problem with binary search template
Using This Template
def binary_search(array) -> int:
def condition(value) -> bool:
pass
left, right = min(search_space), max(search_space) # could be [0, n], [1, n] etc. Depends on problem
while left < right:
mid = left + (right - left) // 2
if condition(mid):
right = mid
else:
left = mid + 1
return left
You just need to implement the condition function here
but before calling it on rotated sorted array you can just sort the array, i.e. undo the rotation
using inclusive exclusive limits makes the thing neater
def binary_search(l, r, cond):
while r - l > 1:
mid = (l + r)//2
if cond(mid):
l = mid
else:
r = mid
return l
this looks for the largest l such that cond(l) is True
and r will be the smallest where cond(r) is False
we can't choose left as min nums bcoz answer is min nums
what do u mean by inclusive exclusive limits
FInally Solved
class Solution:
def findMin(self, nums: List[int]) -> int:
def feasible(num):
if (nums[num]) <= nums[right]:
return False
return True
left,right = 0, len(nums)-1
while left<right:
mid = left + (right-left)//2
if feasible(mid):
right = mid
else:
left = mid+1
print(left)
print(right)
return min(nums) if len(nums) >= 3 else nums[(left+1)%len(nums)]
len(nums) >= 3
any way to modify the code so i don't need to write this statement in feasible part?
like with range(l, r)
l is included in the range, r isn't
you dont need feasible function, because it works like this:
:^)
if val == True:
return val == True
else:
return val != False
I have a 15x15 numpy ndarray. I need to traverse all diagonals and find patterns which are all 1d lists, with a length of 6 or 7, the problem is if i match a pattern i need to know the starting coordinates of the pattern too, what would be an effiecent to check this?
Yes
But if i extraced them, i would not know the starting position of the pattern
In the original matrix
Could you elaborate please?
E.g.: i have a pattern [2, 3, 4, 5] i would want the output to be (0,1),(1,1),(2,1)
what is the benifet of using this?
it makes the update rules for l and r simpler, you have the nice property of cond(l) always being true and cond(r) always being false
Could be altered, but yes.
@fiery cosmos a follow up question on this one, i have around ~40 patterns stored in lists in another file, then the list is imported.
The patterns are for an gomoku ai.
The porblem is i defined the patterns with 1-s only meaning they are like [0,1,1,0] or [1,1,1] however the players are represented with 1 and 2 on the board so i need to be able to switch beetween the values in runtime.
So i would need a switch to convert them into [0,2,2,0] and [2,2,2] respwctivly
The pattern, yes
I could but not sure how does that help me
I wanna avoid duplication of patterns, and i dont want to recreate the whole pattern set everytime i am switching players
It is said that bfs and dfs both run in O(V+E) time, does that apply for both adjacency list and adjacency matrix representations?
Where in adjacency matrix you may write the big-O as O(V^2) since |E| = O(|V|)
|E| = O(|V|^2) **
Yes, but i think i will try to implement it and then get back to you if i need any more help
Thanks
You are correct, it is O(V+E) only for adjacency list
but also usually people only consider adjacency list anyway
adjacency matrices are rare and usually used either for compression of dense graphs, matrix multiplication based algorithms (like for counting triangles), or some transitive closure algorithms (think floyd), and if you have a matrix, you can convert it to a adjacency list in O(size of the matrix), which is worse than O(V + E) (unless you have a lot of duplicate edges, which you can get rid off trivially in 99% of the cases), but... I mean... you got that matrix somehow, or at least you have memory for it allocated, so you can spend some time doing something to it, so you lose nothing in big-O terms if you run that first, and then run DFS/BSF/whatever.
so if every graph is practically representable with adjacency list, and it is a better repr, why bother with other reprs?
It's probably easier to work with adjacency matrices when writing the code out, but the performance is still worse when you have a non-dense graph. Tuple/list indexing to access weight is a constant time operation, and you're not using a significant amount of extra memory
I.e. search is still O(V)
The extra memory to store weight for each node is linear in the number of edges, so O(E)
In non-dense graphs, E = O(V) so, the extra memory totals out to O(V + E) or O(V + V) = O(2V) => still O(V)
honestly, even for weighted graphs lists are better
you just store a pair (to_vertex, weight) and everywhere you need to iterate over edges, simply use for u, w in graph[v] instead of for u in graph[v]
it's not much of a difference
fair, I guess
Here, NeetCode says his solution is O(m*n*26):
https://youtu.be/vzdNOK2oB2E?t=264
But his code is:
from collections import defaultdict
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
res = defaultdict(list)
for s in strs:
count = [0]*26
for c in s:
count[ord(c) - ord("a")] += 1
res[tuple(count)].append(s)
return res.values()
This is O(m*n + m*26) right? He got it wrong? The 26 coming from the conversion from a list to a tuple.
Sure, you're calculating it better, though remember that O(m*n*26) and O(m*n + m*26) are both O(m*n).
Yeh of course! It was just a hypothetical question in case we are using an alphabet with k letters then it'd be O(m*n*k) or O(m*n+m*k)
Ah, that makes sense.
Although I'm a bit confused as to why the O(m*n + m*26) solution (above) is longer than the O(m*n*log(n)) solution below:
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
sorted_strs = []
for i in range(len(strs)):
sorted_strs.append(''.join(sorted(strs[i])))
output = []
already_in_output = {}
for i in range(len(sorted_strs)):
if sorted_strs[i] not in already_in_output:
already_in_output[sorted_strs[i]] = len(output)
output.append([strs[i]])
else:
output[already_in_output[sorted_strs[i]]].append(strs[i])
return output
The leetcode problem he's referring to is this one: https://leetcode.com/problems/group-anagrams/description/
What do you mean by longer?
takes longer sorry
like 15% longer
I'd assume it's purely due to hashmaps overhead?
I'd mostly worry about how long it takes to construct sorted_strs - a loop over all the strings, sorting the characters of each and joining it...
(But also, note that leetcode's values are extremely unreliable; the same program resubmitted minutes afterwards can get a much different rating)
Yeh that's where the O(m*n*log(n)) comes from
Is there a better way of sorting a list of strings?
I guess that's fair
Here I'd say it's a waste of time to construct that list - just iterate over the strings, sorting each right before usage.
I'd write it like this:
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
mapping = {}
for s in strs:
sig = "".join(sorted(s))
mapping.setdefault(sig, []).append(s)
return list(mapping.values()) # it's technically not valid to omit list here, since a dict_values isn't a List
I see
This is indeed cleaner
Complexity is O(len(strs) * len(strs[i]) * log(len(strs[i]))) right?
Yup, that looks right.
In practice I expect the sorting solutions to be faster because sorting, while O(n log n), is a very optimized builtin function, whereas counting what characters the string has, despite being O(n), takes a Python loop.
like, the complexity implies that for large enough n the counting solution would win, but they'd have to some quite dramatic n.
from a bit of testing, for n=100000 sorting is still twice as fast; so naively one could expect the break-even point to be around... what, 10^10? not sure I calculated that right
You're including the generation of the random string, here
that's fair but it's the same for both right?
Sure, it'll just make the difference harder to see
I was timing these; just the sorting and counting:
s = random.choices(string.ascii_lowercase,k=100000);s="".join(s)
def count_chars(s):
counts = [0]*26
for c in s:
counts[ord(c)-97]+=1 # a
return tuple(counts)
%timeit count_chars(s)
31.2 ms ยฑ 12 ms per loop (mean ยฑ std. dev. of 7 runs, 10 loops each)
%timeit "".join(sorted(s))
16.5 ms ยฑ 318 ยตs per loop (mean ยฑ std. dev. of 7 runs, 100 loops each)
it's interesting that as full solutions the sorting one has more problems
oh no I know
in the sorting one i return a list
in the non sorting one i return res.values()
the conversion must be long
actually the 31ms one seems to have been a fluke:
In [22]: %timeit count_chars(s)
20.6 ms ยฑ 984 ยตs per loop (mean ยฑ std. dev. of 7 runs, 10 loops each)
In [23]: %timeit "".join(sorted(s))
16.9 ms ยฑ 369 ยตs per loop (mean ยฑ std. dev. of 7 runs, 100 loops each)
from collections import defaultdict
def groupAnagrams(strs: list[str]) -> list[list[str]]:
mapping = defaultdict(list)
for s in strs:
sig = "".join(sorted(s))
mapping[sig].append(s)
return list(mapping.values())
print(groupAnagrams(["eat","tea","tan","ate","nat","bat"]))
def groupAnagrams2(strs: list[str]) -> list[list[str]]:
res = defaultdict(list)
for s in strs:
count = [0]*26
for c in s:
count[ord(c) - ord("a")] += 1
res[tuple(count)].append(s)
return list(res.values())
print(groupAnagrams2(["eat","tea","tan","ate","nat","bat"]))
import random
random_strings = ["".join([chr(random.randint(97, 122)) for _ in range(10000)]) for _ in range(1000)]
# Big lists (word of size 1000)
%timeit groupAnagrams(random_strings)
%timeit groupAnagrams2(random_strings)
776 ms ยฑ 3.12 ms per loop (mean ยฑ std. dev. of 7 runs, 1 loop each)
682 ms ยฑ 3.12 ms per loop (mean ยฑ std. dev. of 7 runs, 1 loop each)
This seems fair right?
I don't see where the additional problems in the sorting one would come from
Yeah, that looks right
so taking the n to extreme, big O theory is actually right
reassuring
hard to see the difference when it's just a log
The extra time might not be coming from the sorting vs counting here, but from the hashing to access the dict
it's hard to say
they both hash as much right?
though that's again something where the counting solution should be advantaged because the length of sig grows with the inputs while the length of tuple(count) is fixed
Is there any suggested roadmap for learning algorithms? What should I learn first, learn last, or is there no real roadmap? And I should just learn whatever comes to mind.
I found this resource, but don't know if its realistic:
A better way to prepare for coding interviews.
very much conditioned on "python is slow compared to C, avoid running python in your python" ๐
no
i benchmarked the parts that only generate the keys and they still produce the same result
i can't reproduce this
the counting solution still wins at k=100000 for me
Here
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
if not needle:
return 0
haystack_stack = []
needle_stack = []
for i in haystack:
haystack_stack.append(i)
if len(haystack_stack) >= len(needle):
if haystack_stack[-len(needle):] == list(needle):
return len(haystack_stack) - len(needle)
return -1
Is this memory-efficient code? because leetcode shows it beats 95 percent in space.
66 percent in time
No you can do better. You can use O(1) (no extra arrays) if you are fine with it being O(n^2) (you know it's suboptimal and this is not a solution), right? And if you want O(n), the you can get away with O(log len(needle)) extra memory, maybe even better. So no, it is not an optimal solution in both speed and memory.
Btw this solution is super overcomplicated, it is pretty much equivalent to just writing if needle in haystack: ... else return -1. You don't even need stacks.
or if you really want to do things this way you can just use indices
if you're fine with a slight risk of error there is polynomial hashing which can do O(n) with O(1) memory
Oh, that's a good point
You can validate solution right after in O(len(needle)) so you can always be correct
But in this case it will be possible to build an example where it works in O(n^2), I think
im not sure if this is the right place to ask but is there any python library that has maths intervals? I want something like x = interval(1.2, 3.2) and the ability to check whether any arbitrary number lies in that interval or not
from sympy import Interval
x = Interval(1.2, 3.2)
Interval(0, 1).contains(0.5) -> True
ofc sympy has them
why does google search shows obscure libraries and not sympy ๐ญ
thank you
1.2 <= value <= 3.2?
or do you need fancy stuff like math on intervals?
intersections and whatnot
i have this sample code which does the follow:
x = np.arange(25).reshape(5, -1)
print(x.shape)
x = rotate(x, angle=45)
print("\n")
print(x)
x before permutation:
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]
[20 21 22 23 24]]
>>>(5, 5)
>>>
[[ 0 0 0 0 0 0 0]
[ 0 0 0 6 0 0 0]
[ 0 0 4 9 14 0 0]
[ 0 3 8 12 16 21 0]
[ 0 0 10 15 20 0 0]
[ 0 0 0 18 0 0 0]
[ 0 0 0 0 0 0 0]]```
this works as expected,
however when i try to apply it on my code:
```py
board_copy: Board = board.copy()
board_values: npt.ArrayLike = board_copy.get_board()
print(board_values)
print(board_values.shape)
rotated = rotate(board_values, 45)
print(rotated)
>>>[[2. 0. 2. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]
>>>(12, 12)
rotated:[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00
0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00
0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00
0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00
0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00
1.64769036e-04 2.01137262e-02 -8.24857823e-04 6.56837874e-03
3.73857664e-03 -1.04155600e-02 3.32723879e-04 -3.09713083e-03
1.77443895e-03 0.00000000e+00 0.00000000e+00 0.00000000e+00
0.00000000e+00]....```
why am i getting all these random values?
How can i rotate an numpy 2d array by 45 degrees? without using interpolation
Hi I've got a quick question, let's say I have a pandas dataframe with 4 columns, each row of the column either only has one non na value or they're all na. How can I extract that one value in each row or the na value if there is none into one column. I've got methods using .apply to work but my dataframe has more than 200,000 rows so its quite slow. Any way to do this better?
I'm currently halfway through it
To rotate a 2D Numpy array by 45 degrees without using interpolation, follow the steps
- Import the required libraries:
from scipy.ndimage import rotate```
2. Create a sample 2D array:
```arr = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])```
3. Define a function to rotate the array by 45 degrees:
```def rotate_array(arr, angle):
angle = np.deg2rad(angle)
rotated_arr = np.zeros_like(arr, dtype=np.float64)
center_x = arr.shape[1] / 2
center_y = arr.shape[0] / 2
for y in range(arr.shape[0]):
for x in range(arr.shape[1]):
px = x - center_x
py = y - center_y
qx = int(px * np.cos(angle) - py * np.sin(angle) + center_x)
qy = int(px * np.sin(angle) + py * np.cos(angle) + center_y)
if 0 <= qx < arr.shape[1] and 0 <= qy < arr.shape[0]:
rotated_arr[qy, qx] = arr[y, x]
return rotated_arr```
4. Call the function with the array to rotate and the desired rotation angle:
```rotated = rotate_array(arr, 45)
print(rotated)```
The rotate_array function calculates the new position of each pixel based on the given rotation angle using basic trigonometric calculations. The resulting new positions are used to assign the corresponding pixel values from the original array to the rotated array.
Note that this approach might result in some loss of precision due to the discrete nature of the resulting array.
Remember to import the required libraries and define the rotate_array function before calling it. You can modify the function as per your requirements and extend it to handle different cases.
Yes, there is a more efficient way to extract the single non-null value or NaN value from each row of a Pandas DataFrame. You can use the pd.DataFrame.stack() method followed by pd.Series.reset_index() to achieve the desired result.
Here's an example:
import numpy as np```
```# Create a sample DataFrame
df = pd.DataFrame({'col1': [1, np.nan, np.nan],
'col2': [np.nan, 2, np.nan],
'col3': [np.nan, np.nan, 3],
'col4': [4, 5, 6]})```
``` # Extract the single value or NaN from each row
result = df.stack().reset_index(drop=True)```
``` # Output the result
print(result)
Output:
0 1.0
1 2.0
2 3.0
3 4.0
4 5.0
5 6.0```
dtype: float64
By using df.stack(), the DataFrame is converted into a stacked Series object. The reset_index(drop=True) method is then used to reset the index of the resulting Series, dropping the original index and ensuring a continuous numeric index.
!rule 10
Hi I am currently struggling to understand how Quadtrees and Octrees make Depth Sorting faster
This is related to the Painter's Algorithm which is relevant in my computer graphics course and it is mentioned in the script that these trees split the scene into squares/cubes containing at most a certain amount of objects inside of them
But the thing I dont understand here is how the tree sorts itself by the position of the viewer
its so confusing
Wait is it even necessary to sort the tree 
Oh I guess it isn't necessary to sort the tree...
So the Quadtree/Octree is generated once for the entire scene then?
This is very weird. The depth sorting itself is trivial, it is just a normal sorting algorithm. You can't make that faster.
I think it is actually referring to optimizing the polygon intersection. In normal circumstances, you have to intersect every pair of polygons, but by using octrees you can get away with only intersecting polygons in the node. But at the same time, aren't kd-trees better for that?..
Doing a depth sort initially is of course just O(n log n), but wouldn't a tree structure allow inserting new nodes into the sorted tree in O(log n)? don't know if people actually do that, though.
I don't think there is a benefit from it. Traversing the octree tree in O(n) is probably slower than sorting the array of floats in O(n log n).
guys I'm trying to reverse a linked list and the output should be [3,2,1] but instead the output is [2, 1, None]. Do you guys know why this is ?
This is the file I used for learning Linked lists. I'm still new to Python so I don't know a lot.
def display(self):
screen = []
current = Node(next=self.head) # ugly af
while current := current.next: # nice
screen.append(current.value)
return screen
``` ig this should also work
i think you should rename your .display() method to .to_list()
consider making __iter__ method
it would allow you to do list(a), for example: print(list(a)) or print(*a) instead of print(a.display())
def __iter__(self) -> Iterator[T]:
cur = self.head
while cur:
yield cur
cur = cur.next
``` something like that
this is essentially a `display` function, but instead of `screen.append(x)` i do `yield x`
oh, i noticed a typo here, you should fix it ๐
thank you guys so much I was able to fix it.
In python there aren't really any thread safety problems even if some data structures like lists aren't implemented to be thread safe because python executes a single thread at a time?
You're wrong. GIL makes single opcodes atomic, but not groups of opcodes.
So during x.counter += 1 first thread can fetch this value, then second thread fetches, increments and stores here new value, then first increments it and stores.
So, two threads performed +=1 operation, but value incremented only once
!e import dis; dis.dis("x.counter += 1")
@lean walrus :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 0 0 RESUME 0
002 |
003 | 1 2 LOAD_NAME 0 (x)
004 | 4 COPY 1
005 | 6 LOAD_ATTR 1 (counter)
006 | 16 LOAD_CONST 0 (1)
007 | 18 BINARY_OP 13 (+=)
008 | 22 SWAP 2
009 | 24 STORE_ATTR 1 (counter)
010 | 34 LOAD_CONST 1 (None)
011 | 36 RETURN_VALUE
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/6A42ZV3V5VVCLY4JU6RVSU5BVY
(i dimly remember something about += on ints specifically having been made atomic recently? not sure)
To add to this, no matter which groups of operations is atomic, you can not guarantee thread safety, unless you have full control over what is shared and what is locked. For example, if two threads execute something like:
if array.len() > 0:
array.pop()
(overcomplicate this as much as you want: wrap this in classes, functions, whatever)
If the array size is 1, and one thread passes the control flow after the if, before the pop, you will get IndexError no matter what:
array = [element]
# step 1: thread 1 is about to do the "if"
# thread 1 || thread 2
> if array.len() > 0: |> if array.len > 0:
| array.pop() || array.pop()
#step 2: thread 1 is about to do the "if"
# thread 1 || thread 2
| if array.len() > 0: |> if array.len > 0:
> array.pop() || array.pop()
# step 3: thread 1 is about to do the ".pop()"
# thread 1 || thread 2
| if array.len() > 0: || if array.len > 0:
> array.pop() |> array.pop()
# step 4: thread 2 is about to do the ".pop()", but the array is empty
# thread 1 || thread 2
| if array.len() > 0: || if array.len > 0:
| array.pop() |> array.pop()
> ||
# step 5: popping from empty array :(
So you still need to care about mutexes and other means of thread safety.
ok that's a lie, there are languages where there are no locks, and you are guaranteed thread safety and, unsuprisingly, the lack of deadlocks, but those use different synchronization mechanisms
lack of deadlocks? how
well, if you've got no locks, you can't deadlock, can you? ๐
ah
This is how I explained it once: #1107246401550819338 message
Actually, some one here might also have a good idea on how to approach this: #game-development message I am running into exponential time complexity.
my matrix math is busted because matrices are weird bruh ๐ญ
a 3x2 matrix is 3 tall, 2 wide
it sure is
Anyone knows any paper that involves mastering music, what makes a professional mastered track good?
that doesn't help if he wants to keep the row label no?
@fleet verge i saw noone answered your question before, forgot to send this before the thread was locked, but heres what you were looking for to find the longest consecutive subarray
x=[2, 6, 1, 9,10,11,12,4, 5,6,7,8,9,3]
temparray=[]
prevarray=[]
currlongest=[]
for z in range(len(x)):
if z==0:
temparray.append(x[z])
elif x[z]-x[z-1]==1:
temparray.append(x[z])
elif x[z]-x[z-1]!=1:
if len(currlongest) < len(temparray):
currlongest = temparray
temparray = []
print(currlongest)
print(len(currlongest))
what do you mean?
looks like time complexity - O(n), spce complexity - O(1)
what's the time and space complexity in my script?:
class Solution: def climbStairs(self, n: int) -> int: result = 0 for i in range(n//2+1): j = n - i*2 result += factorial(i+j) / (factorial(i) * factorial(j)) return int(result)
that'd depend on the complexity of your factorial implementation
it's from math module
math.factorial(n) takes roughly O(n log n) i believe
so this loop overall is at most O(n^2 log n).
how can i add proxies to a python file
*You can precalculate factorials to improve it
the best way to improve it is actually ||to look at the output for the first few numbers and see the pattern||
Ahh lol
what a funny form though
The most interesting realisation of the ||fibonacci|| that i have seen
oh, it this the cute fact about diagonals in Pascal's triangle?
i.e. this
my consistency with the triangle wasn't great huh?
I have implemented a bijective base 35 in python from scratch, but I want to ask are there any better ways to do it ( ie some library or inbuilt package)
huh, i wonder how to prove that
wikipedia lists this fact without a proof or a reference ๐
proof by induction should work though it's a bit boring
oh, it might actually be a very boring fact
see how it adds things from the two diagonals above?
that should be very easy to show inductively
Am I missing something about leetcode-like sites? everyone suggests I should be 'improving' or 'learning' something and if i'm having problems just do more of them, but they dont seem to be educational, more like asking a 5 year old what's the square root of different numbers are until they somehow miraculously come to a viable solution?
(aside from the questions seemingly not applicable to real world applications and more just a brain teaser)
I think theyโre good measurements of a very narrow ability for certain classes of algorithms.
I guess I was looking for something that could give me off the wall interview like questions but it seems leetcode-likes are more tuned to problem analysis and familiarity with ds/algos which, I dunno it's fine but it's more about if you already understood the problem and are familiar with the solution, and if you're not you're stuck in the sand. There's not many sources explaining the problem analysis to it either so you're stuck just reverse engineering solutions that people post and... well it just doesnt feel very productive
Personally, I agree. I might ask one leetcode style question per interview, and only because I want to see whether candidate can work through that class of problem. Itโs a useful skill and shows maturity in thinking, but thereโs plenty of things to learn
Problems that are just "you either know the solution or not" are generally bad interview questions. The good interview questions will assume some basic ds&a knowledge, and will expect you to break a problem apart into managable pieces that can be attacked with this knowledge
I generally don't find leetcode a good site. The problems are either badly posed or have really crappy constrainst or test cases (or all of that)
I am trying to recusively remove adjacently repeating characters from a string and only leave one character such as "Hellllo Worlllld" returns "Helo World", however the issue that I am running into is that repeating characters of more than 2 my algorithm isn't able to remove and leave one character. Is anyone good at recursion and want to check out my algorithm?
Generally just ask the full question already and post the code. Allows people to drop into the channel and help if they feel like it
Ok so I am trying to recusively remove adjacently repeating characters from a string and only leave one character such as "Hellllo Worlllld" returns "Helo World", however the issue that I am running into is that repeating characters of more than 2 my algorithm isn't able to remove and leave one character. Is there a way to allow me to remove repeating adjacent characters that are greater than 2, and only leave one?
def collapse_string(value, search):
if not value:
return value
else:
if value[0:1] == search and value[1:2] == search:
value = value[1:]
if value[2:3] == search and value[3:4] == search:
value = value[1:]
`return value[0] + collapse_string(value[1:], search)`
this would technically work, but the slicing is unnecessarily expensive
def collapse_string(value, search):
if not value:
return value
while value and value[0] == search:
value = value[1:]
return value[0] + collapse_string(value[1:], value[0])
this then, though again this is slow because of slicing
def collapse_string(s, last=''):
if not s:
return last
if s[0] == last:
return collapse_string(s[1:], s[0])
else:
return last + collapse_string(s[1:], s[0])
you can make it neater with a generator
They want the function to accept a string suchas VALUE and a search parameter such as SEARCH in order to compress the string by the passed in SEARCH argument
that doesn't match what you said before 
I am trying to recusively remove adjacently repeating characters from a string
Apologizes, I thought my code would be a good illustration of what I was going for
regardless, passing an extra argument with the last character seen will make your life easier
you can easily modify the function I gave to only apply the logic to a specific character
So it works, however it seems to remove ever instance of "l" when I replace LAST with SEARCH = "l"
I'd want "Helo World"
def collapse_string(value, search):
if not value:
return value
`if value[0] == search:`
`return collapse_string(value[1:], search)`
`return value[0] + collapse_string(value[1:], search)`
print(collapse_string("Hellllo Worlllld", "l"))
that is cool, despite it is easy to prove
- horizontal lines - sum up to 2^n
- diagonal lines (from your picture) - sum up to fib_n
- maybe other diagonals will result in nice result?
i think, there are even more cool sums in pascal's triangle
idk what this is
oeis doesnt have this sequence
oh, wait, im dumb
there should be 6 instead of 5
reading oeis is now my new hobby
it is crazy how many interpretations this simple sequence has
there is the hockey stick identity
fibonacci?
yeah
I figured out what the issue was, before the logic of my code was if value[0] == search therefore with this logic statement I would remove all instances of search value. But with this new logical statement if value[0] == search and value[1] == search allows me to delete all instances of adjacent repeating characters in the string while also saving one character, so not delete all instances of search. Thank you for the help
Seems though with different values it goes out of range interesting
Hi guys, I want to write code to convert my data from a list of strings to a dictionary tree,
This is the sample data
keys_list = [
'aProperty.aSetting1',
'aProperty.aSetting2',
'aProperty.aSetting3',
'aProperty.aSetting4',
'aProperty.aSetting5',
'aProperty.customSettings4.checkThisOut',
'bProperty.bSetting1.bPropertySubSetting.cData1',
'bProperty.bSetting2',
'cProperty.cSetting',
]
I want it to be in this format
data = {
"aProperty": {
"aSetting1": 1,
"aSetting2": 2,
"aSetting3": 3,
"aSetting4": 4,
"aSetting5": 5,
"customSettings4":{
"checkThisOut":"you will see"
}
},
"bProperty": {
"bSetting1": {
"bPropertySubSetting": True
},
"bSetting2": "bString"
},
"cProperty": {
"cSetting": "cString"
}
}
How can I do this please. I am sure the solution would be using recursion .please note that sample 1 isn't not exactly the same with sample 2, but you get the point, the point is to split the string by the dots into nexted properties.
hello my best ๐๐๐
I thought about this approach but I think I will have to define a seperate iteration block for each step I want the function to go, because for this scenario, I will be having a string of any depth, meaning it can be like "a b.c.d.e.f"
Uhm.. I do not understand, could you give a code snippet
hello
wassup
is making algorithm difficult? imma try to do my hw and its difficult for me since i nub
it's very global question
there are a lot of different algorithms with different difficulty
hi can anyone help me with some theory of computation on propositions?
just ask the question
Can someone explain this?
A short footpath is divided into four numbered squares. You start at square 1 (at time 0). Time is a series of discrete steps. At each timestep, you either step one square forwards or one square backwards, never standing still. You must not move backwards from square 1. For each square s=1,2,3,4 and each time t=0,1,..., let v(t,s) be the proposition with the meaning:
At time t you are at square s.
How many clauses would be needed in a CNF expression to completely describe the rules of movement for t=0,1,2,3 ?
depends, there are a lot of ways to build CNF
even if you consider the most natural ones, it is not obvious
for example, you can eliminate about half of all variables if you consider that you cannot stand on even square on even timestamp
but generally, to aswer that question you simply introduce boolean variables and then describe relation ships between them in a boolean formula, which you then convert to CNF
in this example, you can have t * t variables, X_(time, pos) means that at the time time you are at position pos
and then add constraints from the problem
I think you need 1) X_(0, 1) is true, which is a unit clase, 2) X_(time, pos) --> X_(time + 1, pos - 1) or X_(time + 1, pos + 1), if in bounds. That's a clause of form (!X_(time, pos) or X_(time + 1, pos - 1) or X_(time + 1, pos + 1)), and 3) X(time, pos) --> for every p != pos, not X_(time, p). That's t - 1 clause for every time.
but the question does not really make sense to me
just learned about the word RAM model of sorting. pretty cool
In theoretical computer science, the word RAM (word random-access machine) model is a model of computation in which a random-access machine does bitwise operations on a word of w bits. Michael Fredman and Dan Willard created it in 1990 to simulate programming languages like C.
is anyone considering making a new map app based on the new dataset? i'll get a link
is it published what sorts of algorithms are used to operationalize google or apple maps?
A*
that's pretty much it
of course, it is augmented with a lot of additional heuristics
landmarks is a big one
yeah i saw another resource claiming it was dijkstra's and A*
there are also various tree decompositions methods to help split the problem into smaller parts
also maybe some grid heuristics, idk how often those are used though
If the graph is not "geographical", you can run force simulation on it in N-dimensional space, and it usually becomes more applicable for A* after that
so basically, it's just A*, and seven human-years of work to make it run better for every specific problem
who developed A*
I heard that it was an algorithm for a problem on some competitive programming contest
and it was a harder version of the problem A
so it was labelled A*
and the name sticked
Hart, Nilsson, Raphael
A Formal Basis for the Heuristic Determination
of Minimum Cost Paths
that sounds more believable than what I have been told lol
if arr is []:
return 0
for i in range(len(arr)):
if sum(arr[:i]) - sum(arr[i+1:]) is 0:
return i
return -1
what time complexity would you say this code is?
I think its O(n) but I only vaguely understand what that term means anyways
probably quadratic
how would I optimize it?
prefix sum
I uh, don't get what that means
you do a cumulative sum over the array, then do math to get the answer
class Solution:
def maxConsecutiveAnswers(self, key: str, k: int) -> int:
l,r = 0,1
maxa = 0
while l <len(key):
while r < len(key)-1:
if key[l] == key[r]:
r+=1
if key[l] != key[r] and k!= 0:
r+=1
k-=1
if key[l] != key[r] and k== 0:
break
maxa = max(maxa,r-l+1)
print("k",k)
print(maxa)
print(key[l:r+1])
l+=1
r+=1
return maxa
```
I am thinking something like that but not working
My approach is moving r until we got key[l] != key[r] and k== 0
and we decrease value of k if we got key[l] != key[r]
Heya! @fiery cosmos
Hi!!!!!!!
should all algorithms be less than O(N ^ 2)?
why does every tutorial say that it is bad
this question doesn't make sense. there are things you can't possibly do in less than O(n^2)
it's bad for certain tasks, great for others
does algorithm has certain limit
or do you just keep learning new stuff all the time
not sure what this is doing
I kind of understand the idea
but I think it fails because
- greedy narrowing is sub-optimal
- iterative narrowing works only when you assume that you replace only 'T' or only 'F'
for example, here with k=3:
if you greedily narrow, then each time you'll choose to move the right boundary to the left, because it costs less in terms of length
can u share ur solution?
One more question if anyone?
class Solution:
def findTheDistanceValue(self, arr1: List[int], arr2: List[int], d: int) -> int:
arr1.sort()
arr2.sort()
print(arr1)
print(arr2)
def feasible(m):
print(arr1[m])
ans = False
for i in arr2:
print("diff: ",abs(arr1[m]-i))
if abs(arr1[m]-i)<=d:
ans = True
break
print(ans)
return ans
left, right = 0, len(arr1)-1
while left<right:
mid = left + (right-left)//2
print("mid: ",mid)
if feasible(mid):
right = mid
else:
left = mid+1
return left
```
what performance time does it achieve?
Not working
this was my first attempt:
||```py
def solve(s, k, q):
ix = [-1]
for i, c in enumerate(s):
if c == q:
ix.append(i)
if len(ix) <= k + 1:
yield len(s)
return
ix.append(len(s))
i = 0
j = k + 1
while j < len(ix):
yield ix[j] - ix[i] - 1
j += 1
i += 1
class Solution:
def maxConsecutiveAnswers(self, s: str, k: int) -> int:
return max(max(solve(s, k, 'T')), max(solve(s, k, 'F')))
important tag:
I solved it very memory-inefficiently, for the benefit of faster times
Great!
You have impressive skills
There is also a pretty nice way to solve the problem without seperately doing it as two cases
def solve(s, k):
true_count = false_count = j = 0
for i in range(n):
if s[i] == 'T':
true_count += 1
else:
false_count += 1
while min(true_count, false_count) > k:
if s[j] == 'T':
true_count -= 1
else:
false_count -= 1
j += 1
yield true_count + false_count
hi. wondering if anyone has had experience working with recommendation systems/algorithms. ive found some open source projects and familiarized myself with how theyre made
if you have advice, please tell. thank you
Ok after 10 min of thinking I got it
It is something like this
We have to iterate over those 2 arrays ( nested loops )
back with internet now let me continue
it should be like this:
for num in array1:
for num2 in array2:
now we have to subtract those two from eachother and have to compare that with d if it less greater than or equal to it
If no element in in array2 can statisfy element of array 1 then we will add 1 to our track variable
def distance_value(arr1, arr2, d):
count = 0
for num1 in arr1:
print(f"num1: {num1}")
for num2 in arr2:
print(f"num2: {num2}")
if abs(num1 - num2) <= d:
print("True")
break
else:
count += 1
print(f"count added, new count: {count}")
return count
there we go
Note i realized that abs was important caus we can also a get a negative subtraction and a negative number is never equal to positive number
I finally learned bubble sort yesterday lmao
in python of course, thinking about making it in C++ or C
Or Java, I don't know lol
ALSO
whats the use of binary trees?
you can do that, but it's much more expensive than what's really needed
Hii @haughty mountain
Can i solve this problem with this approach
Hey folks,
I want to create an object of type C and add it to a set, there will be duplicates so I want them to be removed.
I know sets use hashing to distinguish between objects, but I have no idea how the objects are hash.
The object will have two fields (string and enum), I can do with the string field being different, that'll be enough.
Help would be appreciated :)
def __hash__(self) -> int:
return hash((self.s,)) # hash only str field
return hash((self.s, self.e)) # hash enum field too
- implement
__eq__
Yeah
as said above you absolutely want to ensure (and test) that equals objects imply that they have the same hash, so a == b -> hash(a) == hash(b), otherwise you're up to very nasty bugs (speaking from experience years ago! that I still remember)
do we have a polynomial time algorithm to find minimum cost walk to visit all the nodes atleast once?
The travelling salesman problem (TSP) asks the following question: "Given a list of cities and the distances between each pair of cities, what is the shortest possible route that visits each city exactly once and returns to the origin city?" It is an NP-hard problem in combinatorial optimization, important in theoretical computer science and ope...
No
i know this... please note that, i'm asking about a walk where each node and edge can be visited more than once
Thats the same problem
Note that this wiki page also explains why it is the same problem
Hi, i'm currently learning python and it's the first time I do some algo and i'm really bad at it so I would like to know if you have some good ressources to be better at algo ?
anyone here that knows algos at least well?
why dontasktoask link is banned :(
hello every one. I need some learning material for data structures and algorithms
Google - chrome
Or on edx.org the course about data structures and algorithms
freecodecamp has made a tutorial on it too
hello.
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
charset=set()
x,res=0,0
for y in range(len(s)):
------->while s[y] in charset:
charset.remove(s[x])
x+=1
charset.add(s[y])
res=max(len(charset),res)```
This is the solution for finding the longest string that doesn't repeat(leetcode 3) .Can anyone tell me why do we use `while` instead of `if`. Doesn't `charset` only contain one copy of every element, using `set().remove(element)` should work if done once.
What happens here is it removes characters s[x], s[x+1], s[x+2].... from charset, until s[y] is no longer in it - in other words, until we hit and remove a character equal to s[y].
Thanks for the reply,idk how i didn't figure it out
Is there a recursive DP implementation to calculate fibonacci numbers?
i figured out a naive recursive, and a iterative DP, but am struggling to get the recursive DP
What comes to my mind is returning a pair:
def fib2(n: int) -> tuple[int, int]:
"returns fib(n) and fib(n-1)"
if n==1:
return 1,1
b,a = fib2(n-1)
return b+a, b
without it, not sure how it can be done, since the "chain" of recursion will only get you half the needed values. Well, unless you just slap a functools.cache on the function, turning the naive recursion solution into a DP one.
okay i managed to slap together one (well technically two functions)
that's actually a really neat way of doing it
took me a while to grasp it, and i guess you could just have another function that returns only the first part of the tuple
yup
you could also just add a cache in this case
and yeah, this is directly translating a loop to recursion
which is basically never pretty
Guys, starting off programming
Could anyone explain what the string variable means
this doesn't really have anything to do with algorithms, a more appropriate place would be #1035199133436354600 or #python-discussion
Sorry about that
anyone know how i can replace the classic movie lens dataset with my own for a recommendation system? this is the model ill be using: https://github.com/microsoft/recommenders/blob/main/examples/02_model_collaborative_filtering/cornac_bpr_deep_dive.ipynb
what do you need help with?
just finding the answer
i really suck at algebra
i understand how the rotations work and balacne factors work but
just doing that algebraic expression confuses me a lot
ok, but where is the question you need to answer?
B is connected to hA and hC
D is connected to hE
^ this is oldBal(B)
B is conneceted to hA
D is connected to hC and hE
this is newBal(B)
balance factors values can only be like 1 or 0
i just dont know how to express it alegbraically
its in #algos-and-data-structs
this is the question
i just dont know how to notate it and solve it liek this
Which string variable?
Memoize it
So the definition of balance factor is height of left subtree minus height of right subtree.
There are two errors in that calculation. The sign is wrong after the first =. Also, h_a - h_c isn't newBal(B), it is oldBal(B)
To solve the problem of finding newBal(B) - oldBal(B), just substitute in their definitions and see what you get
The h_a will cancel, and you will be left with some expression involving h_c and h_e
don't worry, already understood
def bfsOfGraph(self, V: int, adj: List[List[int]]) -> List[int]:
visited = [False]*V
queue = []
queue.append(0)
visited[0] = True
i = 0
while i<len(queue):
for v in adj[i]:
print(adj[i])
if not visited[v]:
visited[v] = True
queue.append(v)
i+=1
print(queue)
return queue```
What is wrong in my bfs?
You don't mark the starting vertex as visited
but 0 is the starting vertex
and?
If your graph is a cycle of two vertices, you will visit 0, then 1, then 0 again
Given a directed graph. The task is to do Breadth First Traversal of this graph starting from 0.
I think no cycle
I don't think it says it anywhere
that's why visited use
Then you must mark 0 as visited at the start
I marked
Oh, still no?
Lemme see
Ohhh
You use the index of the head of your queue instead of actual vertex
You store vertices in queue, but you never access it
And when you do adj[i] you get vertices adjacent to some other vertex, not the vertex at the head of the queue, which is adj[queue[i]]
but adj[queue[i]] is also don't work
ok weird, I don't see anything else
!e
def bfsOfGraph(V: int, adj: list[list[int]]) -> list[int]:
visited = [False]*V
queue = []
queue.append(0)
visited[0] = True
i = 0
while i<len(queue):
for v in adj[queue[i]]:
if not visited[v]:
visited[v] = True
queue.append(v)
i+=1
return queue
print(bfsOfGraph(4, [[1, 2], [0, 3], [0, 3], [1, 2]]))
@outer rain :white_check_mark: Your 3.11 eval job has completed with return code 0.
[0, 1, 2, 3]
ok, I don't see what I am missing, perhaps someone else will notice
Why do you think that it is wrong? It looks correct to me
Btw I've personally always been a big fan of coding bfs like this in python
!e
def bfsOfGraph(V: int, adj: list[list[int]]) -> list[int]:
visited = [False]*V
bfs = [0]
visited[0] = True
for u in bfs:
for v in adj[u]:
if not visited[v]:
visited[v] = True
bfs.append(v)
return bfs
print(bfsOfGraph(4, [[1, 2], [0, 3], [0, 3], [1, 2]]))
@regal spoke :white_check_mark: Your 3.11 eval job has completed with return code 0.
[0, 1, 2, 3]
It doesn't matter if there is a cycle or not. BFS can be done on any type of graph.
Wow, iterating over a list you expand seems very cursed, but I see how it will work. Less memory-efficient than a queue though.
I guess it can be a bit less memory efficient. But at the same time, it is nice to be able to store the bfs order since you can reuse it.
It can also be very convenient to not have to import deque and try to recall what deques methods are called
I wonder if it is less memory efficient though...
Of course it is O(n) worst case, but if you take a random graph, wouldn't it also be O(n)?
If that's the case, what is the constant?
you're likely to want some per node info anyway
In my experience it doesn't really matter if the bfs is slightly less memory efficient than what is theoretically possible. Storing the graph usually takes considerably more memory anyways, so it likely won't matter.
18 level 1, 9 level 2, 30, level 3, 50 level 4
its 4 correct?
thank you
@fiery cosmos
do you think this is 2?
or 1
its height of right subtree
minus height of leftt
so i think its 3 -2
or wait
2 - 3
it might be -1
i think its -1?
Balance factor of a node in an AVL tree is the difference between the height of the left subtree and that of the right subtree of that node. The self balancing property of an avl tree is maintained by the balance factor. The value of balance factor should always be -1, 0 or +1.
it has to be -1 or 0 or + 1 so its not 2
and its not 0 because we have an uneven
one sub tree is higher
The balance factor of a node is the height of the subtree rooted at its left child minus the height of the subtree rooted at its right child
ah so +1
this example is similar
so i think its +1 for sure
im guessing 3
p.s. to highlight code you need triple `
!code
Where we can hire people?
Thanks it's work but why my code is not working?
what website is that?
btw who is telling you that the "secretCode" is always a number
that's the problem
for somecases the secret code is "\u00a0"
this is not the server for that
this a python discord server, and a channel dedicated to algorithms, and you ask why your java code does not compile
do not do that
(anyway, you probably copied that code from somewhere and it copied with non-breaking spaces instead of normal ones. Just rewrite it, or replace all nbsp-es with default ones)
this is bullshit, ignore that
how is your code not working?
this thing gave the expected ordering
ik, but why doesn't it work for @summer fossil?
I can't be just debug prints, right?
Because aside from that their code looks ok to me
is that like the wrong text formatting?
I'm currently doing this problem: https://codeforces.com/contest/1851/problem/E
My answer uses memoization to avoid calculating the price of potion i twice since calculating it may call loads of other calls and maybe i have done it already.
Here is my code:
from __future__ import annotations
def find_price(pot_idx) -> int:
if final_costs[pot_idx] is None:
if pot_idx in unlimited_potions:
final_costs[pot_idx] = 0
return 0
else:
if mixes[pot_idx]:
cost_mix = sum([find_price(i) for i in mixes[pot_idx]])
if cost_mix >= costs[pot_idx]:
final_costs[pot_idx] = costs[pot_idx]
return costs[pot_idx]
else:
final_costs[pot_idx] = cost_mix
return cost_mix
else:
final_costs[pot_idx] = costs[pot_idx]
return costs[pot_idx]
else:
return final_costs[pot_idx]
if __name__ == "__main__":
n_tests = int(input())
for _ in range(n_tests):
n, k = map(int, input().split())
costs = list(map(int, input().split()))
final_costs = [None for _ in range(n)]
unlimited_potions = list(map(int, input().split()))
unlimited_potions = [k - 1 for k in unlimited_potions]
mixes = [[] for _ in range(n)]
for i in range(n):
mix_i = list(map(int, input().split()))
if len(mix_i) > 1:
mixes[i] = [k - 1 for k in mix_i[1:]]
for pot_idx in range(n):
final_costs[pot_idx] = find_price(pot_idx)
for cost in final_costs:
print(cost, end=" ")
print()
And I have:
Time limit exceeded on test 8
Without memoization I have:
Time limit exceeded on test 4
Can someone help me? I'm a beginner.
Codeforces problems are usually not solvable in python and only in c++
because of the time limits
they are usually solvable, especially for something like div3
there is also pypy
that with enough skill and know-how can get you really really far
i ithink that doesnt make sense
because of the time complexity you can change the code to make a code in python faster
oh there for sure are problems where the intended solution written in python can be too slow
On line 5 you do O(n) operation
ah, nice find
when I do:
if pot_idx in unlimited_potions:
final_costs[pot_idx] = 0
return 0
?
yeah
Maybe I should use a set for unlimited_potions then?
and yeah
since a set is hashed it's O(1), is that true?
Div3 is usually even made in a way to be solvable in python, the problems really only begin to arise at problem D of div2 when python arrays become too slow, trees become impossible to write because of function call overhead, and there no good built-in collections :(. But yeah, you can go very far in python.
you could even put the zeroes in the lookup directly
just a loop and set zeroes
would also start simplifying the function
if you set the zeroes outside before calling and simplify a bit the function can become
def find_price(pot_idx) -> int:
if final_costs[pot_idx] is None:
if mixes[pot_idx]:
cost_mix = sum(find_price(i) for i in mixes[pot_idx])
final_costs[pot_idx] = min(costs[pot_idx], cost_mix)
else:
final_costs[pot_idx] = costs[pot_idx]
return final_costs[pot_idx]
that's fair yeah
annoyingly, no really nice way to remove the inner if-elaw
So update, I got past test 8 thanks to your idea
But runtime error on test 12 so I guess I made another mistake haha
recursion depth probably
I'm actually surprised that had that much of an impact
sounds like it
but i guess it was called n times at worse
when I do contest problems in python I usually avoid recursion if I can
though maybe you can get by with increasing the limit this time
I already had
sys.setrecursionlimit(2*10**9)
I don't know what's the maximum though
that probably is above the maximum if you got a stack overflow, lol
it worked for smaller cases
mmmh
resource.setrlimit(resource.RLIMIT_STACK, (2**29,-1))
This may help
No promises though
I'm thinking how I can make it so that it's not recursive
you need to evaluate things in the right order
It says runtime error ๐ฆ
so it turns into a graph problem
๐ฆ
find a topological ordering of a DAG, compute in that order
There is also starting a new thread with bigger recursion limit, I don't remember if that is allowed on cf though
Anyway, better rewrite non-recursuvely
would it crash as soon as it was set higher?
Ok not gonna lie I've tried to google stuff around what you said but i still have no idea what it means
I know what is a DAG but that's about it
a topological ordering is an ordering where the "dependencies" of a node are always before the node itself
oh so knowing what's the right order is
like i need to find the potions which depend on no mixes
then the one that depends on no other or the ones i just computed
etc etc ?
and this iteratively
(btw thank you so much guys for helping)
one simple algo that I like is conceptually that you keep chopping off leaves of the DAG
chopping off a leaf might expose a new leaf that is now valid to pick
seems this is known as Kahn's algorithm
In computer science, a topological sort or topological ordering of a directed graph is a linear ordering of its vertices such that for every directed edge uv from vertex u to vertex v, u comes before v in the ordering. For instance, the vertices of the graph may represent tasks to be performed, and the edges may represent constraints that one ta...
oh so you make the graph, then you sort it, then you process the leaves, you chop them off, you process the leaves, etc ...
no sorting
in this algo you would find all leaves, and then keep removing leaves until you have nothing left
the order you process the leaves is a topological ordering
oh ok
so now I just need to figure out how to create the graph
obviously the first leaves are the "free" potions
This is the 2nd time I've seen someone struggle on this exact codeforces problem with Python. https://codeforces.com/blog/entry/118668#comment-1051846
My advise is to submit in PyPy3, and avoid using sys.setrecursionlimit. Instead you can use https://pyrival.readthedocs.io/en/latest/bootstrap.html .
I tried doing this modification to your code and it gets AC
https://codeforces.com/contest/1851/submission/217020819
I would assume learning how to do it iteratively is better for learning purposes?
Especially if you want to use Python in the long run, ye
I linked to an iterative solution in my comment on that blog
Well thatโs where my second question comes in, if I start doing harder contests are there questions that are not solvable on python just because it takes too much time?
Compared to a compiled lang
As someone that has solved a ton of codeforces problems purely using Python, I would say that it is unlikely a problem is unsolvable in Python.
Thatโs fair
but you might need to fight for it...
But you sometimes need to put in a lot more work of getting the code to not TLE even if you have the intended solution
Do you know what isograd does? Iโm training on codeforces because my uni organises a competition next year on isograd and isograd doesnโt have a ton of problems
Sorry if Iโm getting off topic btw
I don't know about isograd
in the distant past when I competed I used python when I was confident it would be fast enough without too much hackery, but switched to C++ when I felt I needed raw performance
pajenegod is more of a python masochist than me ๐
why nยฒ?
It will be O(m), where m is number of edges
I need to iterate through all the potions, to add the easiest ones, than re-iterate to add the ones I can make using the ones I already solved, than re-iterate to add ... and this maybe n times because maybe potion n needs n-1 which needs n-2 which ... needs 1
I'm definitely missing something
dag means directed acyclic graph
yeh something like this right?
oh i just realized, you literally code a graph
like a dictionary of nodes and value is a list of the other nodes it goes to?
it just irked me that you said directed ... graph graph don't mind me
and that's O(m) m the number of edges
oh sry my bad
there you would find leaf e, you remove the edges going to e and note that d is a new leaf
hey guys good resources to learn in deep cp?
then remove the edges to d and b and c are exposed as leaves, ...
you can do this pretty lazily
ok and my initial set of leaves is literally the set of "free" potions?
the one i used to treat as a list and that cost me O(n) instead of O(1)
I haven't read the problem closely, but I think yes
I'm gonna give it a go!
this is worth learning regardless
DAGs and topological orderings pop up a bunch
I actually thought competitive programming was easy before starting to train for it a few weeks ago
damn
but it's cool i really like it
getting to div3E within a few weeks isn't too shabby
well it took me a bit more than the time of the competition
There are two ways to find a topological ordering of a DAG.
-
Either do what @haughty mountain is saying and pick and remove one leaf at a time
-
Or do a dfs and pick and remove the outer nodes first (which is what my iterative solution does).
Both of these are common ways to find a topological ordering. For your graph you should end up with either [e,d,c,b,a] or [e,d,b,c,a] (both are valid topological orderings).
ah right, you can also do a dfs to get a topological ordering
Ye, which is very similar to how @stiff quartz dfs solution works
and you get to learn how to do an iterative DFS
which also generalizes to BFS
and Dijkstra
It definitely takes a long time to get good at competitive programming. You have to grind quite a lot of problems before you get good at it.
I think that competitive programming is a great complement to theoretical algorithmic studies. In competitive programming you get to learn to apply and implement algorithms
(i'll answer in five minutes i'm just trying to understand why my solution doesn't work right now ๐ )
damn this is hard because if you remove the edges, then you can't do sum([final_costs[child] for child in dag[leaf]])
so you need a copy of the dag in which you remove the edges but you need to keep the original dag?
I'm a bit struggling to see those equivalences between the iterative and the recursive versions but I hope I'm getting there haha
Yeah I realized ๐
I agree!
right, you would work on a copy or keep other data
e.g. it's enough to keep track of the number of children
You typically dont modify the graph. Instead you keep a boolean list which says if a node has been "removed" or not
Then you ignore any node that has already been removed
you decrement this count of children, if you reach 0 it's a new leaf
Oh I did this:
for node, children in dag.items():
if leaf in children:
children.remove(leaf)
if len(children) == 0:
leaves.append(node)
It's probably a disaster complexity wise though
Everytime I remove a leaf I did this
I was doing the fiery frumpy fenix option
ye
This will be too slow
Makes sense
as said, the thing I usually do is keeping a count of children
Yeah but when you remove a leaf
You can't access its parents
Easily
Without going through all the nodes
Unless you also a keep of parents for each node
you can build a reverse graph
Which i guess would be fine (trade off space complexity time complexity?)
Btw I dont think that children/parent is a good terminology for a DAG.
It is commonly used for trees
A rooted tree is a DAG yes, but not every DAG is a rooted tree
a rooted tree is a DAG
Yes I think with @haughty mountain approach then you will have to build the reverse graph
my graph is a dict[int, list[int]], is that the correct data structure for it?
I feel like if I want to build a reverse graph it might be complicated complexity wise
that's fine
Oh no I can just create it in parallel of creating my initial graph
though you could even use list[list[int]]
That works. I personally prefer a list of lists because it runs slightly faster. But a dict of lists is fine too.
using a set instead of a list in the inner part is also an option that can sometimes be useful, if you need to be able to remove quickly
I don't recall ever having to do this, but it is an option
you can usually do other things yeah
e.g. in this toposort case a fast remove might be nice, but you can also just keep track of the number of out edges
Ye the common method to remove nodes is to not actually modify the graph. Instead you "remove" the node by marking the node as "removed" in some list
oh
makes sense
my brain is currently exploding
damn ok i implemented it
but I think
it's too slow because removing an element from a list is too long
removing from a set is O(1)?
i guess yeah it makes sense
yes
a set is basically elements that are not contiguous in memory
and to find the reference
you hash the integer for example
and it gives you where the element is (by pointing to an index in an array)
along with a bit saying if it's in the set?
first time in my life i have a memory limit ๐
Btw I took a peek at your code. I think it would be a lot easier for you if you just started by creating topological ordering, and then use that topological ordering to solve the problem
It is a lot easier to solve the problem in steps
Um which code?
I knew which problem you are solving, so I went into status and sorted by last submission for that problem
oh fun
Oh I understand what you mean
First I create an array of what nodes to look at
That is also how I submitted a modification of your code here.
yes exactly
Ok it's true that it's a lot more readable
But as expected it didn't change time nor space complexity
Maybe maintaining a dag AND the reverse dag is too expensive
No I think there is simply a bug in your code
The variable leaves should be initialized as all nodes u for which dag[u] is empty
I think that's what I'm doing?
cannot_be_created_with_mix: set[int] = set()
for i in range(n):
mix_i = inlt()
if len(mix_i) > 1:
dag[i] = set([x - 1 for x in mix_i[1:]])
for child in dag[i]:
reverse_dag[child].append(i)
else:
cannot_be_created_with_mix.add(i)
dag[i] = set()
# Leaves = cannot_be_created_with_mix
leaves: list[int] = list(cannot_be_created_with_mix)