« first day (1871 days earlier)      last day (206 days later) » 

12:07 AM
I've been messing around trying to make some python generator expressions and this doesn't work:
the intended output is:
0 1 8

i do have some working code though but close your eyes:
 :For x :In num_list
     :If 20<y←cube x ⋄ :Leave ⋄ :EndIf
oh and sorry, cube function is simply:
8 hours later…
7:58 AM
@BrianBED I don't even see how your dfn-based solution is supposed to work.
1 hour later…
9:21 AM
@BrianBED ⎕←{cubed⌿⍨20>cubed←⍵*⍳5}¯1+⍳5
@RikedyP 0 1 8
3 hours later…
12:33 PM
@Adám i tried very hard :(
⍣ confuses me a lot
@RikedyP thank you so much you are a guinius :D
imma analize it
@RikedyP that ⍵*⍳5 should be just ⍵*3
⎕← ⌿⍨∘(20∘>)⍨3*⍨¯1+⍳5
@FawnLocke 0 1 8
@RikedyP @BrianBED But this is very different. It generates all possibilities and filters, rather than generating just enough.
12:44 PM
ah true
yea i noticed it after a bit
he did get it smaller than my version though ¯\_(ツ)_/¯
@FawnLocke I want back-compose: 20∘>⍛⌿⍨3*⍨¯1+⍳5
ah you guys are wizards. so is there no way of using ⍣ as a generator expression?
not very pretty ways at least
i have x←⍬ ⋄ {x,←⍵*3 ⋄ 1+⍵}⍣{20<⍺*3}0 ⋄ x
num_list = [0,1,2,3,4]
[cube(x) for x in num_list if cube(x)<20]

the reason i'm doing this is im talking to a python programmer and he gave me this expresion to translate for fun. actually not arguing this time just him looking at the language and i was actually not able to translate it to a smaller expresion without using all the ifs and fors
@dzaima oooo ill have a look
12:49 PM
@BrianBED that's precisely the replicate solution
wait oh i took wrong snippet
one second
num_list = [0,1,2,3,4]
[y for x in num_list if (y:= cube(x))<20]
this is the one sorry
that's still the replicate solution
god wait it is? well like, as far as i was told, like im not a python programmer but this apparently stops after the first false value of the if statement... badly explained but yea
if num_list was [0,8,1,9,2,10, 1], you'd get a result of 0 1 2 1*3, but short-circuiting with would stop at the 8
@BrianBED TIO - it does not stop at the first false value
I need a chat with my friend lol
thanks for all the help
12:54 PM
@Adám What do you suggest for monadic ⍛, I had (F y) G y as the sensible option, meaning you could remove that ⍨ too.
@FawnLocke Ah, yes, that.
Ah okay
he said this in one message. flew by me but is probably important in this::
Actually, sorry! That is the case for a generator expression if we assumed the elements were sorted...which they might not be
But it is more efficient still as you iterate over the list once, not twice as you would using filter."
@FawnLocke it's a very sensible & nice & useful option, it just has the drawback that there's no x F (G x) on monadic to behave equally to
12:56 PM
@FawnLocke What do you suggest for array operands of ? I have default value. E.g. 2(1⍛+)10 gives 12 while 1⍛+10 gives 11.
@BrianBED in APL, iterating twice is much less of a concern than in Python
oh why?
@dzaima But that's just one away: F∘G⍨
@BrianBED its APL /s
@Adám I hadn't thought too hard about that, but that's really nice !
12:58 PM
@BrianBED there's no horribly slow python interpreter to take 95% of the time, leaving only 5% for the actual operation you're doing
@Adám but so is F⍛G⍨
@dzaima ahhhhh i see... that sounds very fair
@PyGamer0 i can't keep having "apl does magic" as an excuse lmao
@dzaima i have heard that python is slower than JS
way slower
@dzaima True, but what could F⍛G y be? G y?
@BrianBED why?
does JS do magic?
i should try learning it...
1:00 PM
i mean... just iterating through a loop in js is like... 50 times faster
@dzaima even 1+2+⍳10 is iterating over ⍳10 twice (three times if you count the initial creation of ⍳10). Nearly every sequence of operations (except idioms) just has a separate loop for each operation
@PyGamer0 sure. i dont like the language per se, but its very useful and in demand
js has a lot more money behind its improvement and optimization. some hardcore jitting
@PyGamer0 JS at least tries to be fast. (pypy or whatnot also does, but i don't know to what level)
1:02 PM
I don't think there's much F⍛G y could be that isn't just a ⍨ away. Maybe it should be G F y to match Dyalog's ∘
@Adám I'm not saying F⍛G y shouldn't be (F y) G y. It's definitely the best option
G F y would be useful for saving parentheses i guess, but besides that it'd just be confusing
@dzaima there are plans to speed up cpython ...
@PyGamer0 huh.
I suppose monadic over could've been G F y, nicer than another atop at least
1:19 PM
@Adám "let's make it worse!" Nice promise/quote in your last video of the APL Quest :) Had fun watching it.
1:33 PM
is it worth using array operators in python? like so far i haven't but i'm tempted to try using some APL inspired code, but i wanna ask first because if it isn't worthit then i won't bother
1:45 PM
If the monadic puts its argument on both sides, you could finally do sensible tacit filtering with 10∘<⍛/.
Good point
@BrianBED example?
@FawnLocke Nah, that'd break the pattern that Over pre-processes all argument using G
Fair enough, it only tackles the "issue" of complex right operands needing brackets anyway.
I use ambivalent Over all the time. I think it's better to design a combinator as a single thing on a variable number of arguments when possible.
1:58 PM
Why not (G y) F (G y) then
@PyGamer0 using sum(), all(), functools.reduce(), array calculation stuff involving numpy, that kind of stuff
@BrianBED i use them, but people consider them "unreadable"
(i dont use numpy though)
yea, I can't understand lamda expresions whatsoever in python
and they are super neat
well... look super neat... idk them yet
@BrianBED lambdas are nameless functions
i also made a super slow library for python: pyhof
@FawnLocke Again prevents ambivalent functions from working.
2:08 PM
Ohhhh, I see now
@PyGamer0 what does it do?
@BrianBED lambda x,y: x+y*y is like {⍺+⍵×⍵}, just the names of arguments are explicit (and you can have arbitrarily many of them)
ahh thats a great example
@Adám Maybe in Dyalog's case G F y as monadic before makes sense then. Keeps it symmetrical and consistent
Hmm, or not. It's kinda an outliner, Best to stick to the obviously useful form
@dzaima wait how do i define x and y?
2:22 PM
x,y: is the definition
@BrianBED wdym
wait oh... wait so you can't use them in the same line? like do you have to have a name to the lamda function?
lambda arg1, arg2, arg_with_default=None:...
@BrianBED you can do (lambda x:x+1)(2)
ahhhh ok thats what i was looking for
@BrianBED you can invoke it like (lambda x,y: x+y*y)(4,10)
it's just a regular function
just defined in a single line, instead of multiple
2:25 PM
right makes sense. i did that but i forgot the first parens around the lamda
OOOo i'm gonna use lamdas a lot
i also did this and amazingly i get no syntax error:
print((lambda x=1: x+x)(2))
lambda x, y: x + y - 1 is 1-⍨+ in APL :)
like because i did x=1 i would expect an error but yea
@FawnLocke nothing beats apl :D
that sets a default argument, so if you invoked it with (lambda x=1: x+x)() you'd get 1+1
2:28 PM
in my head now it makes a lot of sense because thats the usual way of setting defaul value for a function
The APL Orchard has become the The Python Terrarium
well i appreciate the help :)
@Adám lmao
2:50 PM
apl quest in 10 mins
@dzaima {⍺,(3*⍨⍵)}⍣5⍨2 this almost works. the problem with starting out with 2 is that well... it starts off with 2... so i did this version but it doesn't work:
{⍺,(3*⍨{⍵≡1:1+⍵ ⋄ ⍵}⍵)}⍣5⍨1
i tried making it incriment by one if its 1 just to get it looping... didn't work

this explodes
there has to be some way of doing this... ill keep working on it
@BrianBED F⍣5⍨ 1 will do 1 F 1 F 1 F 1 F 1 F 1
yes exactly. i can make it work with enough if statements
i think
the problem is that you're still iterating over only ; is always 1 (or 2 in the case of the first expression)
but the output changes across... oh wait only in the second expression... right right i see
2:58 PM
but you want to iterate two variables - the counter, and the result array
so {⍺,(3*⍨⍵)}⍣5⍨2 is f←{2,⍵*3} ⋄ f f f f f 2
@Adám but the expression of the question is to do that: for integers up to 5, if its cube is less than 20, keep, else throw away. I'm sorry idiomatic APL is to do it this way
Welcome to the APL Quest! This weeks quest is Home On The Range:
> Write a dfn which returns the magnitude of the range (i.e. the difference between the lowest and highest values) of a numeric array.
@dzaima this is true... can i use ⍺ to iterate?
This should be fairly simple, except maybe for the empty array case. Any contenders?
yes gimme a min
3:01 PM
@BrianBED no. never changes during
the obvious: {(⌈/-⌊/),⍵}
works for everything except ⍳0 as expected
@dzaima awww
@KamilaSzewczyk Wonder why you wrapped that in {⍵} — because it asks for a dfn?
3:02 PM
but why is ⌊/⍬ not ⍬
because reduction identity element
@KamilaSzewczyk We're not strict about it for Quests. APL trains weren't a thing in 2013.
@KamilaSzewczyk ?
@Richard Shouldn't the sum of an empty list be 0?
3:03 PM
I should think also ⍬
@Richard from a functional programming perspective, when you have a fold over array A, it returns the same value as the fold over array id(f) : A if f is a monoid

im sorry... what...
in simple words: if you append the identity value to the array, you ideally get the same result as if you didn't
@BrianBED It's just an arbitrary way to get infinity. /shrug
@Richard that'd be the only case when the minimum of a numeric array isn't a number, which'd be very weird
3:04 PM
@BrianBED Maximum representable value. The only value which would preserve the other argument when used with
it's not really arbitrary
ok thanks
@Adám my answer: (⌈/⌈⌿)-(⌊/⌊⌿)
Another way to say it is that an identity value I is such that X ≡ I f X and/or X ≡ X f I for any array X.
3:05 PM
seems needlessly complicated, and fails for ⍳0.
@PyGamer0 Fails on rank-3 arrays.
i know "_"
but passed the cases on the problems.tryapl
@PyGamer0 You could do ⌈/⍣≡-⌊/⍣≡ to handle all ranks.
@PyGamer0 Huh, then the reference solution might be wrong.
hm does that apply ⌈/ repeatedly until the depth is 0?
@Adám i considered it but , seemed simpler
3:07 PM
@PyGamer0 Well, until no more changes.
@KamilaSzewczyk Sure. ⍣≡ might be faster though, for large high-rank arrays.
it's tempting to check it
Go for it.
so the failure on ⍬ comes from going out of range of ⎕FR 645?
shouldn't monadic , be very fast since it just queries the underlying ravel?
@KamilaSzewczyk It has to copy the array.
So it is only fast when done in-place, i.e. when ref-count is 1.
3:10 PM
doesn't the ⍣≡ solution require copying the array too
OK, so the reference solution is… suboptimal.
@KamilaSzewczyk No, how so?
@KamilaSzewczyk it creates a new array, but that new array may (or may not) be smaller than the argument
whereas for , the argument and result are always the same size
      ]runtime -c +/,a +/⍣≡a

  +/,a  → 2.6E¯3 |   0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
  +/⍣≡a → 5.7E¯4 | -78% ⎕⎕⎕⎕⎕⎕⎕⎕⎕
@Adám what should empty return?
⎕←{0::{rng←(⌊/,⌈/)⍵ ⋄ ⎕FR←1287 ⋄ -/rng}⍵ ⋄ (⌈/-⌊/)⍵}⍬
3:11 PM
@BrianBED 0
@RikedyP 3.59538627E308
@Adám alr cool
      v←,8 23 3 10 7 2⍴70000⍴1000
      cmpx 'f1 v' 'f2 v'
  f1 v → 2.8E¯6 |  0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
  f2 v → 2.6E¯6 | -7% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
  ⌈/ ⍣≡ -  ⌊/ ⍣≡
  ⌈/ - ⌊/  ,
as expected
3:12 PM
Uh, v is a vector.
oh wait oops stray comma
@dzaima Right, because you force a full copy.
      v←8 23 3 10 7 2⍴?70000⍴1000
      cmpx 'f1 v' 'f2 v'
  f1 v → 1.9E¯4 |   0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
  f2 v → 7.8E¯6 | -96% ⎕⎕
okay, now that's more like it
@KamilaSzewczyk (Why 70000⍴?)
because it's approximately ×/8 23 3 10 7 2
i wanted to fill the array with random data
3:14 PM
now maybe wierd... but works?
@KamilaSzewczyk well you forgot the ?
Seems that +/, is faster for integers, and +/⍣≡ is faster for floats, unless the shape is adversarial.
wait, my solution gives the wrong thing for empties, but the site doesn't check that?
i'm being sloppy today
3:15 PM
@BrianBED honestly not sure there's a better encoding
but i'm right
@BrianBED That's sensible enough.
      v←8 23 3 10 7 2⍴.5×?70000⍴1000
      cmpx 'f1 v' 'f2 v'
  f1 v → 1.8E¯4 |   0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
  f2 v → 4.3E¯5 | -76% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
if we create some floats here and there they get a bit closer
i tried .33333×, etc... and the results are similar
@KamilaSzewczyk They are all floats there.
are they?
maybe according to internal representation.
3:17 PM
If any element of a flat array is a float, all are.
anyway the ravel is faster as expected
⌈/⍣≡0,0⍪,∘.-, :/ not great
my python friend's participating:
f = lambda x: (max(x)-min(x)) if x else 0
@rak1507 Yay, O(n²)
yep lol
3:19 PM
The reference solution isn't actually bad, but someone forgot to use (or any other empty array) as test case. Oops. Will fix.
My take on it: (⊢/-⊣/){⍵[⍋⍵]}⍤,
did you just sort the array o_o
Wait, I have an idea!
@PyGamer0 true true, i forgot it also applies to python
3:21 PM
@Adám would this work? (⊃⍤⌽-⊃){⍵[⍋⍵]}⍤,
@PyGamer0 D'uh, that works. Mine doesn't.
Alternative: (⌈/-⌊/)⊢⍴⍨1⌈×/⍤⍴
BrianBED's {⍵≡⍬:0⋄(⌈/-⌊/),⍵} is clearer, though.
{⎕div←1 ⋄ (+/÷≢)((⌈/=⊢)⊢⍤/⊢),∘.-⍨⍵}
Another O(n²).
{⍵≡⍬:0 ⋄ (⌈/-⌊/)∊⍵}2 2⍴1 2 (3 4)
i use ∊ instead of ",". that makes sense right or na?
3:24 PM
That would make it work on nested arrays, so yes.
great yea thought it was good
A slightly worse sorting based one:
3:27 PM
@ovs Ugh.
@Adám hm, it's possible to utilize ⎕div←1 without being O(n^2): {⎕DIV←1 ⋄ o←{(⍵=⍺⍺/⍵)/⍵} ⋄ (+/÷≢) (⌈o - ⌊o) ,⍵}
It fails for empty arrays though
@ovs Can be shortened to +/2-/{⍵[⍒⍵]}⍤,
@dzaima Oh, good point; the avg is always within the range.
k: {(|/x)-(&/x)} ... i think this is semi valid (as in passes some cases)
Fails on high-rank (i.e. for K, nested) arguments.
3:30 PM
wait {(|/,x)-(&/,x)}
does that work
@PyGamer0 Monadic , is like ,⊂ in APL. You want ,// I think.
array languages are neat
@PyGamer0 What does it give on the empty list? 2?
Any other solutions?
i wanna do a funny one but i can't think of one
Does 0 = f ⍬ really makes sense? The empty set has no minimum/maximum, and if we consider infimum/supremum the difference should be -∞.
3:36 PM
I also used outer product ∘.> - ∘.<
But is just cumbersome
@ovs No it doesn't, but that's what the customer wants, so ¯\_(⍨)_/¯
very random question. is monadic ∊ a recursive operator?
It is a function.
the reason i ask is because my python friend can't replicate it on lists without recursion
@BrianBED And while it could be implemented recursively, I think it just traverses the array.
3:38 PM
like.... best he has is like 5 lines to flaten a nested list
@Adám ah alright
Out of suggestions...
Monadic is almost equivalent to {r←⍬ ⋄ r⊣{0=≡⍵:r,←⍵ ⋄ ∇¨⍵}⍵}
OK, I think that's enough for this week then. See you next week for Float Your Boat!
I'm probably not able to join next week. If I constructed something genius I'll let you know before ;)
4:03 PM
f 0N     / @Adám
wait 0N is integer null
returns: (,{(|/,//x)-(&/,//x)})!,0 ...
1 hour later…
5:21 PM
@Adám can you explain to me why there are 2 commas there?
solves nesting
5:34 PM
i don't understand why ∊ is infront of the comma not behind though
or well... behind wouldn't make sense either
6:10 PM
another sorting solution


« first day (1871 days earlier)      last day (206 days later) »