« first day (455 days earlier)      last day (567 days later) » 

1:37 AM
n¨ must be n×=⍨
 
 
5 hours later…
6:14 AM
@FrownyFrog Almost. It is {n}¨. The difference is that if A←(3 4)(5 6 7) then 2¨A gives 2 2 and not (2 2)(2 2 2). The latter would be the result of (2⍥0)A.
 
ngn
6:38 AM
@Adám - the "under" operator?
 
@ngn Yes, but a really fancy one I came up with.
 
ngn
@Adám have mercy on the implementers :)
 
@Adám something that I would like to see with under, is the ability to do f⍢, and have it reshape the data to it's original shape, although this is does not follow from the definition of under that I know
 
@H.PWiz However, that is exactly the enhancement I came up with:
Try it online:
https://tio.run/##fVM9j9NAEO39KwZR2JbAIuajsERhAUJIkAbxA/actbPg7Fq7a1AUpUEo4gw@cQUdFOToqdxEooF/sn8kzPojvsCJlW1Z45k3770ZkyK/OVuSXGT7Pfz@YjafVmDqr/CCz6gEErwKSAAPS5I7YA9@CiE0p9/M2efpA7M5d029c8E@7UuE4edPHk/jp6Z667mPpi6Evuc@o0qRjGJeLCVZQk5TDURm5YJyDYngac4SreAN03OMH1JEQSXhM9cfmu8sP1M3YD68g67nGgZiwIWNRVAQpUDPpSiz@VDZ2BuvFYzH1rS5jIOQLGOc5DbNOWTE2A8hAf6qWogZSxk5yWlHd6yYTKIoNtWF53X0/NhvMZq2TmlZJrqU2Ifx11QqJrA1ByqlkEEQOJe67MzptsMw9cWvH5Nebyvx2vUWDiuQOLAU2AKtSmmie1x6jDRgmGprqVyWouUSJ7AoSk00sjkw6xHWXuebhfE7qNWxF13wBpyUOjruirqrLVxx/j8se8L77YKNe1XvekPRW0RFKt9v9WosGlrQDiJCPZTgcilQCcmJhJQfkRpd
@ngn No, Dyalog's (and APL's, I think) philosophy is exactly the opposite: Let the language implementers do the hard work so the end-programmer can write simple code.
 
6:55 AM
I can't look at right now. I'm on the bus, but I'll check it out later
 
ngn
7:42 AM
@Adám simple is good, throughout the stack
 
@ngn The concepts have to be simple, the implementation not.
 
8:43 AM
TIOBot logged in!
 
9:03 AM
TIOBot logged in!
 
@z3r0 Welcome. Interested in learning APL?
 
I'm always interested in learning new languages
However, my knowledge about these codegolfing languages are close to null
Up until now, I just read the PPCG pages without understanding much...
 
@z3r0 Apparently, because APL isn't a golfing language; it is a commercial production language. ;-)
 
Oh, ok
 
@z3r0 People on PPCG golf using both dedicated golfing languages and regular programming languages.
@z3r0 However, of mainstream programming languages, APL is almost always the one that requires the least coding (in both hours and characters) to get the job done.
 
9:09 AM
Sorry, I'm a bit lost with all the programming languages available and used around here :|
Where does one get started with APL ?
 
@z3r0 For example right here in this chat room. Do you want a quick intro to the basic tenets of APL?
 
Yes please
 
@z3r0 OK. APL is a bit different than most programming languages. In fact, it descends from traditional mathematical notation rather than from some older programming languages. The main ideas of mathematics (especially linear algebra) were taken, linearised (i.e. to fit on a single line without formatting), and generalised, until a programming language emerged. Hence the name APL
@z3r0 So, there are two basic ideas in APL: The array and the function.
All data resides in arrays, which are rectangular (as in orthogonal) structures with 0 or more dimensions. E.g. a simple scalar number is a 0D array, which in APL lingo usually is called a rank-0 array. A list (or vector) is a rank-1 array. A matrix is rank-2, etc.
APL has no strings, rather characters are simple scalars, and character vector is the closest you'll get to a string. This makes it extremely easy to manipulate the contents.
 
Is the char[] analogy correct ?
 
@z3r0 Well, being interpreted and completely dynamic, APL doesn't have declarations. You just literally provide the data and assign it to a name, and the system takes care of the rest. APL's assignment uses the symbol (so that = can be comparison) e.g.: mystring←'hello world'.
 
9:32 AM
So there are no actual variable types as those are determined automatically, right ?
 
@z3r0 APL functions behave much like - in mathematics. They can either be infix like 5-2 or prefix like -3. APL has a whole bunch of such symbols, and the user can use those to define his own. User defined functions behave in exactly the same way as the built in ones (so called "primitive" functions), i.e. they can be infix or prefix or both.
@z3r0 Right, there's just one variable type, which is the array. The data of the array can be numbers or characters or a mixture (and some other rarer stuff you don't have to worry about for now). Well, maybe I should mention that arrays can also contain arrays, ad infinitum.
@z3r0 And now I think you're ready to look at the transcripts of my previous lessons. I have held weekly lessons during the last half year. I may hold one again tonight if we can find a suitable subject.
 
Thanks for your presentation. I'll look into your lessons
As for tonight, I hope I'll be here but nothing is less certain
 
@z3r0 Great! If I hold a lesson and you miss it, you can always find the transcript there. Also, feel free to ping me in here any time to ask questions. I'm always happy to help.
 
Data at your fingertips i use to say :-)
 
@Stormwind Isn't it more like "data manipulation at your fingertips"?
 
9:43 AM
uuuh Adám, what? Mapunilat... my head :-). Use short words!
But seriously, short story is that it's so extremely fast & easy to set up some advanced math on a piece of data. Fits the visual mind (among others)!
 
@Stormwind f@(tips⊃fingers)⊢data
 
Btw i benchmarked indexing vs. pick yesterday, for single elements only, like a[4] vs. 4⊃a and found (when going to multimillion elements data) that pick is slightly faster.
So i walked through code and changed a number of places.
Greed :-)
 
@Stormwind But they don't do the same thing (if a is nested). You should compare a[4] to 4⌷a.
 
10:01 AM
@Adám i did, pick was faster
well fastest of the tree. No nesting, just simple vectors
 
@Stormwind What order of magnitude was the difference?
 
Minor. Count to to 9 vs count to 10
(not scientificly as you hear)
noticeable though
 
ngn
@Stormwind do you use 400⌶ (Jay's compiler) in the simulator?
 
Nah, waiting to look at that side
Should boost a lot
Like: ⍴{4⊃⍵}¨45000000⍴⊂1 2 3 4 5
 
ngn
@Stormwind yep, non-vectorised code should benefit the most from bytecode
 
10:07 AM
vs. ⍴{⍵[4]}¨45000000⍴⊂1 2 3 4 5
ya
I have talked for an option to hard-type variables inside a function. For a long time, but i understand there's not a big will to do that.
To skip APL's data type resolution in the interpreter. Instead ask me (with a fn header declaration or likewise)
AND JohnD has claimed it wouldn't get much faster... which otoh sounds reasonable.
foo;a;b;bool[11];c[323];d
 
ngn
@Stormwind I tend to agree. You will only skip a test of the array's type (which doesn't matter because the header is right before the data and that memory page is already in cache) and a jump (which would only save you anything if Dyalog's C code has a separate type-specific function to handle that particular type).
 
Maybe, maybe. But also to note is that i mostly work on small data (thought being that the cost of type-check grows in relation to cost of execution of data)
Also, a fair part of the data is persistent, from cycle to cycle (globals). So the type check happens repeatedly, where a single time (or a declaration) would do?
 
Adám has added an event to this room's schedule.
 
10:23 AM
@Stormwind Marshall has been arguing for setting some info flags about arrays so that certain properties wouldn't need re-evaluation until the array is changed. E.g. {A⍳⍵}¨ would benefit from remembering that A is sorted.
 
That is absolutely the right way to think! Flags, mark as dirty, etc.
 
ngn
It's hard to reason about performance. Sometimes a simple linear traversal can be faster than binary search, because of prefetching.
The best bet is to keep all the data as close together as possible - prevent unnecessary cache misses and page faults, to access it in predictable patterns - make use of prefetch, and to work on unitype arrays - make use of the cpu's vector instructions.
 
Ya. Though that's pretty much out of hands in APL, as it's way too smart in managing all that itself.
For one thing i've often wondered if the number of variables affects execution speed.
Ie. single variables vs. data structure dilemma. Is finding the single variable n memory faster that (more easily) finding one only, and then indexing inside that one?
*than
Seems Dyalog finds it's variables pretty fast :-)
 
ngn
10:42 AM
@Stormwind Adam might be able to confirm or deny this: iirc, it normally searches through a stack of "shadow blocks" to resolve a name. With 400⌶ it's different: local variables are converted to indices, so lookup is faster.
 
11:14 AM
"Normal" usage of variables is O(1). There is no run-time searching of stacks or symbol tables or anything like that. Cases that might go slower include:
- referring to a variable via a character vector containing its name, e.g. ⎕NC'foo'. This has to search a symbol table.
- using the same name in different namespaces, e.g. referring to both ns1.foo and ns2.foo. The last namespace a name was seen in is cached; on a cache miss we have to search a symbol table. This also applies to OO-heavy code, which almost inevitably switches into different namespaces all over the place.
 
Ok, nice to get insight!
I have also found that it pays off a lot to ⎕CS, when one works on multiple different namespaces
Trying to minimise the refences to other spaces:
⎕CS #.VESSEL.myNS
fuel-←a←tankloss×#.SYS.T∆ ⍝ Tank loss
fuel⌈←0
FUEL+←a×fuel≠0
#.GUI.valStatus[4 6]←fuel,FUEL ⍝ Status: Fuel amount
HOURS+←#.SYS.T∆

⎕CS #.VESSEL
Nevertheless, there is always things elsewhere
 
@Stormwind You should probably ping when responding to a user that isn't around much (click the on the right of his message, or type @j in front of yours).
 
ngn
Thanks for intervening! So, my memory is failing.
In this example: a←1⋄{⎕←a⋄a←2⋄⎕←a}0
how does it know that the first "a" in the dfn is global and the last is local?
 
@Adám ya. Lazy oldtme chat idler. He'll see it at the end of the day or next week :)
 
@ngn I doesn't "know". symbol← does a ⎕SHADOW 'symbol' before assignment.
@Stormwind No, he won't, because by then the message has been move to the transcript (out of sight), and he will get no indication that a message was directed to him. If you ping, he will get a notification now or next time he's around.
 
11:27 AM
@JayFoad wake up, it's tea time!
Occasionally i find the need to assign something from inside a dfn. Have to use the full namespace path in that case.
(ie not over the dfn result)
 
@Stormwind If the variable already exists, you can use var⊢←newval.
 
hmok @Adám must check that, thx
 
@Stormwind If it doesn't exist, you can abuse a bug: var∘←newval. (But be warned that that is not officially supported, as it doesn't follow APL syntax.)
 
Hmm looks useful @Adám
 
ngn
11:44 AM
@Stormwind ten years later: "we can't fix it, important apps are relying on it!" :)
 
hehe
 
@ngn That's already the case. The official method is ⍎'var←newval' which is horrible, imho.
 
ngn
12:26 PM
@Adám in k they worked around that by always executing it in the global context
 
@ngn So assignments inside functions are global assignments?
 
ngn
correct
{a:1; ."a:2"; a}[] / returns 1
 
@ngn Can you access global values from inside a function?
 
ngn
@Adám yes - you have access to locals and globals, but not semi-globals
 
@ngn What does a:1;{."a:2"; a}[] give?
 
ngn
12:30 PM
@Adám I think it should return 2
 
@ngn So an assignment inside a function shadows that symbol?
 
ngn
@Adám I don't have an actual k interpreter (other than my own, kona, and oK)
 
@ngn I do. Hang on.
 
ngn
@Adám . executes in the global context, so it modifies the global "a"
 
@ngn Yes it does. Looks like it effectively behaves much like Dyalog (except the semi-global part).
 
ngn
12:32 PM
@Adám er... I'm not sure that example proves that.
 
@ValentinR. Welcome. Interested in learning APL?
 
ngn
1:04 PM
note the difference:
a←1⋄{a←2⋄_←⍎'a←3'⋄a}0 ⍝ returns 3
a:1;{a:2;."a:3";a}0 / returns 2
 
 
2 hours later…
2:48 PM
Roger explores dyadic grade, from the simplest cases to the general case, in his latest blog post at https://www.dyalog.com/blog/2018/04/dyadic-grade/
 
3:21 PM
#tio alias view
 
@Adám
Command Aliases:
⍞← -> #TIO do apl-dyalog ⎕←%args%
⎕← -> #TIO run apl-dyalog (⎕NS⍬).⍎'⎕CY''salt''⋄⎕SE.UCMD''box on -fns=on''⊣enableSALT'⋄⎕←%args%

Language Aliases:
apl-dyalog -> [apl]

Message Aliases:
 
#tio alias command ⍞← #TIO do apl-dyalog {0::⎕←⊃⎕DM⋄⎕←%args%}⍬
 
@Adám Added alias for ⍞←
 
#tio alias command ⎕← #TIO apl {0::⎕←⊃⎕DM⋄⎕←%args%}(⎕NS⍬).⍎'⎕CY''salt''⋄⎕SE.UCMD''←box on -f=on -t=tree''⊣enableSALT⋄⍬'
 
@Adám Added alias for ⎕←
 
3:23 PM
#tio alias ⋄ #TIO apl {0::⎕←⊃⎕DM⋄%args%}(⎕NS⍬).⍎'⎕CY''salt''⋄⎕SE.UCMD''←box on -f=on -t=tree''⊣enableSALT⋄⍬'
 
@Adám No alias type called "⋄"
 
#tio alias command ] #TIO apl {0::⎕←⊃⎕DM⋄⎕←⎕SE.UCMD'%args%'}(⎕NS⍬).⍎'⎕CY''salt''⋄⎕SE.UCMD''←box on -f=on -t=tree''⊣enableSALT⋄⍬'
 
@Adám Added alias for ]
 
#tio alias command ⋄ #TIO apl {0::⎕←⊃⎕DM⋄%args%}(⎕NS⍬).⍎'⎕CY''salt''⋄⎕SE.UCMD''←box on -f=on -t=tree''⊣enableSALT⋄⍬'
 
@Adám Added alias for ⋄
 
3:24 PM
New features? :D
 
#tio alias message )help %handle% Dyalog APL Language Elements
 
@Adám Added alias for )help
 
@J.Sallé and ] are new, but the bot was moved to a new server, so I have to set it up again because it has a bug that makes it forget settings when rebooted.
#tio alias message )ref %handle% Dyalog APL Reference Card
 
@Adám Added alias for )ref
 
Ah, I see
 
3:26 PM
#tio alias message )about %handle% You can evaluate a single line of APL by typing it into chat prefixed by ⍞←. Use ⎕← instead for boxed display and multi-line results and use ⋄ instead to silence the first statement Use ] to call user commands. Do not use markdown, but fixed-width (4 initial spaces) is fine. Commands: )lb for language bar, )help for table of language elements, )docs for full documentation, )ref for PDF reference card, )idioms for idiom list.
 
@Adám Added alias for )about
 
#tio alias message )lb %handle% ← +-×÷*⍟⌹○!? |⌈⌊⊥⊤⊣⊢ =≠≤<>≥≡≢ ∨∧⍲⍱ ↑↓⊂⊃⊆⌷⍋⍒ ⍳⍸∊⍷∪∩~ /\⌿⍀ ,⍪⍴⌽⊖⍉ ¨⍨⍣.∘⍤@ ⍞⎕⍠⌸⌺⌶⍎⍕ ⋄⍝→⍵⍺∇& ¯⍬∆⍙Install…
 
@Adám Added alias for )lb
 
#tio alias )docs %handle% Dyalog APL Documentation
 
@Adám No alias type called ")docs"
 
3:27 PM
#tio alias message )idioms %handle% Dyalog APL Idiom List
 
@Adám Added alias for )idioms
 
#tio alias view
 
@Adám
Command Aliases:
⍞← -> #TIO do apl-dyalog {0::⎕←⊃⎕DM⋄⎕←%args%}⍬
⎕← -> #TIO apl {0::⎕←⊃⎕DM⋄⎕←%args%}(⎕NS⍬).⍎'⎕CY''salt''⋄⎕SE.UCMD''←box on -f=on -t=tree''⊣enableSALT⋄⍬'
] -> #TIO apl {0::⎕←⊃⎕DM⋄⎕←⎕SE.UCMD'%args%'}(⎕NS⍬).⍎'⎕CY''salt''⋄⎕SE.UCMD''←box on -f=on -t=tree''⊣enableSALT⋄⍬'
⋄ -> #TIO apl {0::⎕←⊃⎕DM⋄%args%}(⎕NS⍬).⍎'⎕CY''salt''⋄⎕SE.UCMD''←box on -f=on -t=tree''⊣enableSALT⋄⍬'

Language Aliases:
apl-dyalog -> [apl]

Message Aliases:
)help -> %handle% [Dyalog APL Language Elements](help.dyalog.com/16.0/Content/Language/Introduction/…)
 
⍞←'Hello!'
 
@Adám Hello!
 
3:29 PM
⎕←⍳2 3
 
@Adám
┌───┬───┬───┐
│1 1│1 2│1 3│
├───┼───┼───┤
│2 1│2 2│2 3│
└───┴───┴───┘
 
]version -e
 
@Adám
 Dyalog  16.0.31812 64-bit Unicode, BuildID 5b887e36
 OS      Linux 4.15.13-300.fc27.x86_64 #1 SMP Mon Mar 26 19:06:57 UTC 2018 x86_64
 SALT    2.701
 UCMD    2.2
 .NET    (unavailable)
 WS      16.0
 Conga   (unavailable)
 SQAPL   loaded from: cxdya63u64v.so
         Version=SQAPL/PE version 6.3.28200  built Aug 23 2016 13:34:32
         IniFile=SQAPL.INI
 
)help
 
3:30 PM
)ref
 
)about
 
@Adám You can evaluate a single line of APL by typing it into chat prefixed by ⍞←. Use ⎕← instead for boxed display and multi-line results and use ⋄ instead to silence the first statement Use ] to call user commands. Do not use markdown, but fixed-width (4 initial spaces) is fine. Commands: )lb for language bar, )help for table of language elements, )docs for full documentation, )ref for PDF reference card, )idioms for idiom list.
 
#tio alias message )about %handle% You can evaluate a single line of APL by typing it into chat prefixed by ⍞←. Use ⎕← instead for boxed display and multi-line results and use ⋄ instead to silence the first statement. Use ] to call user commands. Do not use markdown, but fixed-width (4 initial spaces) is fine. Commands: )lb for language bar, )help for table of language elements, )docs for full documentation, )ref for PDF reference card, )idioms for idiom list.
 
@Adám Added alias for )about
 
3:32 PM
)lb
 
@Adám ← +-×÷*⍟⌹○!? |⌈⌊⊥⊤⊣⊢ =≠≤<>≥≡≢ ∨∧⍲⍱ ↑↓⊂⊃⊆⌷⍋⍒ ⍳⍸∊⍷∪∩~ /\⌿⍀ ,⍪⍴⌽⊖⍉ ¨⍨⍣.∘⍤@ ⍞⎕⍠⌸⌺⌶⍎⍕ ⋄⍝→⍵⍺∇& ¯⍬∆⍙Install…
 
)idioms
 
@J.Sallé I can't wait for TIO to move to 17.0. Then you'll be able to get help for with ]help ⍣, even here in the chat room.
 
@Adám Oooooh, I'd spam the heck out of ]help
 
3:39 PM
@J.Sallé It won't really give you much more than pressing F1 with the cursor on something. However, it is useful for non-GUI interfaces like the bot, TIO, those using the terminal interface on Linux. It does give you help for errors (e.g. ]help index error) and user commands (e.g ]help ]settings), which F1 won't.
 
@Adám hm, has it been released yet? there's no indication of the latest version over dyalog.com...
 
@EriktheOutgolfer I think this indicates the newest available version pretty clearly:
 
@Adám ah, didn't scroll down enough as it seems...
tbf apparently I'm a little bit more sloppy today...
 
 
1 hour later…
4:52 PM
@Adám did I-Beam really exist in APL\360? can't find it in the spec
although I can apparently type
 
@EriktheOutgolfer Yes it does, I just tried.
 
@Adám :( there are no docs to it then
 
@EriktheOutgolfer Kind of like today's i-beams… Have you looked here?
 
@Adám btw were they called "I-Beams" back then?
yeah I did find that on Google, but upon further inspection it appears that "APL\360-OS" and "APL\360-DOS" aren't the same thing as "APL\360", but I suppose that if it works for IBM OS and (IBM PC/?)DOS it works for typewriter too right?
 
@EriktheOutgolfer Yes. For the pun: I-Beam, and sounds like IBM.
 
5:04 PM
@Adám got the pun, but, at least for me, it doesn't sound like that (Eye-bee-em)
 
@EriktheOutgolfer It has nothing to do with the input mechanism. And DOS is not that of the PC (PC-DOS).
 
@Adám hm, looks like "I-Beam" doesn't find anything when searching through the PDF
I did find where the operators (called "composite functions" back then) are mentioned, but ⌶ is nowhere to be found...
and it's not very convenient to label the pages as chapter.number instead of just a single number
 
@EriktheOutgolfer I think that was necessary so that if they had to re-type some of the text and it would use more or less pages, it wouldn't invalidate pagination on all following already typed pages.
 
5:26 PM
\o/ what will today's lesson be? More multithreading?
 
Welcome to APL Cultivation!
Today, we'll have a look at a very old (and famous) programming problem in the APL world.
(That is, unless someone has a better idea…)
Consider two vectors, e.g. L←'abacba' ⋄ R←'baabaac'.
By now, you should know about dyadic :
⋄ L←'abacba' ⋄ R←'baabaac' ⋄ L⍳R
 
@Adám

Rebuilding user command cache... done

Real time: 1.044 s
User time: 0.987 s
Sys. time: 0.048 s
CPU share: 99.11 %
Exit code: 0
 
⋄ L←'abacba' ⋄ R←'baabaac' ⋄ ⍞←L⍳R
 
@Adám

Rebuilding user command cache... done
2 1 1 2 1 1 4

Real time: 0.988 s
User time: 0.879 s
Sys. time: 0.082 s
CPU share: 97.23 %
Exit code: 0
 
⋄ L←'abacba' ⋄ R←'baabaac' ⋄ ⎕←L⍳R
 
5:33 PM
@Adám
2 1 1 2 1 1 4
 
(Sorry about that noise.)
 
Dyalog bot has a mind of its own, we're used to it
 
But that finds first location in L of each element in R.
However, what if we wanted the first b in R to "consume" the first b in L so that the second b in R would have to contend with the index of the second b in L`?
That is, we want some function which gives 2 1 3 5 6 7 4.
You could call it "iota without replacement".
 
I assume we need some form of recursion?
 
@J.Sallé Oh no, no looping!
 
5:37 PM
D:
 
Let's do it the APL way.
 
Sounds good
 
Let's begin by labelling the elements so we can see what goes where:
⍞←'a1' 'b1' 'a2' 'c1' 'b2' 'a3' ⍳ 'b1' 'a1' 'a2' 'b2' 'a3' 'a4' 'c1'
 
@Adám 2 1 3 5 6 7 4
 
@Adám Okay, so we need a way to "label" the elements?
 
5:40 PM
@J.Sallé Yes, exactly.
 
without actually labeling them, if that makes any sense
 
So, because we numbered the as (which otherwise all match each other) and the bs, the right pairs get matched up.
So if you remember the lesson about , you may recall what ⍋⍋ does.
While gives use the indices that will sort, ⍋⍋ gives us the positions that each element will occupy in the sorted result.
⎕←↑ L(L⍳L)(⍋⍋L⍳L) ⊣ L←'abacba'
 
@Adám
a b a c b a
1 2 1 4 2 1
1 4 2 6 5 3
 
The first line is the data and the second is the indices of the first occurrences (i.e. all identical items will get the same index). The third line is the position that each will occupy when sorted. That means that identical elements get consecutive positions.
E.g. you can see that the first b gets 4 (because there are 3 as) and the second gets 5.
This almost solves the problem.
However, there are a couple of issues:
1. The two arrays must have the same set of elements.
2. The two arrays must have equally many of each unique element
3. The unique elements must initially occur in the same order
Why these conditions?
1. is because otherwise the purely numeric "labels" will match the wrong things.
2. is because otherwise one element's "label" will be paired up the the label of a different value element of the other array.
3. is because otherwise identical "labels" numbers refer to two entirely different things, and so the matching won't give a meaningful result.
But if these conditions are met, we get the right result:
⋄ L←'abacba' ⋄ R←'aaabcb' ⋄ ⎕←(⍋⍋L⍳L)⍳⍋⍋R⍳R
 
@Adám
1 3 6 2 4 5
 
5:55 PM
The first a in R gets paired with the element in position 1 of L, and the second a in R goes with the element in position 3, and the third goes with the last element of L.
@all Clear so far?
 
Yes
 
OK, let's have a stab at how we can ensure that all conditions are eliminated, and then we'll have our solution.
Since we're going to look up elements of R in L anyway, we can use indices into L (that is L⍳R) instead of the lookup of R into itself (R⍳R) This ensures that elements of R are labelled with "L's labelling system".
⋄ L←'abacba' ⋄ R←'bcabaa' ⋄ ⎕←↑L(L⍳L)(⍋⍋L⍳L) ⋄ ⎕←↑R(L⍳R)(⍋⍋L⍳R)
⋄ L←'abacba' ⋄ R←'bcabaa' ⋄ ⎕←↑L(L⍳L)(⍋⍋L⍳L) ⋄ ⎕←↑R(L⍳R)(⍋⍋L⍳R)
⎕←0 0⍴L←'abacba' ⋄ R←'bcabaa' ⋄ ⎕←↑L(L⍳L)(⍋⍋L⍳L) ⋄ ⎕←↑R(L⍳R)(⍋⍋L⍳R)
 
@Adám
a b a c b a
1 2 1 4 2 1
1 4 2 6 5 3
b c a b a a
2 4 1 2 1 1
4 6 1 5 2 3
 
@DyalogAPL I warn you!
You need to read the first three lines and the last three lines separately.
The first line (of each group) is the data, the second line is the first-positions of that data in L. The third is the progressive labelling of that.
No you can see that the first a is labelled 1 for both L and R and the first b is labelled 4 for both L and R.
⎕←0 0⍴L←'abacba' ⋄ R←'bcabaa' ⋄ ⎕←(⍋⍋L⍳L)⍳(⍋⍋L⍳R)
 
@Adám
2 4 1 5 3 6
 
6:07 PM
And so we have that the first b of R takes out element 2 of L, and the c takes out element 4 of L and so on.
But this still requires both sides to have the same set of elements and equally many of each element.
How can we ensure that there are equally many of each unique element on each side?
 
?
Nope
 
Well, if you think about it, L,R and R,L must necessarily have the same set in equal proportions.
 
⍴eshape and unique?
 
But of course this also gives us way more elements than we need. We'll take care of that later.
@J.Sallé Yes, reshape, but we don't want unique, since we need to preserve duplicates. But we're getting ahead of ourselves.
⎕←0 0⍴L←'abacba' ⋄ R←'bcabaa' ⋄ ⎕←(⍋⍋L⍳L,R)⍳(⍋⍋L⍳R,L)
 
@Adám
2 4 1 5 3 6 9 7 11 8 10 12
 
6:16 PM
Notice that this sequence begins with what we want, and now we have equal proportions, so we've eliminated issue 2. We just need to reshape (or take) to chop the unneeded elements:
⎕← ((⍴L)⍴⍋⍋L⍳L,R)⍳((⍴R)⍴⍋⍋L⍳R,L) ⊣ (L R)←'abacba' 'bcdabaa'
 
@Adám
2 4 7 1 5 3 6
 
So many parenthesis though, looks like something I'd code in apl :p
 
Now it works even though we have a d in R which doesn't occur in L. In accordance with the rules of , not-found elements get the index 1+the last index of the left argument. Since we chopped the left list of labels to the length of L, that's what we get.
 
@Adám would it be the same index number if we had multiple elements that don't occur?
 
⎕← ((⍴L)⍴⍋⍋L⍳L,R)⍳((⍴R)⍴⍋⍋L⍳R,L) ⊣ (L R)←'abacba' 'bcdabaaaaa'
 
6:22 PM
@Adám
2 4 7 1 5 3 6 7 7 7
 
Okay, I thought as much
 
And so, we've taken care of issue 1 (different sets of elements).
 
One use case might be in a first-come, first-served queue... let's say you have First Class, Premium, and Economy seats on a plane. This algorithm will use them up in order as requests are processed
 
Btw, this algorithm can be adapted to use with any-rank arrays by using instead of monadic and instead of dyadic and instead of , .
Let's have a look back at what we did. Consider:
⎕←↑ (L R)←'abacba' 'baabaac'
 
@Adám
abacba
baabaac
 
6:31 PM
So we labelled the elements:
⎕←↑ ('a1' 'b8' 'a2' 'c12' 'b9' 'a3')('b8' 'a1' 'a2' 'b9' 'a3' 'a4' 'c12')
 
@Adám
┌──┬──┬──┬───┬──┬──┬───┐
│a1│b8│a2│c12│b9│a3│   │
├──┼──┼──┼───┼──┼──┼───┤
│b8│a1│a2│b9 │a3│a4│c12│
└──┴──┴──┴───┴──┴──┴───┘
 
And looked those labels up:
⍞←('a1' 'b8' 'a2' 'c12' 'b9' 'a3') ⍳ ('b8' 'a1' 'a2' 'b9' 'a3' 'a4' 'c12')
 
@Adám 2 1 3 5 6 7 4
 
But actually, we don't need the original values (the letters); the numeric labels are enough:
⍞←(1 8 2 12 9 3) ⍳ (8 1 2 9 3 4 12)
 
@Adám I have to go eat now, but I have a pretty nifty solution that I think is valid. I'll be back soon
 
6:34 PM
@Adám 2 1 3 5 6 7 4
 
@H.PWiz No worries!
And how did we get those labels?
⎕←↑ (L R)←'abacba' 'baabaac' ⋄ ⎕←(⍴L)⍴⍋⍋L⍳L,R ⋄ ⎕←(⍴R)⍴⍋⍋L⍳R,L
 
@Adám
abacba
baabaac
1 8 2 12 9 3
8 1 2 9 3 4 12
 
So now we can define our function:
⍞←'abacba' {((⍴⍺)⍴⍋⍋⍺⍳⍺,⍵)⍳(⍴⍵)⍴⍋⍋⍺⍳⍵,⍺} 'bcabaa'
 
@Adám 2 4 1 5 3 6
 
@Adám we called it ⍳ without replacement right?
 
6:40 PM
@J.Sallé Yes, or "progressive dyadic iota".
 
Sounds good
 
Now to take Brian's example of filling a plane with multiple classes, using first-come, first-serve, we may want to ask: For each customer, will he fit on the plane?
 
Well that depends on how many seats are available
 
So, say we have a plane like '11bbbpeepee' where 1 is first class, b is business, p is economy plus (extra legroom at emergency exits), and e is regular economy.
And we have a bunch of customers coming to buy seats: '1bbbpppeeeee'. That's one 1st class customer, three business people, three want more legroom, and a load of regular people.
⍞←'11bbbpeepee'  {((⍴⍺)⍴⍋⍋⍺⍳⍺,⍵)⍳(⍴⍵)⍴⍋⍋⍺⍳⍵,⍺} '1bbbpppeeeee'
 
@Adám 1 3 4 5 6 9 12 7 8 10 11 12
 
6:50 PM
Being that the plane only has 11 seats, we can see that one plus and one economy will not fit (indicated by the 12s), but we just want a Boolean, not the actual seating.
 
We can do result ∊(⍴ (or ≢)Result)?
 
So think about it. progressive dyadic iota (or iota without replacement) asks "For each element, where would it go in the remaining elements?" Now we need to ask "For each element, does it fit in (i.e. is it in) the remaining elements?"
@J.Sallé Good, yes, but we don't need to first calculate the indices.
 
I forgot a there also
Ah, I see
you wanna do that directly from the string
 
"is it in" is APL's . Just note that the arguments of and are "reversed" in that the array we look up in is on the left for and on the right for , so we just swap the parts of our function and substitute for the middle :
⍞←'11bbbpeepee'  {((⍴⍵)⍴⍋⍋⍺⍳⍵,⍺)∊((⍴⍺)⍴⍋⍋⍺⍳⍺,⍵)} '1bbbpppeeeee'
 
@Adám 1 1 1 1 1 1 0 1 1 1 1 0
 
6:54 PM
Alternatively, we could just call the function with swapped arguments:
⍞←'1bbbpppeeeee' {((⍴⍺)⍴⍋⍋⍺⍳⍺,⍵)∊(⍴⍵)⍴⍋⍋⍺⍳⍵,⍺} '11bbbpeepee'
 
@Adám 1 1 1 1 1 1 0 1 1 1 1 0
 
This function is "membership without replacement", or "progressive dyadic epsilon".
 
@Adám that would make more sense to me because I'd phrase it as "How many people would fit in this plane."
 
@J.Sallé Yup, that's why and have their arguments in the order they have.
Did you notice the pattern? We are taking two functions and modifying them in a consistent manner? This calls for an operator!
⎕←↑ (p c)←'11bbbpeepee' '1bbbpppeeeee' ⋄ WithoutReplacement←{((⍴⍺)⍴⍋⍋⍺⍳⍺,⍵)⍺⍺(⍴⍵)⍴⍋⍋⍺⍳⍵,⍺} ⋄ ⎕←'11bbbpeepee' ⍳WithoutReplacement '1bbbpppeeeee'
 
@Adám
11bbbpeepee
1bbbpppeeeee
1 3 4 5 6 9 12 7 8 10 11 12
 
6:59 PM
@DyalogAPL I'll assume that's not what we wanted :p
 
⎕←↑ (p c)←'11bbbpeepee' '1bbbpppeeeee' ⋄ WithoutReplacement←{((⍴⍺)⍴⍋⍋⍺⍳⍺,⍵)⍺⍺(⍴⍵)⍴⍋⍋⍺⍳⍵,⍺} ⋄ ⎕←'1bbbpppeeeee' ∊WithoutReplacement '11bbbpeepee'
 
@Adám
11bbbpeepee
1bbbpppeeeee
1 1 1 1 1 1 0 1 1 1 1 0
 
@J.Sallé Retroactively, it is ;-)
Notice how the APL code reads much like normal English.
And that's all for tonight. Thank you for participating!
 
@Adám (much huh?)
 
@Adám hah! Nice one!
@Adám thanks for the lesson!
 
7:02 PM
more looking like a few screams in there :P
 
@EriktheOutgolfer Will these customers be in, without replacement, this plane?
@EriktheOutgolfer In this plane, where, without replacement, will these passengers fit?
@EriktheOutgolfer What do you mean?
 
@Adám oh you seem to mean that it can be read aloud in english, but it certainly doesn't look like much english at a first glance
 
Where without replacement here means without seating two passengers on the same seat.
 
@Adám sure, I don't think an airline would benefit much from forcing two passengers to be hugging :P
 
@EriktheOutgolfer Yes, that's what I mean. APL code can very often be read aload like an English sentence by using for each primitive, an appropriate term for the context. A good rule of thumb is that if your statement doesn't read nicely as English, it is probably too long and should be broken up into separate statements using well-chosen variable names for the intermediate results.
@EriktheOutgolfer Well, you never no with today's low price airlines…
 
7:07 PM
@Adám low price airlines? never, all the bad reputation is on those!
 
ngn
@Adám unless it's on board United :)
 
@ngn there are many United airlines...
 
@Adám My solution was (1⍳⍨⍤1⊢∧+\=+⍀)∘.=⍨ Shorter but slower. If I think about it more, I think I can simplify it some more
 
ngn
@EriktheOutgolfer that one
 
7:44 PM
@H.PWiz That's very cool, but terribly inefficient.
 
@Adám Outer product tends to be
 
ngn
8:01 PM
vector programming in a nutshell:
 
8:56 PM
@EriktheOutgolfer Have you tried APL\360's Kingdom Simulator?
 
@Adám no, is it an I-beam?
 
@EriktheOutgolfer No, it is a computer game that ships with the install.
@EriktheOutgolfer What do you do with a spare quarter million dollar mainframe in the early seventies? Why, make a computer game, of course!
 
@Adám the only thing that is even remotely related to "king" in my installation is a Hercules conf file
btw that's "United Kingdom"
 
@EriktheOutgolfer Wait, your system can start, right?
 
@Adám of course, otherwise I wouldn't be able to talk...
 
9:01 PM
@EriktheOutgolfer Oh, you maybe you don't know how the ancient file system worked?
 
@Adám wait, the game is actually in an unrelated file? I searched for "king"...
 
@EriktheOutgolfer You can't see its files from outside the system, it is all inside the virtual machine.
 
@Adám should I assume that ⎕N... commands exist so that I can actually even see what's there?
 
@EriktheOutgolfer No, they didn't, but most )SystemCommands are present. However, the system is very different from what you're used to on a modern OS, so I'll help you a little. I can't remember, are you on Linux or Windows?
 
@Adám Windows (10)
yeah, there's lots of undocumented stuff in there...
 
9:06 PM
@EriktheOutgolfer OK, so they didn't have today's nested folder structure back then. Instead there was a numbered collection of tapes, and each tape could have one or more workspaces.
@EriktheOutgolfer You can list the workspaces of tape 3 with )LIB 3
@EriktheOutgolfer Then you load a specific workspace with e.g. )LOAD 3 EIGENVALUES
@EriktheOutgolfer Most workspaces contain a variable called HOW or DESCRIBE which will tell you about that workspace.
@EriktheOutgolfer The interesting workspaces are on tapes 1 to 6. Specifically, I was talking about 6 KINGDOM. Load it, and then enter EXPLAIN for an intro, and then START to launch the game. (When you load it, notice that the workspace was last updated in January '76…)
 
@Adám wow underlined letters
 
@EriktheOutgolfer Yes, and now you can see why Dyalog APL has them today; half a century of backwards compatibility!
 
@Adám more like APL333 and APL385 Unicode (the fonts), right?
 
@EriktheOutgolfer Yes, they map underscored letters to Unicode's circled letters, and those are valid in identifiers so that code like this can be ported properly.
I should totally "port" this game to Dyalog APL. It should run without modification.
 
@Adám by "port" you mean "discover where the source is hidden and manage to copy-paste it through that clunky PuTTY"? ;)
 
9:17 PM
@EriktheOutgolfer Wait, do you know how to list a function?
 
@Adám nah, haven't had time to read the entire spec yet :)
 
@EriktheOutgolfer Just enter ∇FUNCTION[⎕]∇, i.e. Gfunction;L'G on a modern US keyboard.
 
@Adám an error?
 
@EriktheOutgolfer What?
 
oh, FUNCTION is the function's name
(still an error)
 
9:20 PM
@EriktheOutgolfer Yes. It says ∇FUNCTION open FUNCTION in the editor, [⎕] list all lines close the editor.
 
@Adám wait has meanings depending on context? hm
ah now I get it
 
@EriktheOutgolfer Well, the editor uses commands inside [] which is unambiguous since APL statements can't begin with a [. E.g. [2] means edit line 2 and [∆5] means remove line 5.
 
@Adám that's...too vintage for me :P /s
 
@EriktheOutgolfer Didn't I link you the full docs for the editor? You can still use it in Dyalog APL, and it is actually still somewhat useful, as it allows you to paste multi-line functions into the session, just type (don't press enter) then paste, then type and press enter. Voila!
 
@Adám ah, I have real life stuff bothering me with school nowadays and I don't always have time to read everything (plus an English→Spanish course over Duolingo)
 
9:29 PM
@EriktheOutgolfer And if you get the ⎕VR of a function or copy from a namespace script (which has the s), you can just paste everything with s and line numbering, right into the session. The leading line numbers will tell the editor which line you want to edit, but since they are consecutive in a normal listing, it doesn't matter.
@EriktheOutgolfer I'm writing an APL program to translate the character set for me… In APL of course.
 

« first day (455 days earlier)      last day (567 days later) »