1 Problem, 6 Programming Languages (C++ vs Rust vs Haskell vs APL vs Clojure vs Scala)

Ғылым және технология

A video taking a look at 6 programming language solutions (C++, Haskell, APL, Rust, Clojure & Scala) to one problem.
ADSP The Podcast: adspthepodcast.com/
Point Free Programming Talk: • "Point-Free or Die: Ta...
Github Links:
C++: github.com/codereport/LeetCod...
Haskell: github.com/codereport/LeetCod...
APL: github.com/codereport/LeetCod...
Rust: github.com/codereport/LeetCod...
Scala: github.com/codereport/LeetCod...
Clojure: github.com/codereport/LeetCod...
Follow me on Twitter: / code_report
Follow me on Github: github.com/codereport

Пікірлер: 355

  • @taylorallred6208
    @taylorallred62083 жыл бұрын

    I love the way you talk about the "beauty" of a solution. It's that sort of thing that reminds me why I love programming. Thank you :)

  • @carlislenightingale8853

    @carlislenightingale8853

    Жыл бұрын

    I prefer the haskell solution to the APL one, because in haskell everyone can get a clue of what is going on whereas with APL you have no clue what you are looking at.

  • @JasonMitchellofcompsci

    @JasonMitchellofcompsci

    Жыл бұрын

    @@carlislenightingale8853 It does require knowing what two symbols mean. But the Haskell is in a similar boat because very few people would expect reading it what the compositional operator is actually doing. For people who don't know it's essentially modifying the order of operations.

  • @svenyboyyt2304

    @svenyboyyt2304

    Жыл бұрын

    JavaScript would be a=b=>Math.max(...b.reduce((c,d)=>c+d,0) which I think is a great balance between simplicity and readability

  • @joshuastein1888
    @joshuastein18883 жыл бұрын

    i use C++ for high performance code , Python for interfacing and Haskell to keep my ego in check

  • @cat-.-

    @cat-.-

    Жыл бұрын

    @@TheRustyCrabwhat is your problem

  • @everythingtube172

    @everythingtube172

    8 ай бұрын

    this

  • @DanBader
    @DanBader3 жыл бұрын

    As a guy who inherited application support for 500,000+ line code base of C and a couple 2-3000 line APL applications i can tell you, I'd much rather see the word MAX written out rather than have to look up every single glyph i stumble upon at 3:30am on a Saturday morning.

  • @DanBader

    @DanBader

    3 жыл бұрын

    Thankfully I've moved on from that job, but the main issues was always taking down one of those special keyboards with 4-5 symbols printed on every key.

  • @CarlK

    @CarlK

    3 жыл бұрын

    I agree. I found APL to be "write only". I couldn't even read and understand my own code after a few days.

  • @mskiptr

    @mskiptr

    3 жыл бұрын

    Could someone enlighten me on some history of APL? It looks so much like an esoteric language, so why is it in actual industry code? Do people just love it that extraordinarily? Does it have some unique killer-feature, or what?

  • @tcnymex

    @tcnymex

    3 жыл бұрын

    @@mskiptr "APL since 1978": dl.acm.org/doi/abs/10.1145/3386319 Also yeah, we love it.

  • @xXxBladeStormxXx

    @xXxBladeStormxXx

    3 жыл бұрын

    People actually wrote applications in APL? That too 3000 line applications? Wtf

  • @holothuroid9111
    @holothuroid91113 жыл бұрын

    In the Scala solution, it is recommended to skip the curly braces. What you are doing here is creating a block. Blocks return their last expression. This block only has one line and is thus unnecessary.

  • @khalilzakariazemmoura8995
    @khalilzakariazemmoura89953 жыл бұрын

    The APL solution seems to be the most straightforward if i figure out where is the max symbol in my keyboard 😁.

  • @tullochgorum6323

    @tullochgorum6323

    3 жыл бұрын

    ​@@alhabshi3k I've been playing with both and prefer the old character set. It was developed by a Harvard professor who was frustrated with the inconsistencies and practical difficulties of conventional mathematical notation. He won the Turing prize for this work. The glyphs are mostly mnemonic and are easier to read than J once you get used to them. Which do you prefer: two plus two equals four 2+2=4 In the best APL version there's an IDE with keyboard shortcuts and point and click buttons. You quickly learn the most common glyphs, and you are writing so much less code that it's really a non-issue. If you get hooked, you can buy a dedicated keyboard for £100.

  • @arraymac227

    @arraymac227

    3 жыл бұрын

    @@alhabshi3k ⌈ is Ctrl+s on the Dyalog keyboard. Googling 'APL keyboard layout' gives some nice diagrams

  • @c4tubo

    @c4tubo

    Жыл бұрын

    On my Portuguese keyboard, a curly brace ({ or }) requires pressing 3 keys. Think about how often I need to type that in C++, Rust, Kotlin, Swift, etc. This is one of the reasons that I am now taking a hard look at Haskell or any other ML.

  • @clintonmead
    @clintonmead3 жыл бұрын

    In the Haskell solution you could just do `foldl1' (+)` and `foldl1' max` to make the reductions explicit

  • @bram9762
    @bram97623 жыл бұрын

    The composition operator is just a function, so that makes 4 functions in the Haskell solution.

  • @whaisonw2865
    @whaisonw28653 жыл бұрын

    If you don't mind spicing the type signature up you can do this in Rust: fn maximum_wealth(v: T) -> Option { v.map(Iterator::sum).max() } The code in this one looks a bit nicer but the data type are just crazy and you have to parse the vectors first as an iterator. Also notice that by returning an Option you can get rid of .unwrap(). This has also the benefit of returning None when your outer Vec is empty and does not throw an exception like other languages would

  • @TheVralapa
    @TheVralapa3 жыл бұрын

    Would be interesting to see benchmark between them. Especially the c++ versions and rust (I work as a c++ developer as well).

  • @MrAbrazildo

    @MrAbrazildo

    Жыл бұрын

    All the shine would be washed out, as 1 realizes how much is paid for them.

  • @briannormant3622

    @briannormant3622

    7 ай бұрын

    ​@@MrAbrazildoI don't know enough about c++ template( it think the std:: accumulate, max, ect is using templates) to say if the compiler will properly optimize them. But 1 think for sure. The good old for loops will obliterate all other solution. I liked the very first one. Very imperative, very procedural. Easy to follow. The Haskell one was nice too, clean and probably as readable for experienced haskell/FP programmers. But the "improved" C++ ones...

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

    The APL solution as someone who doesn't know that language or someone who is new to the language is horrendous. Not to say the C++ solutions are ideal but the for-loop one would be very obvious as to what it's doing for anyone even reasonably familiar with programming. (The rust solution also) I think the Haskell solution is probably the cleanest as someone who has never even programmed before might be able to figure out what it does somewhat. But even if you were Dennis Ritchie himself you wouldn't have the slightest clue what the hell the APL solution is doing without already being very familiar with the language. Less lines of code doesn't always mean better code.

  • @ryantjoa
    @ryantjoa3 жыл бұрын

    Python: return max(map(sum, accounts))

  • @code_report

    @code_report

    3 жыл бұрын

    Nice, that is nicer than mine: github.com/codereport/LeetCode/blob/master/0217_Problem_1.py

  • @henrywang6931

    @henrywang6931

    3 жыл бұрын

    @@code_report I like comprehension more than map, cos it's more explicit and readable.

  • @AM-qx3bq

    @AM-qx3bq

    3 жыл бұрын

    @@henrywang6931 I definitely could be wrong, but I think the expression in code_report's solution is a generator rather than a comprehension list.

  • @henrywang6931

    @henrywang6931

    3 жыл бұрын

    @@AM-qx3bq yeah the sum can take any iterable so generator would work too. A generator can be declared with a comprehension.

  • @PatriceStoessel

    @PatriceStoessel

    3 жыл бұрын

    i'm currently learning QNial, fun language, APL's cousin (github.com/danlm/QNial7) QNial : max byrows sum accounts

  • @JohnTurner313
    @JohnTurner3133 жыл бұрын

    I've been around a long time, learned COBOL on a Burroughs mainframe in the 80s and do cloud architecture and security now. I knew about APL, Haskell, Scala and Clojure but had never seen a solved problem before. All you hear about these days is JS and Python and maybe Go. Thanks for the video, you presented and explained the material very well. It clicked with me vs. a lot of the other coding channels. New subscriber.

  • @user-tk2jy8xr8b

    @user-tk2jy8xr8b

    3 жыл бұрын

    How would the task be solved in COBOL?

  • @shrayesraman5192

    @shrayesraman5192

    2 жыл бұрын

    @@user-tk2jy8xr8b It would be the most verbose solution you can ever seen

  • @neociber24
    @neociber243 жыл бұрын

    For me readbility is the king, Haskell, Rust are what I like the most. For some languages I suppose the programg just crash if the array is empty

  • @Kimbsy1990
    @Kimbsy19902 жыл бұрын

    Cleaner Clojure solutions are available using transducers. (transduce (map (partial apply +)) max input)

  • @pup4301
    @pup43013 жыл бұрын

    I watch these so I can get confused, then I can get my brain adjusted to how much I don't know. Lovw the content.

  • @TheBlenderblob
    @TheBlenderblob3 жыл бұрын

    in c++ with funlib this is just const auto wealth = stream(accounts) | map( fold( add, 0)) | max();

  • @rban123
    @rban1239 ай бұрын

    I find the python solution for this pretty nice: def maximumWealth(mtx): return max(sum(x) for x in mtx)

  • @alejandroenriquez8508
    @alejandroenriquez85083 жыл бұрын

    For me readability is king, only when performance is an issue I would go with more technical solutions. When working with a team, this kind of fancy code tricks make everyone's life a nightmare debugging. Although it is nice to see the possibilities.

  • @xGOKOPx

    @xGOKOPx

    Жыл бұрын

    What do you think is unreadable here? Maybe functional C++ solutions, because of a gazillion of namespaces, but otherwise everything is pretty clear. Yes, even APL (in this case at least)

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

    Question: Is the later versions of the c++ solutions that are parallelized actually faster? The original solution is easily optimized by a compiler. Is the parallelization basically threads? Because I really think some AVX/SIMD and some forloop unrolling will do a better job speeding things up vs the overhead of dealing with threads for such a simple problem. If I've learned anything from pushing performance in C it's don't obfuscate what's actually happening, select which optimization strategy you actually want for the problem starting with very vanilla code, don't get in the way of an optimizing compiler, know your compiler flags because what people think is optimized (-O3) is nothing compared to what you actually get for free by throwing in a few more flags (as long as let those optimizations work by not giving it already optimized code that's been optimized in the wrong direction.) Because of that I've learned to see any time someone says "this code pattern is always faster.. because this feature", I can't help but say yeah right. I'm sure it's really fast. For example, most time when people use a high level utility to speed something up you get at best 4x speed minus overhead.. hopefully. I've seen that letting fully flagged optimizing compilers work their best it can speed things up ten fold on the regular. If you have really modern hardware that's only going to increase as there are more features to leverage. That's why not getting it its way is rule one for fastish code at ease.

  • @aLotOfDoubt
    @aLotOfDoubt3 жыл бұрын

    more elegant clj: (->> data (map (partial apply +)) (apply max))

  • @japedr
    @japedr3 жыл бұрын

    In 3:09, how did you achieve this transition in the video? is it manual editing or did you use a special program for that?

  • @code_report

    @code_report

    3 жыл бұрын

    Microsoft Powerpoint 2019 "Morph" transition

  • @japedr

    @japedr

    3 жыл бұрын

    thanks!

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

    Would we not need to add *std::execution::par* to run it parallel in the reduce/transform_reduce functions?

  • @scoreunder
    @scoreunder3 жыл бұрын

    I'm learning ocaml and here's the solution I would use (with the Batteries library): let maximumWealth = Array.(map sum %> max) Without the Batteries library you don't get sum or max, but they're easy enough to define in terms of folds: let maximumWealth m = let max arr = Array.fold_left max arr.(0) arr in let sum = Array.fold_left ( + ) 0 in m |> Array.map sum |> max

  • @noomade

    @noomade

    2 жыл бұрын

    that order of application is sacrilegious :)

  • @Cirlotube
    @Cirlotube3 жыл бұрын

    I don't know if it is actually any better, but in Scala you could also write it as accounts map(_ sum) max

  • @NikolajLepka
    @NikolajLepka2 жыл бұрын

    I suppose you technically could make the Rust solution point-free if you use the function form of the .iter method if you're ok with an extra map: accounts.iter().map(Vec::iter).map(Sum::sum).max().unwrap() My Rust is a bit rusty though, so I'm not sure if this'll work

  • @kipu44

    @kipu44

    Жыл бұрын

    "My Rust is a bit rusty" 🙂 I know it's not intended but it's a nice pun nevertheless.

  • @BSenta
    @BSenta3 жыл бұрын

    What about safety, if the input is empty would all of them crash? In rust, because you used unwrap it is clear. You could have returned a result so the caller can decides how to handle the error

  • @tcnymex

    @tcnymex

    3 жыл бұрын

    In APL, if the argument to this particular program was an "empty array" (array whose dimensions were zero by zero, or 3 rows by zero colums, or zero rows by 3 colums) the program wouldn't crash, it would simply return you an array of dimension zero by zero

  • @ArnabAnimeshDas

    @ArnabAnimeshDas

    3 жыл бұрын

    In every language you can handle the error if you want to using conditional flow. This causes undefined behaviour if the error is not handled. In Rust you have to handle the errors mandatorily.

  • @ReedoTV
    @ReedoTV3 жыл бұрын

    I don't like that APL one at all. Seems fine in isolation, but I reckon it would have the Perl problem of a script being a cluster fuck when you come back to it years later

  • @fennecbesixdouze1794
    @fennecbesixdouze17942 жыл бұрын

    @10:40 that's because you hardly EVER just take the max of two elements in mathematics. Usually you want a max over some array or set, so you always need to feed ⌈ into some combinator. In other words, because we don't teach combinators in schools, a single-glyph for the "max" binary operation simply isn't very useful. In much the same way, mathematics notation doesn't actually use the symbol "+" for the equivalent of APL's `+\`, instead they use something like an upper case Sigma with explicit range bounds etc. I would agree that it would be very nice to teach combinators in middle school, and even teach kids with stuff like Haskell or APL.

  • @pauloffborba
    @pauloffborba3 жыл бұрын

    I love your work!

  • @sasayakah6342
    @sasayakah63423 жыл бұрын

    The rust's one is very easy to read! awesome videos

  • @dsagman
    @dsagman3 жыл бұрын

    Excellent! My father worked at IBM at same facility as Ken Iverson, inventor of APL. My father noted how Ken had his own printer, which in the 1970s was bigger than a fridge and cost a fortune. Why? “Because he invents things.” Now, can you please explain monads?

  • @tricky778

    @tricky778

    Жыл бұрын

    They're just monoi... Sorry

  • @witoldsz80

    @witoldsz80

    Жыл бұрын

    Monad is just a thing you can use a flatMap with, that's all :D Think it through. Sometimes its called bind, chain or is hidden inside a language feature like async/await in JS, but it's still the same. Ugh, the "monad" drama is so boring. Oops, the m-word drama, considering the monad word is forbidden in some "circles" 😄

  • @tricky778

    @tricky778

    Жыл бұрын

    @@witoldsz80 frankly a statement in c++ is an element of a monad isn't it? A function call is flatmap, semicolons between statements are the monoid operator.

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

    the APL solution looked like a trick, similar to those you can do in C, and everyone tells you not to do them, but you still like them and do them. I agree with you that there should be single char operators for mix/max as they are used too often. The single char reduce operator was the division operator and this is confusing if you don't know APL, which I don't, but I get it. Nice.

  • @JeremyNasmith
    @JeremyNasmith2 жыл бұрын

    Using the same data, how different would it be to find the wealthiest bank instead of the wealthiest client?

  • @robertpeszek6892
    @robertpeszek68923 жыл бұрын

    It is worth noting that maximum has to be a partial function (throw exception or return something like `null` for empty list). Some people (including me) consider using it a bad code. In Haskell, you could use total alternatives, e.g. safe package: maximumMay . map sum

  • @robertpeszek6892

    @robertpeszek6892

    3 жыл бұрын

    .. or use non-empty list type

  • @flyingsquirrel3271
    @flyingsquirrel32713 жыл бұрын

    Very cool stuff! But I have to disagree with your ranking here. IMO, Rust is CLEARLY the winner, just because it's the only one that forces you to explicitly state what you want to happen if the sequence is empty. In practice, that's a huge achievement. And although it's doing that, the implementation is still very clean and readable (and also easily parallelizable).

  • @leo848

    @leo848

    Жыл бұрын

    Exactly! Just add rayon, use par_iter instead of iter and you basically get safe threading for free!

  • @0LoneTech

    @0LoneTech

    Жыл бұрын

    In Haskell, all you'd have to do is change the type to Data.List.NonEmpty, and that corner case wouldn't exist (relocated to input validation where it belongs). It's also the difference between Monoid (e.g. Sum) and Semigroup (e.g. Max). And yes, they're easily parallelizable (start with Control.Parallel.Strategies). Simlarly, the complaint that the reduction wasn't exposed as the same operation could be trivially dealt with using foldl1 or sconcat. Partial functions including head and tail are still controversial, and it's possible to hide them (e.g. use classy prelude). Still, having exceptions beats silently regarding asm as safe imho. Perhaps the most infamous partial function is divide. Does rustc also enforce nonzero divisors?

  • @cataclysmwarshulduar
    @cataclysmwarshulduar3 жыл бұрын

    The question is ill-formed because what happens if the array is empty? Rust makes this problem apparent because you called unwrap. It also showed why I think algorithms in C++ is not entirely useful because it requires so much ritual to get anything done that you question why you did it in the first place. Without pipes, the control flow is not entirely obvious. Admittedly, some of these are done for performance reason, namely, entering the begin and end pointer makes sense in low level terms, but not entirely natural in the way piping are done since something like this is usually achieved by performing a filter instead.

  • @tcnymex

    @tcnymex

    3 жыл бұрын

    In APL, if the argument to this particular program was an "empty array" (array whose dimensions were zero by zero, or 3 rows by zero colums, or zero rows by 3 colums) the program wouldn't crash, it would simply return you an array of dimension zero by zero

  • @cataclysmwarshulduar

    @cataclysmwarshulduar

    3 жыл бұрын

    @@tcnymex that sounds....useless and at best sounds like an honest mistake. Max operation simply does not have an identity so its literally impossible to call Max on an empty array. I have spent many nights pondering upon this problem but I am simply too stupid to come up with anything clever beyond returning Option

  • @steffahn

    @steffahn

    3 жыл бұрын

    @@cataclysmwarshulduar One can count negative infinity as an identity for max. But adding a negative infinity to your numbers is pretty much like adding a None value with Option, so yeah..

  • @LionKing-qp1lk
    @LionKing-qp1lk3 жыл бұрын

    For-for loop and left-folding are single-pass algorithms. Mapping and then searching maximum needs two passes. 2d array to number folding in clojure: (reduce #(max %1 (apply + %2)) Long/MIN_VALUE accounts)

  • @bediakogeorge4488

    @bediakogeorge4488

    3 жыл бұрын

    Second reduce not necessary. Clojure's max function takes variable number of parameters.

  • @bediakogeorge4488

    @bediakogeorge4488

    3 жыл бұрын

    Can use apply instead

  • @bediakogeorge4488

    @bediakogeorge4488

    3 жыл бұрын

    Oh, and why apply over reduce? stackoverflow.com/questions/3153396/clojure-reduce-vs-apply#:~:text=The%20beauty%20of%20apply%20is,work%20with%20variable%20args%20case.

  • @LionKing-qp1lk

    @LionKing-qp1lk

    3 жыл бұрын

    @@bediakogeorge4488 nice quotes. I don't like java-world constant in my solution. You help me to avoid it at all. 1. I want to illustrate why fold is more preferred than mapping and searching => (reduce ,,,) 2. Reduce => I expect to see custom (fn [acc el] ,,,) and maybe a big transient accumulator 3. When I already have a function in my left hand and a collection in the right hand: cons-this-f-to-list-and-eval ~ apply ------------------------ 4. You ask why I prefer one function over other in case they both work. Because of link, I assume you know classic answer "it's not about speed, it's about the way of thinking". Speed: - dropping intermediate results is anyway more important - usually you don't care if they have a little difference in speed because faster collections = faster computing (I bet matrix libs or java primitive arrays with areduce are faster) - unchecked-math magic can change everything Comfort of a man who write both functions in one top-form: Reduce is like a contract "I'll convert collection to result". Do it. Why you need second reduce if you have only one collection?.

  • @CraigPerry

    @CraigPerry

    3 жыл бұрын

    @@LionKing-qp1lk I didn't understand: You help me to avoid it at all. -- are you saying there's a refinement possible to remove the Long/MIN_VALUE ?

  • @the_cheese_cultist
    @the_cheese_cultist2 жыл бұрын

    using C# linq (assuming input is the given matrix: input.Select(acc => acc.Sum()).Max(); or alternatively input.Max(acc => acc.Sum());

  • @Yupppi
    @Yupppi8 ай бұрын

    Damn, thanks a lot! I was just recently thinking maybe I could make a vector calculator with what I had learned and combining this problem to what I had I actually managed to make a pretty neat program that prints out a matrix. Next would be deciding if I should try and use these methods for the arithmetics. Noteworthy: #include for the C++20 solution, it's not you need to import despite the name std::ranges:: and std::views::

  • @tullochgorum6323
    @tullochgorum63233 жыл бұрын

    It's interesting that the OO languages have effectively given up on their claims that OO is the solution to issues of reliability and complexity. Almost all the new features in C++/Java/C# are watered down functional ideas. So why not just use a proper functional language like Haskell or F#?

  • @thecoolnewsguy

    @thecoolnewsguy

    10 ай бұрын

    Performance 😢

  • @briannormant3622

    @briannormant3622

    7 ай бұрын

    I think because first performance and memory. Functional programming tends to use a lot of recursion and immutable. And 2, because FP and PP each have their strength depending of the problem: for the problem in the video, FP would be the way to go. Its really adapted and readable. The haskell one was the cleanest by far. Pure procedural, basically the first C++, which was kinda a C solution. Was clean and easy to follow to. And imo, easier to modify if the problem changed a bit. But for some problem, like the ones that need you to look at neighbors in an array, PP would usually be cleaner. I'm eager to know if a better way exist in FP, but the +1 is the best by far with my (limited) experience. I don't see the point (and difference) with the Haskell and Apl solution. Its the same, but someone decided to rename max, maximum, map, with weird characters. By unit of code. Both are 4 longs.

  • @gscacco
    @gscacco3 жыл бұрын

    In this example the problem fits perfectly the language (APL). In every day programming rarely you will find a mathematical problem like this. What about a web server connected to a MySql db ?

  • @JaycenGiga

    @JaycenGiga

    3 жыл бұрын

    I am by far no expert, but AFAIK, the Dyalog implementation of APL has .NET interoperability. Also, a Database table is more or less a matrix for APL, so you could actually use its strong array capabilities for processing databases.

  • @xavierjulien31
    @xavierjulien313 жыл бұрын

    Suggestions on material to use to learn apl? KZread didn't seem to have a sound support for it, udemy neither. I found microapl.com but I like multiple resources to learn from.

  • @tcnymex

    @tcnymex

    3 жыл бұрын

    Dyalog.com (APL interpreter company) points to tryapl (an apl console in a browser). Dyalog site also has learning manuels etc. Dyalog also runs a yearly student programners contest with cash prizes & a trip to annual APL conference.

  • @code_report

    @code_report

    3 жыл бұрын

    1. TryAPL.org for a quickstart 2. kzread.info for free conference videos 3. chat.stackexchange.com/rooms/52405/the-apl-orchard APL Orchard to ask any questions you have 4. dyalog.com for free software download 5. aplwiki.com

  • @xavierjulien31

    @xavierjulien31

    3 жыл бұрын

    Thank you, looking into it now

  • @nxtktube
    @nxtktube3 жыл бұрын

    In clojure + is a variable arg function and calls reduce internally for more than 2 arguments. So below is enough (->> data (map (partial apply +)) or equivalent (map #(apply + %)) (reduce max))

  • @marciszekely1531

    @marciszekely1531

    Жыл бұрын

    or (->> data (map (partial apply +)) (apply max))

  • @marciszekely1531

    @marciszekely1531

    Жыл бұрын

    or even (comp (partial apply max) (partial map (partial apply +))) for a point-free solution

  • @RachelBowyer
    @RachelBowyer3 жыл бұрын

    You can write the Haskell solution in Clojure! (def maximum-wealth (comp (partial apply max) (partial map (partial apply +)))) "apply +" is needed in Clojure to use + in vector form "apply max" is needed to use max in vector form "partial" is needed as Clojure does not curry functions "comp" is the Clojure way to do function composition Having said that I believe your Clojure solution is more idiomatic and the Haskell solution is cleaner than either Clojure solution!

  • @cryptoworkdonkey
    @cryptoworkdonkey3 жыл бұрын

    Maybe anyone know where everybody can order APL-glyphs KeyCups?

  • @haskell_cat
    @haskell_cat3 жыл бұрын

    Haskell version in which "maximum" is last because it happens last: map sum >>> maxiumum in which each sum is computed in parallel: maximum . parMap rseq sum in which the two reductions are explicit: ala Max foldMap . fmap (ala Sum foldMap)

  • @noomade

    @noomade

    2 жыл бұрын

    You should make some videos buddy!

  • @tricky778

    @tricky778

    Жыл бұрын

    Doesn't ghc have a flag to parallelize automatically? As a pure functional language it shouldn't need to be requested in code.

  • @tricky778

    @tricky778

    Жыл бұрын

    Maximum doesn't happen last, it happens progressively. Maximum begins and upon requiring the sum of the first list element, a sum of one list begins, and so forth. Depending on the selected numerical type, the sums might progress together too, though I couldn't give you an implementation of that type and it's NUM instance off the top of my head.

  • @haskell_cat

    @haskell_cat

    Жыл бұрын

    @@noomade I do, check out my KZread channel by clicking on my avatar!

  • @haskell_cat

    @haskell_cat

    Жыл бұрын

    @@tricky778 It's theoretically possible, but in practice parallelizing everything makes programs slower, not faster, because it introduces some overhead. That's why annotations are currently needed. In theory a sufficiently smart compiler might be able to only parallelize where it improves performance, but that's much harder!

  • @OrbitalCookie
    @OrbitalCookie3 жыл бұрын

    What did other languages than Rust do when you call max on an empty sequence?

  • @nicotollenaere1587

    @nicotollenaere1587

    3 жыл бұрын

    They throw an exception. Or at least Haskell does. But there is not really another sensible behaviour anyway

  • @flyingsquirrel3271

    @flyingsquirrel3271

    3 жыл бұрын

    That really is the key question here! And that's what puts rust lightyears ahead all others in this comparison. It forces you to consider that edge case.

  • @dukereg

    @dukereg

    3 жыл бұрын

    APL returns 0. I'm kinda disappointed because it gracefully handles many complicated things in ways that make far more sense than that.

  • @danielsimon424

    @danielsimon424

    3 жыл бұрын

    @@nicotollenaere1587 But only because the maximum of list of numbers is "difficult" to define. The map should not be a problem...

  • @nicotollenaere1587

    @nicotollenaere1587

    3 жыл бұрын

    @@danielsimon424 I'm not sure what you mean by that. You could imagine that max would work along with a typeclass Ord' that also defines a minimum element, I guess. In this case max [] (if [] has been inferred as an integer list) would return MIN_INT. I'm not sure most people would find that natural. Really, there are only two sensible choices : either give it a type max :: [a] -> Maybe a (which is the same thing as in Rust) or just throw an exception. It's a matter of taste.

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

    Scala solution is most readable and elegant at the same time. It seems like a pseudo code. accounts.map(_.sum).max Even you don't know scala you can read this code and understand what it does.

  • @8bitcoder
    @8bitcoder3 жыл бұрын

    Could you do a performance comparison with larger arrays, such as 1,000,000 x 1,000,000? How much memory is used? How large are the executables, etc. Thanks! Really interesting video.

  • @noomade
    @noomade2 жыл бұрын

    would you prefer something like foldl1 max . map (foldl1 (+)) to be explicit about the reduction?

  • @alpaslaneldemir6904
    @alpaslaneldemir69043 жыл бұрын

    Amazing content thanks a lot !

  • @neilclay5835
    @neilclay58359 ай бұрын

    Very interesting.

  • @LolkeDijkstra
    @LolkeDijkstra15 күн бұрын

    Very nice. I hate the closure snippet. I can only imagine the compiler errors that I would be getting trying to write something similar.

  • @julesgosnell9791
    @julesgosnell97913 жыл бұрын

    What is the fixation with threading macros in Clojure ? I also find the anonymous function shorthand ugly - I much prefer: (reduce max (map (partial reduce +) accounts))

  • @jonseltzer321

    @jonseltzer321

    3 жыл бұрын

    Alternate: (defn max-wealth [accounts] (reduce max (map (partial apply +) accounts))) Video went out of it's way implying Clojure did not have a 'sum' function (e.g. a function that can add more than two values together). Of course Clojure's '+' function does exactly that already (+ 1 2 3 4 5)

  • @okcomputr

    @okcomputr

    3 жыл бұрын

    Once you get used to them, the threading macros are second nature to use and to read as well, and they make for concise clear code. In the beginning I had to stop and analyze code that was using them for a few minutes before it really made sense, but its something you can get accustomed too pretty quickly.

  • @julesgosnell9791

    @julesgosnell9791

    3 жыл бұрын

    @@okcomputr I agree that they have their uses - but in many cases I find them just adding unnecessary complexity - e.g. the example in this video - why, when we have an established and simple syntax, choose to use a more complex one and turn a two-liner into a three-liner ? - I have often seen this done - particularly in a video that should be showcasing the simplicity, brevity and beauty of Clojure/LISP rather than it's ability to toss in arbitrary transformatory macros ? Why when you have finally wrapped your head around an "inside-out" Polish notation would you then use it to write a macro to allow you to scatter random pieces of "outside-in" code with more complex rules around the use of parentheses than your original ? Why, when you have mastered the concepts of recursion and nesting would you want a macro that hides all of this ? It is like trying to read a novel where every few lines you come across some cryptic symbol notifying you that you should stop reading from left->right and start reading right->left - a jarring paradigm shift - .... and all because the author has seemingly not been able to wrap his head as far around the LISP paradigm as you have and would rather write procedural-looking code...or is patronising you by assuming the reverse... end rant :-)

  • @CarloSciolla

    @CarloSciolla

    3 жыл бұрын

    @@julesgosnell9791 while I agree that "less is more" generally speaking, my eyes (trained by years and years of reading and writing clojure professionally) tend to fair better parsing a threading macro form rather than nested forms in most cases with more than two function calls, mostly because such macros do the job for me of letting the forms boundaries "pop off". And if I eventually use nested forms I tend to use newlines / indentation to improve the EDN parsing speed of human eyes (or maybe just my eyes, no need to generalize). All in all it is, I believe, personal preference and possibly more of a style choice (apropos: github.com/bbatsov/clojure-style-guide#threading-macros), but as a bit of a tongue-in-cheek counter argument: why, when you mastered homoiconic languages and macros, mixing thread-first and thread-last together to fit LISP forms into each other like puzzle pieces, would you ever consider the more mundane nested forms more lispy? :-)

  • @ryanburnside9541

    @ryanburnside9541

    3 ай бұрын

    It's become abused culturally. Along with the map-itus. They forget to abstract arrows into selectors and end up churning out reams of arrow macros doing the same thing over and over again. I consider them syntactic saccharine since they actually cause things in the body to be missing one parameter. Do they have a place? Sure in small isolated pockets, when half of your code is the same arrow macro pasted over and over it's hot garbage.

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

    My Solution in Rust would be accounts.into_iter().map(IntoIterator::into_iter).map(Iterator::sum).fold(0, i32::max) yes we could use the advantage of .max(), but it return an option and I don't really like unwraps, you could do a unwrap_or(0) but thats one more line, fold is as readable in my opinion and let you directly place a default

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

    Why you need to do all in 'raw loops' or all in 'algorithms' ? Why not int maximumWealth(std::vector& accs) { int max = std::numeric_limits::min(); for (auto& row : accs) max = std::max(max, std::reduce(begin(row), end(row))); return max; } ??? It is much more readable then two accumulates or smth

  • @EricMesa
    @EricMesa3 жыл бұрын

    Wow, haskell and apl are so beautiful. Also, now I understand why some coders loved haskell during advent of code

  • @martinalcala4823
    @martinalcala48232 жыл бұрын

    We can get a functional definition with JavaScript too! With: const maxWealth = compose(max, map(sum)); We just need this simple helper functions: const map = fn => list => list.map(fn); const sum = list => list.reduce((acc, val) => acc + val, 0); const max = list => Math.max(...list); const compose = (...fns) => arg => fns.reduceRight((value, fn) => fn(value), arg);

  • @Chalisque
    @Chalisque2 жыл бұрын

    Something I was playing with recently was writing sha256sum in C, C++, Rust, Python and other languages. I had no idea where to begin writing it in Haskell, so googled around and took a peek at what someone wrote earlier. For that, the Haskell ends up verbose and ugly compared to C and Rust.

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

    I know I'm late on this video, but the Scala solution could have been way shorter, actually you can declare it as a simple lambda expression :) val maximumWealth: Seq[Seq[Int]] => Int = _.map(_.sum).max

  • @tcnymex
    @tcnymex3 жыл бұрын

    (N.B. This comment is about ADSP podcast; didn't see anywhere to leave a comment on an episode on the podcast page) Conor, My ears perked up when you said any scan is parallel-isable The the formal definition of plus scan a series of numbers like iota 4 equal to 1 2 3 4 is a series of reductions +\ iota 4 is: (+/1),(+/ 1 2),(+/1 2 3),(+/ 1 2 3 4) Because plus is both commutative and associative you can parallelize the +/ first, and then run the +\ as four +/ on four separate cores each of which is running the plus reduce parallel algorithm But that only works for things that are both associative and commutative like plus or multiply, it wouldn't work for things like divide and minus scan ( you could, of course, run each of the four ÷/ required for a "÷\ iota 4" on a separate core, but I don't see how you could parallelize the ÷/ itself) But of course, being an APL guy, I let The interpreter do all the smart optimization, so I very much look forward to gaining some insight from your upcoming podcast episode discussing parallelizing scans. T.C.

  • @ftinkere
    @ftinkere3 жыл бұрын

    Clojure have transducers, they may do it more expressive and shorter

  • @dmitrychurkin4077
    @dmitrychurkin40773 жыл бұрын

    Awesome, BTW, reminds me Context Free channel. Your brother's name Tom? :)

  • @cogspace
    @cogspace2 жыл бұрын

    // The JavaScript solution isn't far off from Scala: const maximumWealth = accounts => ( Math.max(accounts.map(sum)) ) // Although you do have to BYO sum function: const sum = _ => _.reduce((a, b) => a + b)

  • @wagcampbell
    @wagcampbell3 жыл бұрын

    Such a great video 👍 Thanks!!!

  • @PS-dp8yg
    @PS-dp8yg3 жыл бұрын

    Just like you, in my day-to-day work, I avoid for loops, while loops, and do while loops like the plague if possible. I'm a JS developer by day, but I'm learning Haskell on the side. The more I work with Haskell, the more I love it.

  • @YashTrivedi21
    @YashTrivedi213 жыл бұрын

    It's all fun and games until you have to debug 1000 lines of APL and it's just made out of characters. :) Though very informative and good video. Thanks

  • @JaycenGiga

    @JaycenGiga

    3 жыл бұрын

    Now imagine having to debug the same program, but it is 100,000 lines of C++. And I’m not defending APL in this, I am honestly not sure which would be the greater pain in the ass.

  • @RichardvsHimself

    @RichardvsHimself

    3 жыл бұрын

    Often your application / systems code will be lots of names (which you have created yourself) and be just as readable as any other "traditional" language. Just like any other language, you can write code that is unreadable for yourself or others, or you can write code which is perfectly readable and easily maintainable. The power of APL comes when you have to solve problems for yourself, and suddenly you find the relatively small collection of versatile primitives is quite satisfying to work with. On the topic of readability, this bit of conversation had some interesting points chat.stackexchange.com/transcript/message/55173403#55173403 - as an APL chat room, the topic of "why does every think APL is unreadable" comes up every now and again

  • @michaelmonkenbusch5591
    @michaelmonkenbusch55912 жыл бұрын

    Fortran: maxval(sum(x,dim=1)) full program: integer :: x(3,3) = reshape([3, 7, 2, 8, 10, 2, 3, 3, 4],[3,3]) print*, maxval(sum(x,dim=1)) end

  • @Inficate-bd3qu
    @Inficate-bd3qu9 ай бұрын

    A program is beautiful because it is beautiful, not because it is short. I'm fine with people playing code golf but not the entire world is a golf course.

  • @rikihanks
    @rikihanks2 жыл бұрын

    no need to call unwrap in rust, if you are going to assume the result wont failt just call .max()? with the ? operator

  • @leo848

    @leo848

    Жыл бұрын

    Umm no this won't work unless the return type is fallible, which is not the case here. If the return type was Option one could use the ? operator but it would be useless as the fallible result gets returned anyway.

  • @voiceofthetrue1849
    @voiceofthetrue18493 жыл бұрын

    The most beautiful & readable solution in my opinion is the Rust one.

  • @code_report

    @code_report

    3 жыл бұрын

    I really like the Rust as well 👍

  • @ArnabAnimeshDas

    @ArnabAnimeshDas

    3 жыл бұрын

    Rust is the best

  • @noomade

    @noomade

    2 жыл бұрын

    I am curious as to why you find that more readable than the haskell one...

  • @leo848

    @leo848

    Жыл бұрын

    @@noomade I find the haskell one more readable, but the Rust one more efficient and fully safe, as the possibility of an empty list must be handled.

  • @noomade

    @noomade

    Жыл бұрын

    @@leo848 It is handled in Haskell as well. I think in production development people that know what they are doing (i.e. not me) don't use the lists from prelude

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

    solution of same in my language to that i had created: array vec = [ Array[4,5,6], Array[6,7,8], Array[88,88,0], ] loop len[{vec}]: uelem vec:$$I = sum[vec..$$I] arr richesIndex = indicesof[{vec},max[{vec}]] print [richesIndex]

  • @pthomet
    @pthomet6 ай бұрын

    C++, using FunctionalPlus: auto maximumWealth = fplus::fwd::compose(fplus::fwd::transform(fplus::fwd::sum()), fplus::fwd::maximum()); will work on any container, and any numeric type.

  • @heeerrresjonny
    @heeerrresjonny3 жыл бұрын

    I love videos like this! I think Java would be a worthwhile addition to these...especially if you're going to do 3 different versions of C++ lol. Java streams results in a solution that is _very_ similar to Rust, but possibly more readable (assuming KZread doesn't destroy the formatting lol): int max = Stream.of(accounts) .mapToInt(a -> IntStream.of(a).sum()) .max() .getAsInt();

  • @martinlukas6097

    @martinlukas6097

    Жыл бұрын

    In my opinion, in the second line it's more concise and readable to do .mapToInt(i -> i).sum(), instead of invoking the IntStream method. Although you do need to know why the mapToInt(i -> i) is necessary - to convert Stream to IntStream by automatic unboxing.

  • @heeerrresjonny

    @heeerrresjonny

    Жыл бұрын

    @@martinlukas6097 I had to go back and think this through again haha. My example is expecting "accounts" to be of type int[][] (i.e. an array of int arrays). So, the IntStream.of(a) call is taking an array of ints, converting it to an IntStream, and then summing them. I'm not sure where calling mapToInt(i -> i) could fit in there and have it still compile. mapToInt() expects you to map each item in the stream to a single integer, so calling sum() on it won't work (sum() is a reduction that only works for IntStream).

  • @SherubThakur
    @SherubThakur3 жыл бұрын

    (For me) Haskell is the most elegant language. APL just has massive readability issues (for me?). The outlined good point about APL (i.e. explicit 2 reduces) might be a bad advise when considering from the perspective of other langs. reduce is just too general and its existence in code is problematic (from readability standpoint) IMO, I always prefer to use something more restrictive. Let me illustrate that with an example here is the solution just using reduces. maximumWealth = foldr1 max . foldr (\x xs -> (foldr (+) 0 x) : xs) [] Everything here is a reduce (foldr is Haskell's version of reduce). i.e. maximum is a reduce (maximum = foldr1 max) (foldr1 is just like foldr but uses the last element of the list as base value) summation is a reduce (sum = foldr (+) 0) mapping is a reduce (map f = foldr (\x xs -> f x : xs) []) put another way, when you encounter reduce first you have to figure out what it is doing then you understand the solution (which is the same problem with for-loop). That is why I don't like to use reduce ever as a general rule. I say the solution, where there is no reduce, is far simpler to read - maximumWealth = maximum . map sum

  • @noomade

    @noomade

    2 жыл бұрын

    foldr (+) 0 == foldr1 (+) ????

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

    Cool. Now do an http request, and find all instances of /get_file/ between single quotes and rank the results by an integer found within the string. Then try to convince people that the haskell that results from that is beautiful. Javascript, scala, go, and rust will do the best in that order. Then clojure, c++, haskell. I don't know how to do that in APL. It would be very cool if it stays elegant. Then I will have to agree APL is cool if it can do that. Not having 50 bajillion text types might help.

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

    Best example of the elegance of APL. Those 4 symbols literally express the essential mathematical solution; all the rest is noise.

  • @markpascual100
    @markpascual1003 жыл бұрын

    why the dislikes? i'm so confused it's a great video

  • @neociber24

    @neociber24

    3 жыл бұрын

    Good question, I would like to see what people doesn't like. Or maybe just some programming language fanboys.

  • @alexanderskusnov5119

    @alexanderskusnov5119

    3 жыл бұрын

    I think the problem was very simple. Look at Tsoding kzread.infoplaylists

  • @danny-jo1rb
    @danny-jo1rb Жыл бұрын

    my own language named “MaxWealth” has an absolutely beautiful solution: ¥ See its just 1 character isnt that beautiful? Much better than the C++ solution

  • @Aziiz1989
    @Aziiz19892 жыл бұрын

    another solution for Clojure (apply max (apply map + accounts))

  • @Klayperson
    @Klayperson2 жыл бұрын

    all i learned in the first 5 minutes is that i don't fucking know C++, i'm gonna go cry now

  • @cplusplussizeddick1430
    @cplusplussizeddick14303 жыл бұрын

    Ok, it's two lines of code, whoopdidoo. But now what's the time and space complexity in comparison to C++ huh? Everything looks cool and all at first sight until you realize it's inefficiently using resources

  • @philippjungkamp3760

    @philippjungkamp3760

    3 жыл бұрын

    In that case I would consider Rust a contender by performance. The solution he presented seems obviously single threaded but I'd like to point out that by including rayon, one could replace .iter() with .par_iter() and the calculation would work in parallel. Safety-wise it's nice that C++ just returns 0 on an empty accounts list. The Rust solution would need an .unwrap_or(0) instead of just unwrap() to not crash on an empty list. With those modifications Rust would contend in speed with C++ but still be easier to read. (I prefer Rusts default choices of immutability and type inference to manually typing auto and const time and time again)

  • @JaycenGiga

    @JaycenGiga

    3 жыл бұрын

    I don’t know if you mean these languages, but both Haskell and APL have so-called fusion, meaning that multiple traversals through a data structure are be combined into a single one by the compiler. That means that the complexity is actually exactly the same as in C++. Rust Iterators are lazy, so the same applies to it. Plus, all three programs are trivially parallelizable (In Rust we use par_iter, in Haskell parMap or something similar and in APL we can supply an evaluation strategy, including GPU calculation, and just use the exact same program). They are actually fast. Rust is known to be faster-than-C in certain situations and APL with GPU computation enabled also has C-like speed for larger amounts of data without much fiddling around. You really don’t have to sacrifice speed for readability, you can have both!

  • @cplusplussizeddick1430

    @cplusplussizeddick1430

    3 жыл бұрын

    @@philippjungkamp3760 interesting. Thanks for the answer

  • @cplusplussizeddick1430

    @cplusplussizeddick1430

    3 жыл бұрын

    @@JaycenGiga oh wow. That's very interesting then. Thanks for the explanation.

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

    In JavaScript you could do a=b=>Math.max(...b.reduce((c,d)=>c+d,0)) which I think is a great balance between simplicity and readability. You unwrap b with ... after calling reduce on b which takes two arguments: a function and an initial value. c is our sum/initial value and d is each element of b which is then added to c which becomes our new c next iteration.

  • @maraschwartz6731
    @maraschwartz67312 жыл бұрын

    Python solve = lambda m: max([sum(x) for x in m]) matrix here as a list of lists of numbers

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

    I think the best solution for C++ is the first C++11, but using algorithms to do the sum.

  • @DanielKos
    @DanielKos3 жыл бұрын

    From all C++ versions I'd choose that with two for loops. It's very readable. C++17 is the worst IMO. Too many technicalities exposed.

  • @hansiraber

    @hansiraber

    3 жыл бұрын

    yea, he has no clue what he's talking about. "i love algorithms". he's gonna have a heart attack when he discovers all algorithms are made out of compare and conditional jumps :D

  • @DanBader

    @DanBader

    3 жыл бұрын

    Agree, though i could be swayed to one of the newer versions for the built-in parallelism. Since everyones phone has 4 cores to throw at the problem. Lol.

  • @insertoyouroemail

    @insertoyouroemail

    3 жыл бұрын

    @@hansiraber why is that a problem?

  • @markbteeps

    @markbteeps

    3 жыл бұрын

    That's exactly what I thought. The one with for loops is simple and easily understandable. Having said that, I'm an engineer who programs things, rather than a software developer, so I'm not particularly familiar with modern c++ features. Neither are the people who might try to read or maintain my code though, so for loops seem like the way to go for me. I don't really get the benefit of the newer features.

  • @mskiptr

    @mskiptr

    3 жыл бұрын

    Don't for loops expose the technicalities way more? I mean, the only thing closer to the actual implementation and farther from the underlying idea would be explicit go-tos and conditional jumps… IMO, Haskell version is the most readable because it explicitly states we want the maximum of sums. I.e.: maximum = maximum of = . sum = sum s = map The C++ 'algorithms' versions are kind of halfway through. Like if someone inlined the definitions of maximum and sum by hand. But loops are one step of inlining farther. And bring mutability to the table - which is probably the actual reason he dislikes them.

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

    Scala shorter solution: val maximumWealth: Array[Array[Int]] => Int = _.map(_.sum).max

  • @harshrathod50
    @harshrathod503 жыл бұрын

    Very useful content. I didn't knew reduce and transform like things exist, before this. I better learn them. 😇

  • @az-kalaak6215
    @az-kalaak6215 Жыл бұрын

    you did not really compare languages from my point of view, it was more related to comparing library and preimplemented functions :/

  • @user-tk2jy8xr8b
    @user-tk2jy8xr8b3 жыл бұрын

    Agda has a single symbol min as well: ⊓

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

    People are bothered by the smallest things lol. Some will prefer to not have to memorize a new symbol and instead use a very short word like min/max, but definitely to each his own. It IS interesting to have a symbol for those.

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

    try to look at haskell code 2 years after you wrote this code and try to guess what it does without looking at problem it solves

  • @0LoneTech

    @0LoneTech

    3 ай бұрын

    Yes, do. It's easily the most readable of them.

  • @petrushoc
    @petrushoc3 жыл бұрын

    Kotlin val accounts: List val res = accounts.maxOf { it.sum() }

  • @randomseed
    @randomseed3 жыл бұрын

    Fully functional in Clojure: (comp (partial apply max) (partial map (partial apply +)))

  • @noomade

    @noomade

    2 жыл бұрын

    that is interesting... that is like really ugly Haskell :P

  • @ryanburnside9541
    @ryanburnside95413 ай бұрын

    Here is another Clojure solution using no anonymous function and no loss of argument visibility from the arrow macro. (defn max-account [accounts] (reduce max (for [i accounts] (reduce + i))))

  • @MCLooyverse
    @MCLooyverse2 жыл бұрын

    I don't get why you dislike the inside-outness of one solution, but are fine with the right-to-leftness of others. We're talking about functions; they're the same thing -- one just has parentheses.

  • @sillymesilly
    @sillymesilly8 күн бұрын

    What about C?

  • @jdegio
    @jdegio3 жыл бұрын

    I will submit a Groovy one-liner that strikes a nice balance of readability and elegance: ​def maximumWealth(def accounts) { accounts.collect {it.sum()}.max() }

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

    Here's my Scala solution: val maximumWealth: Array[Array[Int]] => Int = _.map(_.sum).max

  • @shanewalsh1573
    @shanewalsh15733 жыл бұрын

    С++ somehow seems the most readable one

Келесі