1 Problem, 4 More Programming Languages (Python vs Kotlin vs F# vs Wolfram)

preview_player
Показать описание
A video taking a look at 4 more programming language solutions (Python, Kotlin, F# & Wolfram Language) to one problem.

Github Links:

Рекомендации по теме
Комментарии
Автор

Thanks for the updated video and the 4 more programming languages!
Btw. in Kotlin, scan is deprecated and is replaced by runningReduce and runningFold. Also, you can reference the plus-operator with Int::plus. Your Kotlin solution could when look like this :

fun maxDepth(s: String) = s
.map { when (it) { '(' -> 1; ')' -> -1; else -> 0 } }
.runningReduce(Int::plus)
.max()

Andrej.
Автор

I've started learning APL because of your videos. Currently I've done the phase 1 problems of 2021 competition.

_rid
Автор

Funny you mention the rust scan allowing you to terminate. In F# we do this with Seq.unfold, which has that very semantic. Very useful for infinite iteration.

ChetHusk
Автор

1:40
Why you would like to iterate over the string several times:
1. Filtering everything that is not "(" or ")"
2. Converting parenthesis to 1 and -1
3. "Running sum"
4. Getting maximum

When you can solve the task via 1 iteration over the string:

example = "(1+(2*3)+((8)/4))+1"

solve = (str) ->
max_depth = 0
depth = 0
for char in string.gmatch(str, ".")
if char == '('
depth += 1
if max_depth < depth
max_depth = depth
else if char == ")"
depth -= 1
max_depth

print solve(example)

?

ryzh
Автор

Cool, lines of code is not a measure of productivity anymore, everything coded in a single line!

guibirow
Автор

As of python 3.10 Guido has approved structured pattern matching (after blocking it a decade and a half 🙈)!

I think it makes the imperative approach surprisingly readable!

def max_depth(s:str) -> int:
result = 0
depth = 0

for char in s:
match char:
case '(':
depth += 1
case ')':
depth -= 1
result = max(depth, result)

return result

maxsuica
Автор

The Wolfram Language one can be made much shorter:
maxDepth = -> 1, ")" -> -1}]

ArkAnimation
Автор

If you never have a None case, you can simply use .fold() instead of .scan() and maintain a max counter within the accumulator. (i.e make your accumulator a tuple)

comradepeter
Автор

Hi code_report!! I've watched so many of your videos because they're great fodder for a programming language I've been designing!! I call it Noda (which is a faux-pluralization of Latin for "knot"), as I'm inspired in part by Knot Theory. I have solved this and many other problems in my language. Here's the (shortest) solution for this one:

max( $+str.[c => (c=="(": 1)(c==")": -1)(0)] )

Breakdown:
str.[c => ...]
This is how I map values (=>). The variable "c" before the map operator (=>) is an element of the list "str" (which is technically a list of characters and is treated as such).
(c=="(": 1)(c==")": -1)(0)
This comprises what I call 'conditional pods'. Each pod executes an if followed by elsifs. The final pod without a conditional at all is the default value. Any boolean evaluation followed by a colon (:) executes an if statement, so the if keyword is entirely unnecessary in this language.
$+
This is a plus scan. When used monadically in conjunction with another operator, $ creates scans. In other contexts (like as a dyadic operator), I use the sigil ($) for subsetting, like in [1, 2] $ [1, 2, 3, 4].
max( )
This is the max function, of course. I typically find writing it out to be clearer than any ASCII operator.

My solution differs from yours in that I map "every" value, just non-parenthetical ones map to 0. In the end, this doesn't effect the value of the maximum of the plus scan so why bother.

Noda is heavily inspired by APL and Python. It is an Array-based programming language at the core, whilst being multiparadigmatic for most uses. The ambition is the bring the terseness and extensibility of APL into a readable, Python-like format written in ASCII. I feel like J and K gloriously failed in this regard. Like many APL solutions, I am typically able to reduce 14-line Python solutions to 1-3 lines at most.

simulatrix
Автор

Python solution without accumulate (python 3.8+)
def max_depth(s):
acc = 0
return max((acc := acc + n for n in (1 if c == '(' else -1 for c in s if c in '()')), default=0)

Автор

You might enjoy filter_map in Rust too; it goes quite well with pattern matching. It essentially allows you to decide to include/exclude elements while mapping them by returning Some/None.

s.chars()
.filter_map(|c| match c {
'(' => Some(1),
')' => Some(-1),
_ => None
})
.scan(0, |a, v| { *a += v; Some(*a) })
.max()
.unwrap_or(0)

I really like the fact that scan supports early termination, but it does lead to noise in many cases where it's not needed. A version without early termination would be nice to have.

mike-barber
Автор

I wonder how performant all these magic operators are, probably a topic for a future video!

guibirow
Автор

how do you make your nice transitions between code blocks? :)

Mikan_uwu
Автор

For f# I'd go with a fold, which, while more complex only runs through the sequence once. In this case the compiler made me use the type annotation for maxDepth though.


let maxDepth: (seq<char> -> int)=
let foldHelper state value =
let maximum, currentvalue = state
let newvalue =
match value with
| '(' -> currentvalue + 1
| ')' -> currentvalue - 1
| _ -> currentvalue
if newvalue > maximum then
newvalue, newvalue
else
maximum, newvalue
Seq.fold foldHelper (0, 0) >> fst

Akronymus_
Автор

APL looks like an EsoLang, but also seems to actually be useful, I feel like i should learn it just for the sake of using obscure characters in code

shadowreaperjb
Автор

f# solution is one of shortest but easy to understand

zhh
Автор

Username at 5:24, transliterated, is Denis Proshutinskij (I think). Here's my stab at a pronunciation guide: "Denis" as Dennis (duh); "Pro" as in prod, "shu" as in shoo, "tin" is short like tin but with a vowel more like the 'ee' in teen, and lastly "skij" almost like ski. Pro(d)-shoo-tin-ski. But I don't really speak Slavic.

jonaskoelker
Автор

Shoutout to F#, one of the most underrated languages out there

mimosorosario
Автор

Got curious after seeing the new APL solution, so I hacked this up for a similar solution in numpy:
lambda s: -diff((array([[*"()"]]).T == [*s]).cumsum(axis=1), axis=0).min()

contextfree
Автор

How easy is it to reason about undocumented apl code?
I mean, it seems elegant and all.. But trying to reason about unknown algorithms seems tough. For me anyway.
Then again, that might not even be the point of the language. I have no idea, heh.

korvmakak