Forum Replies Created

  • jbetz34

    Member
    August 3, 2023 at 12:00 am in reply to: Challenge 4 – World Cup

    Hi Megan,

    If all you want is to print these statements, you don’t necessarily need to cast the columns to symbols or save in a table. Try the following one-liner:

    {x,” from “,y,” scored a goal in the “,z,”th minute”}./: flip(“***”;”;”) 0:`:goals.txt

    By default this prints to the console, so I don’t see why you would need to include the “0N!” .

    The reason you are getting a parse error on the “0N! each ” is because “0N!” is an infix function followed by a postfix iterator. You will have to wrap “0N! in parenthesis (see https://code.kx.com/q/basics/syntax/#prefix-infix-postfix). Also worth noting that “0N!/:” will work here as well.  However, I think even this is unnecessary as “0N!” is unary and natively handles a list of strings.

  • jbetz34

    Member
    December 4, 2022 at 12:00 am in reply to: Joy of q: Let it snow

    A bit more than just Ajax… Joy of q: It’s snowing again

  • jbetz34

    Member
    October 4, 2022 at 12:00 am in reply to: Five easy pieces #2: getting around

     

    Spoiler
    rnd:{[x;nd;m] string%[;s]((ceiling;floor;7h$)`up`dn`nr?m)@:x*s:10 xexp nd}?

    Stealing your solution here, except floor 0.5+ can be replaced with 7h$. It is slightly more efficient and will save about 10 characters, if that matters

  • jbetz34

    Member
    July 4, 2022 at 12:00 am in reply to: Joy of q: Let it snow

    Very cool. A possible improvement might be to asynchronously push on a timer from the q server once connection has been established. That way you don’t have to refresh every time to see the snow fall. Can’t wait to try for myself.

  • jbetz34

    Member
    January 22, 2022 at 11:00 am in reply to: Wordle kdb

    Hi Paul,

    Awesome brain teaser!
    I was inspired by your scoring method to continue development beyond line 1.

    To begin, I used the same import and sanitize functions that you did:

    wordz:system “curl http://wiki.puzzlers.org/pub/wordlists/unixdict.txt“; wordz:wordz where all (5=count each wordz;all each wordz in .Q.a);

    However, instead of using a dictionary format to calculate letter scores, I used a table format. Table format would simplify the query/filtering process as we continue to guess possible words.

    I started with a base table of all the wordz, separating each letter into a positional column in roman numerals (i.e I,II,III –> 1,2,3).

    // create base word table 
    w:([] word:wordz; I:wordz[;0]; II:wordz[;1]; III:wordz[;2]; IV:wordz[;3]; V:wordz[;4]);
    // note that all columns are string type 
    q) w 
    word I II III IV V 
    --------------------- 
    "aaron" a a r o n 
    "ababa" a b a b a 
    "aback" a b a c k 
    "abase" a b a s e 
    "abash" a b a s h

    Next, to replicate the wordzScore using the table format ,  I created a generic probability function that would accept a table of words similar to the base table and a column to analyze. It returns a dictionary of letter probability within that positional column

    // generic wordzScore function 
    // x - words table 
    // y - column to analyze 
    prb:{{x%sum x} ?[x;();y;(count;`i)]}; 
    q)prb[w;`I] 
    a| 0.06868045 
    b| 0.08426073 
    c| 0.08330684 
    d| 0.05055644 
    e| 0.03561208

    I applied that function to each column,  summed across columns and applied back to the original table:

    // apply probability func across columns 
    s:?[t;();0b;n!{(@;x y;y)}[prb[t]] each n:`I`II`III`IV`V];
    // sum across columns and apply to base table 
    t:update score:(exec sum (I;II;III;IV;V) from s) from t; 
    q) t 
    word I II III IV V score 
    ------------------------------- 
    "sauce" s a u c e 0.6 
    "saute" s a u t e 0.6 
    "salle" s a l l e 0.5974563 
    "caine" c a i n e 0.5971383 
    "slate" s l a t e 0.5879173

    Great! Now we are all caught up to where you left off, but in table format.

    One of the most important aspects to wordle is understanding and properly responding to the clues that the game will give after each guess. There are 3 options for each letter:

    • it is not in the word
    • it is in the word, but not in correct position
    • it is in the word and in the correct position

    We can use these clues to limit our words table and recalculate the wordzScore at each step to make sure we take the best guess at each opportunity. I viewed this in 3 parts:

    1. Record guesses and clues from game
    2. Build filter clauses from these clues
    3. Use these filters to recalculate wordzScore

    Starting with the easiest step, #3. Lets put the wordzScore calculation in a function that accepts a parse tree of ‘where’ clauses as an argument:

    // where w exists globally and is base word table 
    // where prb exists globally and is letter probability function 
    topList:{[wc] t:?[`w;wc;0b;()]; s:?[t;();0b;n!{(@;x y;y)}[prb[t]] each n:`I`II`III`IV`V]; 
    t:update score:(exec sum (I;II;III;IV;V) from s) from t; `score xdesc t }

    Then, lets create a table where we can record our guesses, clues from the game and the resulting word filters from that guess (can you tell I love tables?). Simple enough:

    guessTable:([]guess:();clues:();wc:())

    Now comes the tricky part, how to we build a function to generate filters based on the clues. Here’s what I came up with. It is not the most elegant and can definitely be optimized, but it gets the job done.

    // expecting string guess (g) 
    // list of longs corresponding to clues (c) 
    // 0 - not in word; 
    // -1 - correct letter, wrong spot; 
    // 1 - correct letter, correct spot; 
    guess:{[g;c] // if letter is in wrong spot, filter out words where that letter is in that position column 
    wc:{(not;(in;`I`II`III`IV`V@y;x y))}[g] each where c=-1; // if letter is in wrong spot, also filter for words where that letter is in the word column 
    wc,:{(in/:;x y;`word)}[g] each where c=-1; // if letter is not in word, filter out words with that letter in the word column 
    wc,:{(not;(in/:;x y;`word))}[g] each where c=0; // if letter is in the right spot, filter for words with that letter in that position column 
    wc,:{(in;`I`II`III`IV`V@y;x y)}[g] each where c=1; // upsert the guess, clues and filters to the guessTable and display 
    `guessTable upsert enlist (g;c;wc); :guessTable }

    Tying it all together, lets try it out on a sample 5 letter word like “water”:

    q)l qWordle.q 
    q)1#topList() 
    word I II III IV V score 
    --------------------------- 
    "sauce" s a u c e 0.6 // manually entering clues 
    q)guess["sauce";0 1 0 0 -1] 
    guess clues wc 
    ----------------------------------------------------------------------------------------------------------------------------------- 
    "sauce" 0 1 0 0 -1 (~:;(in;`V;"e")) (in/:;"e";`word) (~:;(in/:;"s";`word)) (~:;(in/:;"u";`word)) (~:;(in/:;"c";`word)) (in;`II;"a") 
    q)1#topList raze guessTable`wc 
    word I II III IV V score 
    ----------------------------- 
    "hater" h a t e r 2.62069 // manually entering clues 
    q)guess["hater";0 1 1 1 1] 
    guess clues wc 
    ------------------------------------------------------------------------------------------------------------------------------------- 
    "sauce" 0 1 0 0 -1 ((~:;(in;`V;"e"));(in/:;"e";`word);(~:;(in/:;"s";`word));(~:;(in/:;"u";`word));(~:;(in/:;"c";`word));(in;`II;"a")) 
    "hater" 0 1 1 1 1 ((~:;(in/:;"h";`word));(in;`II;"a");(in;`III;"t");(in;`IV;"e");(in;`V;"r")) 
    q)topList raze guessTable`wc topList raze guessTable`wc 
    word I II III IV V score 
    ------------------------------ 
    "bater" b a t e r 4.111111 
    "dater" d a t e r 4.111111 
    "eater" e a t e r 4.111111 
    "later" l a t e r 4.111111 
    "mater" m a t e r 4.111111 
    "pater" p a t e r 4.111111 
    "rater" r a t e r 4.111111 
    "tater" t a t e r 4.111111 
    "water" w a t e r 4.111111

     

    At this rate, I don’t think we will get it in 6 guesses. But who knew there were so many “*ater” words?
    I am sure there are many improvements to be made here, but I have also spent too much time on this today.

    Thanks Paul, looking forward to more awesome content like this.

    – James

  • jbetz34

    Member
    January 8, 2022 at 12:00 am in reply to: Underneath q is k
  • jbetz34

    Member
    January 8, 2022 at 12:00 am in reply to: Underneath q is k

    q is built on k4, but shakti (k9) has many similar aspects to the k4 language and is better documented here: https://estradajke.github.io/k9-simples/k9/index.html