Re: [Factor-talk] maximum of a seq
Hi Alex, thanks, but I'm on Linux. Nice typo by the way, not sure what is the hotkey on Linus :) By clojure-like I meant what John linked, the persistent vocab. Clojure uses what is coined as functional data structures. It all started with Mr. Okasaki, if you search for "Okasaki functional data structures" you'll find a lot of content. A search like that revealed an SO link where many data structures not discussed in Okasaki's paper are linked: https://cstheory.stackexchange.com/questions/1539/whats-new-in-purely-functional-data-structures-since-okasaki -- Peter Nagy On 2018-12-11 21:35, Alexander Ilin wrote: > Hi, Peter! > >> Any reason why supremum-by and infimum-by are not on the "Searching >> sequences" doc page? If you agree I can add these together with supremum >> and infimum. > > A link in the help system would be useful, I think. I remember myself > discovering those functions by word of mouth, after having read the > documentation multiple times. It would have been nicer if I read about > them in the help. > >> I'll take a look at map-reduce, thanks. I switched from using the factor >> IDE REPL to emacs with Fuel because today I kept creating an infinite >> loop and couldn't break it for the life of me in the IDE. In emacs it >> was C-c C-c. Since I couldn't break it I didn't even know it's an >> infinite loop. That led me to open a file and save the definitions for >> debugging purposes, so I kind of broke my rules at this point. Oh well, >> at least I solved another "day" today, although I'm rather behind at >> this point, not enough time. > > If you work in Windows, there is experimental support for C-Break. > Here's how I enable it in my .factor-rc: > > ! Enable handling of the Ctrl-Break interrupt > USE: listener > t handle-ctrl-break set-global > > Only works on Windows, though. There is no such thing as a global > hotkey in Linus, AFAIK. > >> Another thing that tricked me: >> >> IN: aoc V{ 1 2 3 } 2 head-slice* 3 suffix! >array . >> { 1 } >> IN: aoc V{ 1 2 3 } rest-slice 3 suffix! >array . >> { 2 3 } >> >> Slices work differently than I expected :) Are there clojure-like data >> structures that are immutable and structurally share most of their >> content? > > Not sure about clojure-like. Arrays { } are immutable, while vectors > V{ } are mutable. > You can also have read-only TUPLE: members: > > TUPLE: hello-tuple > { var1 read-only } > { var2 string read-only } > ... > ; > > ---=--- > Александр > > > > ___ > Factor-talk mailing list > Factor-talk@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/factor-talk ___ Factor-talk mailing list Factor-talk@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/factor-talk
Re: [Factor-talk] maximum of a seq
Hi John, thanks for taking the time to answer, look through the code, write your own version and explain it. Your solution to reactions makes more sense, is simpler and doesn't copy. I also learned about new-resizable, like and with. And I like the use of ?last which simplifies the bounds check. Well, I'd expect supremum to go by something that starts with "max", if max is already for 2 objects than maybe maximum and maximum-by would be nice for a sequence. Either way having it in the docs for searching would have been enough for me to find the words. I'll take a look at the docs and hopefully whip up a pull request. -- Peter Nagy On 2018-12-11 22:25, John Benediktsson wrote: > Hi Peter, > > The performance difficulties in your solution arise from using > ``head*`` which makes a new sequence (allocations, copying into new > memory, etc.), rather than a lightweight slice which ``head-slice*`` > does. > > You are right that slices are not what you expect, you might find this > interesting: > > IN: scratchpad "abcdef" dup 3 head-slice CHAR: D suffix! > > --- Data stack: > "abcDef" > T{ slice f 0 3 "abcDef" } > > In-place operations like ``set-nth`` and variations like ``suffix!`` > operate on the underlying sequence. > > The Clojure-like data structures are in ``persistent`` vocabulary. > See, for example ``persistent.vectors``. > > Some of your words like ``upper`` are in the standard library > (``ch>upper``). Also, I found your version didn't remove the extra > newline in the input text, which resulted in an answer that was 1 too > large. > > This looked like a fun puzzle, and I like fun puzzles, so I thought > I'd implement it and maybe provide another solution which could help > with learning: > > USING: ascii fry kernel math sequences ; > > You can tell if two characters match for a possible reaction, if they > are not the same, but are when made to lowercase. I also really like > your subtract and absolute difference should equal 32 approach. > > : match? ( ch1 ch2 -- ? ) > > 2dup = [ 2drop f ] [ [ ch>lower ] bi@ = ] if ; > > My approach uses a stack (either a ``vector`` when processing an > array, or an ``sbuf`` when processing a string). If the stack is > empty (``?last`` returns ``f``), we don't react, otherwise check for a > match on the last character in the stack. > > : react? ( accum ch -- ? ) > [ ?last ] dip over [ match? ] [ 2drop f ] if ; > > An internal word that processes the whole string. If we react, then > we pop the last character from the stack, otherwise push the new one > onto the stack > > : (react) ( accum seq -- accum ) > [ 2dup react? [ drop dup pop* ] [ suffix! ] if ] each ; > > The main word that creates a new resizable sequence to use as a stack, > then applies the reactions: > > : react ( seq -- seq' ) > [ [ length ] [ new-resizable ] [ (react) ] tri ] keep like ; > > The part 2 question tries removing each letter, looking for the > smallest length of reactions: > > : remove-unit ( seq ch -- seq' ) > [ [ = ] [ ch>upper = ] 2bi or ] curry reject ; > > : shortest-react ( seq -- n ) > "abcdefghijklmnopqrstuvwxyz" [ > remove-unit react length > ] with map infimum ; > > I find that often I experiment with different approaches, sometimes > using locals and writing in a more applicative style, other times > starting with small components like ``match?`` and ``react?`` and then > building up an algorithm around it. I do like iteration in the > listener, but also find saving my code and refactoring easier with a > text file and doing F2 or ``refresh-all``, or using like you are FUEL. > > Also, as for finding words. We do want to continue improving > documentation, so if you have contributions there it would be great. > It's sometimes useful to just browse a vocabulary and look at all the > words in a list. Maybe we could think about adding the first sentence > of its documentation, if available, which would also help. You can see > on the help for ``min`` and ``max`` they have related words > ``supremum`` and ``infimum``. Maybe those need better names... > > Best, > John. > > On Tue, Dec 11, 2018 at 8:22 AM wrote: > >> On 2018-12-10 16:40, John Benediktsson wrote: >>> Using fry is convenient. Due to how we bootstrap factor, we can't >> use >>> fry right now in "core" vocabularies, like sequences, so you'll >> see a >>> fair amount of curry and compose which are more or less what fry >> is >>> doing, just not as clean syntax. >>> >>> I love the REPL advent idea, go for it! And as you learn or hit >>> roadblocks or have questions, please share. >>> >>> You can see how supremum-by is implemented by clicking on it in an >>> expression, or doing ``see``. It uses ``after?`` instead of >> ``>``, >>> which allows it to compare other kinds of objects with ``<=>`` >> when >>> numbers are not passed in. >>> >>> A
Re: [Factor-talk] maximum of a seq
Hi Peter, The performance difficulties in your solution arise from using ``head*`` which makes a new sequence (allocations, copying into new memory, etc.), rather than a lightweight slice which ``head-slice*`` does. You are right that slices are not what you expect, you might find this interesting: IN: scratchpad "abcdef" dup 3 head-slice CHAR: D suffix! --- Data stack: "abcDef" T{ slice f 0 3 "abcDef" } In-place operations like ``set-nth`` and variations like ``suffix!`` operate on the underlying sequence. The Clojure-like data structures are in ``persistent`` vocabulary. See, for example ``persistent.vectors``. Some of your words like ``upper`` are in the standard library (``ch>upper``). Also, I found your version didn't remove the extra newline in the input text, which resulted in an answer that was 1 too large. This looked like a fun puzzle, and I like fun puzzles, so I thought I'd implement it and maybe provide another solution which could help with learning: USING: ascii fry kernel math sequences ; You can tell if two characters match for a possible reaction, if they are not the same, but are when made to lowercase. I also really like your subtract and absolute difference should equal 32 approach. : match? ( ch1 ch2 -- ? ) 2dup = [ 2drop f ] [ [ ch>lower ] bi@ = ] if ; My approach uses a stack (either a ``vector`` when processing an array, or an ``sbuf`` when processing a string). If the stack is empty (``?last`` returns ``f``), we don't react, otherwise check for a match on the last character in the stack. : react? ( accum ch -- ? ) [ ?last ] dip over [ match? ] [ 2drop f ] if ; An internal word that processes the whole string. If we react, then we pop the last character from the stack, otherwise push the new one onto the stack : (react) ( accum seq -- accum ) [ 2dup react? [ drop dup pop* ] [ suffix! ] if ] each ; The main word that creates a new resizable sequence to use as a stack, then applies the reactions: : react ( seq -- seq' ) [ [ length ] [ new-resizable ] [ (react) ] tri ] keep like ; The part 2 question tries removing each letter, looking for the smallest length of reactions: : remove-unit ( seq ch -- seq' ) [ [ = ] [ ch>upper = ] 2bi or ] curry reject ; : shortest-react ( seq -- n ) "abcdefghijklmnopqrstuvwxyz" [ remove-unit react length ] with map infimum ; I find that often I experiment with different approaches, sometimes using locals and writing in a more applicative style, other times starting with small components like ``match?`` and ``react?`` and then building up an algorithm around it. I do like iteration in the listener, but also find saving my code and refactoring easier with a text file and doing F2 or ``refresh-all``, or using like you are FUEL. Also, as for finding words. We do want to continue improving documentation, so if you have contributions there it would be great. It's sometimes useful to just browse a vocabulary and look at all the words in a list. Maybe we could think about adding the first sentence of its documentation, if available, which would also help. You can see on the help for ``min`` and ``max`` they have related words ``supremum`` and ``infimum``. Maybe those need better names... Best, John. On Tue, Dec 11, 2018 at 8:22 AM wrote: > On 2018-12-10 16:40, John Benediktsson wrote: > > Using fry is convenient. Due to how we bootstrap factor, we can't use > > fry right now in "core" vocabularies, like sequences, so you'll see a > > fair amount of curry and compose which are more or less what fry is > > doing, just not as clean syntax. > > > > I love the REPL advent idea, go for it! And as you learn or hit > > roadblocks or have questions, please share. > > > > You can see how supremum-by is implemented by clicking on it in an > > expression, or doing ``see``. It uses ``after?`` instead of ``>``, > > which allows it to compare other kinds of objects with ``<=>`` when > > numbers are not passed in. > > > > Also, you might try using ``map-reduce`` which is a little faster than > > using ``unclip-slice`` and ``reduce``, (and using ``_ bi@`` instead of > > ``[ _ call ] bi@`` to simplify): > > > > : max-by ( seq quot -- result ) > > [ ] swap '[ [ _ bi@ > ] 2keep ? ] map-reduce ; inline > > > > Best, > > John. > > > > On Mon, Dec 10, 2018 at 6:46 AM Alexander Ilin > > wrote: > > > >> Hey there! > >> > >> Sure, you can ask us here. I'm on sick leave, so got plenty of > >> time. > >> Coincidentally, working on my Factor hobby project. > >> > >> What you're looking for is called supremum-by. > >> > >> Terminology is a bit uncommon. Look up supremum and infimum in the > >> help system. > >> > >> 10.12.2018, 17:06, "pet...@riseup.net" : > >>> Hello fellow concatenative fans. > >>> > >>> I'm working my way through this year's advent of code[0]. I'm > >> doing it > >>> in factor with a small twist - everything ha
Re: [Factor-talk] maximum of a seq
Hi, Peter! > Any reason why supremum-by and infimum-by are not on the "Searching > sequences" doc page? If you agree I can add these together with supremum > and infimum. A link in the help system would be useful, I think. I remember myself discovering those functions by word of mouth, after having read the documentation multiple times. It would have been nicer if I read about them in the help. > I'll take a look at map-reduce, thanks. I switched from using the factor > IDE REPL to emacs with Fuel because today I kept creating an infinite > loop and couldn't break it for the life of me in the IDE. In emacs it > was C-c C-c. Since I couldn't break it I didn't even know it's an > infinite loop. That led me to open a file and save the definitions for > debugging purposes, so I kind of broke my rules at this point. Oh well, > at least I solved another "day" today, although I'm rather behind at > this point, not enough time. If you work in Windows, there is experimental support for C-Break. Here's how I enable it in my .factor-rc: ! Enable handling of the Ctrl-Break interrupt USE: listener t handle-ctrl-break set-global Only works on Windows, though. There is no such thing as a global hotkey in Linus, AFAIK. > Another thing that tricked me: > > IN: aoc V{ 1 2 3 } 2 head-slice* 3 suffix! >array . > { 1 } > IN: aoc V{ 1 2 3 } rest-slice 3 suffix! >array . > { 2 3 } > > Slices work differently than I expected :) Are there clojure-like data > structures that are immutable and structurally share most of their > content? Not sure about clojure-like. Arrays { } are immutable, while vectors V{ } are mutable. You can also have read-only TUPLE: members: TUPLE: hello-tuple { var1 read-only } { var2 string read-only } ... ; ---=--- Александр ___ Factor-talk mailing list Factor-talk@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/factor-talk
Re: [Factor-talk] maximum of a seq
On 2018-12-10 16:40, John Benediktsson wrote: > Using fry is convenient. Due to how we bootstrap factor, we can't use > fry right now in "core" vocabularies, like sequences, so you'll see a > fair amount of curry and compose which are more or less what fry is > doing, just not as clean syntax. > > I love the REPL advent idea, go for it! And as you learn or hit > roadblocks or have questions, please share. > > You can see how supremum-by is implemented by clicking on it in an > expression, or doing ``see``. It uses ``after?`` instead of ``>``, > which allows it to compare other kinds of objects with ``<=>`` when > numbers are not passed in. > > Also, you might try using ``map-reduce`` which is a little faster than > using ``unclip-slice`` and ``reduce``, (and using ``_ bi@`` instead of > ``[ _ call ] bi@`` to simplify): > > : max-by ( seq quot -- result ) > [ ] swap '[ [ _ bi@ > ] 2keep ? ] map-reduce ; inline > > Best, > John. > > On Mon, Dec 10, 2018 at 6:46 AM Alexander Ilin > wrote: > >> Hey there! >> >> Sure, you can ask us here. I'm on sick leave, so got plenty of >> time. >> Coincidentally, working on my Factor hobby project. >> >> What you're looking for is called supremum-by. >> >> Terminology is a bit uncommon. Look up supremum and infimum in the >> help system. >> >> 10.12.2018, 17:06, "pet...@riseup.net" : >>> Hello fellow concatenative fans. >>> >>> I'm working my way through this year's advent of code[0]. I'm >> doing it >>> in factor with a small twist - everything happening inside the >> REPL. >>> Makes it more fun and challenging (for me), although I don't have >> any >>> code to show for it in the end. >>> >>> I'm trying to find the right tools for the job since there's a lot >> of >>> words already available. Sometimes I reinvent something before I >> find >>> it, e.g. I wrote a last-n before finding last*. >>> >>> Would it be OK if I sometimes ask you for tips on what would be >>> idiomatic/simpler/shorter/faster than what I have(n't) found? >>> >>> The first problem I really couldn't find is picking a maximum from >> a >>> sequence based on a quotation pulling out the key. An example will >> say >>> it the best I guess: >>> { { 1 2 } { 1 3 } { -1 4 } } [ second ] max-by . >>> >>> { -1 4 } >>> >>> Here is my definition: >>> >>> : max-by ( seq quot -- result ) [ unclip-slice ] dip '[ [ [ _ call >> ] bi@ ] 2keep ? ] reduce ; inline >>> >>> Using fry for such a general word would be a bit of an overkill >> but for >>> demonstration purposes it's OK I guess. >>> >>> Is there no standard word that already does something similar? Or >> is >>> there a way to write this with the existing sequence combinators >> that >>> it's so short there was no need to create this generic word? >>> >>> -- >>> >>> Peter Nagy >>> >>> >>> ___ >>> Factor-talk mailing list >>> Factor-talk@lists.sourceforge.net >>> https://lists.sourceforge.net/lists/listinfo/factor-talk >> >> ---=--- >> Александр >> >> ___ >> Factor-talk mailing list >> Factor-talk@lists.sourceforge.net >> https://lists.sourceforge.net/lists/listinfo/factor-talk > ___ > Factor-talk mailing list > Factor-talk@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/factor-talk Jon, Alex, hi. Any reason why supremum-by and infimum-by are not on the "Searching sequences" doc page? If you agree I can add these together with supremum and infimum. I'll take a look at map-reduce, thanks. I switched from using the factor IDE REPL to emacs with Fuel because today I kept creating an infinite loop and couldn't break it for the life of me in the IDE. In emacs it was C-c C-c. Since I couldn't break it I didn't even know it's an infinite loop. That led me to open a file and save the definitions for debugging purposes, so I kind of broke my rules at this point. Oh well, at least I solved another "day" today, although I'm rather behind at this point, not enough time. As far as roadblocks go, here is my solution to the 5th day. (react) is ugly with t/f, that's where I had the infinite loop and just quickly hacked the solution in. It takes quite a while to run, showing profile output further down: USING: arrays io.encodings.utf8 io.files kernel math math.ranges prettyprint sequences ; IN: aoc : reacts? ( a b -- ? ) - abs 32 = ; : (react) ( seq -- seq ? ) dup [ last ] [ dup length 2 - swap nth ] bi reacts? [ 2 head* t ] [ f ] if ; : has-2? ( seq -- ? ) length 2 >= ; : react ( seq -- seq ) dup has-2? [ (react) [ react ] when ] when ; : (flow) ( seq seq -- seq seq ) unclip-slice swap [ suffix! ] dip ; : flow ( seq seq -- seq ) dup empty? [ drop ] [ (flow) [ react ] dip flow ] if ; : load5 ( -- str ) "5.txt" utf8 file-contents ; : solve5 ( seq seq -- len ) flow length ; : upper ( c -- c ) dup 96 > [ 32 - ] when ; : nounit ( seq u -- seq ) [ [ upper ] dip = not ] curry
Re: [Factor-talk] maximum of a seq
Using fry is convenient. Due to how we bootstrap factor, we can't use fry right now in "core" vocabularies, like sequences, so you'll see a fair amount of curry and compose which are more or less what fry is doing, just not as clean syntax. I love the REPL advent idea, go for it! And as you learn or hit roadblocks or have questions, please share. You can see how supremum-by is implemented by clicking on it in an expression, or doing ``see``. It uses ``after?`` instead of ``>``, which allows it to compare other kinds of objects with ``<=>`` when numbers are not passed in. Also, you might try using ``map-reduce`` which is a little faster than using ``unclip-slice`` and ``reduce``, (and using ``_ bi@`` instead of ``[ _ call ] bi@`` to simplify): : max-by ( seq quot -- result ) [ ] swap '[ [ _ bi@ > ] 2keep ? ] map-reduce ; inline Best, John. On Mon, Dec 10, 2018 at 6:46 AM Alexander Ilin wrote: > Hey there! > > Sure, you can ask us here. I'm on sick leave, so got plenty of time. > Coincidentally, working on my Factor hobby project. > > What you're looking for is called supremum-by. > > Terminology is a bit uncommon. Look up supremum and infimum in the help > system. > > 10.12.2018, 17:06, "pet...@riseup.net" : > > Hello fellow concatenative fans. > > > > I'm working my way through this year's advent of code[0]. I'm doing it > > in factor with a small twist - everything happening inside the REPL. > > Makes it more fun and challenging (for me), although I don't have any > > code to show for it in the end. > > > > I'm trying to find the right tools for the job since there's a lot of > > words already available. Sometimes I reinvent something before I find > > it, e.g. I wrote a last-n before finding last*. > > > > Would it be OK if I sometimes ask you for tips on what would be > > idiomatic/simpler/shorter/faster than what I have(n't) found? > > > > The first problem I really couldn't find is picking a maximum from a > > sequence based on a quotation pulling out the key. An example will say > > it the best I guess: > > > >> { { 1 2 } { 1 3 } { -1 4 } } [ second ] max-by . > > > > { -1 4 } > > > > Here is my definition: > > > > : max-by ( seq quot -- result ) [ unclip-slice ] dip '[ [ [ _ call ] bi@ > >> ] 2keep ? ] reduce ; inline > > > > Using fry for such a general word would be a bit of an overkill but for > > demonstration purposes it's OK I guess. > > > > Is there no standard word that already does something similar? Or is > > there a way to write this with the existing sequence combinators that > > it's so short there was no need to create this generic word? > > > > -- > > > > Peter Nagy > > > > > > ___ > > Factor-talk mailing list > > Factor-talk@lists.sourceforge.net > > https://lists.sourceforge.net/lists/listinfo/factor-talk > > ---=--- > Александр > > > > ___ > Factor-talk mailing list > Factor-talk@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/factor-talk > ___ Factor-talk mailing list Factor-talk@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/factor-talk
Re: [Factor-talk] maximum of a seq
Hey there! Sure, you can ask us here. I'm on sick leave, so got plenty of time. Coincidentally, working on my Factor hobby project. What you're looking for is called supremum-by. Terminology is a bit uncommon. Look up supremum and infimum in the help system. 10.12.2018, 17:06, "pet...@riseup.net" : > Hello fellow concatenative fans. > > I'm working my way through this year's advent of code[0]. I'm doing it > in factor with a small twist - everything happening inside the REPL. > Makes it more fun and challenging (for me), although I don't have any > code to show for it in the end. > > I'm trying to find the right tools for the job since there's a lot of > words already available. Sometimes I reinvent something before I find > it, e.g. I wrote a last-n before finding last*. > > Would it be OK if I sometimes ask you for tips on what would be > idiomatic/simpler/shorter/faster than what I have(n't) found? > > The first problem I really couldn't find is picking a maximum from a > sequence based on a quotation pulling out the key. An example will say > it the best I guess: > >> { { 1 2 } { 1 3 } { -1 4 } } [ second ] max-by . > > { -1 4 } > > Here is my definition: > > : max-by ( seq quot -- result ) [ unclip-slice ] dip '[ [ [ _ call ] bi@ >> ] 2keep ? ] reduce ; inline > > Using fry for such a general word would be a bit of an overkill but for > demonstration purposes it's OK I guess. > > Is there no standard word that already does something similar? Or is > there a way to write this with the existing sequence combinators that > it's so short there was no need to create this generic word? > > -- > > Peter Nagy > > > ___ > Factor-talk mailing list > Factor-talk@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/factor-talk ---=--- Александр ___ Factor-talk mailing list Factor-talk@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/factor-talk
[Factor-talk] maximum of a seq
Hello fellow concatenative fans. I'm working my way through this year's advent of code[0]. I'm doing it in factor with a small twist - everything happening inside the REPL. Makes it more fun and challenging (for me), although I don't have any code to show for it in the end. I'm trying to find the right tools for the job since there's a lot of words already available. Sometimes I reinvent something before I find it, e.g. I wrote a last-n before finding last*. Would it be OK if I sometimes ask you for tips on what would be idiomatic/simpler/shorter/faster than what I have(n't) found? The first problem I really couldn't find is picking a maximum from a sequence based on a quotation pulling out the key. An example will say it the best I guess: > { { 1 2 } { 1 3 } { -1 4 } } [ second ] max-by . { -1 4 } Here is my definition: : max-by ( seq quot -- result ) [ unclip-slice ] dip '[ [ [ _ call ] bi@ > ] 2keep ? ] reduce ; inline Using fry for such a general word would be a bit of an overkill but for demonstration purposes it's OK I guess. Is there no standard word that already does something similar? Or is there a way to write this with the existing sequence combinators that it's so short there was no need to create this generic word? -- Peter Nagy ___ Factor-talk mailing list Factor-talk@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/factor-talk