I created a partial solution that also uses jdb using help from Dan's solution and others in my question yesterday. I didn't re-implement the import logic.
https://gist.github.com/joebo/6857220 I enjoyed exploring the data with jdb. I don't think it really helped with the solution, but made it easier to query the results. I could have used jdb for the frequency counts but opted for the built-in. I wasn't sure going into it how jdb would fit. My code is definitely beginner code. I left some of the explicit definitions in. Also, I think it's really a neat workflow to define a function that works on scalar inputs and then it seems to generally work with vector inputs -- http://www.jsoftware.com/help/jforc/loopless_code_i_verbs_have_r.htm I had this in an earlier version and removed it when I scored each race individually. scores=.(2{:: races) scorePlace"0 <"1 pointsForRace"0 cts 1 scorePlace pointsForRace 10 3 1 scorePlace pointsForRace 100 10 (1 1) scorePlace"0 <"1 pointsForRace"0 (10,100) 3 10 As someone coming from a C background, this is incredible. Thanks everyone for all the help. Sidebar: I tried creating a wiki account and posting it there in case it is a useful example of how to interact with jdb. It says I can't edit my homepage. On Sat, Oct 5, 2013 at 8:36 PM, Raul Miller <[email protected]> wrote: > I am surprised. > > Thank you, > > -- > Raul > > > On Sat, Oct 5, 2013 at 1:55 PM, Dan Bron <[email protected]> wrote: > > Thanks, this makes sense and I believe reflects the language of the > Dictionary. > > > > However, there is a discrepancy between the parser defined in the > Dictionary and the one implemented in the interpreter with regard to when > names are resolve [1,2]. In particular, while the Dictionary says name > resolution occurs as described below, in practice name resolution is only > immediate (i.e., when the name is popped of the stack) for nouns. For > non-nouns, including verbs, adverbs, conjunctions, and undefined names, > name resolution is deferred as long as possible. > > > > [1] "Adverbs/Conjunctions are stacked by name": > > http://www.jsoftware.com/pipermail/general/2002-January/010688.html > > > > [2] "Stacking by name": > > > http://www.jsoftware.com/pipermail/programming/2009-August/015810.html > > > > > > -----Original Message----- > > From: [email protected] [mailto: > [email protected]] On Behalf Of Raul Miller > > Sent: Friday, October 04, 2013 12:20 AM > > To: Chat forum > > Subject: Re: [Jchat] my programm looks terrible > > > > Name resolution happens when the name is shifted past the top of the > stack if the name refers to a noun, an adverb or a conjunction. It does > not happen for names which refers to verbs nor does it happen for undefined > names. The parsing rules treat undefined names as if they were verbs (and > this can be an error, if the definition of the verb is needed). > > > > Note also that the name of a verb has a locale associated with it. > > This can happen in three different ways: > > > > 1) name_locale_ > > 2) name__localereference > > 3) name > > > > In case 1), the locale is included in with the name. In case 2) there's > an indirect reference to the locale (it's identified in another variable > which is accessible in the current context). > > > > ex_a_=: 1 > > ex_b_=: 2 > > ex=: <'a' > > ex__ex > > 1 > > > > In case 3) there's an implied reference to the current locale, and I > thought this was retained even if the verb is processed in another locale, > but when I tested this idea I found it not to be the case in my example: > > > > f_a_=: 3: > > f_b_=: 4: > > do_a_ 'g_b_=: f' > > > > g_b_ '' > > 4 > > > > I think I am puzzled by this result, I was expecting a 3. > > > > Does anyone feel like telling me where I went wrong? > > > > Thanks, > > > > -- > > Raul > > > > > > On Thu, Oct 3, 2013 at 7:38 PM, Dan Bron <[email protected]> wrote: > >> Thanks. This walkthrough of how the parser thinks about things (as > opposed to how I think about things) was helpful for me. > >> > >> Could you further elaborate on this statement? > >> > >>> Name resolution happens when a name is shifted from the first position > >>> on the stack to the second. > >> > >> In particular, does this apply to all name resolutions, or just > pronouns? Are there cases where name resolution is deferred until the > actual value (as opposed to nameclass) of the name is needed to evaluate a > sentence? > >> > >> -Dan > >> > >> Please excuse typos; composed on a handheld device. > >> > >> On Oct 3, 2013, at 1:56 PM, Raul Miller <[email protected]> wrote: > >> > >>> [caution: i have been interrupted several times while composing this > >>> message. I been trying to make things consistent but if something > >>> looks inconsistent you should assume that your observations are > >>> accurate and then experiment to find out what really happens. > >>> Assuming, of course, you have time...] > >>> > >>> Personally, I am fond of making sure people understand the basics. So > >>> let's take the line that Dan advertised as being sneaky: > >>> > >>> RE =. +1 :n=. |. <;._2 noun define > >>> > >>> J executes its sentences from right to left. So the first word it > >>> encounters is 'define' which has the definition (: 0). In addition to > >>> being a perhaps cute smiley, this is the 'explicit definition' defined > >>> at http://www.jsoftware.com/help/dictionary/d310n.htm > >>> > >>> Since that's pretty much the whole language, let's kind of skip over > >>> it and just accept, for now, that it's defining something. > >>> > >>> The next word encountered is 'noun' which has the definition (0). > >>> Zero, if you recall, is the thing that if you add 3 to it you get 3. > >>> In other words, it's just a number. > >>> > >>> Anyways, when we combine 0 and (: 0) we get (0 : 0) - when executed, > >>> the J interpreter grabs subsequent lines from the session until > >>> terminated by a closing parenthesis. (This is, perhaps, a slight nudge > >>> at the lisp crowd, who use the closing parenthesis for a similar > >>> purpose despite their lack of respect for individual lines.) The > >>> result of evaluating (0 : 0) will then be those lines. (This can be > >>> fun to play with.) > >>> > >>> Anyways, at this point we have executed two rules from > >>> http://www.jsoftware.com/help/dictionary/dicte.htm > >>> > >>> The first rule was 3 Adverb and the second rule was the '4 Conj' rule > >>> listed near the bottom of the page. > >>> > >>> This second rule has the pattern: > >>> > >>> EDGE+AVN VERB+NOUN CONJ VERB+NOUN 4 Conj > >>> > >>> In other words, when executing a sentence, J is looking at four of the > >>> elements of the sentence (perhaps worth noting that some of those > >>> elements can be empty - this is important for ending a sentence) and > >>> for this rule, those elements must match this pattern: > >>> > >>> leftmost (EDGE+AVN): the emptiness off the left side of the sentence > >>> an assignment operator, a left parenthesis, or an adverb or a verb or > >>> a noun. > >>> > >>> next from the left (VERB+NOUN): a verb or a noun > >>> > >>> next after that (CONJ): a conjunction > >>> > >>> rightmost: (VERB+NOUN): a verb or a noun. > >>> > >>> In this example, both of the VERB+NOUN values were the number 0, and > >>> the CONJ was the explicit definition symbol. (Hopefully this is > >>> explicit enough?) > >>> > >>> Anyways, here's a more mechanical description of how this shift reduce > >>> grammar works: > >>> > >>> sentence: RE =. +1 :n=. |. <;._2 noun define > >>> > >>> parsed into tokens: > >>> ;:' RE =. +1 :n=. |. <;._2 noun define' > >>> ┌──┬──┬─┬─┬─┬─┬──┬──┬─┬──┬──┬────┬──────┐ > >>> │RE│=.│+│1│:│n│=.│|.│<│;.│_2│noun│define│ > >>> └──┴──┴─┴─┴─┴─┴──┴──┴─┴──┴──┴────┴──────┘ > >>> > >>> (If your email client messes up the display of that result, just > >>> execute the sentence for yourself in a J interpreter. That should > >>> reproduce the same result.) > >>> > >>> Once J has the sentence and has parsed it into tokens, it can treat > >>> the result as a queue, shifting the rightmost element from the queue > >>> onto its evaluation stack (and then after each shift doing a pattern > >>> match against the parsing rules and executing the first match). If > >>> nothing matches, J performs no operation and attempts another shift. > >>> Name resolution happens when a name is shifted from the first position > >>> on the stack to the second. > >>> > >>> So at the point the '3 Adverb' rule triggered, the queue looked like > this: > >>> > >>> RE =. + 1 : n =. |. < ;. > >>> > >>> And the stack looked like this: > >>> > >>> leftmost: _2 > >>> next left: 0 > >>> next left: : 0 > >>> rightmost: > >>> > >>> The parsing rule for 3 Adverb look like this: > >>> > >>> EDGE+AVN VERB+NOUN ADV ANY 3 Adverb > >>> > >>> The '3 Adverb' off on the right hand side is just a label and not a > >>> part of the rule itself. > >>> > >>> Also the 'VERB+NOUN' and 'ADV' parts of the rule are highlighted. > >>> That's not portable to email. Highlighted means that that's the part > >>> of the rule whose values are used in the execution (and these used > >>> values will be removed and replaced with the result of the execution > >>> of the rule). > >>> > >>> So after executing 3 Adverb the stack looks like this > >>> > >>> leftmost: _2 > >>> next left: (lots of text) > >>> next left: > >>> rightmost: > >>> > >>> Anyways, after completing an execution J goes back to doing its > >>> shifting (and pattern matching (and maybe some execution as well), and > >>> when the next execution comes around, the queue looks like this: > >>> > >>> RE =. + 1 : n =. > >>> > >>> and the stack looks like this: > >>> > >>> leftmost: |. > >>> next left: < > >>> next left: ;. > >>> rightmost: _2 > >>> next right: (lots of text) > >>> > >>> J only inspects the top four elements of the stack during pattern > >>> matching but the stack itself will have an arbitrary depth. > >>> > >>> And, remembering our '4 Conj' rule, it was: > >>> EDGE+AVN VERB+NOUN CONJ VERB+NOUN 4 Conj > >>> > >>> and if you looked up that parsing and execution page in the > >>> dictionary, you'd see that both the VERB+NOUN entries were highlighted > >>> as was the CONJ. So the part being executed here is < ;. _2 and those > >>> glue together to get a verb that splits on a final delimiting > >>> character, chopping it off, and boxing each resulting string. And > >>> since we know that our final character in this case will be a newline > >>> character, we can call the expected result here a list of boxed lines. > >>> > >>> For our next step, the queue looks like this: > >>> > >>> RE =. + 1 : n > >>> > >>> and the stack looks like this: > >>> > >>> leftmost: =. > >>> next left: |. > >>> next left: <;._2 > >>> rightmost: lots of text > >>> > >>> And the rule being executed is '1 Monad', and the elements being > >>> processed are the two rightmost. > >>> > >>> For our next step in execution, the queue looks like > >>> > >>> RE =. + 1 : n > >>> > >>> and the stack looks like > >>> > >>> leftmost: n > >>> next left: =. > >>> next left: |. > >>> rightmost: boxed lines > >>> > >>> Again, the '1 Monad' rule should trigger, reversing the list of boxes. > >>> > >>> Now here is a subtle issue which I am not completely certain about: I > >>> believe that the next execution step occurs without moving anything > >>> from the queue. The '7 Is' rule should kick in here, with the stack > >>> being: > >>> > >>> leftmost: n > >>> next left: =. > >>> next left: reversed boxes of lines > >>> rightmost: > >>> > >>> This step should set the local value 'n' and should have a result > >>> which is the reversed boxes of lines. > >>> > >>> After some more shifting, the queue should look like this: > >>> > >>> RE =. > >>> > >>> And the stack should be: > >>> > >>> leftmost: + > >>> next left: 1 > >>> next left: : > >>> rightmost: reversed boxes of lines > >>> > >>> Here, '4 Conj' takes action and the result is an adverb. > >>> > >>> Next, we get a queue of > >>> > >>> RE > >>> > >>> and a stack of > >>> > >>> leftmost: =. > >>> next left: + > >>> next left: 1 : (reversed boxes of lines) > >>> rightmost: > >>> > >>> and the '3 Adverb' rule takes action. The boxed lines are then > >>> evaluated as the body of this adverb. > >>> > >>> Next our queue is empty, and our stack looks like > >>> > >>> leftmost: R > >>> next left: =. > >>> next left: evaluated result > >>> rightmost: empty > >>> > >>> Finally, we have this: > >>> > >>> leftmost: empty queue marker > >>> next left: evaluated result > >>> next left: > >>> rightmost: > >>> > >>> And no rules can trigger here, and since the queue is now empty for > >>> real, no syntax error is triggered and we are done executing the > >>> sentence. (I showed the queue as having only the supplied tokens, but > >>> really there's an "end of queue" token on the far left that we needed > >>> to make this last step work right.) > >>> > >>> Anyways, hopefully I did not make too many mistakes here, and you can > >>> either understand something of how J's parsing works despite my > >>> mistakes or you can at least understand enough to ask questions about > >>> the things I have not treated properly. > >>> > >>> Thanks, > >>> > >>> -- > >>> Raul > >>> > >>> On Wed, Oct 2, 2013 at 11:35 PM, inv2004 . <[email protected]> wrote: > >>>> Thank you very much! Sorry I cannot answer something about it right > now, > >>>> because I need much more time to read it and to understand. > >>>> > >>>> But I see none of < > and { :) > >>>> > >>>> Thank you, > >>>> > >>>> > >>>> On Wed, Oct 2, 2013 at 10:04 PM, Dan Bron <[email protected]> wrote: > >>>> > >>>>> Alexander (inv2004) wrote: > >>>>>> Description I am trying to calculate: > >>>>>> http://www.usacycling.org/news/user/story.php?id=580 > >>>>>> source data: https://dl.dropboxusercontent.com/u/34917039/2013.txt > >>>>>> J source: https://dl.dropboxusercontent.com/u/34917039/1.j > >>>>> > >>>>> I knocked together an implementation in J (based on my > perhaps-mistaken > >>>>> understanding of your problem): > >>>>> > >>>>> > >>>>> > http://jsoftware.com/svn/DanBron/trunk/uncategorized/scoreRoadRace.ijs > >>>>> > >>>>> It didn't take very long to code, but unfortunately it would take > much > >>>>> longer to explain it in prose. Also, the style is very peculiar to > me, > >>>>> which means it's dense, and uses some sneaky tricks, so even veteran > J > >>>>> programmers may find it obscure (e.g. executing the first paragraph, > which > >>>>> defines 'RE', in reverse order). > >>>>> > >>>>> I know your goal wasn't to solve this little race scoring puzzle, > but to > >>>>> use > >>>>> the puzzle as a means to learn J. So, if I get some more time over > the > >>>>> week, > >>>>> I may select and dissect pieces of the code. > >>>>> > >>>>> In the meantime, it may be worth your while to play with it on your > own. If > >>>>> you want to do that, it'll probably be easiest and most fruitful to > break > >>>>> it > >>>>> into pieces and try them out, interactively, in the J session. > >>>>> > >>>>> So I recommend you replace all the local assignments (=.) with global > >>>>> assignments (=:), so all the intermediate names will be available to > >>>>> inspect > >>>>> and play with individually*. > >>>>> > >>>>> For example, I think you'll be interested in 'score' and > 'catSumCount' (and > >>>>> their respective dependencies), because these are the heart of the > problem > >>>>> and also highlight how J expresses such ideas differently, and > perhaps more > >>>>> elegantly, than other programming languages: > >>>>> > >>>>> score 1+i. 3 NB. Fewer than 5 racers > >>>>> 0 0 0 > >>>>> score 1+i. 5 NB. 5 racers > >>>>> 3 2 1 0 0 > >>>>> score 1+i. 10 NB. 10 racers > >>>>> 3 2 1 0 0 0 0 0 0 0 > >>>>> score 1+i. 11 NB. 11 racers > >>>>> 7 5 4 3 2 1 0 0 0 0 0 > >>>>> > >>>>> > >>>>> pointGroup 1+i. 3 NB. Fewer than 5 racers > >>>>> 0 > >>>>> pointGroup 1+i. 5 NB. 5 racers > >>>>> 3 2 1 > >>>>> pointGroup 1+i. 10 NB. 10 racers > >>>>> 3 2 1 > >>>>> pointGroup 1+i. 11 NB. 11 racers > >>>>> 7 5 4 3 2 1 > >>>>> > >>>>> > >>>>> pointGroup > >>>>> (0;3 2 1;7 5 4 3 2 1;8 6 5 4 3 2 1;10 8 7 6 5 4 3 2 1) {::~ 4 > 10 20 > >>>>> 49 I. # > >>>>> > >>>>> > >>>>> catSumCount 8 7 10 0 3 0 0 0 1 NB. 9 races, score=29, > category=3 > >>>>> +-+--+-+ > >>>>> |3|29|9| > >>>>> +-+--+-+ > >>>>> catSumCount 5 4 0 7 NB. 4 races, score=16, category=4 > >>>>> +-+--+-+ > >>>>> |4|16|4| > >>>>> +-+--+-+ > >>>>> catSumCount 3000 NB. 1 race, score=super high, but still > >>>>> category=4 > >>>>> +-+----+-+ > >>>>> |4|3000|1| > >>>>> +-+----+-+ > >>>>> > >>>>> catSumCount > >>>>> +/ (category ; ;) # > >>>>> > >>>>> (+/ category #) 8 7 10 0 3 0 0 0 1 > >>>>> 3 > >>>>> > >>>>> (+/ , #) 8 7 10 0 3 0 0 0 1 > >>>>> 29 9 > >>>>> > >>>>> 29 category 9 NB. x=sum of scores, y=# of races > >>>>> 3 > >>>>> 35 category 7 > >>>>> 1 > >>>>> 35 category 2 > >>>>> 1 > >>>>> 33 category 5 > >>>>> 2 > >>>>> > >>>>> category > >>>>> 4 <. 1 + 35 30 20 I. (* 2&<:) > >>>>> > >>>>> It's worth noting the core parts of the scoring algorithm, > 'pointGroup' and > >>>>> 'category', are both based on the dyad I. [1]. This is because those > parts > >>>>> of the scoring system are defined in terms of ranges (a race of 5 to > 10 > >>>>> riders, a race of 11 to 20 riders vs. a total score from 0 to 20, a > total > >>>>> score from 21 to 30, etc). > >>>>> > >>>>> The dyad I., interval index, is a sterling example of the > expressivity and > >>>>> economy of J's notation. Here, it allows us to define these ranges > by their > >>>>> essential characteristics, the demarcation lines between levels, > rather > >>>>> than > >>>>> the (repetitive, superfluous) contents of each level. Not only is > this > >>>>> convenient, but critically, it allows these essential > characteristics stand > >>>>> out in our code, rendering it at once briefer and clearer. The > >>>>> fundamentals > >>>>> are immediately exposed. > >>>>> > >>>>> For example, compare 'category' with the original 'cat' or > 'pointGroup' > >>>>> with > >>>>> the original 'points'. Heck, compare the code defining GROUPs to the > table > >>>>> in the official scoring site you linked! Sometimes, formalizing a > problem > >>>>> makes it even clearer than the specification. And, that little itch > you > >>>>> feel to start playing with these rules, now that they're exposed and > >>>>> accessible?* That's what we mean when we say the notation is > "suggestive". > >>>>> > >>>>> I hope this gives you a flavor of the benefits, and joys, of J. > >>>>> > >>>>> -Dan > >>>>> > >>>>> * And because it's really easy to do, given J's short feedback loop > and > >>>>> interactive nature. > >>>>> > >>>>> [1] Definition of the dyad I., "Interval Index" > >>>>> http://www.jsoftware.com/help/dictionary/dicapdot.htm > >>>>> > >>>>> > >>>>> > >>>>> > ---------------------------------------------------------------------- > >>>>> For information about J forums see > http://www.jsoftware.com/forums.htm > >>>> > >>>> > >>>> > >>>> -- > >>>> Regards, > >>>> Alexander. > >>>> ---------------------------------------------------------------------- > >>>> For information about J forums see > http://www.jsoftware.com/forums.htm > >>> ---------------------------------------------------------------------- > >>> For information about J forums see http://www.jsoftware.com/forums.htm > >> ---------------------------------------------------------------------- > >> For information about J forums see http://www.jsoftware.com/forums.htm > > ---------------------------------------------------------------------- > > For information about J forums see http://www.jsoftware.com/forums.htm > > > > ---------------------------------------------------------------------- > > For information about J forums see http://www.jsoftware.com/forums.htm > ---------------------------------------------------------------------- > For information about J forums see http://www.jsoftware.com/forums.htm > ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm
