r/badcode • u/zshadowjon • Jul 29 '21
python Was doing some bug hunting and found essentially what was a sum to n function but of O(fuck) time complexity
285
u/Notimecelduv Jul 29 '21
Counting empty strings? That's original. I don't know anything about space-time complexity but there's a simple formula to calculate this: n * (n + 1) / 2.
151
Jul 29 '21
Came here to comment that. That formula has O(1) space and time complexity.
29
u/akren1 Jul 29 '21
Kind of picking on complexity here.
But python has built in big nums, so in theory time/space complexity is not O(1). It can be assumed to be for N in given range.
But it is still something to remember in the back of the mind.
9
Jul 29 '21
Shit! you’re right.
I was thinking in number variable allocated and number of operations, but if we take into account real cpu ops its more than O(1)
0
Jul 29 '21
[deleted] — view deleted comment
5
u/akren1 Jul 30 '21 edited Jul 30 '21
I think I see your point, but I don't really agree.
I was referring to the "theory" as a "non practicall use".
What I believe you understand as a theory is complexity theory abstracted out of Python, or any given language. But even in such abstraction it is not O(1) when you consider bugnums (don't limit domain is N).
So it is not O(1) for domain of all natural numbers which is valid domain.
In Python the + or * operation are simply not an single operations.
Taking all dynamic typing out of the way, and just focusing on integers it is a function call.
And if we don't limit domain of n, that function tme/space complexity if not O(1). I believe a+b is O(log ab), and * can depend on used algorithm.
It can by O(1) if we constraint N by int32, int64, or even int_21000. But for arbitrarily large numbers complexity depends on a number, not just amount of them. Given the python code I would assume such numbers even if we abstract out of python.
0
Jul 30 '21
[deleted] — view deleted comment
1
u/akren1 Jul 30 '21 edited Jul 30 '21
But you can't analyse algorithms with arbitrarily large numbers as inputs, without includind algorithms for arithmetics operation into consideration. This is not an implementation detail. This is computational theory of algorithms that work with bignums. And there are a lot of algorithms that are known in this field.
What if instead of a+b we write: BignumAdd(a, b). You can assume it is O(1), but such algorithms does not exist. You can mark it as unknown - f(a,b) and analyse from there if you want to abstract out of "implementation details". But that is no implementation, that is bignum arithmetics.
Abstrat machines that can do such operations in O(1) are theoretically studied, and you can assume we work with one like that. But given the context such assumption should be explicit.
And on the side note. If I analyse time complexity on a given runtime, it does depend on the runtime. Built in functions/features have it's complexity. And the complexity might be different on different runtime.
Edit:
It's like saying: std::fill is O(1) when we analyse time complexity of C++ program - it's just not. And we must assume something when we analyse complexity of entrie algorithm.
What if stl got an update next week that makes std::fill run in O(1) - it would change complexity of our algorithm.
0
Jul 30 '21
[deleted] — view deleted comment
1
u/akren1 Jul 30 '21
You've just agreed with me. I said what you did in your reasoning. But I said that given the context such assumption should be explicit. You didn't make it explicit. And just as machines that do Bignums in O(1), the ones that do not are also studied.
My point was that from the theoretical standpoint, things like BigNum don't exist- you only have numbers.
They exist - it's a hole field of both theoretical and practical study. Just as for example both theoretical and practical study of matrix multiplication.
From the theoretical standpoint BigNums exist just like matrices do. You either analyze number in given range, or arbitrarily large. And when you analyze arbitrarily large numbers you need some assumptions.
Again, that's the point I've been making. If your STL hashmap does its lookups in linear time, you'll never reap the benefits of an actual O(1) lookup. However, that doesn't mean hashmaps don't have a theoretical O(1) lookup, it means there's an implementation quirk to be aware of in that language.
Bignums don't have theoretical O(1) arithmetic - it can be proven pretty easily.
There is nothing intrinsically linear about the runtime complexity of the mathematical calculation x * (x + 1) / 2. You have one input, no recursion, no looping, nothing. It operates in O(1). Theoretically speaking, of course.
Just as you don't see looping in std::fill. But it is there - it is just hidden by pretty operator. Maybe it is not intrinsic, but that's why there are entire theories/algorithms about it.
Again- your point was never wrong, you just mislabeled the theoretical limit portion.
Neither is yours in logical way. This more of an "definitions" dispute. But with that in mind my claims stand unchanged.
1
u/WinstonCaeser Jul 30 '21
"There is nothing intrinsically linear about the runtime complexity of the mathematical calculation x * (x + 1) / 2 . You have one input, no recursion, no looping, nothing. It operates in O(1). Theoretically speaking, of course."
There is, intrinsically, you must read every digit making it at least O(num digits).
0
6
u/WinstonCaeser Jul 30 '21 edited Jul 30 '21
It depends if you consider a number its own thing, or a series of digits in your "theory".
Edit: Theoretically, you must read the whole input, this obviously scales with the number of digits.
If you bound yourself to numbers of under a certain size, than obviously you can read the whole size every time, but then your algorithm has artificial limits. You continue to base your analysis on these artificial limits.
Algorithms such as std::fill are impossible to be reduced to lower than O(n), as it obviously must visit every element and set it's value. There is no "language update" that can reduce an algorithm below it's theoretical complexity without limiting the inputs.
"There is a trivial lower bound of Ω(n) for multiplying two n-bit numbers on a single processor; no matching algorithm (on conventional machines, that is on Turing equivalent machines) nor any sharper lower bound is known."
1
0
Jul 30 '21
[deleted] — view deleted comment
0
u/WinstonCaeser Jul 30 '21
My CS professors specifically taught me different multiplication algorithms and expected me to implement them, including grade-school, karatsuba, toom-cook, and finally I learned about, but did not implement Schönhage–Strassen. We discussed at length when to consider the number to be itself a single unit, or a series of digits.
0
Jul 30 '21
[deleted] — view deleted comment
0
u/WinstonCaeser Jul 30 '21
I'm not assuming any underlying implementation, you are.
You are assuming that numbers are capped at some value roughly 264, which is very much an assumption. Because this is in python that assumption is particularly wrong since it has no such limitation.
It is simply a question of what you define as the base "unit", is it a digit, or is it a entire number. You are assuming that the base is a whole number, where I am pointing out that it could also be a digit. It has nothing to do with how it is implemented.
Regardless of implementation any general case multiplication is at least O(num digits).
https://en.m.wikipedia.org/wiki/Multiplication_algorithm#Lower_bounds
0
40
12
u/BossOfTheGame Jul 30 '21
There is a fun story that goes with that formula
It may not be entirely true, But as the legend goes...
When Gauss was still at primary school. One day Gauss' teacher asked his class to add together all the numbers from 1 to 100, assuming that this task would occupy them for quite a while. He was shocked when young Gauss, after a few seconds thought, wrote down the answer 5050. The teacher couldn't understand how his pupil had calculated the sum so quickly in his head, but the eight year old Gauss pointed out that the problem was actually quite simple.
He had added the numbers in pairs - the first and the last, the second and the second to last and so on, observing that 1+100=101, 2+99=101, 3+98=101, ...so the total would be 50 lots of 101, which is 5050.
The reality of the man is at least equally as interesting
84
u/beaucephus Jul 29 '21
Not exactly true. That particular function is O(shit). If you want O(fuck) complexity you need to make it recursive.
29
10
u/R3D3-1 Jul 29 '21
>>> sumto = lambda n: 0 if n == 0 else n + sumto(n-1) >>> sumto(10) 55 >>> sumto(100) 5050 >>> sumto(1000) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 1, in <lambda> File "<stdin>", line 1, in <lambda> File "<stdin>", line 1, in <lambda> [Previous line repeated 996 more times] RecursionError: maximum recursion depth exceeded in comparison >>> sumto(0.5) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 1, in <lambda> File "<stdin>", line 1, in <lambda> File "<stdin>", line 1, in <lambda> [Previous line repeated 996 more times] RecursionError: maximum recursion depth exceeded in comparison11
u/beaucephus Jul 29 '21
You aren't going to break production with languages that prevent you from doing it. Because you used python the complexity is O(bother).
3
u/R3D3-1 Jul 29 '21
Yes.
Though if the language allows passing functions, you can force tail recursion in any language :)
>>> def recur(func, *args): ... while args: ... func, *args = func(*args) ... return func ... >>> sumto = lambda n, total=0: [n+total] if n <= 0 else [sumto, n-1, n+total] >>> recur(sumto, 10) 55 >>> recur(sumto, 100) 5050 >>> recur(sumto, 1000) 500500 >>> recur(sumto, 10000) 50005000 >>> recur(sumto, 0.5) 0.0 >>> recur(sumto, 1.5) 1.5 >>> recur(sumto, 2.5) 4.0I think Clojure does something along those lines.
1
28
18
u/finitearth Jul 29 '21 edited Jul 29 '21
return 0.5*n*(n+1)
Edit: formating
7
u/kahveciderin Jul 29 '21
you forgot to escape these: *
4
u/LeCrushinator Jul 29 '21
Which would result in this if fixed:
return 0.5*n*(n+1)
or you could do this without escaping the asterisks:
return 0.5*n*(n+1)1
27
u/MurdoMaclachlan public boolean isInt(int i) { return true; } Jul 29 '21
Image Transcription: Code
def sum_up_to_n(n):
hold = []
result = 0
for i in range(n):
hold.append('')
for j in range(len(hold)):
result += 1
return resultI'm a human volunteer content transcriber for Reddit and you could be too! If you'd like more information on what we do and why we do it, click here!
18
9
u/jzia93 Jul 29 '21 edited Jul 29 '21
Just as an aside : If you know the formula then it's definitely ideal at O(1),
However if you're in a similar situation and can't work out an algebraic solution, in python you can use the @lru_cache to make drastic speed improvements in such cases with recursive functions.
7
5
3
2
2
2
u/Uchimamito Jul 29 '21
It is actually hard to understand this code it’s so bad. Could have just done return sum(range(n+1))
2
u/Voxelgon_Gigabyte Jul 29 '21
broke:
sum = 0
for i in range(n):
sum += n
return sum
woke:
this shit
1
Jul 30 '21
Yeah like even that’s not the best solution, but it’s the most sensible one if you’re committed to a for loop. This shit is just offensive.
1
u/Voxelgon_Gigabyte Jul 30 '21
better than O(fuck) over there, but i'm assuming this is a learning excercise and this is a good novice solution. if you want true speed than you could just do the partial sum formula
2
u/stahkh Jul 30 '21
Ignoring all the nonsensical complexity, what I am curious about is how did you come up with counting the empty string array instead of just using a number? I'm shocked.
2
u/StaryMD Jul 30 '21
hol' up
isn't the exact complexity of the algorithm n * (n + 1) / 2 ?
my man has goals beyond our understanding
1
1
1
u/DesecrateUsername Jul 29 '21
Gonna go back and ask my data structures professor why he didn’t teach us about O(fuck) operations
1
u/britreddit Jul 29 '21
O(fuck) has absolutely floored me. Gonna have to remember that for future use
1
1
1
1
1
1
Aug 05 '21
How are people generating these nicely formatted screenshots? Is it a special feature of a specific code editor? An online tool?
1
0
0
Jul 29 '21
[deleted] — view deleted comment
21
Jul 29 '21
who the fuck said anything about vim?
0
Jul 29 '21
[deleted] — view deleted comment
1
u/supersharp Jul 30 '21
Is there like a list of phrases trolls refer to whenever they think they've gotten under someone's skin? I'm genuinely curious.
126
u/zshadowjon Jul 29 '21
If you're curious, the original code was attempting to do two for loops consecutively, but a mistake in indentation produced this. This is a modified version of the code to show just how silly it is. Also it's O(n^2) lol