1 Problem, 24 Programming Languages

A video taking a look at 24 programming language solutions (C, Go, C++, Rust, D, Clojure, Ruby, Elixir, Haskell, Racket, Python, APL, J, BQN, PHP, Scala, Erlang, Typescript, Javascript, Java, Kotlin, Swift, Dart, C#) to one problem.
Solutions on GitHub: github.com/codereport/LeetCod...
ADSP Podcast: adspthepodcast.com/
Array Cast: www.arraycast.com/
Contest: 327
Problem Name: Maximum Count of Positive Integer and Negative Integer
Problem Link: leetcode.com/problems/maximum...
Problem Type: Greedy
Chapters:
0:00 Intro
0:31 Problem Description
1:14 Test Cases & Solution Explanation
1:55 Programming Language Solution Categories
2:59 C Solution
3:22 Go Solution
3:35 PHP Solution
4:09 Python Solution
4:25 Dart, Swift & Erlang Solutions
5:00 Javascript & Typescript Solutions
5:17 Clojure & Racket Solutions
5:56 C#, Elixir & Kotlin Solutions
6:20 Scala & Ruby Solutions
6:51 Java & D Solutions
7:14 Haskell Solution
8:15 C++ Solution 1
10:02 C++ Solution 2
10:24 C++ Solution 3
11:03 Rust Solution 1
11:40 Rust Solution 2
11:57 Rust Solution 3
12:19 J, APL & BQN Solutions
12:42 BQN Explanation
17:15 Best Solution Awards
18:15 Performance Comparison
19:05 Outro
Follow me on Github: github.com/codereport
Follow me on Twitter: / code_report
Follow me on LinkedIn: / codereport

Пікірлер: 557

  • @blt_r
    @blt_r Жыл бұрын

    For your first rust solution you could have used `.iter()` instead of `.into_iter()` to not consume the vec, and not clone it. Like this: fn maximum_count(nums: Vec) -> i32 { std::cmp::max( nums.iter().filter(|&&n| n nums.iter().filter(|&&n| n > 0).count(), ) as i32 } Also in idiomatic rust this function would have taken `&[i32]` and returned `usize`, but I guess there's nothing I can do about it :(

  • @Bo15307

    @Bo15307

    Жыл бұрын

    Yes you should always use .iter() unless you need mutability and/or want to move the values somewhere else

  • @tamburine

    @tamburine

    Жыл бұрын

    I also thought that you can pass nums by reference (borrow it). Plus make it a slice instead of vector, so the solution become more general. fn maximum_count(nums: &[i32]) -> i32 { ...

  • @code_report

    @code_report

    Жыл бұрын

    Yea, this is way nicer! I tried using .iter() but clearly didn't set up the lambda correctly. Thanks : )

  • @albertz0

    @albertz0

    Жыл бұрын

    So much more sexy

  • @Jplaysterraria

    @Jplaysterraria

    Жыл бұрын

    @@code_report The problem with iter is that you get an extra reference (Iterator), instead of into_iter (Iterator), then in filter you take &Item, which ends up being a double reference (&&T), then you have to either do (|&&n| n I'd like to see a .filter() that takes Clone types by value, but I don't think that's allowed in the type system. and it could be a footgun if someone decides to make their 16kiB struct copy. (An example of a real 16kiB struct is the Asahi Linux M1 GPU driver structs, they literally overflow the kernel stack if you try to construct them normally)

  • @oj0024
    @oj0024 Жыл бұрын

    The performance difference between C++/C and Rust seems to be C++/C using gcc and rust using a llvm backend, if you use clang for C you get almost the same codegen as rust.

  • @adaskalov

    @adaskalov

    Жыл бұрын

    Perhaps, but then Swift should be near Rust performance, since it also uses llvm.

  • @matthewsanetra

    @matthewsanetra

    Жыл бұрын

    @@adaskalov No, because despite Swift also using LLVM the language still does other abstractions e.g. the ABI boxes

  • @keremardicli4013

    @keremardicli4013

    Жыл бұрын

    Plus for loop is always faster than foreach. So PHP would run faster with a for loop. But it is already very fast thank to C interpreter

  • @GeorgeFosberry

    @GeorgeFosberry

    Жыл бұрын

    What about time spent on I/O? I'm not familiar with Leetcode, but assume that input is read from files, as usual. I suspect that the author of this video used for C++ solutions, which is notorious for being very slow by default.

  • @Klayperson

    @Klayperson

    Жыл бұрын

    On leetcode, your don't have to do i/o yourself, as the environment calls your function with all the test cases for you. The author of the video only had to include and

  • @interested_in_everything
    @interested_in_everything Жыл бұрын

    I really like the code transition effects. Very well produced video.

  • @oantolin

    @oantolin

    Жыл бұрын

    Conor made a video explaining how he makes these transitions, it's pretty cool: kzread.info/dash/bejne/iJxn25OenMSTj9Y.html

  • @raffimolero64

    @raffimolero64

    Жыл бұрын

    My only complaint is the framerate. It's otherwise a really clear and beautiful explanation.

  • @puppergump4117

    @puppergump4117

    Жыл бұрын

    Looks like it's all done by a library called Manim.

  • @h0rst
    @h0rst Жыл бұрын

    I would think the solution in C (and similar solutions with a single for loop) could be even faster once you take into account that the numbers are sorted. Start the loop and count the number of negatives. As soon as you encounter a number that is not negative, stop. We now have the number of negative elements. Next up, count the number of zeroes, and stop as soon as you encounter a positive element. The number of positive elements is now simply equal to the total size minus the number of negative elements minus the number of zeroes. So on average, you only have to loop through half of the input array. Optimized for speed, not for readability/maintainability.

  • @qqii

    @qqii

    Жыл бұрын

    You can replicate the C++ std::equal_range manually in C for the best time complexity. Instead of looping to count the number of negatives, you can binary search for the first element that is positive, then count down to the first element that is negative.

  • @add-iv

    @add-iv

    Жыл бұрын

    @@qqii counting down makes this worst case O(n) 😉

  • @qqii

    @qqii

    Жыл бұрын

    Your right! I translated the "count the number of zeros" from your solution, which is actually O(n) if it's all 0s. That makes the 1 binary search method O(log2(N) + N) So actually ideally you'd do two binary searches, the 2nd with the smaller range (essentially std::lower_bound and std::upper_bound) for O(2 * log2(N)) = O(log2(N)).

  • @MrAbrazildo

    @MrAbrazildo

    Жыл бұрын

    @@qqii Better would be to binary search for the 1st non negative, and then, starting by that position, search the first non zero.

  • @michelderosa2695

    @michelderosa2695

    Жыл бұрын

    @h0rst That solution could still be a bit too slow, imagine the array being passed is made up of 3 negative numbers, 1000 0's and 2 positives, it'll still take awhile to go over the array. Instead peek at the values from both ends at once, say using index starting at 0, while barrier is size_of(array)-1, each pass you increment index and decrement barrier.. once index == barrier *or* (num[index] == 0) && (num[barrier] == 0) .. in this scenario you quit the loop after 3 peeks, for the array example I mentioned.

  • @ubhelbr
    @ubhelbr Жыл бұрын

    In PHP you probably forgot to put an opening tag in the beginning so the syntax highlighting is correct and your program will simply output its contents :)

  • @programmingjobesch7291
    @programmingjobesch7291 Жыл бұрын

    C, PHP, JS, C#, Python, Kotlin and Dart are the best looking/most readable to me for sure.

  • @vm-seventy
    @vm-seventy Жыл бұрын

    The array programming languages always fascinate me because of how informationally dense they are! They perform operations that other languages require like 5 lines to describe in just 1 line.

  • @kahnfatman

    @kahnfatman

    10 ай бұрын

    @code_report Could you give me your insights on the trade off between: 1. Finding/Training developers to read/understand/maintain APL/BQN code vs FP vs imperative programming languages 2. Maintainability/Extensibility of the code base I have the feeling that BQNish code is awesome to certain extent but how can I sell this to my tech lead??

  • @MegaEnpassant
    @MegaEnpassant Жыл бұрын

    Scala has prefix max function: Math.max Performant Scala code, similar to Rust: def maximumCount(nums: Array[Int]): Int = { def op(v: (Int, Int), e: Int) = (if (e > 0) v._1 + 1 else v._1, if (e val (pos, neg) = nums.foldLeft((0, 0))(op) Math.max(pos, neg) }

  • @davidkatz1017
    @davidkatz1017 Жыл бұрын

    Hi Connor, great video as always. Just a note that in D you only need one cast (from result of `max`) because `max` is a template and will return the common type of its two arguments.

  • @jesusjar11
    @jesusjar11 Жыл бұрын

    The Kotlin solution could be "improved" by using the `it` keyword which is a implicit name for the parameter of a "single-parameter" lambda so { it 0 } respectively o/

  • @PavitraGolchha

    @PavitraGolchha

    Жыл бұрын

    Kotlin looked too good and readable

  • @chri-k

    @chri-k

    Жыл бұрын

    why in the world would they chose “it” of all things

  • @PavitraGolchha

    @PavitraGolchha

    Жыл бұрын

    it is because it is :)

  • @vardhanpatil5222

    @vardhanpatil5222

    Жыл бұрын

    Yes, the function would end up as ``` fun maximumCount(nums: IntArray): Int { return maxOf( nums.count { it nums.count { it > 0 }, ) } ``` I just found out that youtube doesn't have a way to enter monospace text.

  • @chri-k

    @chri-k

    Жыл бұрын

    @@vardhanpatil5222 Yep. Unicode has monospace version of the characters of the Latin alphabet and Arabic numerals ( although many fonts render them as something weird ), but not the rest of ASCII.

  • @soniablanche5672
    @soniablanche5672 Жыл бұрын

    You have to remember that Big O(n) complexity only matters if the N is big enough, maybe that's why the C++ solution wasn't the fastest, maybe if the array used is large enough you can see the difference.

  • @SiarheiSiamashka

    @SiarheiSiamashka

    Жыл бұрын

    As the others already noticed, the binary search C++ solution has O(N) time complexity because the vector is passed not by reference but by value. Creating a copy of the vector ruins performance.

  • @Adam_le_Zigoto

    @Adam_le_Zigoto

    Жыл бұрын

    @@SiarheiSiamashka that's why C++ with const correctness should be the fastest, or same to Rust

  • @kolyan199816

    @kolyan199816

    Жыл бұрын

    Nope. The caller can put nums by rvalue: maximumCount(std::move(nums))

  • @khatdubell

    @khatdubell

    Жыл бұрын

    @@kolyan199816 "Can" doesn't guarantee "does". But even without that, I suspect the C++ solution would still be slow. This is a list of 2000 ints. 2k elements of 4 bytes. 8kb. Easily fits inside a l1 cache. The predictability of going linearly through the array is going to outperform the random access required to do a binary search on the array (which is what equal range does under the hood) This is why its important to know your data and your hardware to pick correct algorithms. Ofcourse the only way to know for sure is to measure both and see.

  • @puppergump4117

    @puppergump4117

    Жыл бұрын

    @@khatdubell I feel like they butchered the c++ solutions. There's no need to try to use every single stl function for a single problem. The simpler your code is, like in the c solution, the better it can be optimized.

  • @FrankieTheKneeMan
    @FrankieTheKneeMan7 ай бұрын

    Your comment about excessive duplication on the haskell solution got me thinking, and actually, you can reduce repitition a _lot_ in haskell with some creative use of partition (from Data.List), filter, and uncurry: maximumCount = uncurry (on max length) . partition (

  • @porlando12
    @porlando12 Жыл бұрын

    Amazing video! I'd love to see you include some more data science languages like R and Julia.

  • @MCRuCr

    @MCRuCr

    8 ай бұрын

    julia> func(arr::Vector{ 0), sum(arr . 10 μs with a 2000 element array amazing stuff

  • @alxjones
    @alxjones Жыл бұрын

    In Kotlin, lambdas with one parameter can use `it` as a default name. So instead of `e -> e < 0`, you can just do `it < 0`.

  • @Player_X_YT2
    @Player_X_YT2 Жыл бұрын

    4:14 You're iterating twice through the array, you can do what you did in php or you can do this for a more efficient time: neg = 0 for i, n in enumerate(nums): if n0: return max(neg, len(nums)-i) return neg

  • @terrydaniel9045
    @terrydaniel9045 Жыл бұрын

    Here is a fun Julia solution: If nums is the given vector then sol = max(sum(0 .nums))

  • @rubenverg
    @rubenverg Жыл бұрын

    Scala: x.filter(_ != 0).groupBy(_.sign).values.map(_.size).max

  • @Jebusankel

    @Jebusankel

    Жыл бұрын

    When I started I thought groupMapReduce would do this more elegantly, but really it's more cryptic nums.groupMapReduce(_.sign)(_ => 1)(_ + _).values.max The docs say groupMapReduce is more efficient. I didn't know about _.sign. Thanks for that.

  • @rubenverg

    @rubenverg

    Жыл бұрын

    @@Jebusankel looks a bit better with a K combinator: nums.groupMapReduce(_.sign)(const(1))(_ + _).values.max

  • @rubenverg

    @rubenverg

    Жыл бұрын

    @@Jebusankel but yeah, it's slightly less clear in what it's doing, especially because gmr isn't really common either

  • @spencerwhite3400
    @spencerwhite3400 Жыл бұрын

    Hate to be that guy, but you don't need `.clone()` in the rust solution if you use `.iter()` (by reference) instead of `.into_iter()` (by value). Also, the std library provides a `.partition_point()` method on slices, so you could've done the solution in O(log n) just like the cpp solution. Also, you could've parallelized the solution because Rust™ guarantees™fearless concurrency™.

  • @gabrielcastilho4168

    @gabrielcastilho4168

    Жыл бұрын

    That .clone() was so annoying to watch haha

  • @5FT6MAN

    @5FT6MAN

    Жыл бұрын

    Wouldnt this increase the space complexity tho brother?

  • @what42pizza

    @what42pizza

    Жыл бұрын

    I've got good news and bad news. The good news is that I've made a multithreaded version! The bad news is that it's terrible. (and I'm not sure if I'll be able to give a link)

  • @what42pizza

    @what42pizza

    Жыл бұрын

    The PB link id is XtSyyU53

  • @what42pizza

    @what42pizza

    Жыл бұрын

    Actually I was able to make a much better version using rayon (PB id 73k7yP4X)

  • @dashnone
    @dashnone Жыл бұрын

    with Python you need not put the comprehension into a list and pass it to `len`; you can just sum the comprehension: def maximumCount(self, nums: List[int]) -> int: return max(sum(x 0 for x in nums))

  • @xslvrxslwt

    @xslvrxslwt

    Жыл бұрын

    yes, and that's why it's slower seventy five times than C.

  • @andyl.5998

    @andyl.5998

    Жыл бұрын

    @@xslvrxslwt Yes, python is slower. But it's slower for other reasons, not because of the stylish preference of the commenter.

  • @noomade

    @noomade

    Жыл бұрын

    xslvrxslwt The style is not the issue, for example the haskell version provided can be written maximumCount = (on max length . filter (>0)) (filter (

  • @aragonnetje

    @aragonnetje

    Жыл бұрын

    personally i'd prefer keeping the iterators shorter, to save work on the sum, like this: def maximumCount(self, nums: List[int]) -> int: return max(sum(1 for x in nums if x 0)) slight difference in preference, but adding up a list of zeroes at the end is something i don't like. not that the performance difference is likely to be noticable

  • @ihve

    @ihve

    Жыл бұрын

    @@aragonnetje your solution is equivalent to the other one, because the booleans will just be implicitly converted to integer when applying the sum function.

  • @nERVEcenter117
    @nERVEcenter117 Жыл бұрын

    Sad for D right here, if we could see performance metrics it'd be right there with Java and Rust. I loved using it so much.

  • @halneufmille
    @halneufmille Жыл бұрын

    3 Julia solutions: max(sum(nums .> 0),sum(nums . max(count((0), nums)) To avoid using 0, count or nums more than once: maximum((count(c(0), nums) for c ∈ ()))

  • @miguelraz4156

    @miguelraz4156

    Жыл бұрын

    Oh, that's a sweet last solution!

  • @mjiii

    @mjiii

    Жыл бұрын

    Or, if you prefer the O(log n) way: function maximum_count(nums) zeros = searchsorted(nums, 0) negatives = firstindex(nums) : zeros.start - 1 positives = zeros.stop + 1 : lastindex(nums) maximum(length, (negatives, positives)) end

  • @willyhorizont8672
    @willyhorizont8672 Жыл бұрын

    Subscribed! I love the content!

  • @modolief
    @modolief Жыл бұрын

    Phenomenal. Simply phenomenal.

  • @10e999
    @10e999 Жыл бұрын

    This video highlights perfectly why I like C: One of the best performance while being trivial to read. Nice video as always ! I hope to see zig as a contender in the future :)

  • @alexhiatt3374

    @alexhiatt3374

    Жыл бұрын

    Yeah, I found the majority of these (except Rust, C#, and Kotlin) to be incredibly confusing. Whereas the C solution is simple, clear, and neck-and-neck with Rust.

  • @briannormant3622

    @briannormant3622

    Жыл бұрын

    This is probably what i love the most about C: because the std is bare one you don't waste time using reduction lambda and whatnot. By design the language will make you implement the simplest and (most of the time) fastest solution. A of that while style being clear and readable (not like APL...). Only gripe about the syntax is function pointers, they look atrocious and need you to take a piece of paper to really understand what it actually mean. Would be simpler with a arrow notation.

  • @TerjeMathisen
    @TerjeMathisen Жыл бұрын

    BTW, you can also solve this with SIMD vector ops, processing 8 32-bit ints in each iteration (Just pad the array with enough zero values to make it a multiple of 8 in length!) load 8 ints, compare for greater with an an array of 8 zeroes, generating 0/-1 mask values, then do the same except for less than zero. Use two accumulator arrays, one for positive and one for negative values, just remember to subtract each new value. At the end we make horizontal sums across the pair of 8 individual accumulators and take the global max. This is just 5 AVX ops per 8 ints, so it will run in less than a clock cycle per entry.

  • @gshan994

    @gshan994

    Жыл бұрын

    How to code it bdw

  • @TerjeMathisen

    @TerjeMathisen

    Жыл бұрын

    @@gshan994 Programming in the comment box will probably be buggy. :.(

  • @TerjeMathisen

    @TerjeMathisen

    Жыл бұрын

    The loop will look like this while (len >= 8) { _m256i curr = __mm256_lddqu_si256(*inp256++); _m256i posmask = _mm256_cmpgt_epi32(curr, zero256); _m256i negmask = _mm256_cmplt_epi32(*curr, zero256); posacc = _mm256_sub_epi32(posacc, posmask); negacc = _mm256_sub_epi32(negacc, negmask); len -= 8; } So one load from memory, two compares to generate the masks and two subs to update the accumulators!

  • @gshan994

    @gshan994

    Жыл бұрын

    @@TerjeMathisen looks cool 😎

  • @tanveerhasan2382

    @tanveerhasan2382

    Жыл бұрын

    Impressive, very nice

  • @ihve
    @ihve Жыл бұрын

    It is worth mentioning, that in python you also have the option to use map function which you can directly substitute for the list comprehension and a filter function. However, to get the length of it, you need to convert it to a list, but I think it's zero-cost since filters are not copying data.

  • @BrianWoodruff-Jr

    @BrianWoodruff-Jr

    Жыл бұрын

    A faster Python solution would be: max(sum(x 0 for x in nums))

  • @roietbd2992

    @roietbd2992

    Жыл бұрын

    @@BrianWoodruff-Jr An even faster Python solution would be max(len([x for x in nums if x 0]))

  • @ChimeraGilbert

    @ChimeraGilbert

    Жыл бұрын

    @@BrianWoodruff-Jr your solution works significantly slower than the one in the video on my machine.

  • @BrianWoodruff-Jr

    @BrianWoodruff-Jr

    Жыл бұрын

    @@ChimeraGilbert Interesting. I tried RoieTBD's solution and it was slower on my machine. You are saying my solution is slower on yours. I wonder how much of that is due to what we set "nums" to, how much to which python version we're using (CPython, pypy, etc), and how much to our hardware.

  • @katrinabryce

    @katrinabryce

    Жыл бұрын

    Another option in Python is to use Numpy. In my experience, that can be several orders of magnitude faster than list comprehension. Eg on a list with 10 million items I worked on recently, execution time went down from 10 minutes to less than a second, not including io time to get the list into memory.

  • @japedr
    @japedr Жыл бұрын

    In the C solutions you can take advantage of the implicit cast to write: pos += (nums[i] > 0); neg += (nums[i] This is probably what you want to do in x86 assembly to avoid branches (but perhaps the compiler can come up with a crazy smarter solution).

  • @bigboysteen7638

    @bigboysteen7638

    Жыл бұрын

    compilers already those obvious branchless optimisations by default, or use conditional operations (cmov, etc), readability > blind optimization

  • @user-gr5ec2tf5s

    @user-gr5ec2tf5s

    Жыл бұрын

    @@bigboysteen7638 Readability can be improved by comment section

  • @unconv
    @unconv Жыл бұрын

    Had to stop the video and do the PHP version before you started to show the examples. I'm so happy that I figured out the same solution 😄(except I used type declarations, more verbose variable names and ended on a positive note instead of negative 😉) function max_count( array $numbers ): int { $negative_count = 0; $positive_count = 0; foreach( $numbers as $number ) { if( $number $negative_count++; } elseif( $number > 0 ) { $positive_count++; } } return max( $negative_count, $positive_count ); }

  • @11rchitwood
    @11rchitwood Жыл бұрын

    In R: max(sum(x > 0), sum(x < 0))

  • @Instinctive
    @Instinctive Жыл бұрын

    Only once through the list in Haskell: maxCount = uncurry (on max length) . span (

  • @jomy10-games
    @jomy10-games Жыл бұрын

    For the first Rust solution, do you really need to clone if you would instead use iter instead of into_iter? (It’s been a while since I’ve written Rust though)

  • @awwastor
    @awwastor Жыл бұрын

    I assume they gave the JVM heat up time and didn’t measure it’s start up, in which case it makes sense that it’s quite fast, because it likely only used the allocation it made while starting up and acted basically as a bump allocator, never actually freeing memory or running the garbage collector (maybe a peek at the memory usage could reveal some stuff). I’m also willing to believe that whatever Java JIT was used outperformed the GCC optimisations, because Java compilers are extremely good nowadays. The difference between C/C++ and Rust is probably because if I recall correctly GCC is used for c and c++, while rust relies on LLVM which generally generates better machine code

  • @atiedebee1020

    @atiedebee1020

    8 ай бұрын

    Clang has consistently been slower than GCC for me and leetcode timings are a joke

  • @Daniel_WR_Hart

    @Daniel_WR_Hart

    16 күн бұрын

    @@atiedebee1020 I only tried making a few submission in Java (around 2021 I think), and every time it would report as 0ms. JS would give me at a bare minimum 40ms, so I think their Java performance reporting is/was especially broken

  • @LambOfDemyelination
    @LambOfDemyelination Жыл бұрын

    8:05 I feel like (max `on` length . flip filter xs) (>0) (

  • @roerd
    @roerd Жыл бұрын

    A bit weird that there's just a single solution that takes advantage of the input data being sorted. All other solutions actually solve a more general problem than what was being described. binsearch solution in Python: from bisect import bisect_left, bisect_right def maximum_count(nums): a = bisect_left(nums, 0) b = bisect_right(nums, 0, a) return max(a, len(nums) - b)

  • @MCRuCr
    @MCRuCr8 ай бұрын

    julia> func(arr::Vector{ 0), sum(arr . takes 10 μs with a 2000 element array

  • @Axman6
    @Axman6 Жыл бұрын

    The Haskell solution using the foldl package is pretty nice: fold (max prefilter (0) length)

  • @flowname

    @flowname

    10 ай бұрын

    What's the performance implications of this composed Foldl compared to the hand-written one below? There must be some difference. uncurry max $ foldl' (\acc x -> bimap (+ fromEnum (x > 0)) (+ fromEnum (x < 0)) acc) (0, 0) [-1,-2,-3, 0, 0, 1,2]

  • @Axman6

    @Axman6

    10 ай бұрын

    @@flowname there’s definitely some overhead to the extra data types needed by , unless the compiler is smart enough to completely remove them. That would be faster but the code is less reusable

  • @flowname

    @flowname

    10 ай бұрын

    @@Axman6 is it always guaranteed to be a single pass at all times though? Extra allocations are fine as long as it always converts to exactly one pass. I guess it's implied by the package when it mentions streaming in the README, but just in case :)

  • @Axman6

    @Axman6

    10 ай бұрын

    @@flowname yep, the foldl package defines a type which basically matches the arguments you’d give to the foldl function, and takes care of passing each input to each sub-Fold, and aggregating their intermediate states, and also adding a projection function to get the final answer: data Fold a b = forall s. Fold (s -> a -> s) s (s -> b) (Fold function, initial/current state, projection to final type).

  • @pdr.
    @pdr. Жыл бұрын

    Because it's pre-sorted, it's slightly faster in Haskell to use takeWhile, dropWhile and/or span: mc xs = (max `on` length) neg pos where (neg, nonneg) = span (

  • @chaddaifouche536

    @chaddaifouche536

    Жыл бұрын

    Right, but I think the main improvement in your solution is to use `on` as infix, that just read much more naturally! ;-)

  • @qqii

    @qqii

    Жыл бұрын

    @@chaddaifouche536 Although it's elegant and probably doesn't make a difference for smaller and unsorted inputs, just like std::equal_range I find it quite elegant to actually use the sorted property of the list.

  • @user-hr1fr5xs4p
    @user-hr1fr5xs4p8 ай бұрын

    Haskell analog for BQN program: f xs = on max g () where g p = length $ filter (p 0) xs

  • @pauhull
    @pauhull Жыл бұрын

    In kotlin instead of writing the lambda as { e -> e < 0 } you could have written it as { it < 0 }

  • @Jebusankel
    @Jebusankel Жыл бұрын

    Java can be done with one pass over the data Collections.max(Arrays.stream(nums).boxed() .collect(Collectors.partitioningBy(n -> n > 0, Collectors.counting())).values()); Scala can take the same approach using groupMapReduce. group-by for Clojure.

  • @adambickford8720
    @adambickford8720 Жыл бұрын

    I think a lot of it depends on how you use the language in some cases. For example, I'd likely write it in kotlin to take 1 pass: ``` fun maxCount(nums: Iterable): Int = nums.fold(listOf(0, 0)) { counts, i -> when { i > 0 -> listOf(counts[0], counts[1] + 1) i listOf(counts[0] + 1, counts[1]) else -> counts } } .max() ``` It only takes an Iterable, which is a pretty strong hint to its performance.

  • @cyclotron007
    @cyclotron007 Жыл бұрын

    Gave this problem to ChatGPT and asked it to solve it in APL. As usual (my experience with CGPT & programming), it got the overall concept right but almost every line contained a silly misstep. But it learnt from its mistakes, ultimately producing a conventionally structured, functional APL solution. I then gave it Hoekstra's APL solution, which it attempted to explain ... but it confused the Over operator with Each, so had to give it the formal definition of Over. Eventually it produced a passable explanation. Getting ChatGPT to explain APL expressions in plain English - therein lies an unexplored opportunity!

  • @shambhav9534

    @shambhav9534

    Жыл бұрын

    I'm mostly fascinated at it's ability to learn on the spot.

  • @c4tubo

    @c4tubo

    Жыл бұрын

    Please show us what APL code ChatGPT came up with at each step.

  • @FreeStyleKid777
    @FreeStyleKid777 Жыл бұрын

    what are those hierogliphs at the end? I didn't even know I had those symbols on my keyboard. What am I watching?

  • @captainaxlerod1297
    @captainaxlerod1297 Жыл бұрын

    Thanks for breaking it down and explaining it to us non-mathematically inclined individuals

  • @qqii
    @qqii Жыл бұрын

    I would have loved to see std::equal_range-equivalent solutions in other languages, as although the problem only states a small input size it would have been most interesting to see how other languages handle operations on sorted lists and taking advantage of the sorted list property.

  • @0LoneTech

    @0LoneTech

    6 ай бұрын

    Here's one in BQN: (⌈´ 0⊸≍∘≠ |∘- ⍋⟜¯1‿0) For an array sorted in ascending order, find the last places that -1 and 0 would fit. Take the absolute difference from 0 and length of the array respectively, then maximum.

  • @movax20h
    @movax20h9 ай бұрын

    Nice and comprehensive. Nitpics: Erlang does have fold and other reductions primitives in lists module. Also in Python, instead of doing len([....]) with list comprehension, use list generator: len(...) (without square brackets). Result will be the same. Also Python 2 had reduce primitive, but it was removed from core language, but is as a function in itertools or functools package. Also in Erlang, D, and Python, you can easily do single pass over array using fold, and storing data in a tuples. Example in Erlang: Add = fun({A,B},{C,D}) -> {A+C,B+D} end. lists:max(tuple_to_list(lists:foldl(fun(E, Acc) -> Add(Acc, {if E 1; true -> 0 end, if E > 0 -> 1; true -> 0 end}) end, {0,0}, A))). Or if you want to be more fancy: GenericReduce = fun(Map, Agg, Init, List) -> lists:foldl(fun(E, Acc) -> Agg(Map(E), Acc) end, Init, List) end. lists:max(tuple_to_list(GenericReduce(fun(E) -> {if E 1; true -> 0 end, if E > 0 -> 1; true -> 0 end} end, fun({A,B},{C,D}) -> {A+C,B+D} end, {0,0}, A))).

  • @RoyRope
    @RoyRope8 ай бұрын

    Go recently added the min/max functions to the standard library too, this is now possible due to the recent introduction of generics. ☺ For how much I disliked Python initially, I really love the clean way of solving things like this now.

  • @razvbir
    @razvbir Жыл бұрын

    You can write functional code in php, too

  • @Alex-dn7jq
    @Alex-dn7jq Жыл бұрын

    In Rust you don't have to clone the vectors, instead you should use .iter() instead of .into_iter() so that the iteration doesn't consume the vector.

  • @codingzone4019
    @codingzone4019 Жыл бұрын

    your video is crazy, and I love it.

  • @iCeManMeltingSC2
    @iCeManMeltingSC2 Жыл бұрын

    With clojure you can actually do it with a single reduce, which is actually faster than the solution presented. Like so: (defn maximum-count2 [nums] (apply max (reduce (fn [[neg pos] v] (if (pos? v) [neg (inc pos)] [(inc neg) pos])) [0 0] nums))) Not the most beautiful code, but it does it in a single pass. (bench (maximum-count v)) Evaluation count : 397260 in 60 samples of 6621 calls. Execution time mean : 153.486508 µs Execution time std-deviation : 1.470614 µs Execution time lower quantile : 151.619876 µs ( 2.5%) Execution time upper quantile : 156.210734 µs (97.5%) Overhead used : 2.367798 ns => nil (bench (maximum-count2 v)) Evaluation count : 971880 in 60 samples of 16198 calls. Execution time mean : 62.433205 µs Execution time std-deviation : 540.384065 ns Execution time lower quantile : 61.499199 µs ( 2.5%) Execution time upper quantile : 63.337031 µs (97.5%) Overhead used : 2.367798 ns

  • @AvrDusk
    @AvrDusk Жыл бұрын

    Can you do a video comparing the differences between APL and BQN?

  • @fredesch3158
    @fredesch3158 Жыл бұрын

    Could you explain the bind operator in bqn? I could follow the logic until the bind thing, I just don't understand why you could remove the identity function from the fork after binding the zero.

  • @0LoneTech

    @0LoneTech

    6 ай бұрын

    (0

  • @MrEo89
    @MrEo89 Жыл бұрын

    Couldn’t you do it in Julia? It’s popukarity is skyrocketing among all data-intensive fields/sectors. I’d greatly appreciate it if it were a “standing” example language.

  • @s90210h
    @s90210h Жыл бұрын

    24 solutions in BQN and APL would have made me equally happy but this was interesting

  • @vikingthedude
    @vikingthedude8 ай бұрын

    Can't we implement the "One Reduction" method in many of the languages of the "Two Reductions" section? Like in JS/TS, we could array.reduce() and accumulate the pair, just like in rust

  • @quelkun

    @quelkun

    6 ай бұрын

    Yes, in JS you could write this: Math.max(...nums.reduce(([pos, neg], n) => [pos + (n > 0), neg + (n And it would iterate only once

  • @mjiii
    @mjiii Жыл бұрын

    Using list comprehension in Python is (memory) inefficient because it builds two new lists. I would write it using sum with generator expressions instead: max(sum(x 0 for x in nums))

  • @aragonnetje

    @aragonnetje

    Жыл бұрын

    to prevent some counting up of zeroes in the binary mask, you could also do: max(sum(1 for x in nums if x 0))

  • @flowname

    @flowname

    10 ай бұрын

    @@aragonnetje it still scans twice, and if nums is a stream itself, you'll have to tee it with all the implications of tee

  • @user-rr6my1lo2k
    @user-rr6my1lo2k Жыл бұрын

    In julia, you can do one reduction as well: maximumcount(x) = reduce(((post, neg), v) -> (post + (v > 0), neg + (v maximum

  • @futuza
    @futuza Жыл бұрын

    The 1st C++ solution can probably be improved if you pass the vector 'nums' by ref (&), instead of copying it. Operating on the vector directly should give a bit of a speed up. It's my 2nd favorite solution though, I just really like C's classical easy to read syntax. Lamda expressions, iterators, while all nice, sometimes make the code harder to read imo. Guess that's why I like C++, you can use whatever works/reads best, including classic C style, or do something more modern.

  • @kasdejong6425

    @kasdejong6425

    Жыл бұрын

    the rust solution also uses clone though, since the value isn’t borrowed. So this would make the rust solution even faster right?

  • @khatdubell

    @khatdubell

    Жыл бұрын

    @@kasdejong6425 The rust compiler is exceedingly competent at optimizing code. I say this as someone who is not a fan of the language.

  • @SiarheiSiamashka
    @SiarheiSiamashka Жыл бұрын

    In D language it's possible to have a single pass fold solution similar to Rust and also a binary search solution similar to C++: int maximum_count_single_pass_fold(const int[] nums) { return nums.fold!("a+(b>0)", "a+(b

  • @drjd2
    @drjd2 Жыл бұрын

    I have many questions about how this tests are actually conducted. Is the input compiled into the same source as the function? If so, compiler optimizations influence the outcome heavily. Also which compile options are used for some of the languages, like c# (native compilation), c++, c, rust (compiler, optimizations), java (which runtime). Also how often where the tests running (to see impact of jit compilation on some languages). You can see at the difference between Java and Kotlin that probably the java compiler optimized most of the code out? Without further knowledge we can't say anything. It might even be that all calculation is already done at compile time by the optimizer (see input above) and the results are worthless for a real life scenerio.

  • @DoraTheExploder
    @DoraTheExploder Жыл бұрын

    In order for VSCode to highlight PHP syntax you have to start the doc with the proper tag

  • @stepmi
    @stepmi Жыл бұрын

    Array is sorted, there's no need to check it all. For negatives you start from the beginning and look for first non-negative. Index of that first would be the count. For positives - same, but from the end, and search non-positive. Count would be distance from that to the end index.

  • @ahmadrezadorkhah9574
    @ahmadrezadorkhah9574 Жыл бұрын

    Thanks man, useful information, rust (my favorite language) rocks everywhere

  • @duartelucas5746
    @duartelucas5746 Жыл бұрын

    What’s the theme? I really like the contrast between yellow and the blue/purple and grey

  • @code_report

    @code_report

    Жыл бұрын

    It is Material Theme (Ocean)

  • @travisporco
    @travisporco6 ай бұрын

    10:45 is all that hyperbyzantium really an improvement over that simple C solution?

  • @bowildmusic
    @bowildmusic7 ай бұрын

    The C program is suboptimal. You can program the same loop without the if statements (either add the Boolean result or use it as an array index for the correct variable to add to). The if cases are slowing down the code.

  • @user-zu4ft8yw9e
    @user-zu4ft8yw9e3 ай бұрын

    The snippets do not provide a list of 24 programming languages used to solve problems in the previous context. However, based on the information provided, some common programming languages that are widely used for various purposes include Java, Python, C++, JavaScript, Ruby, PHP, Swift, and many more.

  • @manemobiili
    @manemobiili Жыл бұрын

    You're a beast code_report! PS: Go Ruby!

  • @JonRonnenberg
    @JonRonnenberg Жыл бұрын

    Was Haskell missing in the performance chart? And did you show the C# solution?

  • @milesrout
    @milesrout10 ай бұрын

    The best solution is the C version. I suspect the Rust version is being optimised out because you have made the input a compile-time constant.

  • @malstream
    @malstream8 ай бұрын

    Milliseconds for an array of several elements did not bother the author and he compiled a performance comparison. One of the funniest coding videos in recent times, perhaps it deserves a good analysis.

  • @aboltus99

    @aboltus99

    6 ай бұрын

    What made you laugh?

  • @quelkun
    @quelkun6 ай бұрын

    I'd like to share some Ruby here. First, if you like short code the solution could be written like this: def maximum_count(nums) = [nums.count(&:positive?), nums.count(&:negative?)].max If you like the Kotlin version, you can do exactly the same in Ruby: def maximum_count(nums) = [nums.count{ |e| e 0 }].max If you like clever solutions, this one only iterates once over the array: def maximum_count(nums) = nums.reduce([0, 0]) { |(pos, neg), n| [pos + n.clamp(0, 1), neg - n.clamp(-1, 0) ] }.max I chose to stick with the oneliner solution because youtube doesn't have syntax coloration but I would have used the other style in my code... Anyway that was my 2 cents!

  • @tauraamui
    @tauraamui Жыл бұрын

    In the Go example you did not need the else blocks at all. You could have the two if statements, the first if block would just end with a continue, and the else if could just be a second if. The final else block could have been omitted entirely and just been a single return statement after the final if.

  • @secahl
    @secahl7 ай бұрын

    Very clever KZreadr. I like it. I Enjoy looking from different dimension, every KZreadr should know psychology. Create conversations on everyone minds without 'em realising and this was a perfect content. Keep up 'em great work 🙏 Lastly.. keeping 'em rust close to c++ makes you a award winning perfect psychologist.

  • @10defo
    @10defo Жыл бұрын

    Wondering if the performance of clojure would be similar to that of scala (both JVM)

  • @iCeManMeltingSC2

    @iCeManMeltingSC2

    Жыл бұрын

    (bench (maximum-count v)) Evaluation count : 397260 in 60 samples of 6621 calls. Execution time mean : 153.486508 µs Execution time std-deviation : 1.470614 µs Execution time lower quantile : 151.619876 µs ( 2.5%) Execution time upper quantile : 156.210734 µs (97.5%) Overhead used : 2.367798 ns

  • @PixelOutlaw
    @PixelOutlaw Жыл бұрын

    You can use the Clojure/Racket solution in Common Lisp but here's a little more flavorful option that only traverses the list once. Those two solutions probably have an implicit double iteration. (loop :for i :in list :when (plusp i) :count i :into e :when (minusp i) :count i :into o :finally (return (max e o)))

  • @cb6619
    @cb6619 Жыл бұрын

    I feel like I'm missing something here. It seems like you're optimizing for the least amount of redundancy and characters typed in the implementation and being as clever as possible. It would have been quicker, and significantly more readable and maintainable to just use a for loop. Someone who's never seen the piece of code before can look at it and instantly understand what's going on. With super clever solutions like the c++ or bqn one it's gonna take someone a second to understand what's going on. A plain, non exciting solution is going to be easier to write, debug, read, and maintain.

  • @gabrieldoon

    @gabrieldoon

    Жыл бұрын

    It seems (to me) like the entire point of the video is to be as clever as possible. It's essentially a showcase of the crazy things these languages can do once you get into the deeper stuff. I don't believe that the narrator would actually advocate for doing this in production code. Code golf is in a similar vein.

  • @seanthesheep

    @seanthesheep

    8 ай бұрын

    Most of the examples in the video seem idiomatic and straightforward to me, especially for the languages that support functional style. I think you just think they're clever because you're not used to them. A for loop will seem like the solution to everything if you only use a language that forces you to use them

  • @aczajka74

    @aczajka74

    7 ай бұрын

    Some of the languages don't even have for loops my guy

  • @ifstatementifstatement2704

    @ifstatementifstatement2704

    6 ай бұрын

    Yeah I don’t get this insistance on using the most obscure implementation possible. We are programming, not writing math. So use the commands of the programming language.

  • @joro550
    @joro550 Жыл бұрын

    You probably all ready know that you didn't do the most performant solution in all languages but I found the c# one particularly egregious, with that code you would essentially be iteratring through the list twice (seeing as it's max 2k list then you have the potential of going through 4k items. I ran some benchmarks and your solution was 22,978 ns where as a solution that looks like: public int Span() { var (pos, neg) = (0, 0); var span = CollectionsMarshal.AsSpan(_numbers); for (var i = 0; i { var item = span[i]; if (item > 0) pos++; if (item } return Math.Max(pos, neg); } would be 593 ns, which is a HUGE leap in performance

  • @klopt305
    @klopt305 Жыл бұрын

    that bqn solution is gorgeous

  • @neuraloutlet
    @neuraloutlet Жыл бұрын

    Python looking real lonely in the list comp section. Here is the similar set-builder solution from SETL, it makes use of the cardinality operator # which I quite enjoy: proc maximumCount(nums); return #[x in nums | x #[y in nums | y > 0]; end proc;

  • @auditusich
    @auditusich Жыл бұрын

    Why performance of this kotlin Benchmark so slow? Kotlin and java are using the same jvm cli commands, is not it?

  • @Johnnydhee
    @Johnnydhee Жыл бұрын

    With all the Scala code I’ve seen in production, 600ms to perform that operation is staggering…

  • @otter502
    @otter502 Жыл бұрын

    I had a cool possible solution (I am new to programming) Since the list is sorted you could use that to your advantage Count the positive values through the list until you reach the end of the list or a value that is ≤0, then count the number of zeros, Then do something like Max ( positive, length - positive - # of zeros) This only works if the list is sorted (If it is sorted in an ascending order then switch negatives with the # of positive values and switch ≤0 with ≥0)

  • @mikolajwojnicki2169

    @mikolajwojnicki2169

    Жыл бұрын

    Hey, as you become more experienced you'll understand the tradeoff between code complexity and performance. Your code would work, but it would be much more complex while only increasing performance by about 0.5. Usually you want to keep the code simple so that others can follow it easily. If speed is very important there are much better algorithms like the binary search or equal_range mentioned in the video.

  • @giorgiobarchiesi5003
    @giorgiobarchiesi50036 ай бұрын

    Great video, thanks. It gives a limited but extremely significant idea of the different language coding styles. A bit less convincing to me is the performance part. for instance, have you tried to natively compile Dart and C# code? That way you can obtain machine-specific executable code, that I would expect to run much faster, compared to the results shown in the video.

  • @del1an
    @del1an Жыл бұрын

    3:24 A trick I use in languages that don't have a ternary operator is: return pos > neg && pos || neg

  • @miguelraz4156
    @miguelraz4156 Жыл бұрын

    Another cool video Conor! The Julia solution for the 2 linear algorithms could look like max(count((0), xs)) Keep the videos coming, and hope to see more Julia in the future (or hear about it in the ArrayCast :D)

  • @code_report

    @code_report

    Жыл бұрын

    I actually coded Julia as the 25th language but decided 24 (4*6 grid) looked better. 😂 I can came up with: max(sum(xs . 0))

  • @chrisjduplessis

    @chrisjduplessis

    Жыл бұрын

    For the O(log(n)) solution, you would get something not as pretty: function f(x::Vector{Int64})::Int64 s = searchsorted(x, 0) return max(s.start - 1, length(s) - s.stop) end Would be nice to see a solution that's not prone to an off by one error.

  • @spacelem

    @spacelem

    Жыл бұрын

    I tested that against my naive approach of count(xs .< 0), and there were 0 allocations and it took 0.3x as long, so that's a good spot!

  • @GreenThePear
    @GreenThePear Жыл бұрын

    please make another video like this, I started learning APL because of it

  • @AntonioZL
    @AntonioZL6 ай бұрын

    Python may have a lot of problems, but it's solution to this problem in particular is so freaking elegant.

  • @youexpire
    @youexpire8 ай бұрын

    May I know the reason why you did not include Free Pascal (open source) or Delphi (has a community edition)?

  • @argonwheatbelly637

    @argonwheatbelly637

    7 ай бұрын

    Probably for the same reason FORTRAN and COBOL aren't here. Time, space, etc... Maybe in another video?

  • @zappellin2398
    @zappellin2398 Жыл бұрын

    I was actually surprised on how fast PHP was but considering it's close to C I guess it make some sense

  • @khatdubell
    @khatdubell Жыл бұрын

    Your description of equal_range is incorrect. It doesn't return the first one equal to the value, it returns the first _not less_ than the value. i.e. >= A very important difference.

  • @MrSMGun
    @MrSMGun Жыл бұрын

    You can use lambdas in php so it can end up similar to c#

  • @user-fx5hz6eq8i
    @user-fx5hz6eq8i Жыл бұрын

    Where are clojure on performance graph?

  • @alexshirley9531
    @alexshirley9531 Жыл бұрын

    You could've added the Bisect module for Python and done the Equivalent of std::upper/lower_bound

  • @user-zu4ft8yw9e
    @user-zu4ft8yw9e3 ай бұрын

    The purpose of the video showcasing 24 programming language solutions is to demonstrate how different programming languages can be used to solve various problems efficiently and effectively. It aims to showcase the versatility and capabilities of each language in solving programming challenges, highlighting the unique features and strengths of each language in the context of problem-solving.

  • @NikolajLepka
    @NikolajLepka Жыл бұрын

    Note that not all lisps use the question mark convention for predicates. Common Lisp uses the suffix p in Common Lisp, they'd be called plusp and minusp instead of pos? and neg?.

  • @eL3M3nT4LisT
    @eL3M3nT4LisT7 ай бұрын

    What about the implementation in zig

  • @keatonhatch6213
    @keatonhatch6213 Жыл бұрын

    Oh man that first Rust solution could’ve been so much cleaner. You don’t need into_iter() for this, just iter() so you don’t need to clone. std::cmp::max( nums.iter().filter(|e| **e > 0).count(), nums.iter().filter(|e| **e ) as i32

  • @caiovinicius8448
    @caiovinicius8448 Жыл бұрын

    Nice!!!