#algos-and-data-structs
1 messages Β· Page 35 of 1
I agree, however, it doesn't seem to me that I'm doing something different
oh wait, ye ok
Oh, maybe the problem is sum([final_costs[child] for child in copy_of_my_dag[node]])
I'm doing this sum way too many times
It doesn't really address the space complexity though
oh no it does, I don't need to have a copy of my dag
Your code gets AC using PyPy3 (if you remove that sys.setrecursionlimit call, otherwise you will get MLE) https://codeforces.com/contest/1851/submission/217030953
So your code is good
Oh
It runs a tad bit slow, but that is to be expected since you are using dictionaries and sets everywhere
What is PyPy under the hood
It compiles Python?
Whereas CPython compiles Python to intermediate bytecode that is then interpreted by a virtual machine, PyPy uses just-in-time (JIT) compilation to translate Python code into machine-native assembly language.
I never understand anything when things like this are written
PyPy is basically Python but with a JIT.
I always thought JIT was not as good as compiling
If you do JIT you compile a lot of times?
If you compile it beforehands you don't lose as much time?
Ye it definitely isnt as good as compiling, but many times it is faster than not using a JIT
The issue with Python is that you cant really compile it before running it. Kind of your only possiblity to speed up Python is to use a JIT
π
Nice!
You can also try out modifying your original solution like this https://codeforces.com/contest/1851/submission/217020819
It isn't like your orignal submission was wrong
With a DFS?
Oh, with the bootstrap thing
Yeh, I saw it but I thought it might be interesting to learn how to do it iteratively
boostrap is a funny invention of mine, I find it very useful
You know how recursion uses a stack, right?
Ehm
Yeh I'm not sure I understand the code
I figured you had your own stack instead on relying on the one the recursive calls automatically make
So you store everything in an object?
btw you can just do a print(*thing) to print space separated stuff
oh
damn clever
The bootstrap code is pretty crazy. I doubt even the biggest Python nerds here would understand how it works without thinking about it for a while.
Interesting, I've never tried asking chatgpt about it. Maybe you could try asking it to explain some code that uses bootstrap
!e
from types import GeneratorType
def bootstrap(f, stack=[]):
def wrappedfunc(*args, **kwargs):
if stack:
return f(*args, **kwargs)
to = f(*args, **kwargs)
while True:
if type(to) is GeneratorType:
stack.append(to)
to = next(to)
else:
stack.pop()
if not stack:
break
to = stack[-1].send(to)
return to
return wrappedfunc
@bootstrap
def fib(n):
if n <= 2:
yield 1
else:
yield (yield fib(n - 1)) + (yield fib(n - 2))
print(fib(10))
@regal spoke :white_check_mark: Your 3.11 eval job has completed with return code 0.
55
You can check the conversation I tried to have with it
But ngl, I do understand what you're trying to do
But not sure I understand each line of the bootstrap wrapper π
Wow that is impressive
That is scarily accurate
The secret to understanding it is to know how generators work in Python
A function is a generator if it uses yield
You can interact with a generator by either using next or send.
send let's you send information back to the generator, so by using send the yield expression can have a return value
That is how something like this can make sense yield (yield fib(n - 1)) + (yield fib(n - 2))
It's the paid version, might be why it's a bit more impressive than what we usually think chatgpt can do
Do you understand how send works?
I'm trying to figure it out
oh the yield inside the generator
receives what the send sends?
Yes
!e
def adder():
x = yield 0
while 1:
x += yield x
G = adder()
print(next(G))
print(G.send(5))
print(G.send(8))
@regal spoke :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 0
002 | 5
003 | 13
yep makes sense
I was gonna say i don't know when i would ever use that
but you obviously found a very interesting use case
interesting/mildly cursed
what's the if stack path again?
oh wait, it's more cursed than on first glance isn't it
Calling fib(10) initializes the bootstrap if the stack is empty, but otherwise you are inside fib, and in that case fib(10) returns a generator
It definitely is pretty cursed 
So I tried doing the dfs thing
And I've been quite stupid
Cos my dfs function was recursive
It is a good idea to implement the dfs solution with recursion at first, and then think about how to switch out the recursion with pushing and popping a stack
Yeh I wanted to try your idea because we didn't need like three objects holding the graph simultaneously (dag, reverse_dag and original_dag)
And no sets either
And the solution actually works perfectly on Python
Well you never actually need any sets or dicts
yeh for the remove i could've used an array of booleans to keep track right?
Well yes, but for the leaves approach you also need to keep a count of how many "live" parents a node has
I can see pros and cons for both methods
Yeah the topological sort using dfs is a bit weird because you kind of launch dfs n times since there's no "initial root"
This is a very common approach for a ton of different algorithms on directed graphs
For example for identifying all strongly connected components
It might feel a bit weird, but it is also used in a ton of well known algorithms.
for node in graph:
# for each node in the graph, if it's not visited, run dfs on it
if not visited[node]:
dfs_stack.append(node)
while dfs_stack:
current_node = dfs_stack[-1] # we don't pop yet, we only pop when everything "down" is visited
if not visited[current_node]:
visited[current_node] = True
for neighbor in graph[current_node]:
if not visited[neighbor]:
dfs_stack.append(neighbor)
else:
dfs_stack.pop()
stack.append(current_node)
Is that the right way to do topological sorting with dfs?
I feel like it's weird to not pop, add what's "dowstream", and only pop after
I like to do things a bit differently. For each node I store two different values in the stack
For the "pretraversal" I store the node index
And for the "posttraversal" I store the bit reversal of the node index
Like this
for node in graph:
# for each node in the graph, if it's not visited, run dfs on it
if not visited[node]:
dfs_stack.append(node)
while dfs_stack:
current_node = dfs_stack.pop()
if current_node < 0: # Everything "down" has been visited
current_node = ~current_node
stack.append(current_node)
elif not visited[current_node]:
visited[current_node] = True
dfs_stack.append(~current_node)
for neighbor in graph[current_node]:
if not visited[neighbor]:
dfs_stack.append(neighbor)
I see
I didn't know about the bit reversal operator
you reverse the sign bit is that why you do if current_node < 0?
to know if it's pretraversal or posttraversal?
I could have used just -, but then it wouldnt have worked if node = 0
Bit reversal of x is exactly the same as -x - 1. So 0 is mapped to -1. And ~~x is x.
oh yeah fair
Btw there is one thing that makes bit reversal pretty nice to use in Python. If you have a list and want to index it from reverse, then you can use bit reverse:
!e
A = [2,6,7,8]
print(A[2])
A.reverse()
print(A[~2])
@regal spoke :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 7
002 | 7
!e
A = [2,6,7,8,9,10]
print(A[2])
A.reverse()
print(A[~2])
@stiff quartz :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 7
002 | 7
ngl I'm a bit confused
All ~x is, is -x - 1
Which turns out to be really nice for indexing lists in reverse
This was verified with my Python console but I can't wrap my mind around the mathematical proof behind it
I get that the first bit is probably the sign
Thats not how integers work. There is no sign bit
@regal spoke :white_check_mark: Your 3.11 eval job has completed with return code 0.
5
The result of the bit AND between 5 and -1 is 5 since -1 is simply infinitely many 1s. In fact, the bit AND between any number and -1 is itself.
hm
Yes, there is.
Maybe I should have said there is no single sign bit
I understand that
Except it's kind of implicit within two's complement
That just says that -x is ~x + 1, which is the same formula as what I gave. I said that ~x is -x - 1. These formulas are equivalent
!e
print(2)
print(~2)
A = [2,6,7]
print(A[2])
A.reverse()
print(A[~2])
@stiff quartz :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 2
002 | -3
003 | 7
004 | 7
fair fair
The reason why I like using ~ here is that I can think in the same way if I want to index a list forwards as backwards.
I'm not personally a big fan of using A[-1] to find the last element in A. I personally much rather use A[~0]. I think It is very nice and symmetrical to use A[0] to find the first element, and A[~0] to find the last element.
!e
A = [2,6,7,8,9,10]
B = A[::-1]
print(A, B)
for k in range(len(A)):
print(A[k])
print(B[~k])
@stiff quartz :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | [2, 6, 7, 8, 9, 10] [10, 9, 8, 7, 6, 2]
002 | 2
003 | 2
004 | 6
005 | 6
006 | 7
007 | 7
008 | 8
009 | 8
010 | 9
011 | 9
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/ONE4T36QFGPUOINKQ6TZ3XLBYE
I get that, although I kinda used [-1] for years now
soo π
thank you so much btw for your patience
and your help!
I defintely learned a lot
it's down to how we decide to encode signed integers in a computer
twos complement
Ah I just thought of a good explanation.
The sum of x and ~x have all bits equal to 1 (i.e. their sum is -1), so x + ~x = -1. It follows from this that ~x = -x - 1 and -x = ~x + 1.
For this leetcode problem https://leetcode.com/problems/number-of-sub-arrays-with-odd-sum/
in the solution ``` def numOfSubarrays(self, nums):
E,O,T = 0,0,0
sum1 = 0
for num in nums:
sum1 = (sum1+num)%2
if sum1:
T=T+1+E
else:
T+=O
if sum1:
O+=1
else:
E+=1
return T % (10 ** 9 + 7)
I don't get why we are doing if the sum is odd we add even counts and if summ is even we add odd counts
don't understand the reasoning behind it
It's easier if you think about it recursively:
Let's call x1 x2 x3... xp your array
The sums of subarrays x1, x1+x2... are written s1 s2... sp
Assuming we already know the number of subarrays with odd sum until p-1 as T.
The new subarrays to check are x1 x2... xp, x2... xp,... Basically the xi:p.
sp = si + xi+1...p for all i.
Or xi+1...p = sp - si.
If sp is odd(sum1), the subarray i+1:p has an odd sum if and only if si is even. You add the number of even si to T.
If sp is even, that subarray i+1:p has an odd sum if and only if si is odd. You add the number of odd si to T.
In the case where sp is odd, you add one for the full array.
hi
Oh I love this explanation
:incoming_envelope: :ok_hand: applied timeout to @halcyon anvil until <t:1691146349:f> (10 minutes) (reason: duplicates spam - sent 4 duplicate messages).
The <@&831776746206265384> have been alerted for review.
hi, not exactly sure what channel to put this in but I thought this would be the most fitting. I'm working on a cryptology project that uses a Ceaser cipher model which means I have to shift letters by numbers and I thought using ASCII would work well for this but I'm having some trouble figuring out how to get the letters to their ASCII numbers. would appreciat help!
string.ascii_lowercase is equal to "abc...z", you can use that as a reference and access their number using the index method
sorry, im a bit of a beginner, would you mind explaining the index method?
It gives you the index of the substring(here a character for instance b) in the string you use it on
For instance "abc".index("b") returns 1
There are two really useful functions for this in Python, ord and char
!e
print(ord('S'))
print(chr(ord('S')))
@regal spoke :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 83
002 | S
ord takes in a character and outputs its ascii value. chr does the opposite, it takes the ascii value and outputs the character it corresponds to
in general unicode codepoint, not ascii value
@woven blaze
I knoweth not where to contact thee so this help channel might work.
#1137377803877228655 message
I tried: if event.type==pygame.K_ESCAPE and event.type==pygame.KEYDOWN:.
To conclude again: I want to stop the last time.sleep(1.0) run when the rabota becomes false because now it waits for the sleep that is already running to finish and executes its functions, while everything else stops, closes right away. And I want to use a specific hotkey rather than any, since we made hotkey to be working so I am going one step further because I can.
Should be event.key == pygame.K_ESCAPE insted of type
@scarlet jolt
For if I change:
for event in pygame.event.get():
if event.type==pygame.K_ESCAPE:
To:
for event in pygame.event.get():
if event.key==pygame.K_ESCAPE:
The whole "While Rabota" loop works just a single time and never again.
are there any books you guys would recommend for learning the foundamentals of algos and DS in Python (and other languages)?
@tame bear I found the problem, probal is not online, perhaps thou art still interested in helping me.
You were on this problem a few minutes ago.
Introduction to algorithms is great if you want a very comprehensive reference. I haven't read any other introductory book though
I'm having a look at Amazon, and its 85 dollars only for the ebook π€―
Yes it's an absurd price since it's a textbook
I didn't buy it personally
migh as well just look for the pdf online...
thnx anyways
that was fast, thanks
for some reason it dosent work in Italy
perhaps they restric the country? it says: This site canβt be reached with 'DNS_PROBE_FINISHED_NXDOMAIN'
oops
you can open a new thread for this will help you there
I can not. Help me here.
Dost thou found a way to fix it?
okay can you send that specific part where you suspect issue?
I send it multiple times!
but i don't have it rn
Dear Lord! @woven blaze
That is the issue! Man, what art thou tripping?! I literally repeat the same thing over and over again, as clear and as simple as it could be! It is not possible for me to say this any better! Ic thanke thee. It is better for us to leave, goodbye!
sorry i just forgot the context
Ah. Well. I do not know. It is all linked there. And Discord is messed up, does not allow me to make a thread. For not to insult thee, here is the problem yet again.
import time
import pygame
from threading import Thread
Rabota=True
pygame.init()
window=pygame.display.set_mode((200,150))
def my_function():
while Rabota:
time.sleep(5.0)
print("Every second.")
my_thread = Thread(target=my_function)
my_thread.start()
while Rabota:
for event in pygame.event.get():
if event.type==pygame.KEYDOWN:
print("Hotkey.")
Rabota=False
pygame.quit()
# PyGame is used somewhere else in the code, not important.
my_thread.join
I would like hotkey to be specific rather than any, and sleep of threading to break on when Boolean - Rabota turns to "False" rather than waiting to finish the thread it already started (the ongoing thread).
okay thanks give me a second will download pygame and try that out
Then you need to import it, I will adjust the code.
no need will do that
Done.
I do not know, the hotkey does not work without a Screen, which I have but the code is not important, thou can probably make it.
Just needs a four more lines than I originaly provided. And I updated the code to include them. This is the lines that go into that code up above.
import pygame
pygame.init()
window=pygame.display.set_mode((200,150))
pygame.quit()
import time
from threading import Thread, Event
import pygame
Rabota = True
pygame.init()
my_event = Event()
def my_function():
my_event.clear()
print("my event: ", my_event.is_set())
while not my_event.is_set():
time.sleep(1)
print("Every second.")
my_thread = Thread(target=my_function)
my_thread.start()
window = pygame.display.set_mode((200, 150))
while Rabota:
for event in pygame.event.get():
if event.type == pygame.QUIT: # Usually wise to be able to close your program.
print("riased quit event")
my_event.set()
raise SystemExit
elif event.type == pygame.KEYDOWN:
print("key down event")
print(event.key)
if event.key == 1073742050:
print("got the vent")
Rabota = False
my_event.set()
pygame.quit()
# PyGame is used somewhere else in the code, not important.
try this i've tested working for me
@scarlet jolt
What key is 27?
escape?
press and see what event you're getting
i thiink events are based on the ascii
Because nothing happens when I press any hotkey.
did you get "key down event" in log?
And where dost thou set Rabota to be False, is that not useful? No, I do not get that text Printed. Maybe I made it wrong.
yes we don't need that rabota if you want you can set it
can you send me screenshot of the log and keypress part ?
Thou (you) never use events variable?
yes i didn't just for testing i've added that
Nothing.
I have this:
while Rabota:
for event in pygame.event.get():
if event.type==pygame.QUIT:
print("riased quit event")
my_event.set()
raise SystemExit
if event.type==pygame.KEYDOWN:
print("key down event")
print(event.key)
if event.key == 27:
print("got the vent")
my_event.set()
press it multiple times i think doesn't detect?
that's not required yours is also correct
ooh any other issue?
"key down event
1073742050"
1073742050
add it in that if condition
It is weird and yes there are issues but I do not know how to say.
inplace of 27
yes it's have to press it multiple times
what's that tell me
I can not, it is complicated, the thing does not close.
Just stops printing. Why do we not use Rabota?
is it required?
And it does not break the loop, everything is the same but with another issue.
I use it as a loop, ikt is important.
I am going back to the beginning.
ooh yes i forgot you can set it to false after that keyevent
give me a second
Modified that please check
I removed everything, I need to make it again.
oops
Nothing happens.
How can it work for thee I do not udnerstand.
And that event thing you imported and used is confusing anyway.
Ooh but it's working for me
can you test just that part insted of directly integrating with existing code?
I do not know how to because Pycharm is extremely messy.
I will not attempt that.
Stupid software.
I can not believe how stupid it is.
I got thousands of files every time I oppen it and everything is hidden and weird.
No no pycharm is not messy it depends on the user
I tested and seems like it fixes the hotkey, it works, although seems not works always and instant, and seems like the other part where loop is supposed to break and sleeping not to work is the same, it still prints after.
No way, this is truly it, I give up. Ic thanke thee very much!
Nonsense this Python is! Cna not fix the simplex thing.
We tried. We can not make it.
What can we do? There is no way.
I said I spend days and weeks on this.
okay try something else
Yes, but not related to this. This is done, proven to be impossible.
Goodbye!
This is the last day I was patient with this bugged nonsense.
I don't know why it is not working
can u plz rewrite correct code for me
I am busy for some days nows i am starting again
To us your code seems correct. So we were wondering what it is that makes you think that it is wrong
Did you submit it to some website and got wrong answer?
Or like, why do you think it is wrong
but it's now working on gfg
Is there anyway to optimize the selection sort just like in bubble sort where if there are no swaps done, then the array is sorted
I dont think so. I also dont know why you would want to optimize selection sort
Just wondered
I think the only O(n^2) sorting algorithm that has some interesting algorithmic uses is insert sort
How so?
Part of the reason for this is that the "expensive" insert step is in practice super cheap cause it just shifts stuff around in memory
I think for an array you need to move all the elements to the right
I think it is expensive
in case of insertion sort
If you count the number of operations then it looks expensive
But moving stuff around in memory like that is one of the things that a computer has been optimized to do
I see
Another nice thing about it is that you can access this super fast insert in Python just by doing .insert on a list
Yeah cause of linked list right?
I'm not talking about linked lists at all
I still can't wrap my head around this thing, you still have to move n elements
Ye but it is one of those things that computers have been designed to quickly do
It is still O(n) to do an insert
But it has a very small constant cost
But the swap takes less time than insertion right?
No
Why?
Or what do you mean by swap?
swapping two elements takes constant time, unlike insertion, but it's not very valid to say that it means it's faster.
Like in bubble sort
One swap is definitely cheaper than an insert
But an insert is still remarkably cheap for what it is
I've tried implementing and benchmarked tons of Python implementations of balanced binary trees that can be used to mantain sorted data
It turns out that data structures based on insert sort are simply faster, even when n becomes rather huge (like 1e7)
I'm talking about data structures based on insert sort like this https://grantjenks.com/docs/sortedcontainers/
I've heard somewhere that python lists are just linked lists
No Python lists are not linked lists
They work in the same way as vector does in C++
Looks like I have to revisit some basic concepts
Lists in Python allocate more memory than they intitally need, in order for .append to run quickly
And then when that memory becomes filled, it reallocates (again with some extra memory to make .append run quickly)
a nit, but in particular it's more like vector<shared_ptr<...>>
yup, the lists grow like https://github.com/python/cpython/blob/main/Objects/listobject.c#L68-L72
Objects/listobject.c lines 68 to 72
* The growth pattern is: 0, 4, 8, 16, 24, 32, 40, 52, 64, 76, ...
* Note: new_allocated won't overflow because the largest possible value
* is PY_SSIZE_T_MAX * (9 / 8) + 6 which always fits in a size_t.
*/
new_allocated = ((size_t)newsize + (newsize >> 3) + 6) & ~(size_t)3;```
which I note is actually quite slow growth (powers of 9/8), I think a common implementation in programming languages is to double in size each time.
there has been plenty of arguments about what's the optimal factor
googling it, I see people saying that GCC uses 2, and that MSVC uses 1.5
hmm, this is for C++'s std::vector, right?
ye
looks like Rust's Vec uses doubling too: https://doc.rust-lang.org/src/alloc/raw_vec.rs.html#396-399
Btw another thing to note about insert sort. Suppose you are sorting up to 256 elements, then you can keep track of the sorted permutation using only 1 byte per element.
This can be used to further cut down the cost of the insert step in insert sort
Another notable thing is that Python does not over allocate if the new size is closer to overallocated size than to the old size. So in a sense, the growth factor might even become as small as 17/16.
actually, what does std::vector or other vecs in compile languages do in the case of resize?
still double even if you only need one additional element or allocate as little as they need?
Rust avoid overallocating if the resize has already more than doubled the old size. So rust doesnt have this weird quirk
ok, makes sense
But I'm not sure about c++
It's just that I just realized that I have re-implement vector multiple times and upon resize I always (re)allocate max(capacity, new_size)
never though about it working in O(n^2)
Btw here is an interesting read about realloc https://stackoverflow.com/questions/44487537/why-does-naive-string-concatenation-become-quadratic-above-a-certain-length/44487738#44487738
realloc() works in mysterious ways
There is also this blog https://www.pypy.org/posts/2023/01/string-concatenation-quadratic.html
This is a super brief blog post responding to an issue that we got on the PyPy
issue tracker. I am moving my response to the blog (with permission of the
submitter) to have a post to point to, since i
Interesting
has anyone here solved programming problems from the euler project?
I would expect resizes take long time only at the memory page boundaries though
(well, depends on the allocator implementation I suppose)
That's just an ordinary linked list though, isn't it?
oh, you mean, like, have empty nodes at the end? I don't see why though; that just gets you extra memory usage without changing complexity
Argh, linked list
the most overhyped and overused data structure ever
useful literally never
and still taught as if it is a holy grail of programming
it is used either:
- To ensure the memory location of an object does not change (why don't use std::deque's structure in that case though? Or even vector of pointers?)
- In hashmaps (or other structures) to store the information about element order
- When O(1) merge time is needed
- In concurrent data structures
- In low level (think OS development) fields where allocation is difficult
I don't know any other usecases
C++ std::deque is an interesting alternative to vector. It avoid reallocations by allocating its memory in blocks of like 16 elements each, and then having a lookup table for pointers to the blocks. Its time complexity is at least as good as vector for any operation.
No reallocations also means that pointers arent invalidated, unlike for pointers to elements in a vector.
yes, and yet it fails as a double ended queue implementation
cyclical vector has better performance
I dont think it fails as a double ended queue. It got fast inserts and removal on both ends.
yes, but I you benchmark it against simple looped vector, the latter will crush it
Its real fail is that MSVC has a shit implementation of deque only allocating "blocks" of 1 element. So depending on your system you can have really bad performance
that's even worse
Btw, many of the times I've seen people use std::deque it was used because its pointers dont get invalidated, and because its a double ended queue
yeah people do that
it's technically more memory efficient than allocating memory for every object
but still less memory efficient than memory arenas thingy
I recall reading a proposal for a better "vector" in C++, but unfortunately I dont think that ever became a thing
Let me see if I can find it somewhere
The same data structure later on got rediscovered https://news.ycombinator.com/item?id=20872696
I don't see anything surprising about it
just an average "sqrt-decomposed" data structure
but seeing it in the context of deque implementation is interesting
https://practice.geeksforgeeks.org/problems/bfs-traversal-of-graph/1
Can anyone solve this
Nope direct on gfg
Have you trΓed submitting your own code #algos-and-data-structs message without the prints?
well Now i am confused about dfs
#User function Template for python3
from typing import List
from queue import Queue
class Solution:
#Function to return Breadth First Traversal of given graph.
def bfsOfGraph(self, 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
```It's work
Well some website has different dfs article and some have different dfs I am confused!
BFS and DFS are two different things. The problem you linked and the code you posted is BFS
i know i am just generally asking i am confused about both
dfs use stack
and bfs use Queue
In my soln. I am also using queue for bfs
GFG Sucks but leetcode has no problem for calculating dfs/bfs of graph
Here is a dfs problem https://leetcode.com/problems/binary-tree-inorder-traversal/
are there any examples of recursive generators that are used in BFS style instead of DFS?
and is it even possible to do the former with generator-functions?
What are you asking about, generators in BFS style and DFS style?
I've never heard of anything like that before
yeah so instead of doing a recursive functions where you store the state in a parameters that gets passed on recursively, and at the end returns a list of nodes, you do that with a generator function
which is more eficcient, because if dont need all the nodes, but maybe just the first 5, the generator will stop there.
so I did this which is actually for a trie data structure, but it uses DFS instead of BFS
# TrieDict: TypeAlias = dict[str | bool, 'TrieDict' | str]
def extract_keywords_from_trie(trie: TrieDict) -> Iterator[str]:
for key, val in trie.items():
# if the key is true the value will be the keyword
if key is True:
yield val
elif isinstance(val, dict):
yield from extract_keywords_from_trie(trie=val)
but I'm trying to convert it to a BFS algorithm so it explores the nodes level by level
I think it is significantly easier to do that kind of generator with BFS
BFS doesn't use any recursion to begin with, so you can just yield whenever you append something to the queue
its true that you dont need recursion
I came up with these two solutions that seem to work
def extract_keywords_from_trie(trie: TrieDict) -> Iterator[str]:
nodes = deque([trie])
while nodes:
current_node = nodes.popleft()
for key, val in current_node.items():
if key is True:
yield val
elif isinstance(val, dict):
nodes.append(val)
def extract_keywords_from_trie_bfs(trie: TrieDict) -> Iterator[str]:
next_level = []
for key, val in trie.items():
if key is True:
yield val
elif isinstance(val, dict):
next_level.append(val)
for node in next_level:
yield from extract_keywords_from_trie(trie=node)
That looks weird. I think ideally you want to yield stuff at the same time as you do nodes.append. What you are doing currently could become very expensive even if you just want the first 5 yields
Another thing that I personally prefer is to BFS by just for looping over a list like this ```py
nodes = [trie]
for current_node in nodes:
for key, val in current_node.items():
if key is True:
yield val
elif isinstance(val, dict):
nodes.append(val)
You dont technically need any deque
but you cant append to the list that your iterating over
Turns out that in Python you can
π
right
its not a syntax error, but still very bad practice
and the deque is the same as the list, its just more performant for popping the first element
I dont know why it would be very bad practice other than it being a slightly obscure feature
You can, but it might break (i dont think it is explicitly documented that it is allowed)
Dicts dont support adding/removing values during iteration
!e
lst = [1, 2]
for x in lst:
lst.append(x)
@brazen python :warning: Your 3.11 eval job timed out or ran out of memory.
[No output]
this is why its very bad
I can agree that it being obscure and probably not explicity documented, but I dont agree that a loop like that means it is bad
With deque you could also accidently fill up the memory by getting stuck in some infinite loop
!e ```py
l = [*range(10)]
for x in l:
print(x)
del l[0]
print(l)
@lean walrus :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 0
002 | 2
003 | 4
004 | 6
005 | 8
006 | [5, 6, 7, 8, 9]
That's why it is bad
I agree
Well I dont
besides, in general you always want to avoid reading and writing at the same time
When you iterate over an list Python internally has an index that increments by 1 over and over
Thats all it is
for loops in python usually mean "do some stuff with every item of this collection"
Code like this is extremely obscure and hard to read, that's why i think it is bad
If you do write loop like this, consider leaving good explanation comment before it
As with anything obscure, if you want someone to be able to read your code and understand it, then it is bad
If you want something less obscure you could just manually do the indexing yourself
i = 0
nodes = [trie]
while i < len(nodes):
current_node = nodes[i]
for key, val in current_node.items():
if key is True:
yield val
elif isinstance(val, dict):
nodes.append(val)
i += 1
It is fundamentally the exact same thing
Code that modifies a collection while iterating over that same collection can be tricky to get right. Instead, it is usually more straight-forward to loop over a copy of the collection or to create a new collection:

Another thing I just realized, that bottom implementation is not a BFS
You cant just mix BFS and recursion like that
In a BFS, you need to do everything in parallell
As you've coded it now, you will start the 3rd layer before you are finished with the 2nd layer
your wrong, it is BFS.
you can do both BFS and DFS, both iteratively, and also recursively
All I'm saying is that what you've got there is not a BFS
aight if you say so π
This is an example of a graph where you'd get the wrong order
You would get to the node in the bottom left before reaching the node in the bottom right
Speaking about obscure code. A fun obscurity test is to show a Python code to chatgpt and ask it to translate it to C++.
https://chat.openai.com/share/9dc786f6-4134-462f-a66e-ddd453efe86a If it succeed then the code is in some sense reasonable.
Chatgpt is successfully able to translate the bfs that appends onto a list while iterating over it into c++
However, it is less successful with something like this ```py
B = [0] * len(A)
for i in range(len(A)):
B[i] = A[-i]
it's not a bfs
!e
from collections import deque
from typing import Iterator
TrieDict = dict
def extract_keywords_from_trie(trie: TrieDict) -> Iterator[str]:
nodes = deque([trie])
while nodes:
current_node = nodes.popleft()
for key, val in current_node.items():
if key is True:
yield val
elif isinstance(val, dict):
nodes.append(val)
def extract_keywords_from_trie_bfs(trie: TrieDict) -> Iterator[str]:
next_level = []
for key, val in trie.items():
if key is True:
yield val
elif isinstance(val, dict):
next_level.append(val)
for node in next_level:
yield from extract_keywords_from_trie(trie=node)
t = {
'a': {
True: 'a',
'b': { True: 'ab' }
},
'c': {
True: 'c',
'd': { True: 'cd' }
},
}
for x in extract_keywords_from_trie_bfs(t):
print(x)
@haughty mountain :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | a
002 | ab
003 | c
004 | cd
a bfs order would start with a and b before getting to ab and cd
oh your right
the two functions are separate, its just a typo that one calls the other
so the first works
but the second ironically does the opposite
Even if you fix that, the second function would still not be a BFS
my bad, you were right
im having a problem in which i can't reach a variable.
the variable is located at a function and i'm trying to reach it in a function that is inside of the parent function but cannot. any suggestions?
Python3 has a keyword called nonlocal
thanks
https://leetcode.com/discuss/study-guide/2360573/Become-Master-In-Graph
I found this great article but it is in java can anyone give me python code
I hate to say it, but you can ask chatgpt to translate it π
It is one thing it is relatively ok at
I'm sure it will understand basic java
But also I recommend you to try and understand java yourself
You don't have to know the language to understand it
haven't been here in a while
Is there any good introductory course available for dsa in python? Im new to dsa and am looking to explore the field
Hi, I'm doing a backtracking algorithm for the knight's tour problem. My current solution works, but I feel like there's ways to optimize it.
def board_filled(n,board):
for i in range(n):
for j in range(n):
if board[i][j] == 0:
return False
return True
def knights_tour(n):
board = [[0 for i in range(n)] for j in range(n)]
backtrack([(0,0)],1,n,board)
for i in board:
print(i)
def backtrack(sols:list,counter,n,board):
possible_moves = [(1,2),(-1,2),(1,-2),(-1,-2),(2,1),(-2,1),(2,-1),(-2,-1)]
prev_x,prev_y = sols[len(sols)-1]
if board_filled(n,board):
return sols
if (prev_x) not in range(n) or (prev_y) not in range(n) or board[prev_x][prev_y] != 0:
sols.pop()
return False
board[prev_x][prev_y] = counter
for (x,y) in possible_moves:
sols.append((x+prev_x,y+prev_y))
if backtrack(sols,counter+1,n,board):
return True
board[prev_x][prev_y] = 0
sols.pop()
return False
knights_tour(5)
mainly any ways to optimise the backtrack() function would be appreciated
wait, are you allowing it to go to squares it has already visited?
why?
or wait, you deal with that in the beginning of the call
yeah i kill the function if the square it wants to go has been occupied
though maybe i could just not let it call it in the first place
if so why do you need to check the board_filled like that?
oh right
if counter = n*n it should work right? because the only way counter reaches that if it's successful
something like that yeah
i mainly just wanted to check the general structre
might be + 1
i'm a bit unsure on how a 'general backtracking' algorithm looks like
google search hasn't helped me much
depending on your indexing with counter
yeah but i mean like for any problem involving backtracking
right now i'm basically using this template i came up with
but i don't know if it's the best way to do it
because right now the only way my implementation works is because return attempt is evaulated as true
sorry it might be a bit of a loaded question
if you can direct me to any resources i'd be happy to just check them
it's just this kind of pattern:
for all options:
update state with option
try to recurse
if successful:
return with success
else:
undo update
with the undoing of the update to avoid discarding all the prior work
what does 'try to recurse' mean here?
"does picking this option next work"
which usually is a recursive call to your function
right but my problem is this
say one of the calls do work
it will return sucess, (with the solution)
but then that return is just basically...gone?
idk how to explain it properly
like if the succesful function returns success, it's meaningless since i need it's parent functions to pass that value to the initial function (the one that started the recursion)
and the only way i managed to do that is
sol =backtrack(solution + i):
if sol:
return sol
so like if anytime one of the functions returns, say an array that passed all constraints
then the function that called it will 'pass it down'
it's a bit awkward wrt data flow yes
i guess i'll just stick with what i have since it seems to work
and you know what they say don't touch it if it works
I like using closures for this, e.g. here is one that would output all solutions
def all_solutions(...):
sols = []
def backtrack(...):
if this is solution:
sols.append(...)
return True
for all valid options:
update state
backtrack(...)
undo update
backtrack(...)
return sols
you could probably make a generator function work instead actually, which might be neat
are both the backtrack calls the same? or are the arguements different?
i'm relatively new to python syntax so what does 'all' mean here?
something like this with a generator
def backtrack(...):
if this is solution:
yield solution
return
for all valid options:
update state
yield from backtrack(...)
undo update
oh, I'm just writing pseudocode, not actual python code
oh okay lol
this would lazily generate all solutions, and the caller could decide to only get the first one
does puting a def inside another function definition mean that sols is accesbile to it?
like i don't need to pass sols as a function parameter?
but honestly thank you very much for clarifying this for me
this backtracking stuff is messing with my head
so tysm
yeah, the inner function can access things in the outer scope
here is an example using generator functions to generate all solutions lazily, this finds partitions of a number, i.e. unique ways of adding up to some number
!e
def gen_partitions(n, max_allowed, picked):
if n < 0:
return
if n == 0:
yield picked
return
for i in range(1, max_allowed+1):
picked.append(i)
yield from gen_partitions(n - i, i, picked)
picked.pop()
def partitions(n):
return gen_partitions(n, n, [])
for p in partitions(5):
print(p)
@haughty mountain :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | [1, 1, 1, 1, 1]
002 | [2, 1, 1, 1]
003 | [2, 2, 1]
004 | [3, 1, 1]
005 | [3, 2]
006 | [4, 1]
007 | [5]
and you could easily just pick the first solution from this and you wouldn't even compute the rest
you should be able to see the same patterns as before
Slicing is a way of accessing a part of a sequence by specifying a start, stop, and step. As with normal indexing, negative numbers can be used to count backwards.
Examples
>>> letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> letters[2:] # from element 2 to the end
['c', 'd', 'e', 'f', 'g']
>>> letters[:4] # up to element 4
['a', 'b', 'c', 'd']
>>> letters[3:5] # elements 3 and 4 -- the right bound is not included
['d', 'e']
>>> letters[2:-1:2] # Every other element between 2 and the last
['c', 'e']
>>> letters[::-1] # The whole list in reverse
['g', 'f', 'e', 'd', 'c', 'b', 'a']
>>> words = "Hello world!"
>>> words[2:7] # Strings are also sequences
"llo w"
Hello, I have written some code to sample m number of pauli strings (without replacement). But its super inefficient.
#Inefficient implementation (Possibly make it better?, ok for proof of concept?)
def create_random_pauli_strings(num_qubits, num_basis, seed):
pauli_chars = ["I", "X", "Y", "Z"]
all_pauli_strings = list(product(*([pauli_chars] * num_qubits)))
all_pauli_strings.remove(tuple(["I"] * num_qubits)) #Remove identity
random.seed(seed)
random_pauli_strings = random.sample(all_pauli_strings, k=num_basis)
random_pauli_strings = list(map(lambda x : "".join(x), random_pauli_strings))
return random_pauli_strings
Right now I am expanding every single possible cartesian product of I,X,Y, and Z and sampling them. For instance if num_qubits is 2, all_pauli_strings will expand to [IX, IY, IZ, XX, XY, XZ, ...] (the length of the list will be 15). Then lets say m is 3, so I will sample XX, YY, and ZI (you cannot repeat any of the strings).
This code is particullary bad beause the length of all_pauli_stings will expand exponentially, the length will be in fact 2 ** (2 * num_qubits) - 1
Any ideas of how I can achieve this without having a gigantic list?
Wouldn't it just be 2**num_qubits - 1?
Anyway, seems that you want to sample some random elements from a cartesian product. That's definitely possible, because you can enumerate a cartesian product in an intuitive way:
let's say we consider product("ab", repeat=2)
n element
0 aa
1 ab
2 ba
3 bb
This is just n written in base-2, with 0 replaced by a and 1 by b.
Whereas if you have product("abc", repeat=2), that'd be like writing the number in base-3 and replacing 012 with abc respectively.
So just generate num_basis integers from 1 to 2**num_qubits - 1 inclusive, and transform them into the actual elements this way.
base-4, then.
Yep
Oh I see what ur saying
That is a def a much clever way of doing it
So num qubits is just gonna detemine length of my bitstring
Or I guess 4base string
Thank you @vocal gorge !
Yeah, something like:
def product_nth(iterables, n: int):
"Returns the nth element of product(*iterables)"
res = []
for i in range(len(iterables) - 1, -1, -1):
n, mod = divmod(n, len(iterables[i]))
res.append(iterables[i][mod])
return tuple(res[::-1])
def create_random_pauli_strings(num_qubits, num_basis, seed):
pauli_chars = ("I", "X", "Y", "Z")
random.seed(seed)
random_ns = random.sample(range(1, 4**num_qubits), k=num_basis)
return [product_nth([pauli_chars] * num_qubits, n) for n in random_ns]
(This approach might also be vectorizable with numpy, if more performance is desired.)
cool
which I have code for in this channel from some time ago when someone wanted to generate DNA sequences

~1s for generating 100M nucleotides
The problem is, they need to be distinct.
that makes it much more problematic. Could use an approach like in my python version though, just vectorized. Would be fast-ish.
Do you actually want to remove the ["I"] * num_qubits tuple?
Is performance important? If it is then my guess is that the fastest thing is to generate all pauli strings up to like length 5 or 10. Then sample as many of them as you need and concatenate them
The idea is that in theory it should be efficient
In practice not really because we are prolly not gonna use anything more than 3 or 4
But the idea of converting it into base 4 should work
3 or 4 what?
As mentioned here
Qubits
What about just sampling a random 5qbit string and cutting it down to 4 qbits?
But in theory it should be efficient for any number of qubits :)
Even 10 is an insane number of strings
It's still an exponential algorithm is what I'm trying to say
What I'm proposing would work for any number of qbits
? How so
for a random 22 long qbit string, I would sample five random 5 long qbit strings
remove the last 3 qbits from the last sample
and concatenate them
Not sure if I follow, I still think that the solution confuses reptile stated is the best
It's essentially constant time
Or actually linear
!e I have a really terrible numpy thing
import numpy as np
import random
n = 10
k = 8
r = np.array(random.sample(range(1, 4**n), k), dtype=int)
n_range = np.arange(n, dtype=int).reshape((n, 1))
indices = r >> 2*n_range & 3
elements = np.frombuffer(b'IXYX', dtype=np.uint8)
ascii_arr = np.take(elements, indices)
res = np.frombuffer(ascii_arr.tobytes(), dtype=np.dtype(f'S{n}'))
print(res)
@haughty mountain :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | [b'XXXXIYXYYI' b'XYIXXXXIXI' b'XXIYYXXXYX' b'IIXIYYIXYX' b'YIYIYXXXYX'
002 | b'XXXYXYIXII' b'YXYXYXYIIX' b'XIIIYIXXIY']
np.array(random.sample can be a np.random.randint with replace=False
now, what is happening here... oh, I get it. yeah, that's about what I had in mind for vectorization.
it's a bit awkward
is np.take(elements, indices) different from elements[indices]?
and I think you can't get away from using int with this approach
err, good question
it's probably the same in this case
Btw I suspect the bottleneck might be the random.sample
using the numpy version will be a lot quicker probably
though I suspect this is very premature optimization unless we expect to want to pick tons of elements
just doing the sane pure python version from earlier seems like a sane choice
also, if k is much smaller than 4**n rejection sampling could be a very good and simple option
!e something like this
import random
def random_pauli_str(n):
return ''.join(random.choice('IXYX') for _ in range(n))
n = 10
k = 8
res = set()
while len(res) < k:
s = random_pauli_str(n)
if s != 'I'*n:
res.add(s)
print(res)
@haughty mountain :white_check_mark: Your 3.11 eval job has completed with return code 0.
{'IYIXYXYXYX', 'XXYYYXYXYI', 'YXIXIYXYYX', 'IYXXYIIXXX', 'IXXXXIXIIX', 'XIYIYYXXXY', 'XXXIXXYXII', 'YXXYIYXYXX'}
hey, first try without test running
idk if this is really rejection sampling, but it feels a bit like it
you forgot s not in res
not needed
oh, right
I was about to write it before I realized it was a bit silly of a check when we have a set anyway
Could even add 1*n to set at the start and remove it at the end
and do <= in the while
yeah, it's another option
@wooden belfry Do you actually want the sampling without replacement?
from what was said earlier, yes

Usually sampling without replacement just complicates things mathematically
This code is going to do pretty badly if you ask for all possible strings
yeah, I mentioned this caveat just before
Hi
Hi everyone, I'm currently working with opencv for computer vision and my problem is that I'd like to dilate or erode random parts of an image but not the entire image itself. Does someone know how it is possible to do that ? I'd greatly appreciate your help π
Hi, just for curiosity, when I'm coding an algorithm with multiple index and need to increment or decrement at the end or beginning of the code (pointer++ or i = start +1 in the code), is there any trick to remember, without iterate the code in my head or memorize the entire algorithm? sorry java code public static int[] quickSortRec(int start, int end, int[] list) { if(start < end) { int pivot = list[start]; int pointer = start; for (int i = start + 1; i <= end; i++) { if (list[i] < pivot) { pointer++; swap(pointer, i, list); } } swap(pointer, start, list); quickSortRec(start, pointer - 1, list); quickSortRec(pointer + 1, end, list); return list; } return list; }
if you know how the algo is supposed to work you should know what goes where
it's less memorizing and more understanding the algo
I usually visualize an arbitrary array in my head with arrows as pointers
I think what you have there is basically as good as it will get. It gets a bit tricky no matter how you code it.
My personal preference would be to code it like this.
int pivot = list[start];
++start; // ignore the pivot element for now
int j = start;
for (int i = start; i < end; ++i) {
if (list[i] < pivot) {
swap(i, j, list);
++j;
}
}
swap(start - 1, j - 1, list); // place pivot at j - 1 (in the middle)
quickSortRec(start - 1, j - 1, list);
quickSortRec(j, end, list);
The reason I prefer coding quicksort like this is that the for loop part of the code becomes really nice, short and simple.
Also, I changed the code to use [start, end) instead of [start, end].
is there any trick to remember, without iterate the code in my head or memorize the entire algorithm?
When I implement an algorithm I try to break it down into steps. I view the quicksort as having 3 steps
- Choosing the pivot
int pivot = list[start];
++start; // ignore the pivot element for now
- Create the partitioning.
Places everything < the pivot to the left, and everything >= the pivot to the right.
The variable j marks the index to the first element >= pivot. If there is no element >= pivot, then j = end.
int j = start;
for (int i = start; i < end; ++i) {
if (list[i] < pivot) {
swap(i, j, list);
++j;
}
}
- Place the pivot in the middle and recursively sort the two partitions
swap(start - 1, j - 1, list); // place pivot at j - 1 (in the middle)
quickSortRec(start - 1, j - 1, list);
quickSortRec(j, end, list);
One really nice thing about doing it like this is that step 2 doesn't depend on how you picked your pivot. Step 2 would look exactly the same if for example you picked the last element to be the pivot.
yeah like I try to divide the code in steps and also visualize the array to check the corner cases, but my brain is not good to do that without errors, I need to review the code to check these cases and run the tests to validate π’
Once you've broken it down into steps, you can check that each step is correct seperately.
Step 3 has a slightly awkward edge case (which happens if all elements were bigger than the pivot). In that case the pivot happens to get swapped with itself. But importantly that doesn't matter for the correctness of step 1 and 2
hmm, okay I will try to think about that, to quick sort is just one case, but sometimess it is really dificult to visualize the algorithm. I thought maybe I can test a case with 1 element and 2 elements in my brain to simplify the validation π€, or try to code the algorithm and consider the corners at the end. idk
1. eg, business hours for a store are 9 AM to 12 PM on Monday
1. we only have 2 observations for this store on a particular date (Monday) in our data at 10:14 AM and 11:15 AM
2. we need to fill the entire business hours interval with uptime and downtime from these 2 observations based on some sane interpolation logic```
what would be best way to solve this
i can assume the store is active in it's active hours unless one entry says inactive
just looking for another pair of eyes
has anyone ever done a question called pow(x ,n) on leetcode its question 50 on it?
You can just use the built in pow in Python
or use math.pow
Can someone help me with a hangman problem
Can someone suggest what type of algorithms I can use to solve it
You could get a decent-ish solver by just trying the most common letter among the possible guesses each time.
https://youtu.be/v68zYyaEmEA obligatory mention
An excuse to teach a lesson on information theory and entropy.
Special thanks to these supporters: https://3b1b.co/lessons/wordle#thanks
Help fund future projects: https://www.patreon.com/3blue1brown
An equally valuable form of support is to simply share the videos.
Contents:
0:00 - What is Wordle?
2:43 - Initial ideas
8:04 - Information theory...
and then someone plays jazz
All the problem statements are given in the screenshots can anyone help me improve my code(im returning correct outputs only for a few cases, others are failing)
The argument to the function "sum_of_intervals" is an array of arrays FYI
Hi, I was recommended to use
base64.b64encode(os.urandom(32))[:8]
question is, isn't this the same thing?
base64.b64encode(os.urandom(6))
if run time was a factor, wouldn't the ladder code be better?
hello, question, I found this website its like, an algorithm a day, and Im on one called Kadane's Algorithm, and it seems to be an algorithm for getting the sum of the array? why do that when you can just sum()?
def solution(nums):
start_time = time.time()
maxCurrent = nums[0]
maxGlobal = nums[0]
for i,val in enumerate(nums):
if i == 0:
pass
else:
maxCurrent = max(val, maxCurrent + val)
if maxCurrent > maxGlobal:
maxGlobal = maxCurrent
print ("My program took", time.time() - start_time, "to run")
return maxGlobal
Thats the code for it and I dont quite understand what the benefit of something like this would be
Could you link the website?
Kadane algorthim has o(n) time complexity while brute force approach has o(n^2) time complexity
so going through a list and doing sum += currentlistnum is o(n^2)?
Nope
U use only one for loop and iterate for n elements
right, so why you kadane algorithm if just sum(list) does the same thing and even got me faster results
well a question has lot of testcases not one
like [1,2,-4,-3]
sum of list is not working here
Sum(list) gives you the sum of the entire array not the subarray
yeah!
right which gives the same answer anyway?
No
and sum of array is not the right answer always
Did you read the website you sent?
right answe is sum of [1,2] here not sum(list)
I did but I guess I dont understand it
in the end it seems like he's still just adding together every number in the array
yeah idk im completely lost as to what the goal is
so the only time it wouldnt just return the sum of the full array is if the end numbers are negative?
like [2,4,2,-2,-5]
it would just return 8
What about [1,2,-3,4] what is the largest subarray sum here
4
[1,2,-3,5]
5
6
Nope it's 5
Subarrays are [2] or [2,2] or [5] or [-3,5]
Does that make it more clear?
That's one aswell
so 9 is the maximum
Whoops sorry I'm not helpful rn
You have the right idea I was spewing nonsense let me give you a better example
[1,2,-4,5]
it says its 5 but I dont see why cuz wouldnt [1,2,5] be a valid subarray
Cuz it's not contiguous
5 follows -4 and not 2
So to include 5 you have to either have it by itself or include numbers previous to it
So in this case the max subarray is just [5]
well i cant tihnk of anything else cuz I still dont see why sometimes it seems like its just the sum of the full array and sometimes not
Same concept
Cuz 2 + 1 - 2 > 0
yeah idk im too stupid for this I guess, I appreciate you trying to help but I dont think ill be able to understand this
I was being dumb again it is not 7
Its 6 - 1 + 7
Don't give up it's jusd I'm not very helpful rn
It's the full sum because the negative number is less or equal to the sum previous to it
ouhhh
so if at any point when making a subarray it goes negative
you start a new one
disregarding the number that made it go negative
1,2,-4,5
1+2+-4 is -1, so since -4 made it go negative the max subarray so far is 3
Well I think you initial misunderstanding was with how these tubarrays worked
then start the next one after the disregarded number
I was using that examples more to illustrate why the sum of full array doesn't work and to make you think more about the subarray
But you understand those now right?
Try to read about the algorithm again and see if you understand why it is useful if u have any questions feel free to ask
im gonna go sleep I have work in the morning
but yeah ill ping you if anything tomorrow if I understand it further or not
Feel free to but I hope other people answer because I think my explanations are kinda shit
basically if you know the max subarray that ends at n-1 what is the maximum subarray that ends at n?
you have two options, you could either add the number at n (so + value[n] to the previous max), or you could decide to start a new subarray (which would give you a sum of 0)
those are the only two choices, so pick the best one
which ends up as "if adding value[n] makes things go negative, just pick the empty subarray from this point"
just saying that doesn't explain why it works
ah, from the later discussion I got the impression that the confusion was about how it works
never mind then
and a good example for why just taking the sum isn't optimal would be something like
1 -1000 2
picking -1000 at all would be terrible
Have you tried to find an appropriat algorithm?
There are tons of ways that you can solve this. BFS or DFS will both work.
It is even possible to solve this by counting the number of connected components
just counting? I can see finding the components and verifying they are trees (k vertices, k-1 edges)
i.e. "is this a forest?"
A graph is a forest iff #connected_components = n - m (where n is the number of nodes and m is the number of edges)
(but yeah, the even more obvious solution is to do a bunch of traversals and seeing if you hit yourself)
ah
yeah that works
@blissful kiln ask the egg question here
Yo I am trying to create a custom hashing(encrypting) method for password encryption which we can also ecrypt
using a custom wordlist
like
a means 0n%
Hashing != Encrypting
not sure if this is the wrong place for this sort of thing, but I'll give it a go anyhow! how do I think through this problem, what sort of tools do I need to pick up in order to get better at solving them?
The Empire State Building is 102 stories high. A man wanted to know the highest floor from which he could drop an egg without the egg breaking. He proposed to drop an egg from the top floor. If it broke, he would go down a floor, and try it again. He would do this until the egg did not break. At worst, this method requires 102 eggs. Implement a method that at worst uses seven eggs.
ikiikik
Do you have any ideas how to proceed?
Iβll ask the same question differently: imagine Waldo is hiding in a 100 story building. You can go to any floor and ask: is Waldo on this floor and if not: is he above or is he below?
Which floor would you go to first - that would definitely reduce the number of floors youβd have to search the most?
thanks for the illustrative example, I know that I want to at least use a binary search, but it's the limit of no more than seven eggs that I have trouble with.
102 stories, I'd probably start at 51.
Great, so how many floors are left? 50ish, right? So now, what floor do you check next?
Do this a few times and see what happens when you get to 7 searches
if it breaks, I'd fall down to 25, if it breaks I'd fall down to 12, if it breaks I'd fall down to 6, then 3.
It's binary search problem?
with a constraint on the amount of egtgs.
Yes, and how many floors are left on the 7th drop?
(Or 7th check)
def eggchecker(eggs, k):
def feasible(building, egg):
//Your code here aka main logic
left, right = 0, eggs
mid = left+(right-left)//2
if feasible(mid,k):
right = mid
else:
left = mid+1
return left
hi need help with leetcode roman numerals,
it might be easier if we have a reference floor where the egg does not break, but does at the next floor, rather than no number here.
so if the egg doesn't break at floor 12, but does at 13.
if we're searchin 102 floors, and we divide by 2 for each floor it breaks, we end up at 12, that's fine.
assume that our highest floow is now 11.
not sure how to show the difference for 4s and 9s in py
we arrive at 6, where it doesn't break, and know that it's between 6-12.
how do we think of that range of 6 numbers, with three eggs left?
(51, 25, 12, 6, x, x, x)
to arrive at 11
sorry if I'm not making sense, let me know if I am.
51 - 25 - 12 - 6 - 3 - 2 - 1, 7 eggs, right?
sure
Or, in your example.
why'd they have to use eggs though... just start on the first floor π it's going to break
@agile sundial let's assume we're using your skull instead
51-25-12-6-9-10-11 or 6-9-11-x depending on how your rounding
how are you getting from 6-9-10?
After 6, you know itβs 7-11, so split it (9) and check
Then itβs above 9, so you know itβs 10 or 11
At this point, Iβd write a little code and test it
I just want to think it through, because I don't think it follows in the same way
so say we have 99, I'd approach it by dividing i.e., 102 - 51
at this point it doesn't break, (99 is our reference)
so I'm thinking I'd add 51 + (51 / 2)
which is 76.5, still too low
adding 76.5 + (76.5 / 2) > 102, so maybe just 76.5 + (51 / 2) which is 88
still too low here.
we arrive at 101 in the next iteration
there's a range of 11, 100 - 89.
we have two @agile sundial skulls left
so the increment isn't good enough
51 - 76 - 89 - 96 - 99
Thatβs divide remainder by 2 and add (or sub) to last floor
I guess you have a math error going from 88 to 101
You shouldβve gone 88 to 95 or 96 (depending on rounding)
I wonder how well this will work but I'll try to code it today or tomorrow.
thanks for helping me think through it
is there anything that you're still concerned about when looking at this problem?
No, seems straightforward. Write yourself a test case that tries each scenario and tells you how many tries it took.
Writing test cases first is a very good practice.
this... is just a puzzle for children, no? it does not require binary search or something. You just need two eggs. Or am I missing something?
the goal is to minimize eggs, not attempts
wait, one egg
whatever, I'm dumb
You need one egg
lol, you're right
bruh
Hello there anyone knows about boyer moore voting algorithm for knowing the majority problem? If so I have been finding the concept of counter incrementing and decrementing and the candidate switching until a majority element appears not intuitive . I know that a majority element exists at least n/2 + 1 and is larger than the remaining elements but can't fathom behind the intuition of counter . Does anyone here know a rigorous proof for that algorithm?
Unless I am reading the question wrong or we are assuming the eggs work like actual eggs I think you need binary search since he's looking for the highest floor
god fking dammit
no
try floor one. If it failed you found the floor. Otherwise take the egg you just used (it did not break, you can reuse it), and try floor two
repeat until it breaks
Oh, this is one of my favourite algos of all time!
The proof for it is beatiful
Sure if they work like real eggs otherwise this is just a linear sesrch
If it's floor 102 your worst case is still 102 floors
Every element can either decrement or increment the counter. For every decrement, there must be some other element, which incremented a counter, and it must be not equal to the one decrementing, by construction of the algorithm. Imagine now that we split operations (and corresponding sequence elements) in decrement-increment pairs, leaving some last increments without a pair (possibly none). Notice how those last increments are corresponding to the same element. Consider the majority element. Elements in the pair must be different. How much pairs can there possibly be? Well, at most n/2, obviously. But, the majority element appears more than n/2 times! This means that the last increments must be caused by that majority element. Therefore, this element is the last element counter is being incremented for.
P.S. I rewrote this like 5 times lol.
floors, not eggs
we don't care about floors
we must minimize eggs
Your method still uses 102 skulls at worst
Nvm
U right
Disregard me
Since this doesn't take place in reality the structural integrity of the shell does not matter
To be fair, the specification didnβt say which was to minimized, only that it must not exceed 7 eggs. Nor the properties of a egg after repeated drops. Third, the common sense answer is: 0, since any chicken egg will break from even a first floor drop.
But perhaps weβre talking faberge eggs ?
what are your favourite algo/proof books?
I have never read one, I just had good teachers
intriguing
minimize the number of tested floors using k eggs is an interesting enough problem
if k=1 you can only linear search small to large
if k is large enough, I think k >= log2(n_floors), you can binary search
what about the cases between?
the classical problem is with k=2 iirc
which can be solved checking only O(||sqrt(n)||) floors
and it generalizes pretty neatly with some math
Algorithm n data structure is very difficult
thanks for your input, I'm not sure how this would be solved with k=2, do you have any papers I could read?
the question to look at is, given that you have 2 eggs and n tries, how many floors can you cover?
I guess let f(n, k) be the floors you can cover with n tries and k eggs
f(n, 1) = n
because you can only linear search from below
f(0, k) = 0
so what is f(n, 2)?
you do some test and the outcome is that you spent a test and may or may not have broken an egg, and you have covered one floor
f(n, 2) = f(n-1, 1) + f(n-1, 2) + 1
this is the relevant recurrence for k=2
oh I see what you mean - I thInk for the example I illustrated, and not the leetcode problem, that we have 7 eggs, i.e., 7 tries, across 102 floors which using this notation would be f(7, 1) I guess.
or f(7, 7) would be more accurate probably, as once an egg breaks we can't reconstruct it
clarify your meaning here please.
context: The Empire State Building is 102 stories high. A man wanted to know the highest floor from which he could drop an egg without the egg breaking. He proposed to drop an egg from the top floor. If it broke, he would go down a floor, and try it again. He would do this until the egg did not break. At worst, this method requires 102 eggs. Implement a method that at worst uses seven eggs.
still with me @haughty mountain?
I think the recurrence is missing a +1 actually
and solving it is fairly straightforward
||expand recursively to get||
||f(n, 2) = f(n-1, 1) + 1 + f(n-2, 1) + 1 + ... + f(1, 1) + 1 + f(0, 1) + 1 + f(0, 2)||
||f(n, 2) = n + n-1 + ... + 1 + 0||
||f(n, 2) = n*(n+1)/2||
I realized when actually solving it the answer was off π
the intuitive logic is ||that if you have 10 tries you can try floor 10 first, if the egg breaks you have enough tries to search through floors 1-9, if the egg does not break you know floor 10 is ok and you're in the same situation with 1 less try||
so you can now try floor ||10+9||
||and again you have enough eggs to cover floors 11-18, ...||
you're so much better than I am at thinking through algorithms, golly
any books you'd highly recommend?
I haven't really learned through books much for cs
gotta take that genius IQ and make some chatbots with it.
the question there is, what's the smallest x such that f(x, 7) >= 102
the 7 egg, 102 case in particular is part of one of the easier edge cases
nods
if the number of eggs β₯ number of tries things boil down to just binary search
with 7 eggs you can for sure do it in 7 tries
I think it ends up that you can cover 2^7-1 = 127 in that case (didn't really derive this, but it feels correct, 2^0 - 1 = 0 and whatnot)
almost seems trivial, yeah.
well, it's the easier case for sure
totally. I'll try for a solution in the afternoon.
other than the trivial 1 egg case
if you don't read books for cs, I'm guessing you have a math/combinatorics/logic background? or how else do you find yourself learning if not through books?
unless you pop into lectures or you're YouTube heavy.
I do have a bunch of math background, but learning cs has mostly been doing programming contests and researching stuff I ended up needing to learn
oh interesting
which could be as simple as reading a wiki article or whatever, but sometimes might require digging into papers as well
I suppose if your math is robust, everything else is relatively easy.
the problem solving you train when studying math/physics/whatever translates fairly well to cs
and some math has direct applicability as well
ty for your time btw
Another interesting question is to minimize walking for the given amount of eggs. Like with one egg you have to walk n*(n-1) (if my math is right) because you need to get the egg back. With 7 eggs just n is enough. What about 3?
n*(n+1)
and I guess n would be the number of floors in your question?
sanity check n=1 yields distance 2
which is correct if you assume you need to end up at ground level afterwards
if not then it's n*(n+1) - n
or just n^2
Hi, if someone did problem D of Codeforces yesterday, why is this code too slow for problem D of Round 892 Problem D (https://codeforces.com/contest/1859/problem/D). I'm using memoisation to not compute twice the maximum distance from the same xi, and make sure i track the last_portal used to not try and use portals that would lead to a smaller end point, but it's still too long, i'm not even sure what the complexity of my algo is (it would be O(q+n_portals^2), right? But because of the multiple break statements it should be less than that on average)
def get_as_far_as_possible(xi: int, last_portal_idx: int) -> int:
if xi in memoisation:
return memoisation[xi]
else:
for portal_idx, portal in enumerate(portals):
if portal[0] <= xi <= portal[1] and portal[3] > xi:
xi = portal[3]
xi = get_as_far_as_possible(xi, portal_idx)
break
if portal_idx > last_portal_idx:
break
memoisation[xi] = xi
return xi
if __name__ == "__main__":
n_tests: int = int_input()
for _ in range(n_tests):
memoisation: dict[int, int] = {}
n_portals: int = int_input()
portals: list[list[int]] = []
for _ in range(n_portals):
portals.append(line_integers())
q: int = int_input() # len(x)
x: list[int] = line_integers()
portals = sorted(portals, key=lambda i: i[3], reverse=True)
result = []
for start_position in x:
result.append(get_as_far_as_possible(start_position, n_portals))
print(*result)
And I tried to understand the tutorial but I'm not sure I understood what they meant with scanline (I know what the scanline algo is, I just don't understand how you can apply it here)
And I'm not very good at reading c++ which they wrote their solution is so i'm a bit confused now
been trying to figure out this stuff for an hour or two and i'm dying
I figured I could do something like scanning all the portals for all positions (so basically computing the answer for all positions decreasing from 10^9 to 1) to not have any quadratic term (but it would O(n_positions*n_portals)) but there are so many more positions that it doesn't seem worth it
I merged useless portals like this:
# merge portals
portals = sorted(portals, key=lambda i: i[2])
stack_portals: list[list[int]] = [portals[0]]
for portal in portals[1:]:
if portal[2] <= stack_portals[-1][3]:
stack_portals[-1][0] = min(stack_portals[-1][0], portal[0])
stack_portals[-1][1] = max(stack_portals[-1][1], portal[1])
stack_portals[-1][3] = max(stack_portals[-1][3], portal[3])
else:
stack_portals.append(portal)
but it's still too slow 
i get further in the tests though
I dont see how your get_as_far_as_possible function could ever be fast enough
If a point isn't in the range of any portal than it will take O(n) time
is it a problem?
Sure there are loads of queries but most will be in the range of at least a portal
It would be easy to make a test case where none of them is in the range of a portal
so should i make a set containing all the positions that are not in the range of a portal beforehands?
that seems kinda bad of a fix
especially since there are so many positions
iterating over them is even worse than iterating through all the portals
Btw I'm not sure I follow your solution idea from reading the code. Are you trying to go for a greedy approach?
yep! I think that's the right idea, for each point, you try to go to the rightmost part of any portal you can take. But you sort the portals before hands based on that rightmost part (decreasing order) so that the first one "you can take" ends up being the one sending you the furthest
and since the portals have "continuous ranges" it's pointless to go left at any point
so i just always go at the rightmost part of the portal
One thing you could do is to add the queries as intervals with l = a = b = r = x_i.
I can see how to do that using two pointers on sorted portals.
But that is not what your code is doing 
I'm not sure what you mean by that?
Umm
What I do is I've sorted it based on the rightmost part
And then I iterate through all the portals
And the first one I can take
will bring me to the rightmost part i can get to
and then i call again the same function
since i might have unlocked "new portals"
but I think that's where the memoisation should help a lot
however it's still like O(nΒ²)
which is surely enough too much
even if i merge useless portals
In the input you have been given n portals, but you could see it like you have been given n + q portals. Every query position x_i can be thought of as a portal going to it self.
Mm, yes that's fair, although I'm struggling to see how that'd help?
The way I would solve this problem is that I would figure out the maximum coordinate you can reach if you start at b and use 0 or more teleports
In that case interpreting the queries as portals helps a ton
I might be wrong but I feel like that's basically the same as I'm doing right? You end up with O(nΒ²) since for a given portal you might need to use n other portals
The trick is to use two pointers
Starting from the portal with the largest value of b
I'd have to sort my list in increasing rightmost-part-of-portals, the right pointer going up everytime i unlock a new portal from a fixed position, updating my array memoisation along the way and whenever i can't get to the next portal, i move both the left and the right pointer to the next (unattainable) portal, achieving O(n)?
I really think you want to go throught the portals in decreasing b order
Instead of increasing
Yeh that's what i was doing until now (without the two pointers), but with decreasing b order, I'm struggling to see how I could use two pointers
https://codeforces.com/contest/1859/submission/218676627 Here is a two pointer solution
damn
The reason that my submission is kinda slow is that sorted is really slow in Python for sorting non-interger lists
i was trying to code one and i have an infinite loop somewhere
(im trying to see if what i tried to code works before checking your solution)
Here is a kinda codegolfed version https://codeforces.com/contest/1859/submission/218678866
This is currently the shortest solution to this problem on codeforces.
I just rewrote the code to be more compact and use fewer lines of code.
If you sort under "status" by AC submission to the problem ordered by "solution size", then my solution is first.
that's something I hope I can have fun doing in a few decades π
so far from doing this, just trying to get AC and understanding first π
i've noticed literally no one uses python in the first 200 people
it's probably why no one has short solutions i guess
Btw I'm not saying that I actually codegolfed it. It is just that my solution is short and simple.
I even left in a comment in the code
yeah yeah course
I dont think my solution would be all that much longer in C++.
ngl i don't understand why the tutorial talks about multiset and all that stuff
when your solution is apparently way easier to understand
although i'm still trying to make my two-pointer approach work
there are two tutorials, a video of a guy explaining he did coordinate compression and used priority queues and it was all c++ so i was lost
and the written one was talking about multiset, which is a dsa i didn't really know so i was a bit lost when trying to understand the code
Just so you know, multiset speciafically refers to std::multiset in C++
It is a sorted data structure
Python doesnt have anything like that built in
I think i found that there was a library in python that had it, but it's probably not built in so i don't think i can use it on codeforces
I use https://github.com/cheran-senthil/PyRival/blob/master/pyrival/data_structures/SortedList.py whenever I need some kinda of sorted datastructure
It is my own implementation